Skip to content

Commit

Permalink
Merge pull request #1743 from dtolnay/rawaddr
Browse files Browse the repository at this point in the history
Add Expr::RawAddr
  • Loading branch information
dtolnay authored Oct 17, 2024
2 parents 4a2dab7 + f5c9fd3 commit e565d5f
Show file tree
Hide file tree
Showing 17 changed files with 512 additions and 32 deletions.
4 changes: 4 additions & 0 deletions src/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool {
| Expr::Paren(_)
| Expr::Path(_)
| Expr::Range(_)
| Expr::RawAddr(_)
| Expr::Reference(_)
| Expr::Repeat(_)
| Expr::Return(_)
Expand Down Expand Up @@ -105,6 +106,7 @@ pub(crate) fn confusable_with_adjacent_block(mut expr: &Expr) -> bool {
(None, None) => stack.pop(),
}
}
Expr::RawAddr(e) => Some(&e.expr),
Expr::Reference(e) => Some(&e.expr),
Expr::Return(e) => {
if e.expr.is_none() && stack.is_empty() {
Expand Down Expand Up @@ -246,6 +248,7 @@ pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool {
| Expr::Match(_)
| Expr::Paren(_)
| Expr::Path(_)
| Expr::RawAddr(_)
| Expr::Reference(_)
| Expr::Repeat(_)
| Expr::Return(_)
Expand Down Expand Up @@ -291,6 +294,7 @@ pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool {
Some(end) => expr = end,
None => return false,
},
Expr::RawAddr(e) => expr = &e.expr,
Expr::Reference(e) => expr = &e.expr,
Expr::Return(e) => match &e.expr {
Some(e) => expr = e,
Expand Down
124 changes: 113 additions & 11 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ ast_enum_of_structs! {
/// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
Range(ExprRange),

/// Address-of operation: `&raw const place` or `&raw mut place`.
RawAddr(ExprRawAddr),

/// A referencing operation: `&a` or `&mut a`.
Reference(ExprReference),

Expand Down Expand Up @@ -574,6 +577,18 @@ ast_struct! {
}
}

ast_struct! {
/// Address-of operation: `&raw const place` or `&raw mut place`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ExprRawAddr #full {
pub attrs: Vec<Attribute>,
pub and_token: Token![&],
pub raw: Token![raw],
pub mutability: PointerMutability,
pub expr: Box<Expr>,
}
}

ast_struct! {
/// A referencing operation: `&a` or `&mut a`.
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
Expand Down Expand Up @@ -904,6 +919,7 @@ impl Expr {
| Expr::Paren(ExprParen { attrs, .. })
| Expr::Path(ExprPath { attrs, .. })
| Expr::Range(ExprRange { attrs, .. })
| Expr::RawAddr(ExprRawAddr { attrs, .. })
| Expr::Reference(ExprReference { attrs, .. })
| Expr::Repeat(ExprRepeat { attrs, .. })
| Expr::Return(ExprReturn { attrs, .. })
Expand Down Expand Up @@ -1099,6 +1115,17 @@ ast_enum! {
}
}

#[cfg(feature = "full")]
ast_enum! {
/// Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable
/// isn't the implicit default.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub enum PointerMutability {
Const(Token![const]),
Mut(Token![mut]),
}
}

#[cfg(feature = "parsing")]
pub(crate) mod parsing {
#[cfg(feature = "full")]
Expand All @@ -1111,8 +1138,8 @@ pub(crate) mod parsing {
use crate::expr::{
Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe, ExprWhile, ExprYield,
Label, RangeLimits,
ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
};
use crate::expr::{
Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
Expand Down Expand Up @@ -1151,7 +1178,6 @@ pub(crate) mod parsing {

mod kw {
crate::custom_keyword!(builtin);
crate::custom_keyword!(raw);
}

// When we're parsing expressions which occur before blocks, like in an if
Expand Down Expand Up @@ -1468,20 +1494,31 @@ pub(crate) mod parsing {

if input.peek(Token![&]) {
let and_token: Token![&] = input.parse()?;
let raw: Option<kw::raw> = if input.peek(kw::raw)
let raw: Option<Token![raw]> = if input.peek(Token![raw])
&& (input.peek2(Token![mut]) || input.peek2(Token![const]))
{
Some(input.parse()?)
} else {
None
};
let mutability: Option<Token![mut]> = input.parse()?;
if raw.is_some() && mutability.is_none() {
input.parse::<Token![const]>()?;
}
let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
Some(input.parse()?)
} else {
None
};
let expr = Box::new(unary_expr(input, allow_struct)?);
if raw.is_some() {
Ok(Expr::Verbatim(verbatim::between(&begin, input)))
if let Some(raw) = raw {
Ok(Expr::RawAddr(ExprRawAddr {
attrs,
and_token,
raw,
mutability: match mutability {
Some(mut_token) => PointerMutability::Mut(mut_token),
None => PointerMutability::Const(const_token.unwrap()),
},
expr,
}))
} else {
Ok(Expr::Reference(ExprReference {
attrs,
Expand Down Expand Up @@ -2359,6 +2396,21 @@ pub(crate) mod parsing {
}
}

#[cfg(feature = "full")]
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ExprRawAddr {
fn parse(input: ParseStream) -> Result<Self> {
let allow_struct = AllowStruct(true);
Ok(ExprRawAddr {
attrs: Vec::new(),
and_token: input.parse()?,
raw: input.parse()?,
mutability: input.parse()?,
expr: Box::new(unary_expr(input, allow_struct)?),
})
}
}

#[cfg(feature = "full")]
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ExprReference {
Expand Down Expand Up @@ -2970,6 +3022,21 @@ pub(crate) mod parsing {
}
}

#[cfg(feature = "full")]
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for PointerMutability {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![const]) {
Ok(PointerMutability::Const(input.parse()?))
} else if lookahead.peek(Token![mut]) {
Ok(PointerMutability::Mut(input.parse()?))
} else {
Err(lookahead.error())
}
}
}

fn check_cast(input: ParseStream) -> Result<()> {
let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
if input.peek2(Token![await]) {
Expand Down Expand Up @@ -3004,8 +3071,8 @@ pub(crate) mod printing {
use crate::expr::{
Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe, ExprWhile, ExprYield,
Label, RangeLimits,
ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
};
use crate::expr::{
Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
Expand Down Expand Up @@ -3131,6 +3198,8 @@ pub(crate) mod printing {
Expr::Path(e) => e.to_tokens(tokens),
#[cfg(feature = "full")]
Expr::Range(e) => print_expr_range(e, tokens, fixup),
#[cfg(feature = "full")]
Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
#[cfg(feature = "full")]
Expr::Repeat(e) => e.to_tokens(tokens),
Expand Down Expand Up @@ -3689,6 +3758,28 @@ pub(crate) mod printing {
}
}

#[cfg(feature = "full")]
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for ExprRawAddr {
fn to_tokens(&self, tokens: &mut TokenStream) {
print_expr_raw_addr(self, tokens, FixupContext::NONE);
}
}

#[cfg(feature = "full")]
fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
outer_attrs_to_tokens(&e.attrs, tokens);
e.and_token.to_tokens(tokens);
e.raw.to_tokens(tokens);
e.mutability.to_tokens(tokens);
print_subexpression(
&e.expr,
fixup.trailing_precedence(&e.expr) < Precedence::Prefix,
tokens,
fixup.subsequent_subexpression(),
);
}

#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for ExprReference {
fn to_tokens(&self, tokens: &mut TokenStream) {
Expand Down Expand Up @@ -3929,4 +4020,15 @@ pub(crate) mod printing {
}
}
}

#[cfg(feature = "full")]
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for PointerMutability {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
}
}
}
}
29 changes: 29 additions & 0 deletions src/gen/clone.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions src/gen/debug.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e565d5f

Please sign in to comment.