2019-10-16 08:59:30 +00:00
|
|
|
use crate::base::ExtCtxt;
|
2020-02-29 17:37:32 +00:00
|
|
|
use rustc_ast::ptr::P;
|
2021-06-22 18:00:58 +00:00
|
|
|
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
|
2022-12-05 03:16:41 +00:00
|
|
|
use rustc_ast::{attr, token, util::literal};
|
2020-08-21 23:11:00 +00:00
|
|
|
use rustc_span::source_map::Spanned;
|
2020-04-19 11:00:18 +00:00
|
|
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
2023-11-24 14:32:05 +00:00
|
|
|
use rustc_span::{Span, DUMMY_SP};
|
2022-11-23 00:55:16 +00:00
|
|
|
use thin_vec::{thin_vec, ThinVec};
|
2013-02-15 05:50:03 +00:00
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
impl<'a> ExtCtxt<'a> {
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
|
2019-09-21 19:01:10 +00:00
|
|
|
self.path_all(span, false, strs, vec![])
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn path_ident(&self, span: Span, id: Ident) -> ast::Path {
|
2016-10-29 21:54:04 +00:00
|
|
|
self.path(span, vec![id])
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn path_global(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
|
2019-09-21 19:01:10 +00:00
|
|
|
self.path_all(span, true, strs, vec![])
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn path_all(
|
|
|
|
&self,
|
2017-07-23 17:50:56 +00:00
|
|
|
span: Span,
|
2013-05-19 05:53:42 +00:00
|
|
|
global: bool,
|
2020-04-19 11:00:18 +00:00
|
|
|
mut idents: Vec<Ident>,
|
2019-09-21 19:01:10 +00:00
|
|
|
args: Vec<ast::GenericArg>,
|
2013-08-07 16:47:28 +00:00
|
|
|
) -> ast::Path {
|
2018-12-02 12:15:42 +00:00
|
|
|
assert!(!idents.is_empty());
|
|
|
|
let add_root = global && !idents[0].is_path_segment_keyword();
|
2022-09-08 07:22:52 +00:00
|
|
|
let mut segments = ThinVec::with_capacity(idents.len() + add_root as usize);
|
2018-12-02 12:15:42 +00:00
|
|
|
if add_root {
|
|
|
|
segments.push(ast::PathSegment::path_root(span));
|
|
|
|
}
|
2018-03-18 00:53:41 +00:00
|
|
|
let last_ident = idents.pop().unwrap();
|
2018-03-19 00:54:56 +00:00
|
|
|
segments.extend(
|
|
|
|
idents.into_iter().map(|ident| ast::PathSegment::from_ident(ident.with_span_pos(span))),
|
|
|
|
);
|
2019-09-21 19:01:10 +00:00
|
|
|
let args = if !args.is_empty() {
|
2020-03-22 03:40:05 +00:00
|
|
|
let args = args.into_iter().map(ast::AngleBracketedArg::Arg).collect();
|
2023-03-16 22:00:08 +00:00
|
|
|
Some(ast::AngleBracketedArgs { args, span }.into())
|
2016-12-10 06:45:58 +00:00
|
|
|
} else {
|
2017-07-23 16:32:36 +00:00
|
|
|
None
|
2016-12-10 06:45:58 +00:00
|
|
|
};
|
2018-08-31 00:01:26 +00:00
|
|
|
segments.push(ast::PathSegment {
|
|
|
|
ident: last_ident.with_span_pos(span),
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
args,
|
|
|
|
});
|
2020-08-21 22:51:23 +00:00
|
|
|
ast::Path { span, segments, tokens: None }
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
|
2014-01-09 13:05:33 +00:00
|
|
|
ast::MutTy { ty, mutbl }
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 16:25:31 +00:00
|
|
|
pub fn ty(&self, span: Span, kind: ast::TyKind) -> P<ast::Ty> {
|
2020-08-21 22:18:04 +00:00
|
|
|
P(ast::Ty { id: ast::DUMMY_NODE_ID, span, kind, tokens: None })
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
Optimize the code produced by `derive(Debug)`.
This commit adds new methods that combine sequences of existing
formatting methods.
- `Formatter::debug_{tuple,struct}_field[12345]_finish`, equivalent to a
`Formatter::debug_{tuple,struct}` + N x `Debug{Tuple,Struct}::field` +
`Debug{Tuple,Struct}::finish` call sequence.
- `Formatter::debug_{tuple,struct}_fields_finish` is similar, but can
handle any number of fields by using arrays.
These new methods are all marked as `doc(hidden)` and unstable. They are
intended for the compiler's own use.
Special-casing up to 5 fields gives significantly better performance
results than always using arrays (as was tried in #95637).
The commit also changes the `Debug` deriving code to use these new methods. For
example, where the old `Debug` code for a struct with two fields would be like
this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => {
let debug_trait_builder = &mut ::core::fmt::Formatter::debug_struct(f, "S2");
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f1", &&(*__self_0_0));
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f2", &&(*__self_0_1));
::core::fmt::DebugStruct::finish(debug_trait_builder)
}
}
}
```
the new code is like this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => ::core::fmt::Formatter::debug_struct_field2_finish(
f,
"S2",
"f1",
&&(*__self_0_0),
"f2",
&&(*__self_0_1),
),
}
}
```
This shrinks the code produced for `Debug` instances
considerably, reducing compile times and binary sizes.
Co-authored-by: Scott McMurray <scottmcm@users.noreply.github.com>
2022-06-17 07:08:36 +00:00
|
|
|
pub fn ty_infer(&self, span: Span) -> P<ast::Ty> {
|
|
|
|
self.ty(span, ast::TyKind::Infer)
|
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
|
2016-02-08 15:53:21 +00:00
|
|
|
self.ty(path.span, ast::TyKind::Path(None, path))
|
2014-11-20 20:08:48 +00:00
|
|
|
}
|
|
|
|
|
2013-06-17 19:16:30 +00:00
|
|
|
// Might need to take bounds as an argument in the future, if you ever want
|
|
|
|
// to generate a bounded existential trait type.
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn ty_ident(&self, span: Span, ident: Ident) -> P<ast::Ty> {
|
2014-11-20 20:08:48 +00:00
|
|
|
self.ty_path(self.path_ident(span, ident))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 13:39:48 +00:00
|
|
|
pub fn anon_const(&self, span: Span, kind: ast::ExprKind) -> ast::AnonConst {
|
2019-02-05 15:50:00 +00:00
|
|
|
ast::AnonConst {
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
2020-05-19 20:56:20 +00:00
|
|
|
value: P(ast::Expr {
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
kind,
|
|
|
|
span,
|
|
|
|
attrs: AttrVec::new(),
|
|
|
|
tokens: None,
|
|
|
|
}),
|
2019-02-05 15:50:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn const_ident(&self, span: Span, ident: Ident) -> ast::AnonConst {
|
2019-02-05 15:50:00 +00:00
|
|
|
self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident)))
|
|
|
|
}
|
|
|
|
|
2022-12-28 17:06:11 +00:00
|
|
|
pub fn ty_ref(
|
2019-07-31 11:40:32 +00:00
|
|
|
&self,
|
2013-08-31 16:13:04 +00:00
|
|
|
span: Span,
|
2013-11-30 22:00:39 +00:00
|
|
|
ty: P<ast::Ty>,
|
2013-07-05 12:33:52 +00:00
|
|
|
lifetime: Option<ast::Lifetime>,
|
2013-09-02 01:45:37 +00:00
|
|
|
mutbl: ast::Mutability,
|
2013-11-30 22:00:39 +00:00
|
|
|
) -> P<ast::Ty> {
|
2022-12-28 17:06:11 +00:00
|
|
|
self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl)))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2013-12-31 20:55:39 +00:00
|
|
|
|
2014-08-27 13:19:17 +00:00
|
|
|
pub fn ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> {
|
2016-02-08 15:53:21 +00:00
|
|
|
self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl)))
|
2014-08-27 13:19:17 +00:00
|
|
|
}
|
2013-12-31 20:55:39 +00:00
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn typaram(
|
|
|
|
&self,
|
2014-04-03 00:53:57 +00:00
|
|
|
span: Span,
|
2020-04-19 11:00:18 +00:00
|
|
|
ident: Ident,
|
2018-06-14 11:08:58 +00:00
|
|
|
bounds: ast::GenericBounds,
|
2018-05-27 19:07:09 +00:00
|
|
|
default: Option<P<ast::Ty>>,
|
|
|
|
) -> ast::GenericParam {
|
|
|
|
ast::GenericParam {
|
2018-03-19 00:54:56 +00:00
|
|
|
ident: ident.with_span_pos(span),
|
2014-01-30 17:28:02 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2022-08-17 02:33:42 +00:00
|
|
|
attrs: AttrVec::new(),
|
2018-05-28 12:33:28 +00:00
|
|
|
bounds,
|
2018-05-27 19:07:09 +00:00
|
|
|
kind: ast::GenericParamKind::Type { default },
|
2019-09-09 12:26:25 +00:00
|
|
|
is_placeholder: false,
|
2022-04-28 19:59:41 +00:00
|
|
|
colon_span: None,
|
2014-01-30 17:28:02 +00:00
|
|
|
}
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
|
2020-01-14 04:30:29 +00:00
|
|
|
ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
|
2014-11-07 11:53:45 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef {
|
2014-11-07 11:53:45 +00:00
|
|
|
ast::PolyTraitRef {
|
2022-11-21 22:17:20 +00:00
|
|
|
bound_generic_params: ThinVec::new(),
|
2015-02-05 08:46:01 +00:00
|
|
|
trait_ref: self.trait_ref(path),
|
2017-08-07 05:54:09 +00:00
|
|
|
span,
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-17 13:51:25 +00:00
|
|
|
|
2023-02-07 20:59:48 +00:00
|
|
|
pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
|
2018-06-14 11:23:46 +00:00
|
|
|
ast::GenericBound::Trait(
|
|
|
|
self.poly_trait_ref(path.span, path),
|
2023-02-07 20:59:48 +00:00
|
|
|
if is_const {
|
2023-11-24 14:32:05 +00:00
|
|
|
ast::TraitBoundModifier::MaybeConst(DUMMY_SP)
|
2023-02-07 20:59:48 +00:00
|
|
|
} else {
|
|
|
|
ast::TraitBoundModifier::None
|
|
|
|
},
|
2018-06-14 11:23:46 +00:00
|
|
|
)
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime {
|
2018-03-19 00:54:56 +00:00
|
|
|
ast::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) }
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
Optimize the code produced by `derive(Debug)`.
This commit adds new methods that combine sequences of existing
formatting methods.
- `Formatter::debug_{tuple,struct}_field[12345]_finish`, equivalent to a
`Formatter::debug_{tuple,struct}` + N x `Debug{Tuple,Struct}::field` +
`Debug{Tuple,Struct}::finish` call sequence.
- `Formatter::debug_{tuple,struct}_fields_finish` is similar, but can
handle any number of fields by using arrays.
These new methods are all marked as `doc(hidden)` and unstable. They are
intended for the compiler's own use.
Special-casing up to 5 fields gives significantly better performance
results than always using arrays (as was tried in #95637).
The commit also changes the `Debug` deriving code to use these new methods. For
example, where the old `Debug` code for a struct with two fields would be like
this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => {
let debug_trait_builder = &mut ::core::fmt::Formatter::debug_struct(f, "S2");
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f1", &&(*__self_0_0));
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f2", &&(*__self_0_1));
::core::fmt::DebugStruct::finish(debug_trait_builder)
}
}
}
```
the new code is like this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => ::core::fmt::Formatter::debug_struct_field2_finish(
f,
"S2",
"f1",
&&(*__self_0_0),
"f2",
&&(*__self_0_1),
),
}
}
```
This shrinks the code produced for `Debug` instances
considerably, reducing compile times and binary sizes.
Co-authored-by: Scott McMurray <scottmcm@users.noreply.github.com>
2022-06-17 07:08:36 +00:00
|
|
|
pub fn lifetime_static(&self, span: Span) -> ast::Lifetime {
|
|
|
|
self.lifetime(span, Ident::new(kw::StaticLifetime, span))
|
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
|
2020-11-17 19:27:44 +00:00
|
|
|
ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
Don't use match-destructuring for derived ops on structs.
All derive ops currently use match-destructuring to access fields. This
is reasonable for enums, but sub-optimal for structs. E.g.:
```
fn eq(&self, other: &Point) -> bool {
match *other {
Self { x: ref __self_1_0, y: ref __self_1_1 } =>
match *self {
Self { x: ref __self_0_0, y: ref __self_0_1 } =>
(*__self_0_0) == (*__self_1_0) &&
(*__self_0_1) == (*__self_1_1),
},
}
}
```
This commit changes derive ops on structs to use field access instead, e.g.:
```
fn eq(&self, other: &Point) -> bool {
self.x == other.x && self.y == other.y
}
```
This is faster to compile, results in smaller binaries, and is simpler to
generate. Unfortunately, we have to keep the old pattern generating code around
for `repr(packed)` structs because something like `&self.x` (which doesn't show
up in `PartialEq` ops, but does show up in `Debug` and `Hash` ops) isn't
allowed. But this commit at least changes those cases to use let-destructuring
instead of match-destructuring, e.g.:
```
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
{
let Self(ref __self_0_0) = *self;
{ ::core::hash::Hash::hash(&(*__self_0_0), state) }
}
}
```
There are some unnecessary blocks remaining in the generated code, but I
will fix them in a follow-up PR.
2022-06-24 00:20:54 +00:00
|
|
|
pub fn stmt_let_pat(&self, sp: Span, pat: P<ast::Pat>, ex: P<ast::Expr>) -> ast::Stmt {
|
|
|
|
let local = P(ast::Local {
|
|
|
|
pat,
|
|
|
|
ty: None,
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
kind: LocalKind::Init(ex),
|
|
|
|
span: sp,
|
|
|
|
attrs: AttrVec::new(),
|
|
|
|
tokens: None,
|
|
|
|
});
|
|
|
|
self.stmt_local(local, sp)
|
|
|
|
}
|
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt {
|
Optimize the code produced by `derive(Debug)`.
This commit adds new methods that combine sequences of existing
formatting methods.
- `Formatter::debug_{tuple,struct}_field[12345]_finish`, equivalent to a
`Formatter::debug_{tuple,struct}` + N x `Debug{Tuple,Struct}::field` +
`Debug{Tuple,Struct}::finish` call sequence.
- `Formatter::debug_{tuple,struct}_fields_finish` is similar, but can
handle any number of fields by using arrays.
These new methods are all marked as `doc(hidden)` and unstable. They are
intended for the compiler's own use.
Special-casing up to 5 fields gives significantly better performance
results than always using arrays (as was tried in #95637).
The commit also changes the `Debug` deriving code to use these new methods. For
example, where the old `Debug` code for a struct with two fields would be like
this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => {
let debug_trait_builder = &mut ::core::fmt::Formatter::debug_struct(f, "S2");
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f1", &&(*__self_0_0));
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f2", &&(*__self_0_1));
::core::fmt::DebugStruct::finish(debug_trait_builder)
}
}
}
```
the new code is like this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => ::core::fmt::Formatter::debug_struct_field2_finish(
f,
"S2",
"f1",
&&(*__self_0_0),
"f2",
&&(*__self_0_1),
),
}
}
```
This shrinks the code produced for `Debug` instances
considerably, reducing compile times and binary sizes.
Co-authored-by: Scott McMurray <scottmcm@users.noreply.github.com>
2022-06-17 07:08:36 +00:00
|
|
|
self.stmt_let_ty(sp, mutbl, ident, None, ex)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stmt_let_ty(
|
|
|
|
&self,
|
|
|
|
sp: Span,
|
|
|
|
mutbl: bool,
|
|
|
|
ident: Ident,
|
|
|
|
ty: Option<P<ast::Ty>>,
|
|
|
|
ex: P<ast::Expr>,
|
|
|
|
) -> ast::Stmt {
|
2013-10-20 12:31:23 +00:00
|
|
|
let pat = if mutbl {
|
2022-08-30 22:34:35 +00:00
|
|
|
self.pat_ident_binding_mode(sp, ident, ast::BindingAnnotation::MUT)
|
2013-10-20 12:31:23 +00:00
|
|
|
} else {
|
|
|
|
self.pat_ident(sp, ident)
|
|
|
|
};
|
2014-09-13 16:06:01 +00:00
|
|
|
let local = P(ast::Local {
|
2017-08-07 05:54:09 +00:00
|
|
|
pat,
|
Optimize the code produced by `derive(Debug)`.
This commit adds new methods that combine sequences of existing
formatting methods.
- `Formatter::debug_{tuple,struct}_field[12345]_finish`, equivalent to a
`Formatter::debug_{tuple,struct}` + N x `Debug{Tuple,Struct}::field` +
`Debug{Tuple,Struct}::finish` call sequence.
- `Formatter::debug_{tuple,struct}_fields_finish` is similar, but can
handle any number of fields by using arrays.
These new methods are all marked as `doc(hidden)` and unstable. They are
intended for the compiler's own use.
Special-casing up to 5 fields gives significantly better performance
results than always using arrays (as was tried in #95637).
The commit also changes the `Debug` deriving code to use these new methods. For
example, where the old `Debug` code for a struct with two fields would be like
this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => {
let debug_trait_builder = &mut ::core::fmt::Formatter::debug_struct(f, "S2");
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f1", &&(*__self_0_0));
let _ = ::core::fmt::DebugStruct::field(debug_trait_builder, "f2", &&(*__self_0_1));
::core::fmt::DebugStruct::finish(debug_trait_builder)
}
}
}
```
the new code is like this:
```
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Self {
f1: ref __self_0_0,
f2: ref __self_0_1,
} => ::core::fmt::Formatter::debug_struct_field2_finish(
f,
"S2",
"f1",
&&(*__self_0_0),
"f2",
&&(*__self_0_1),
),
}
}
```
This shrinks the code produced for `Debug` instances
considerably, reducing compile times and binary sizes.
Co-authored-by: Scott McMurray <scottmcm@users.noreply.github.com>
2022-06-17 07:08:36 +00:00
|
|
|
ty,
|
2013-09-07 02:11:55 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2021-06-22 18:00:58 +00:00
|
|
|
kind: LocalKind::Init(ex),
|
2013-07-19 05:38:55 +00:00
|
|
|
span: sp,
|
2019-12-03 15:38:34 +00:00
|
|
|
attrs: AttrVec::new(),
|
2020-09-10 20:59:30 +00:00
|
|
|
tokens: None,
|
2020-11-17 19:27:44 +00:00
|
|
|
});
|
2022-06-02 12:00:04 +00:00
|
|
|
self.stmt_local(local, sp)
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Generates `let _: Type;`, which is usually used for type assertions.
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
|
2016-08-26 16:23:42 +00:00
|
|
|
let local = P(ast::Local {
|
|
|
|
pat: self.pat_wild(span),
|
|
|
|
ty: Some(ty),
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
2021-06-22 18:00:58 +00:00
|
|
|
kind: LocalKind::Decl,
|
2017-08-07 05:54:09 +00:00
|
|
|
span,
|
2019-12-03 15:38:34 +00:00
|
|
|
attrs: AttrVec::new(),
|
2020-11-17 19:27:44 +00:00
|
|
|
tokens: None,
|
2016-08-26 16:23:42 +00:00
|
|
|
});
|
2022-06-02 12:00:04 +00:00
|
|
|
self.stmt_local(local, span)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt {
|
2020-11-17 19:27:44 +00:00
|
|
|
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
|
2016-08-26 16:23:42 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
|
2020-11-17 19:27:44 +00:00
|
|
|
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
|
2014-06-10 20:54:13 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
|
2016-06-26 02:19:34 +00:00
|
|
|
self.block(
|
|
|
|
expr.span,
|
2023-01-30 03:13:27 +00:00
|
|
|
thin_vec![ast::Stmt {
|
2016-06-26 02:19:34 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2016-06-23 09:51:18 +00:00
|
|
|
span: expr.span,
|
2019-09-26 16:34:50 +00:00
|
|
|
kind: ast::StmtKind::Expr(expr),
|
2016-06-23 09:51:18 +00:00
|
|
|
}],
|
|
|
|
)
|
|
|
|
}
|
2023-01-30 03:13:27 +00:00
|
|
|
pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> {
|
2020-08-21 21:52:52 +00:00
|
|
|
P(ast::Block {
|
|
|
|
stmts,
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
rules: BlockCheckMode::Default,
|
|
|
|
span,
|
|
|
|
tokens: None,
|
2021-09-02 18:34:03 +00:00
|
|
|
could_be_bare_literal: false,
|
2020-08-21 21:52:52 +00:00
|
|
|
})
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 13:39:48 +00:00
|
|
|
pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
|
2020-05-19 20:56:20 +00:00
|
|
|
P(ast::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None })
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(path.span, ast::ExprKind::Path(None, path))
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr> {
|
2013-05-19 05:53:42 +00:00
|
|
|
self.expr_path(self.path_ident(span, id))
|
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_self(&self, span: Span) -> P<ast::Expr> {
|
2019-08-10 23:20:18 +00:00
|
|
|
self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2022-08-08 14:17:08 +00:00
|
|
|
pub fn expr_field(&self, span: Span, expr: P<Expr>, field: Ident) -> P<ast::Expr> {
|
|
|
|
self.expr(span, ast::ExprKind::Field(expr, field))
|
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_binary(
|
|
|
|
&self,
|
|
|
|
sp: Span,
|
|
|
|
op: ast::BinOpKind,
|
2014-09-13 16:06:01 +00:00
|
|
|
lhs: P<ast::Expr>,
|
|
|
|
rhs: P<ast::Expr>,
|
|
|
|
) -> P<ast::Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs))
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
|
2019-09-21 19:07:28 +00:00
|
|
|
self.expr(sp, ast::ExprKind::Unary(UnOp::Deref, e))
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
|
2019-12-16 16:28:40 +00:00
|
|
|
self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2013-05-15 22:55:57 +00:00
|
|
|
|
2023-01-30 05:29:52 +00:00
|
|
|
pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
|
|
|
|
self.expr(sp, ast::ExprKind::Paren(e))
|
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_call(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
expr: P<ast::Expr>,
|
2022-11-23 00:55:16 +00:00
|
|
|
args: ThinVec<P<ast::Expr>>,
|
2019-07-31 11:40:32 +00:00
|
|
|
) -> P<ast::Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(span, ast::ExprKind::Call(expr, args))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2022-11-23 00:55:16 +00:00
|
|
|
pub fn expr_call_ident(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
id: Ident,
|
|
|
|
args: ThinVec<P<ast::Expr>>,
|
|
|
|
) -> P<ast::Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_call_global(
|
|
|
|
&self,
|
|
|
|
sp: Span,
|
2020-04-19 11:00:18 +00:00
|
|
|
fn_path: Vec<Ident>,
|
2022-11-23 00:55:16 +00:00
|
|
|
args: ThinVec<P<ast::Expr>>,
|
2014-09-13 16:06:01 +00:00
|
|
|
) -> P<ast::Expr> {
|
2013-05-19 05:53:42 +00:00
|
|
|
let pathexpr = self.expr_path(self.path_global(sp, fn_path));
|
|
|
|
self.expr_call(sp, pathexpr, args)
|
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
|
2018-04-16 03:44:39 +00:00
|
|
|
self.expr(b.span, ast::ExprKind::Block(b, None))
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
2021-03-15 21:36:07 +00:00
|
|
|
pub fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField {
|
|
|
|
ast::ExprField {
|
2018-03-18 13:47:09 +00:00
|
|
|
ident: ident.with_span_pos(span),
|
2017-01-04 03:13:01 +00:00
|
|
|
expr: e,
|
2017-08-07 05:54:09 +00:00
|
|
|
span,
|
2017-01-04 03:13:01 +00:00
|
|
|
is_shorthand: false,
|
2019-12-03 15:38:34 +00:00
|
|
|
attrs: AttrVec::new(),
|
2019-08-14 01:22:51 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2019-09-09 12:26:25 +00:00
|
|
|
is_placeholder: false,
|
2017-01-04 03:13:01 +00:00
|
|
|
}
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_struct(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
path: ast::Path,
|
2023-01-30 04:39:22 +00:00
|
|
|
fields: ThinVec<ast::ExprField>,
|
2019-07-31 11:40:32 +00:00
|
|
|
) -> P<ast::Expr> {
|
2021-03-16 00:15:53 +00:00
|
|
|
self.expr(
|
|
|
|
span,
|
2020-12-10 12:20:07 +00:00
|
|
|
ast::ExprKind::Struct(P(ast::StructExpr {
|
|
|
|
qself: None,
|
|
|
|
path,
|
|
|
|
fields,
|
|
|
|
rest: ast::StructRest::None,
|
|
|
|
})),
|
2021-03-16 00:15:53 +00:00
|
|
|
)
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_struct_ident(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
2020-04-19 11:00:18 +00:00
|
|
|
id: Ident,
|
2023-01-30 04:39:22 +00:00
|
|
|
fields: ThinVec<ast::ExprField>,
|
2014-09-13 16:06:01 +00:00
|
|
|
) -> P<ast::Expr> {
|
2013-05-19 05:53:42 +00:00
|
|
|
self.expr_struct(span, self.path_ident(span, id), fields)
|
|
|
|
}
|
|
|
|
|
2022-12-05 03:16:41 +00:00
|
|
|
pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
|
|
|
|
let suffix = Some(ast::UintTy::Usize.name());
|
|
|
|
let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
|
|
|
|
self.expr(span, ast::ExprKind::Lit(lit))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2022-08-01 07:14:55 +00:00
|
|
|
|
2022-12-05 03:16:41 +00:00
|
|
|
pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
|
|
|
|
let suffix = Some(ast::UintTy::U32.name());
|
|
|
|
let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
|
|
|
|
self.expr(span, ast::ExprKind::Lit(lit))
|
2015-02-23 03:07:38 +00:00
|
|
|
}
|
2022-08-01 07:14:55 +00:00
|
|
|
|
2022-12-05 03:16:41 +00:00
|
|
|
pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
|
|
|
|
let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
|
|
|
|
self.expr(span, ast::ExprKind::Lit(lit))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2022-12-05 03:16:41 +00:00
|
|
|
pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
|
|
|
|
let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
|
|
|
|
self.expr(span, ast::ExprKind::Lit(lit))
|
2022-08-01 07:14:55 +00:00
|
|
|
}
|
|
|
|
|
2022-12-05 03:16:41 +00:00
|
|
|
pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> {
|
|
|
|
let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None);
|
|
|
|
self.expr(span, ast::ExprKind::Lit(lit))
|
2022-08-01 07:14:55 +00:00
|
|
|
}
|
|
|
|
|
2022-12-05 03:16:41 +00:00
|
|
|
pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
|
|
|
|
let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
|
|
|
|
self.expr(span, ast::ExprKind::Lit(lit))
|
2022-08-01 07:14:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-21 22:38:24 +00:00
|
|
|
/// `[expr1, expr2, ...]`
|
2022-11-23 00:55:16 +00:00
|
|
|
pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
|
2017-01-16 07:36:10 +00:00
|
|
|
self.expr(sp, ast::ExprKind::Array(exprs))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2022-06-21 22:38:24 +00:00
|
|
|
|
|
|
|
/// `&[expr1, expr2, ...]`
|
2022-11-23 00:55:16 +00:00
|
|
|
pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
|
2022-06-21 22:38:24 +00:00
|
|
|
self.expr_addr_of(sp, self.expr_array(sp, exprs))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2022-06-21 22:38:24 +00:00
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(sp, ast::ExprKind::Cast(expr, ty))
|
2013-09-17 04:12:18 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
|
2019-05-22 04:41:15 +00:00
|
|
|
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
|
2022-11-23 00:55:16 +00:00
|
|
|
self.expr_call_global(sp, some, thin_vec![expr])
|
2013-09-17 04:12:18 +00:00
|
|
|
}
|
|
|
|
|
2022-01-10 06:01:12 +00:00
|
|
|
pub fn expr_none(&self, sp: Span) -> P<ast::Expr> {
|
|
|
|
let none = self.std_path(&[sym::option, sym::Option, sym::None]);
|
|
|
|
self.expr_path(self.path_global(sp, none))
|
|
|
|
}
|
2022-11-23 00:55:16 +00:00
|
|
|
pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(sp, ast::ExprKind::Tup(exprs))
|
2014-07-01 16:39:41 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_fail(&self, span: Span, msg: Symbol) -> P<ast::Expr> {
|
2013-05-19 05:53:42 +00:00
|
|
|
self.expr_call_global(
|
|
|
|
span,
|
2019-08-10 15:38:27 +00:00
|
|
|
[sym::std, sym::rt, sym::begin_panic].iter().map(|s| Ident::new(*s, span)).collect(),
|
2022-11-23 00:55:16 +00:00
|
|
|
thin_vec![self.expr_str(span, msg)],
|
2017-06-27 02:26:52 +00:00
|
|
|
)
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
|
2016-11-16 10:52:37 +00:00
|
|
|
self.expr_fail(span, Symbol::intern("internal error: entered unreachable code"))
|
2013-09-17 14:45:49 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
|
2019-05-22 04:41:15 +00:00
|
|
|
let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
|
2022-11-23 00:55:16 +00:00
|
|
|
self.expr_call_global(sp, ok, thin_vec![expr])
|
2014-03-18 17:58:26 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
|
2019-05-22 04:41:15 +00:00
|
|
|
let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
|
2014-09-07 21:57:26 +00:00
|
|
|
let ok_path = self.path_global(sp, ok);
|
2019-05-22 04:41:15 +00:00
|
|
|
let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
|
2014-09-07 21:57:26 +00:00
|
|
|
let err_path = self.path_global(sp, err);
|
2014-03-18 17:58:26 +00:00
|
|
|
|
2020-07-14 05:05:26 +00:00
|
|
|
let binding_variable = Ident::new(sym::__try_var, sp);
|
2014-03-18 17:58:26 +00:00
|
|
|
let binding_pat = self.pat_ident(sp, binding_variable);
|
|
|
|
let binding_expr = self.expr_ident(sp, binding_variable);
|
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// `Ok(__try_var)` pattern
|
2022-11-23 00:55:16 +00:00
|
|
|
let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]);
|
2014-03-18 17:58:26 +00:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// `Err(__try_var)` (pattern and expression respectively)
|
2022-11-23 00:55:16 +00:00
|
|
|
let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]);
|
2014-09-07 21:57:26 +00:00
|
|
|
let err_inner_expr =
|
2022-11-23 00:55:16 +00:00
|
|
|
self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]);
|
2019-02-28 22:43:53 +00:00
|
|
|
// `return Err(__try_var)`
|
2016-02-08 15:05:05 +00:00
|
|
|
let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr)));
|
2014-03-18 17:58:26 +00:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// `Ok(__try_var) => __try_var`
|
2019-08-27 23:16:35 +00:00
|
|
|
let ok_arm = self.arm(sp, ok_pat, binding_expr);
|
2019-02-28 22:43:53 +00:00
|
|
|
// `Err(__try_var) => return Err(__try_var)`
|
2019-08-27 23:16:35 +00:00
|
|
|
let err_arm = self.arm(sp, err_pat, err_expr);
|
2014-03-18 17:58:26 +00:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// `match head { Ok() => ..., Err() => ... }`
|
2023-01-30 04:10:59 +00:00
|
|
|
self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
|
2014-03-18 17:58:26 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 15:18:31 +00:00
|
|
|
pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
|
2020-07-27 22:02:29 +00:00
|
|
|
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
|
2016-02-11 18:16:33 +00:00
|
|
|
self.pat(span, PatKind::Wild)
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> {
|
2016-02-11 18:16:33 +00:00
|
|
|
self.pat(span, PatKind::Lit(expr))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
|
2022-08-30 22:34:35 +00:00
|
|
|
self.pat_ident_binding_mode(span, ident, ast::BindingAnnotation::NONE)
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_ident_binding_mode(
|
|
|
|
&self,
|
2013-08-31 16:13:04 +00:00
|
|
|
span: Span,
|
2020-04-19 11:00:18 +00:00
|
|
|
ident: Ident,
|
2022-08-30 22:34:35 +00:00
|
|
|
ann: ast::BindingAnnotation,
|
2014-09-13 16:06:01 +00:00
|
|
|
) -> P<ast::Pat> {
|
2022-08-30 22:34:35 +00:00
|
|
|
let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
|
2013-05-19 05:53:42 +00:00
|
|
|
self.pat(span, pat)
|
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
|
2016-08-15 18:28:17 +00:00
|
|
|
self.pat(span, PatKind::Path(None, path))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_tuple_struct(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
path: ast::Path,
|
2022-11-23 00:55:16 +00:00
|
|
|
subpats: ThinVec<P<ast::Pat>>,
|
2016-08-15 18:28:17 +00:00
|
|
|
) -> P<ast::Pat> {
|
2020-12-10 12:20:07 +00:00
|
|
|
self.pat(span, PatKind::TupleStruct(None, path, subpats))
|
2016-08-15 18:28:17 +00:00
|
|
|
}
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_struct(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
path: ast::Path,
|
2023-01-30 03:58:23 +00:00
|
|
|
field_pats: ThinVec<ast::PatField>,
|
2019-08-14 23:35:36 +00:00
|
|
|
) -> P<ast::Pat> {
|
2020-12-10 12:20:07 +00:00
|
|
|
self.pat(span, PatKind::Struct(None, path, field_pats, false))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2022-11-23 00:55:16 +00:00
|
|
|
pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
|
2019-07-09 07:25:18 +00:00
|
|
|
self.pat(span, PatKind::Tuple(pats))
|
2014-07-27 22:11:02 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
|
2019-05-22 04:41:15 +00:00
|
|
|
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
|
2014-07-27 22:11:02 +00:00
|
|
|
let path = self.path_global(span, some);
|
2022-11-23 00:55:16 +00:00
|
|
|
self.pat_tuple_struct(span, path, thin_vec![pat])
|
2014-07-27 22:11:02 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 23:16:35 +00:00
|
|
|
pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
|
2013-09-02 01:45:37 +00:00
|
|
|
ast::Arm {
|
2021-06-16 22:11:13 +00:00
|
|
|
attrs: AttrVec::new(),
|
2019-08-27 23:16:35 +00:00
|
|
|
pat,
|
2013-05-19 05:53:42 +00:00
|
|
|
guard: None,
|
2023-11-27 02:15:56 +00:00
|
|
|
body: Some(expr),
|
2019-03-30 22:54:29 +00:00
|
|
|
span,
|
2019-08-14 01:22:51 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2019-09-09 12:26:25 +00:00
|
|
|
is_placeholder: false,
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn arm_unreachable(&self, span: Span) -> ast::Arm {
|
2019-08-27 23:16:35 +00:00
|
|
|
self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-30 04:10:59 +00:00
|
|
|
pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(span, ast::ExprKind::Match(arg, arms))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
2013-05-17 13:51:25 +00:00
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn expr_if(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
cond: P<ast::Expr>,
|
2014-09-13 16:06:01 +00:00
|
|
|
then: P<ast::Expr>,
|
|
|
|
els: Option<P<ast::Expr>>,
|
|
|
|
) -> P<ast::Expr> {
|
2013-09-20 06:08:47 +00:00
|
|
|
let els = els.map(|x| self.expr_block(self.block_expr(x)));
|
2016-02-08 15:05:05 +00:00
|
|
|
self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els))
|
2013-05-19 05:53:42 +00:00
|
|
|
}
|
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn lambda(&self, span: Span, ids: Vec<Ident>, body: P<ast::Expr>) -> P<ast::Expr> {
|
2013-05-19 05:53:42 +00:00
|
|
|
let fn_decl = self.fn_decl(
|
2019-09-21 19:05:31 +00:00
|
|
|
ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(),
|
2020-02-15 03:10:59 +00:00
|
|
|
ast::FnRetTy::Default(span),
|
2018-03-22 15:55:57 +00:00
|
|
|
);
|
2013-05-19 05:53:42 +00:00
|
|
|
|
2016-04-20 18:44:07 +00:00
|
|
|
// FIXME -- We are using `span` as the span of the `|...|`
|
|
|
|
// part of the lambda, but it probably (maybe?) corresponds to
|
|
|
|
// the entire lambda body. Probably we should extend the API
|
|
|
|
// here, but that's not entirely clear.
|
2017-10-07 14:36:28 +00:00
|
|
|
self.expr(
|
|
|
|
span,
|
2022-09-08 00:52:51 +00:00
|
|
|
ast::ExprKind::Closure(Box::new(ast::Closure {
|
|
|
|
binder: ast::ClosureBinder::NotPresent,
|
|
|
|
capture_clause: ast::CaptureBy::Ref,
|
2022-12-20 16:15:55 +00:00
|
|
|
constness: ast::Const::No,
|
2023-12-05 21:39:36 +00:00
|
|
|
coroutine_kind: None,
|
2022-09-08 00:52:51 +00:00
|
|
|
movability: ast::Movability::Movable,
|
2017-10-07 14:36:28 +00:00
|
|
|
fn_decl,
|
|
|
|
body,
|
2022-09-08 00:52:51 +00:00
|
|
|
fn_decl_span: span,
|
2022-11-09 15:09:28 +00:00
|
|
|
// FIXME(SarthakSingh31): This points to the start of the declaration block and
|
|
|
|
// not the span of the argument block.
|
|
|
|
fn_arg_span: span,
|
2022-09-08 00:52:51 +00:00
|
|
|
})),
|
2017-10-07 14:36:28 +00:00
|
|
|
)
|
2013-08-15 06:06:33 +00:00
|
|
|
}
|
2013-05-17 13:51:25 +00:00
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
|
2016-10-25 23:17:29 +00:00
|
|
|
self.lambda(span, Vec::new(), body)
|
2013-08-15 06:06:33 +00:00
|
|
|
}
|
2013-05-15 22:55:57 +00:00
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: Ident) -> P<ast::Expr> {
|
2016-10-25 23:17:29 +00:00
|
|
|
self.lambda(span, vec![ident], body)
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
|
|
|
|
2023-01-30 03:13:27 +00:00
|
|
|
pub fn lambda_stmts_1(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
stmts: ThinVec<ast::Stmt>,
|
|
|
|
ident: Ident,
|
|
|
|
) -> P<ast::Expr> {
|
2016-10-25 23:17:29 +00:00
|
|
|
self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
2020-04-19 11:00:18 +00:00
|
|
|
pub fn param(&self, span: Span, ident: Ident, ty: P<ast::Ty>) -> ast::Param {
|
2013-05-19 05:53:42 +00:00
|
|
|
let arg_pat = self.pat_ident(span, ident);
|
2019-08-27 11:24:32 +00:00
|
|
|
ast::Param {
|
2019-12-03 15:38:34 +00:00
|
|
|
attrs: AttrVec::default(),
|
2019-06-09 10:58:40 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2013-05-19 05:53:42 +00:00
|
|
|
pat: arg_pat,
|
2019-07-26 22:52:37 +00:00
|
|
|
span,
|
2019-06-09 10:58:40 +00:00
|
|
|
ty,
|
2019-09-09 12:26:25 +00:00
|
|
|
is_placeholder: false,
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
2013-05-15 22:55:57 +00:00
|
|
|
}
|
2013-05-17 13:51:25 +00:00
|
|
|
|
2022-05-28 09:12:34 +00:00
|
|
|
// `self` is unused but keep it as method for the convenience use.
|
2022-11-23 00:55:16 +00:00
|
|
|
pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
|
2014-01-09 13:05:33 +00:00
|
|
|
P(ast::FnDecl { inputs, output })
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn item(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
name: Ident,
|
2022-08-17 02:34:33 +00:00
|
|
|
attrs: ast::AttrVec,
|
2019-09-26 16:51:36 +00:00
|
|
|
kind: ast::ItemKind,
|
|
|
|
) -> P<ast::Item> {
|
2014-09-13 16:06:01 +00:00
|
|
|
P(ast::Item {
|
|
|
|
ident: name,
|
2017-08-07 05:54:09 +00:00
|
|
|
attrs,
|
2014-09-13 16:06:01 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2019-09-26 16:51:36 +00:00
|
|
|
kind,
|
2020-08-21 23:11:00 +00:00
|
|
|
vis: ast::Visibility {
|
|
|
|
span: span.shrink_to_lo(),
|
|
|
|
kind: ast::VisibilityKind::Inherited,
|
|
|
|
tokens: None,
|
|
|
|
},
|
2017-08-07 05:54:09 +00:00
|
|
|
span,
|
2017-07-11 00:44:46 +00:00
|
|
|
tokens: None,
|
2014-09-13 16:06:01 +00:00
|
|
|
})
|
2013-05-17 13:51:25 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn item_static(
|
|
|
|
&self,
|
2014-06-10 20:54:13 +00:00
|
|
|
span: Span,
|
|
|
|
name: Ident,
|
|
|
|
ty: P<ast::Ty>,
|
2023-03-29 08:50:04 +00:00
|
|
|
mutability: ast::Mutability,
|
2014-09-13 16:06:01 +00:00
|
|
|
expr: P<ast::Expr>,
|
|
|
|
) -> P<ast::Item> {
|
2023-03-29 08:37:47 +00:00
|
|
|
self.item(
|
|
|
|
span,
|
|
|
|
name,
|
|
|
|
AttrVec::new(),
|
2023-03-29 14:14:11 +00:00
|
|
|
ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()),
|
2023-03-29 08:37:47 +00:00
|
|
|
)
|
2014-06-10 20:54:13 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 11:40:32 +00:00
|
|
|
pub fn item_const(
|
|
|
|
&self,
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 15:17:01 +00:00
|
|
|
span: Span,
|
|
|
|
name: Ident,
|
|
|
|
ty: P<ast::Ty>,
|
|
|
|
expr: P<ast::Expr>,
|
|
|
|
) -> P<ast::Item> {
|
2023-03-29 09:20:45 +00:00
|
|
|
let defaultness = ast::Defaultness::Final;
|
|
|
|
self.item(
|
|
|
|
span,
|
|
|
|
name,
|
|
|
|
AttrVec::new(),
|
2023-05-04 14:08:33 +00:00
|
|
|
ast::ItemKind::Const(
|
|
|
|
ast::ConstItem {
|
|
|
|
defaultness,
|
|
|
|
// FIXME(generic_const_items): Pass the generics as a parameter.
|
|
|
|
generics: ast::Generics::default(),
|
|
|
|
ty,
|
|
|
|
expr: Some(expr),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
),
|
2023-03-29 09:20:45 +00:00
|
|
|
)
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 15:17:01 +00:00
|
|
|
}
|
|
|
|
|
Avoid more `MetaItem`-to-`Attribute` conversions.
There is code for converting `Attribute` (syntactic) to `MetaItem`
(semantic). There is also code for the reverse direction. The reverse
direction isn't really necessary; it's currently only used when
generating attributes, e.g. in `derive` code.
This commit adds some new functions for creating `Attributes`s directly,
without involving `MetaItem`s: `mk_attr_word`, `mk_attr_name_value_str`,
`mk_attr_nested_word`, and
`ExtCtxt::attr_{word,name_value_str,nested_word}`.
These new methods replace the old functions for creating `Attribute`s:
`mk_attr_inner`, `mk_attr_outer`, and `ExtCtxt::attribute`. Those
functions took `MetaItem`s as input, and relied on many other functions
that created `MetaItems`, which are also removed: `mk_name_value_item`,
`mk_list_item`, `mk_word_item`, `mk_nested_word_item`,
`{MetaItem,MetaItemKind,NestedMetaItem}::token_trees`,
`MetaItemKind::attr_args`, `MetaItemLit::{from_lit_kind,to_token}`,
`ExtCtxt::meta_word`.
Overall this cuts more than 100 lines of code and makes thing simpler.
2022-11-29 07:43:44 +00:00
|
|
|
// Builds `#[name]`.
|
|
|
|
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
|
|
|
|
let g = &self.sess.parse_sess.attr_id_generator;
|
|
|
|
attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
|
2013-05-17 14:19:28 +00:00
|
|
|
}
|
|
|
|
|
Avoid more `MetaItem`-to-`Attribute` conversions.
There is code for converting `Attribute` (syntactic) to `MetaItem`
(semantic). There is also code for the reverse direction. The reverse
direction isn't really necessary; it's currently only used when
generating attributes, e.g. in `derive` code.
This commit adds some new functions for creating `Attributes`s directly,
without involving `MetaItem`s: `mk_attr_word`, `mk_attr_name_value_str`,
`mk_attr_nested_word`, and
`ExtCtxt::attr_{word,name_value_str,nested_word}`.
These new methods replace the old functions for creating `Attribute`s:
`mk_attr_inner`, `mk_attr_outer`, and `ExtCtxt::attribute`. Those
functions took `MetaItem`s as input, and relied on many other functions
that created `MetaItems`, which are also removed: `mk_name_value_item`,
`mk_list_item`, `mk_word_item`, `mk_nested_word_item`,
`{MetaItem,MetaItemKind,NestedMetaItem}::token_trees`,
`MetaItemKind::attr_args`, `MetaItemLit::{from_lit_kind,to_token}`,
`ExtCtxt::meta_word`.
Overall this cuts more than 100 lines of code and makes thing simpler.
2022-11-29 07:43:44 +00:00
|
|
|
// Builds `#[name = val]`.
|
|
|
|
//
|
2022-12-27 06:14:40 +00:00
|
|
|
// Note: `span` is used for both the identifier and the value.
|
Avoid more `MetaItem`-to-`Attribute` conversions.
There is code for converting `Attribute` (syntactic) to `MetaItem`
(semantic). There is also code for the reverse direction. The reverse
direction isn't really necessary; it's currently only used when
generating attributes, e.g. in `derive` code.
This commit adds some new functions for creating `Attributes`s directly,
without involving `MetaItem`s: `mk_attr_word`, `mk_attr_name_value_str`,
`mk_attr_nested_word`, and
`ExtCtxt::attr_{word,name_value_str,nested_word}`.
These new methods replace the old functions for creating `Attribute`s:
`mk_attr_inner`, `mk_attr_outer`, and `ExtCtxt::attribute`. Those
functions took `MetaItem`s as input, and relied on many other functions
that created `MetaItems`, which are also removed: `mk_name_value_item`,
`mk_list_item`, `mk_word_item`, `mk_nested_word_item`,
`{MetaItem,MetaItemKind,NestedMetaItem}::token_trees`,
`MetaItemKind::attr_args`, `MetaItemLit::{from_lit_kind,to_token}`,
`ExtCtxt::meta_word`.
Overall this cuts more than 100 lines of code and makes thing simpler.
2022-11-29 07:43:44 +00:00
|
|
|
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
|
|
|
|
let g = &self.sess.parse_sess.attr_id_generator;
|
|
|
|
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Builds `#[outer(inner)]`.
|
|
|
|
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
|
|
|
|
let g = &self.sess.parse_sess.attr_id_generator;
|
|
|
|
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
|
2013-05-17 14:19:28 +00:00
|
|
|
}
|
2013-08-29 19:10:02 +00:00
|
|
|
}
|