diff --git a/src/classify.rs b/src/classify.rs index 42732e6d8..c125fc216 100644 --- a/src/classify.rs +++ b/src/classify.rs @@ -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(_) @@ -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() { @@ -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(_) @@ -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, diff --git a/src/expr.rs b/src/expr.rs index 409131b4f..8b9f030ac 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -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), @@ -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, + pub and_token: Token![&], + pub raw: Token![raw], + pub mutability: PointerMutability, + pub expr: Box, + } +} + ast_struct! { /// A referencing operation: `&a` or `&mut a`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] @@ -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, .. }) @@ -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")] @@ -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, @@ -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 @@ -1468,7 +1494,7 @@ pub(crate) mod parsing { if input.peek(Token![&]) { let and_token: Token![&] = input.parse()?; - let raw: Option = if input.peek(kw::raw) + let raw: Option = if input.peek(Token![raw]) && (input.peek2(Token![mut]) || input.peek2(Token![const])) { Some(input.parse()?) @@ -1476,12 +1502,23 @@ pub(crate) mod parsing { None }; let mutability: Option = input.parse()?; - if raw.is_some() && mutability.is_none() { - input.parse::()?; - } + let const_token: Option = 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, @@ -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 { + 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 { @@ -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 { + 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]) { @@ -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, @@ -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), @@ -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) { @@ -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), + } + } + } } diff --git a/src/gen/clone.rs b/src/gen/clone.rs index 975756139..037da1bc3 100644 --- a/src/gen/clone.rs +++ b/src/gen/clone.rs @@ -270,6 +270,8 @@ impl Clone for crate::Expr { crate::Expr::Path(v0) => crate::Expr::Path(v0.clone()), #[cfg(feature = "full")] crate::Expr::Range(v0) => crate::Expr::Range(v0.clone()), + #[cfg(feature = "full")] + crate::Expr::RawAddr(v0) => crate::Expr::RawAddr(v0.clone()), crate::Expr::Reference(v0) => crate::Expr::Reference(v0.clone()), #[cfg(feature = "full")] crate::Expr::Repeat(v0) => crate::Expr::Repeat(v0.clone()), @@ -621,6 +623,19 @@ impl Clone for crate::ExprRange { } } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::ExprRawAddr { + fn clone(&self) -> Self { + crate::ExprRawAddr { + attrs: self.attrs.clone(), + and_token: self.and_token.clone(), + raw: self.raw.clone(), + mutability: self.mutability.clone(), + expr: self.expr.clone(), + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprReference { @@ -1647,6 +1662,20 @@ impl Clone for crate::PathSegment { } } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::PointerMutability { + fn clone(&self) -> Self { + match self { + crate::PointerMutability::Const(v0) => { + crate::PointerMutability::Const(v0.clone()) + } + crate::PointerMutability::Mut(v0) => { + crate::PointerMutability::Mut(v0.clone()) + } + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PredicateLifetime { diff --git a/src/gen/debug.rs b/src/gen/debug.rs index fe1179c9f..54a12dba2 100644 --- a/src/gen/debug.rs +++ b/src/gen/debug.rs @@ -441,6 +441,8 @@ impl Debug for crate::Expr { crate::Expr::Path(v0) => v0.debug(formatter, "Path"), #[cfg(feature = "full")] crate::Expr::Range(v0) => v0.debug(formatter, "Range"), + #[cfg(feature = "full")] + crate::Expr::RawAddr(v0) => v0.debug(formatter, "RawAddr"), crate::Expr::Reference(v0) => v0.debug(formatter, "Reference"), #[cfg(feature = "full")] crate::Expr::Repeat(v0) => v0.debug(formatter, "Repeat"), @@ -958,6 +960,25 @@ impl crate::ExprRange { formatter.finish() } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::ExprRawAddr { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.debug(formatter, "ExprRawAddr") + } +} +#[cfg(feature = "full")] +impl crate::ExprRawAddr { + fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { + let mut formatter = formatter.debug_struct(name); + formatter.field("attrs", &self.attrs); + formatter.field("and_token", &self.and_token); + formatter.field("raw", &self.raw); + formatter.field("mutability", &self.mutability); + formatter.field("expr", &self.expr); + formatter.finish() + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprReference { @@ -2385,6 +2406,25 @@ impl Debug for crate::PathSegment { formatter.finish() } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::PointerMutability { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("PointerMutability::")?; + match self { + crate::PointerMutability::Const(v0) => { + let mut formatter = formatter.debug_tuple("Const"); + formatter.field(v0); + formatter.finish() + } + crate::PointerMutability::Mut(v0) => { + let mut formatter = formatter.debug_tuple("Mut"); + formatter.field(v0); + formatter.finish() + } + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PredicateLifetime { diff --git a/src/gen/eq.rs b/src/gen/eq.rs index 936293c39..cffa5d296 100644 --- a/src/gen/eq.rs +++ b/src/gen/eq.rs @@ -297,6 +297,10 @@ impl PartialEq for crate::Expr { (crate::Expr::Path(self0), crate::Expr::Path(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Range(self0), crate::Expr::Range(other0)) => self0 == other0, + #[cfg(feature = "full")] + (crate::Expr::RawAddr(self0), crate::Expr::RawAddr(other0)) => { + self0 == other0 + } (crate::Expr::Reference(self0), crate::Expr::Reference(other0)) => { self0 == other0 } @@ -610,6 +614,17 @@ impl PartialEq for crate::ExprRange { && self.limits == other.limits && self.end == other.end } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::ExprRawAddr {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::ExprRawAddr { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.mutability == other.mutability + && self.expr == other.expr + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprReference {} @@ -1622,6 +1637,22 @@ impl PartialEq for crate::PathSegment { self.ident == other.ident && self.arguments == other.arguments } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::PointerMutability {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::PointerMutability { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (crate::PointerMutability::Const(_), crate::PointerMutability::Const(_)) => { + true + } + (crate::PointerMutability::Mut(_), crate::PointerMutability::Mut(_)) => true, + _ => false, + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PredicateLifetime {} diff --git a/src/gen/fold.rs b/src/gen/fold.rs index c3de09668..ab794056c 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -269,6 +269,11 @@ pub trait Fold { fn fold_expr_range(&mut self, i: crate::ExprRange) -> crate::ExprRange { fold_expr_range(self, i) } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_expr_raw_addr(&mut self, i: crate::ExprRawAddr) -> crate::ExprRawAddr { + fold_expr_raw_addr(self, i) + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_reference(&mut self, i: crate::ExprReference) -> crate::ExprReference { @@ -723,6 +728,14 @@ pub trait Fold { fn fold_path_segment(&mut self, i: crate::PathSegment) -> crate::PathSegment { fold_path_segment(self, i) } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_pointer_mutability( + &mut self, + i: crate::PointerMutability, + ) -> crate::PointerMutability { + fold_pointer_mutability(self, i) + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_predicate_lifetime( @@ -1339,6 +1352,9 @@ where crate::Expr::Range(_binding_0) => { crate::Expr::Range(full!(f.fold_expr_range(_binding_0))) } + crate::Expr::RawAddr(_binding_0) => { + crate::Expr::RawAddr(full!(f.fold_expr_raw_addr(_binding_0))) + } crate::Expr::Reference(_binding_0) => { crate::Expr::Reference(f.fold_expr_reference(_binding_0)) } @@ -1734,6 +1750,20 @@ where end: (node.end).map(|it| Box::new(f.fold_expr(*it))), } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_expr_raw_addr(f: &mut F, node: crate::ExprRawAddr) -> crate::ExprRawAddr +where + F: Fold + ?Sized, +{ + crate::ExprRawAddr { + attrs: fold_vec(node.attrs, f, F::fold_attribute), + and_token: node.and_token, + raw: node.raw, + mutability: f.fold_pointer_mutability(node.mutability), + expr: Box::new(f.fold_expr(*node.expr)), + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_reference( @@ -3060,6 +3090,24 @@ where arguments: f.fold_path_arguments(node.arguments), } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_pointer_mutability( + f: &mut F, + node: crate::PointerMutability, +) -> crate::PointerMutability +where + F: Fold + ?Sized, +{ + match node { + crate::PointerMutability::Const(_binding_0) => { + crate::PointerMutability::Const(_binding_0) + } + crate::PointerMutability::Mut(_binding_0) => { + crate::PointerMutability::Mut(_binding_0) + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_predicate_lifetime( diff --git a/src/gen/hash.rs b/src/gen/hash.rs index 4dedba4a1..51345eada 100644 --- a/src/gen/hash.rs +++ b/src/gen/hash.rs @@ -456,59 +456,64 @@ impl Hash for crate::Expr { state.write_u8(26u8); v0.hash(state); } - crate::Expr::Reference(v0) => { + #[cfg(feature = "full")] + crate::Expr::RawAddr(v0) => { state.write_u8(27u8); v0.hash(state); } + crate::Expr::Reference(v0) => { + state.write_u8(28u8); + v0.hash(state); + } #[cfg(feature = "full")] crate::Expr::Repeat(v0) => { - state.write_u8(28u8); + state.write_u8(29u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Return(v0) => { - state.write_u8(29u8); + state.write_u8(30u8); v0.hash(state); } crate::Expr::Struct(v0) => { - state.write_u8(30u8); + state.write_u8(31u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Try(v0) => { - state.write_u8(31u8); + state.write_u8(32u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::TryBlock(v0) => { - state.write_u8(32u8); + state.write_u8(33u8); v0.hash(state); } crate::Expr::Tuple(v0) => { - state.write_u8(33u8); + state.write_u8(34u8); v0.hash(state); } crate::Expr::Unary(v0) => { - state.write_u8(34u8); + state.write_u8(35u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Unsafe(v0) => { - state.write_u8(35u8); + state.write_u8(36u8); v0.hash(state); } crate::Expr::Verbatim(v0) => { - state.write_u8(36u8); + state.write_u8(37u8); TokenStreamHelper(v0).hash(state); } #[cfg(feature = "full")] crate::Expr::While(v0) => { - state.write_u8(37u8); + state.write_u8(38u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Yield(v0) => { - state.write_u8(38u8); + state.write_u8(39u8); v0.hash(state); } #[cfg(not(feature = "full"))] @@ -843,6 +848,18 @@ impl Hash for crate::ExprRange { self.end.hash(state); } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::ExprRawAddr { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.mutability.hash(state); + self.expr.hash(state); + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprReference { @@ -2086,6 +2103,23 @@ impl Hash for crate::PathSegment { self.arguments.hash(state); } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::PointerMutability { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + match self { + crate::PointerMutability::Const(_) => { + state.write_u8(0u8); + } + crate::PointerMutability::Mut(_) => { + state.write_u8(1u8); + } + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PredicateLifetime { diff --git a/src/gen/visit.rs b/src/gen/visit.rs index 6c96a3f31..419fb5930 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -264,6 +264,11 @@ pub trait Visit<'ast> { fn visit_expr_range(&mut self, i: &'ast crate::ExprRange) { visit_expr_range(self, i); } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_expr_raw_addr(&mut self, i: &'ast crate::ExprRawAddr) { + visit_expr_raw_addr(self, i); + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_reference(&mut self, i: &'ast crate::ExprReference) { @@ -685,6 +690,11 @@ pub trait Visit<'ast> { fn visit_path_segment(&mut self, i: &'ast crate::PathSegment) { visit_path_segment(self, i); } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_pointer_mutability(&mut self, i: &'ast crate::PointerMutability) { + visit_pointer_mutability(self, i); + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_predicate_lifetime(&mut self, i: &'ast crate::PredicateLifetime) { @@ -1355,6 +1365,9 @@ where crate::Expr::Range(_binding_0) => { full!(v.visit_expr_range(_binding_0)); } + crate::Expr::RawAddr(_binding_0) => { + full!(v.visit_expr_raw_addr(_binding_0)); + } crate::Expr::Reference(_binding_0) => { v.visit_expr_reference(_binding_0); } @@ -1786,6 +1799,20 @@ where v.visit_expr(&**it); } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_expr_raw_addr<'ast, V>(v: &mut V, node: &'ast crate::ExprRawAddr) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + skip!(node.and_token); + skip!(node.raw); + v.visit_pointer_mutability(&node.mutability); + v.visit_expr(&*node.expr); +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_reference<'ast, V>(v: &mut V, node: &'ast crate::ExprReference) @@ -3142,6 +3169,21 @@ where v.visit_ident(&node.ident); v.visit_path_arguments(&node.arguments); } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_pointer_mutability<'ast, V>(v: &mut V, node: &'ast crate::PointerMutability) +where + V: Visit<'ast> + ?Sized, +{ + match node { + crate::PointerMutability::Const(_binding_0) => { + skip!(_binding_0); + } + crate::PointerMutability::Mut(_binding_0) => { + skip!(_binding_0); + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_predicate_lifetime<'ast, V>(v: &mut V, node: &'ast crate::PredicateLifetime) diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index b70a4227e..997ef266b 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -265,6 +265,11 @@ pub trait VisitMut { fn visit_expr_range_mut(&mut self, i: &mut crate::ExprRange) { visit_expr_range_mut(self, i); } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_expr_raw_addr_mut(&mut self, i: &mut crate::ExprRawAddr) { + visit_expr_raw_addr_mut(self, i); + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_reference_mut(&mut self, i: &mut crate::ExprReference) { @@ -686,6 +691,11 @@ pub trait VisitMut { fn visit_path_segment_mut(&mut self, i: &mut crate::PathSegment) { visit_path_segment_mut(self, i); } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_pointer_mutability_mut(&mut self, i: &mut crate::PointerMutability) { + visit_pointer_mutability_mut(self, i); + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_predicate_lifetime_mut(&mut self, i: &mut crate::PredicateLifetime) { @@ -1356,6 +1366,9 @@ where crate::Expr::Range(_binding_0) => { full!(v.visit_expr_range_mut(_binding_0)); } + crate::Expr::RawAddr(_binding_0) => { + full!(v.visit_expr_raw_addr_mut(_binding_0)); + } crate::Expr::Reference(_binding_0) => { v.visit_expr_reference_mut(_binding_0); } @@ -1787,6 +1800,20 @@ where v.visit_expr_mut(&mut **it); } } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_expr_raw_addr_mut(v: &mut V, node: &mut crate::ExprRawAddr) +where + V: VisitMut + ?Sized, +{ + for it in &mut node.attrs { + v.visit_attribute_mut(it); + } + skip!(node.and_token); + skip!(node.raw); + v.visit_pointer_mutability_mut(&mut node.mutability); + v.visit_expr_mut(&mut *node.expr); +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_reference_mut(v: &mut V, node: &mut crate::ExprReference) @@ -3142,6 +3169,21 @@ where v.visit_ident_mut(&mut node.ident); v.visit_path_arguments_mut(&mut node.arguments); } +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_pointer_mutability_mut(v: &mut V, node: &mut crate::PointerMutability) +where + V: VisitMut + ?Sized, +{ + match node { + crate::PointerMutability::Const(_binding_0) => { + skip!(_binding_0); + } + crate::PointerMutability::Mut(_binding_0) => { + skip!(_binding_0); + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_predicate_lifetime_mut(v: &mut V, node: &mut crate::PredicateLifetime) diff --git a/src/lib.rs b/src/lib.rs index ea1277788..5b2f86939 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -363,7 +363,7 @@ pub use crate::error::{Error, Result}; mod expr; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] -pub use crate::expr::{Arm, Label, RangeLimits}; +pub use crate::expr::{Arm, Label, PointerMutability, RangeLimits}; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::expr::{ @@ -375,8 +375,8 @@ pub use crate::expr::{ pub use crate::expr::{ ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprGroup, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch, - ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, - ExprYield, + ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, + ExprWhile, ExprYield, }; #[cfg(feature = "parsing")] diff --git a/src/precedence.rs b/src/precedence.rs index 1a26f195d..936a0c51d 100644 --- a/src/precedence.rs +++ b/src/precedence.rs @@ -102,7 +102,7 @@ impl Precedence { Expr::Binary(e) => Precedence::of_binop(&e.op), Expr::Let(_) => Precedence::Let, Expr::Cast(_) => Precedence::Cast, - Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix, + Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix, Expr::Array(_) | Expr::Async(_) diff --git a/src/stmt.rs b/src/stmt.rs index 51d000581..ac8238a98 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -367,6 +367,7 @@ pub(crate) mod parsing { | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) + | Expr::RawAddr(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) diff --git a/src/token.rs b/src/token.rs index 061e8806c..646271325 100644 --- a/src/token.rs +++ b/src/token.rs @@ -721,6 +721,7 @@ define_keywords! { "override" pub struct Override "priv" pub struct Priv "pub" pub struct Pub + "raw" pub struct Raw "ref" pub struct Ref "return" pub struct Return "Self" pub struct SelfType @@ -899,6 +900,7 @@ macro_rules! Token { [override] => { $crate::token::Override }; [priv] => { $crate::token::Priv }; [pub] => { $crate::token::Pub }; + [raw] => { $crate::token::Raw }; [ref] => { $crate::token::Ref }; [return] => { $crate::token::Return }; [Self] => { $crate::token::SelfType }; diff --git a/syn.json b/syn.json index d14299d38..e425ca17f 100644 --- a/syn.json +++ b/syn.json @@ -775,6 +775,11 @@ "syn": "ExprRange" } ], + "RawAddr": [ + { + "syn": "ExprRawAddr" + } + ], "Reference": [ { "syn": "ExprReference" @@ -1619,6 +1624,35 @@ } } }, + { + "ident": "ExprRawAddr", + "features": { + "any": [ + "full" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "and_token": { + "token": "And" + }, + "raw": { + "token": "Raw" + }, + "mutability": { + "syn": "PointerMutability" + }, + "expr": { + "box": { + "syn": "Expr" + } + } + } + }, { "ident": "ExprReference", "features": { @@ -4152,6 +4186,26 @@ } } }, + { + "ident": "PointerMutability", + "features": { + "any": [ + "full" + ] + }, + "variants": { + "Const": [ + { + "token": "Const" + } + ], + "Mut": [ + { + "token": "Mut" + } + ] + } + }, { "ident": "PredicateLifetime", "features": { @@ -5544,6 +5598,7 @@ "Pub": "pub", "Question": "?", "RArrow": "->", + "Raw": "raw", "Ref": "ref", "Return": "return", "SelfType": "Self", diff --git a/tests/debug/gen.rs b/tests/debug/gen.rs index 9f726683a..d900ece2b 100644 --- a/tests/debug/gen.rs +++ b/tests/debug/gen.rs @@ -856,6 +856,15 @@ impl Debug for Lite { } formatter.finish() } + syn::Expr::RawAddr(_val) => { + let mut formatter = formatter.debug_struct("Expr::RawAddr"); + if !_val.attrs.is_empty() { + formatter.field("attrs", Lite(&_val.attrs)); + } + formatter.field("mutability", Lite(&_val.mutability)); + formatter.field("expr", Lite(&_val.expr)); + formatter.finish() + } syn::Expr::Reference(_val) => { let mut formatter = formatter.debug_struct("Expr::Reference"); if !_val.attrs.is_empty() { @@ -1513,6 +1522,17 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ExprRawAddr"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("mutability", Lite(&self.value.mutability)); + formatter.field("expr", Lite(&self.value.expr)); + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprReference"); @@ -3532,6 +3552,20 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.value { + syn::PointerMutability::Const(_val) => { + formatter.write_str("PointerMutability::Const")?; + Ok(()) + } + syn::PointerMutability::Mut(_val) => { + formatter.write_str("PointerMutability::Mut")?; + Ok(()) + } + } + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PredicateLifetime"); @@ -5011,6 +5045,11 @@ impl Debug for Lite { formatter.write_str("Token![->]") } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Token![raw]") + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![ref]") diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs index cc48587ae..7231bd640 100644 --- a/tests/test_precedence.rs +++ b/tests/test_precedence.rs @@ -186,9 +186,9 @@ fn librustc_parse_and_rewrite(input: &str) -> Option> { fn librustc_parenthesize(mut librustc_expr: P) -> P { use rustc_ast::ast::{ - AssocItem, AssocItemKind, Attribute, BinOpKind, Block, BorrowKind, BoundConstness, Expr, - ExprField, ExprKind, GenericArg, GenericBound, Local, LocalKind, Pat, PolyTraitRef, Stmt, - StmtKind, StructExpr, StructRest, TraitBoundModifiers, Ty, + AssocItem, AssocItemKind, Attribute, BinOpKind, Block, BoundConstness, Expr, ExprField, + ExprKind, GenericArg, GenericBound, Local, LocalKind, Pat, PolyTraitRef, Stmt, StmtKind, + StructExpr, StructRest, TraitBoundModifiers, Ty, }; use rustc_ast::mut_visit::{walk_flat_map_item, MutVisitor}; use rustc_ast::visit::{AssocCtxt, BoundKind}; @@ -240,7 +240,7 @@ fn librustc_parenthesize(mut librustc_expr: P) -> P { fn noop_visit_expr(e: &mut Expr, vis: &mut T) { match &mut e.kind { - ExprKind::AddrOf(BorrowKind::Raw, ..) | ExprKind::Become(..) => {} + ExprKind::Become(..) => {} ExprKind::Struct(expr) => { let StructExpr { qself, diff --git a/tests/test_stmt.rs b/tests/test_stmt.rs index e30c29cf2..b2a49b053 100644 --- a/tests/test_stmt.rs +++ b/tests/test_stmt.rs @@ -21,7 +21,18 @@ fn test_raw_operator() { Stmt::Local { pat: Pat::Wild, init: Some(LocalInit { - expr: Expr::Verbatim(`& raw const x`), + expr: Expr::RawAddr { + mutability: PointerMutability::Const, + expr: Expr::Path { + path: Path { + segments: [ + PathSegment { + ident: "x", + }, + ], + }, + }, + }, }), } "#);