From abaf55933c0a3b4d2c535370a8cebb2e375817f4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Oct 2024 23:26:10 +0200 Subject: [PATCH 1/3] Add Token![raw] --- src/expr.rs | 3 +-- src/token.rs | 2 ++ syn.json | 1 + tests/debug/gen.rs | 5 +++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 409131b4f..f5862721f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1151,7 +1151,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 +1467,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()?) 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..0c6714564 100644 --- a/syn.json +++ b/syn.json @@ -5544,6 +5544,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..b636f4d7a 100644 --- a/tests/debug/gen.rs +++ b/tests/debug/gen.rs @@ -5011,6 +5011,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]") From 38ebbec7d977720148374f10a44c131f2e5b54bc Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Oct 2024 23:31:06 +0200 Subject: [PATCH 2/3] Add PointerMutability --- src/expr.rs | 41 +++++++++++++++++++++++++++++++++++++++-- src/gen/clone.rs | 14 ++++++++++++++ src/gen/debug.rs | 19 +++++++++++++++++++ src/gen/eq.rs | 16 ++++++++++++++++ src/gen/fold.rs | 26 ++++++++++++++++++++++++++ src/gen/hash.rs | 17 +++++++++++++++++ src/gen/visit.rs | 20 ++++++++++++++++++++ src/gen/visit_mut.rs | 20 ++++++++++++++++++++ src/lib.rs | 2 +- syn.json | 20 ++++++++++++++++++++ tests/debug/gen.rs | 14 ++++++++++++++ 11 files changed, 206 insertions(+), 3 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index f5862721f..67892640e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1099,6 +1099,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")] @@ -1112,7 +1123,7 @@ pub(crate) mod parsing { 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, + Label, PointerMutability, RangeLimits, }; use crate::expr::{ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro, @@ -2969,6 +2980,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,7 +3030,7 @@ pub(crate) mod printing { 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, + Label, PointerMutability, RangeLimits, }; use crate::expr::{ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro, @@ -3928,4 +3954,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..e8f422b02 100644 --- a/src/gen/clone.rs +++ b/src/gen/clone.rs @@ -1647,6 +1647,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..967e01cc4 100644 --- a/src/gen/debug.rs +++ b/src/gen/debug.rs @@ -2385,6 +2385,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..028dad354 100644 --- a/src/gen/eq.rs +++ b/src/gen/eq.rs @@ -1622,6 +1622,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..fe6d93a19 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -723,6 +723,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( @@ -3060,6 +3068,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..b16daf9d7 100644 --- a/src/gen/hash.rs +++ b/src/gen/hash.rs @@ -2086,6 +2086,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..ccedc03b2 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -685,6 +685,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) { @@ -3142,6 +3147,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..7249c69a2 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -686,6 +686,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) { @@ -3142,6 +3147,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..d5574fe07 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::{ diff --git a/syn.json b/syn.json index 0c6714564..3219c679a 100644 --- a/syn.json +++ b/syn.json @@ -4152,6 +4152,26 @@ } } }, + { + "ident": "PointerMutability", + "features": { + "any": [ + "full" + ] + }, + "variants": { + "Const": [ + { + "token": "Const" + } + ], + "Mut": [ + { + "token": "Mut" + } + ] + } + }, { "ident": "PredicateLifetime", "features": { diff --git a/tests/debug/gen.rs b/tests/debug/gen.rs index b636f4d7a..c5132ad3f 100644 --- a/tests/debug/gen.rs +++ b/tests/debug/gen.rs @@ -3532,6 +3532,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"); From f5c9fd326b13dc3aeb080f65cff21cd238ab3631 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Oct 2024 23:32:20 +0200 Subject: [PATCH 3/3] Add Expr::RawAddr --- src/classify.rs | 4 ++ src/expr.rs | 84 +++++++++++++++++++++++++++++++++++----- src/gen/clone.rs | 15 +++++++ src/gen/debug.rs | 21 ++++++++++ src/gen/eq.rs | 15 +++++++ src/gen/fold.rs | 22 +++++++++++ src/gen/hash.rs | 41 ++++++++++++++------ src/gen/visit.rs | 22 +++++++++++ src/gen/visit_mut.rs | 22 +++++++++++ src/lib.rs | 4 +- src/precedence.rs | 2 +- src/stmt.rs | 1 + syn.json | 34 ++++++++++++++++ tests/debug/gen.rs | 20 ++++++++++ tests/test_precedence.rs | 8 ++-- tests/test_stmt.rs | 13 ++++++- 16 files changed, 299 insertions(+), 29 deletions(-) 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 67892640e..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, .. }) @@ -1122,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, PointerMutability, 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, @@ -1486,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, @@ -2369,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 { @@ -3029,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, PointerMutability, 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, @@ -3156,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), @@ -3714,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) { diff --git a/src/gen/clone.rs b/src/gen/clone.rs index e8f422b02..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 { diff --git a/src/gen/debug.rs b/src/gen/debug.rs index 967e01cc4..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 { diff --git a/src/gen/eq.rs b/src/gen/eq.rs index 028dad354..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 {} diff --git a/src/gen/fold.rs b/src/gen/fold.rs index fe6d93a19..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 { @@ -1347,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)) } @@ -1742,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( diff --git a/src/gen/hash.rs b/src/gen/hash.rs index b16daf9d7..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 { diff --git a/src/gen/visit.rs b/src/gen/visit.rs index ccedc03b2..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) { @@ -1360,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); } @@ -1791,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) diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index 7249c69a2..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) { @@ -1361,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); } @@ -1792,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) diff --git a/src/lib.rs b/src/lib.rs index d5574fe07..5b2f86939 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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/syn.json b/syn.json index 3219c679a..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": { diff --git a/tests/debug/gen.rs b/tests/debug/gen.rs index c5132ad3f..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"); 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", + }, + ], + }, + }, + }, }), } "#);