Skip to content

Commit 06791ea

Browse files
authored
Merge pull request #85 from dtolnay/externsafe
Print safe and explicitly unsafe foreign items
2 parents 91ebe48 + db38f77 commit 06791ea

File tree

1 file changed

+117
-20
lines changed

1 file changed

+117
-20
lines changed

src/item.rs

+117-20
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ impl Printer {
9191
self.outer_attrs(&item.attrs);
9292
self.cbox(INDENT);
9393
self.visibility(&item.vis);
94-
self.signature(&item.sig);
94+
self.signature(
95+
&item.sig,
96+
#[cfg(feature = "verbatim")]
97+
&verbatim::Safety::Disallowed,
98+
);
9599
self.where_clause_for_body(&item.sig.generics.where_clause);
96100
self.word("{");
97101
self.hardbreak_if_nonempty();
@@ -794,7 +798,11 @@ impl Printer {
794798
self.outer_attrs(&foreign_item.attrs);
795799
self.cbox(INDENT);
796800
self.visibility(&foreign_item.vis);
797-
self.signature(&foreign_item.sig);
801+
self.signature(
802+
&foreign_item.sig,
803+
#[cfg(feature = "verbatim")]
804+
&verbatim::Safety::Disallowed,
805+
);
798806
self.where_clause_semi(&foreign_item.sig.generics.where_clause);
799807
self.end();
800808
self.hardbreak();
@@ -844,8 +852,10 @@ impl Printer {
844852
#[cfg(feature = "verbatim")]
845853
fn foreign_item_verbatim(&mut self, tokens: &TokenStream) {
846854
use syn::parse::{Parse, ParseStream, Result};
847-
use syn::{Attribute, Token, Visibility};
848-
use verbatim::{FlexibleItemFn, FlexibleItemStatic, FlexibleItemType, WhereClauseLocation};
855+
use syn::{Abi, Attribute, Token, Visibility};
856+
use verbatim::{
857+
kw, FlexibleItemFn, FlexibleItemStatic, FlexibleItemType, WhereClauseLocation,
858+
};
849859

850860
enum ForeignItemVerbatim {
851861
Empty,
@@ -855,6 +865,16 @@ impl Printer {
855865
TypeFlexible(FlexibleItemType),
856866
}
857867

868+
fn peek_signature(input: ParseStream) -> bool {
869+
let fork = input.fork();
870+
fork.parse::<Option<Token![const]>>().is_ok()
871+
&& fork.parse::<Option<Token![async]>>().is_ok()
872+
&& ((fork.peek(kw::safe) && fork.parse::<kw::safe>().is_ok())
873+
|| fork.parse::<Option<Token![unsafe]>>().is_ok())
874+
&& fork.parse::<Option<Abi>>().is_ok()
875+
&& fork.peek(Token![fn])
876+
}
877+
858878
impl Parse for ForeignItemVerbatim {
859879
fn parse(input: ParseStream) -> Result<Self> {
860880
if input.is_empty() {
@@ -869,15 +889,13 @@ impl Printer {
869889
let defaultness = false;
870890

871891
let lookahead = input.lookahead1();
872-
if lookahead.peek(Token![const])
873-
|| lookahead.peek(Token![async])
874-
|| lookahead.peek(Token![unsafe])
875-
|| lookahead.peek(Token![extern])
876-
|| lookahead.peek(Token![fn])
877-
{
892+
if lookahead.peek(Token![fn]) || peek_signature(input) {
878893
let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
879894
Ok(ForeignItemVerbatim::FnFlexible(flexible_item))
880-
} else if lookahead.peek(Token![static]) {
895+
} else if lookahead.peek(Token![static])
896+
|| ((input.peek(Token![unsafe]) || input.peek(kw::safe))
897+
&& input.peek2(Token![static]))
898+
{
881899
let flexible_item = FlexibleItemStatic::parse(attrs, vis, input)?;
882900
Ok(ForeignItemVerbatim::StaticFlexible(flexible_item))
883901
} else if lookahead.peek(Token![type]) {
@@ -953,7 +971,11 @@ impl Printer {
953971
fn trait_item_fn(&mut self, trait_item: &TraitItemFn) {
954972
self.outer_attrs(&trait_item.attrs);
955973
self.cbox(INDENT);
956-
self.signature(&trait_item.sig);
974+
self.signature(
975+
&trait_item.sig,
976+
#[cfg(feature = "verbatim")]
977+
&verbatim::Safety::Disallowed,
978+
);
957979
if let Some(block) = &trait_item.default {
958980
self.where_clause_for_body(&trait_item.sig.generics.where_clause);
959981
self.word("{");
@@ -1149,7 +1171,11 @@ impl Printer {
11491171
if impl_item.defaultness.is_some() {
11501172
self.word("default ");
11511173
}
1152-
self.signature(&impl_item.sig);
1174+
self.signature(
1175+
&impl_item.sig,
1176+
#[cfg(feature = "verbatim")]
1177+
&verbatim::Safety::Disallowed,
1178+
);
11531179
self.where_clause_for_body(&impl_item.sig.generics.where_clause);
11541180
self.word("{");
11551181
self.hardbreak_if_nonempty();
@@ -1277,15 +1303,32 @@ impl Printer {
12771303
}
12781304
}
12791305

1280-
fn signature(&mut self, signature: &Signature) {
1306+
fn signature(
1307+
&mut self,
1308+
signature: &Signature,
1309+
#[cfg(feature = "verbatim")] safety: &verbatim::Safety,
1310+
) {
12811311
if signature.constness.is_some() {
12821312
self.word("const ");
12831313
}
12841314
if signature.asyncness.is_some() {
12851315
self.word("async ");
12861316
}
1287-
if signature.unsafety.is_some() {
1288-
self.word("unsafe ");
1317+
#[cfg(feature = "verbatim")]
1318+
{
1319+
if let verbatim::Safety::Disallowed = safety {
1320+
if signature.unsafety.is_some() {
1321+
self.word("unsafe ");
1322+
}
1323+
} else {
1324+
self.safety(safety);
1325+
}
1326+
}
1327+
#[cfg(not(feature = "verbatim"))]
1328+
{
1329+
if signature.unsafety.is_some() {
1330+
self.word("unsafe ");
1331+
}
12891332
}
12901333
if let Some(abi) = &signature.abi {
12911334
self.abi(abi);
@@ -1381,12 +1424,16 @@ mod verbatim {
13811424
use crate::iter::IterDelimited;
13821425
use crate::INDENT;
13831426
use syn::ext::IdentExt;
1384-
use syn::parse::{ParseStream, Result};
1427+
use syn::parse::{Parse, ParseStream, Result};
13851428
use syn::{
13861429
braced, token, Attribute, Block, Expr, Generics, Ident, Signature, StaticMutability, Stmt,
13871430
Token, Type, TypeParamBound, Visibility, WhereClause,
13881431
};
13891432

1433+
pub mod kw {
1434+
syn::custom_keyword!(safe);
1435+
}
1436+
13901437
pub struct FlexibleItemConst {
13911438
pub attrs: Vec<Attribute>,
13921439
pub vis: Visibility,
@@ -1401,13 +1448,15 @@ mod verbatim {
14011448
pub attrs: Vec<Attribute>,
14021449
pub vis: Visibility,
14031450
pub defaultness: bool,
1451+
pub safety: Safety,
14041452
pub sig: Signature,
14051453
pub body: Option<Vec<Stmt>>,
14061454
}
14071455

14081456
pub struct FlexibleItemStatic {
14091457
pub attrs: Vec<Attribute>,
14101458
pub vis: Visibility,
1459+
pub safety: Safety,
14111460
pub mutability: StaticMutability,
14121461
pub ident: Ident,
14131462
pub ty: Option<Type>,
@@ -1425,6 +1474,13 @@ mod verbatim {
14251474
pub where_clause_after_eq: Option<WhereClause>,
14261475
}
14271476

1477+
pub enum Safety {
1478+
Unsafe,
1479+
Safe,
1480+
Default,
1481+
Disallowed,
1482+
}
1483+
14281484
pub enum WhereClauseLocation {
14291485
// type Ty<T> where T: 'static = T;
14301486
BeforeEq,
@@ -1474,7 +1530,16 @@ mod verbatim {
14741530
defaultness: bool,
14751531
input: ParseStream,
14761532
) -> Result<Self> {
1477-
let sig: Signature = input.parse()?;
1533+
let constness: Option<Token![const]> = input.parse()?;
1534+
let asyncness: Option<Token![async]> = input.parse()?;
1535+
let safety: Safety = input.parse()?;
1536+
1537+
let lookahead = input.lookahead1();
1538+
let sig: Signature = if lookahead.peek(Token![extern]) || lookahead.peek(Token![fn]) {
1539+
input.parse()?
1540+
} else {
1541+
return Err(lookahead.error());
1542+
};
14781543

14791544
let lookahead = input.lookahead1();
14801545
let body = if lookahead.peek(Token![;]) {
@@ -1493,14 +1558,21 @@ mod verbatim {
14931558
attrs,
14941559
vis,
14951560
defaultness,
1496-
sig,
1561+
safety,
1562+
sig: Signature {
1563+
constness,
1564+
asyncness,
1565+
unsafety: None,
1566+
..sig
1567+
},
14971568
body,
14981569
})
14991570
}
15001571
}
15011572

15021573
impl FlexibleItemStatic {
15031574
pub fn parse(attrs: Vec<Attribute>, vis: Visibility, input: ParseStream) -> Result<Self> {
1575+
let safety: Safety = input.parse()?;
15041576
input.parse::<Token![static]>()?;
15051577
let mutability: StaticMutability = input.parse()?;
15061578
let ident = input.parse()?;
@@ -1530,6 +1602,7 @@ mod verbatim {
15301602
Ok(FlexibleItemStatic {
15311603
attrs,
15321604
vis,
1605+
safety,
15331606
mutability,
15341607
ident,
15351608
ty,
@@ -1601,6 +1674,20 @@ mod verbatim {
16011674
}
16021675
}
16031676

1677+
impl Parse for Safety {
1678+
fn parse(input: ParseStream) -> Result<Self> {
1679+
if input.peek(Token![unsafe]) {
1680+
input.parse::<Token![unsafe]>()?;
1681+
Ok(Safety::Unsafe)
1682+
} else if input.peek(kw::safe) {
1683+
input.parse::<kw::safe>()?;
1684+
Ok(Safety::Safe)
1685+
} else {
1686+
Ok(Safety::Default)
1687+
}
1688+
}
1689+
}
1690+
16041691
impl Printer {
16051692
pub fn flexible_item_const(&mut self, item: &FlexibleItemConst) {
16061693
self.outer_attrs(&item.attrs);
@@ -1635,7 +1722,7 @@ mod verbatim {
16351722
if item.defaultness {
16361723
self.word("default ");
16371724
}
1638-
self.signature(&item.sig);
1725+
self.signature(&item.sig, &item.safety);
16391726
if let Some(body) = &item.body {
16401727
self.where_clause_for_body(&item.sig.generics.where_clause);
16411728
self.word("{");
@@ -1658,6 +1745,7 @@ mod verbatim {
16581745
self.outer_attrs(&item.attrs);
16591746
self.cbox(0);
16601747
self.visibility(&item.vis);
1748+
self.safety(&item.safety);
16611749
self.word("static ");
16621750
self.static_mutability(&item.mutability);
16631751
self.ident(&item.ident);
@@ -1708,5 +1796,14 @@ mod verbatim {
17081796
self.end();
17091797
self.hardbreak();
17101798
}
1799+
1800+
pub fn safety(&mut self, safety: &Safety) {
1801+
match safety {
1802+
Safety::Unsafe => self.word("unsafe "),
1803+
Safety::Safe => self.word("safe "),
1804+
Safety::Default => {}
1805+
Safety::Disallowed => unreachable!(),
1806+
}
1807+
}
17111808
}
17121809
}

0 commit comments

Comments
 (0)