diff --git a/src/parser/grammar/items/mod.rs b/src/parser/grammar/items/mod.rs index 4afe2e4186..588fca4c61 100644 --- a/src/parser/grammar/items/mod.rs +++ b/src/parser/grammar/items/mod.rs @@ -81,38 +81,74 @@ fn item(p: &mut Parser) { CONST_ITEM } }, - // test unsafe_trait - // unsafe trait T {} - UNSAFE_KW if la == TRAIT_KW => { + UNSAFE_KW => { p.bump(); - traits::trait_item(p); - TRAIT_ITEM - } + let la = p.nth(1); + match p.current() { + // test unsafe_trait + // unsafe trait T {} + TRAIT_KW => { + traits::trait_item(p); + TRAIT_ITEM + } - // test unsafe_auto_trait - // unsafe auto trait T {} - UNSAFE_KW if p.at_kw(1, "auto") && p.nth(2) == TRAIT_KW => { - p.bump(); - p.bump_remap(AUTO_KW); - traits::trait_item(p); - TRAIT_ITEM - } + // test unsafe_auto_trait + // unsafe auto trait T {} + IDENT if p.at_kw("auto") && la == TRAIT_KW => { + p.bump_remap(AUTO_KW); + traits::trait_item(p); + TRAIT_ITEM + } - // test unsafe_impl - // unsafe impl Foo {} - UNSAFE_KW if la == IMPL_KW => { - p.bump(); - traits::impl_item(p); - IMPL_ITEM - } + // test unsafe_impl + // unsafe impl Foo {} + IMPL_KW => { + traits::impl_item(p); + IMPL_ITEM + } - // test unsafe_default_impl - // unsafe default impl Foo {} - UNSAFE_KW if p.at_kw(1, "default") && p.nth(2) == IMPL_KW => { - p.bump(); - p.bump_remap(DEFAULT_KW); - traits::impl_item(p); - IMPL_ITEM + // test unsafe_default_impl + // unsafe default impl Foo {} + IDENT if p.at_kw("default") && la == IMPL_KW => { + p.bump_remap(DEFAULT_KW); + traits::impl_item(p); + IMPL_ITEM + } + + // test unsafe_extern_fn + // unsafe extern "C" fn foo() {} + EXTERN_KW => { + abi(p); + if !p.at(FN_KW) { + item.abandon(p); + p.error().message("expected function").emit(); + return + } + fn_item(p); + FN_ITEM + } + + // test unsafe_fn + // unsafe fn foo() {} + FN_KW => { + fn_item(p); + FN_ITEM + } + + t => { + item.abandon(p); + let message = "expected `trait`, `impl` or `fn`"; + + // test unsafe_block_in_mod + // fn foo(){} unsafe { } fn bar(){} + if t == L_CURLY { + error_block(p, message); + } else { + p.error().message(message).emit(); + } + return; + } + } } MOD_KW => { diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 7e1b22ee59..53a116fb7f 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1,6 +1,6 @@ use super::Event; use super::input::{InputPosition, ParserInput}; -use SyntaxKind::{self, EOF, TOMBSTONE, IDENT}; +use SyntaxKind::{self, EOF, TOMBSTONE}; pub(crate) struct Marker { pos: u32, @@ -161,8 +161,8 @@ impl<'t> Parser<'t> { self.inp.kind(self.pos + n) } - pub(crate) fn at_kw(&self, n: u32, t: &str) -> bool { - self.nth(n) == IDENT && self.inp.text(self.pos + n) == t + pub(crate) fn at_kw(&self, t: &str) -> bool { + self.inp.text(self.pos) == t } pub(crate) fn current(&self) -> SyntaxKind { diff --git a/tests/data/parser/inline/0011_unsafe_fn.rs b/tests/data/parser/inline/0011_unsafe_fn.rs new file mode 100644 index 0000000000..33cfc4cd7a --- /dev/null +++ b/tests/data/parser/inline/0011_unsafe_fn.rs @@ -0,0 +1 @@ +unsafe fn foo() {} diff --git a/tests/data/parser/inline/0011_unsafe_fn.txt b/tests/data/parser/inline/0011_unsafe_fn.txt new file mode 100644 index 0000000000..23eca1d655 --- /dev/null +++ b/tests/data/parser/inline/0011_unsafe_fn.txt @@ -0,0 +1,13 @@ +FILE@[0; 19) + FN_ITEM@[0; 19) + UNSAFE_KW@[0; 6) + WHITESPACE@[6; 7) + FN_KW@[7; 9) + WHITESPACE@[9; 10) + IDENT@[10; 13) "foo" + L_PAREN@[13; 14) + R_PAREN@[14; 15) + WHITESPACE@[15; 16) + L_CURLY@[16; 17) + R_CURLY@[17; 18) + WHITESPACE@[18; 19) diff --git a/tests/data/parser/inline/0012_unsafe_extern_fn.rs b/tests/data/parser/inline/0012_unsafe_extern_fn.rs new file mode 100644 index 0000000000..1295c2cd22 --- /dev/null +++ b/tests/data/parser/inline/0012_unsafe_extern_fn.rs @@ -0,0 +1 @@ +unsafe extern "C" fn foo() {} diff --git a/tests/data/parser/inline/0012_unsafe_extern_fn.txt b/tests/data/parser/inline/0012_unsafe_extern_fn.txt new file mode 100644 index 0000000000..547cb499d7 --- /dev/null +++ b/tests/data/parser/inline/0012_unsafe_extern_fn.txt @@ -0,0 +1,18 @@ +FILE@[0; 30) + FN_ITEM@[0; 30) + UNSAFE_KW@[0; 6) + ABI@[6; 18) + WHITESPACE@[6; 7) + EXTERN_KW@[7; 13) + WHITESPACE@[13; 14) + STRING@[14; 17) + WHITESPACE@[17; 18) + FN_KW@[18; 20) + WHITESPACE@[20; 21) + IDENT@[21; 24) "foo" + L_PAREN@[24; 25) + R_PAREN@[25; 26) + WHITESPACE@[26; 27) + L_CURLY@[27; 28) + R_CURLY@[28; 29) + WHITESPACE@[29; 30) diff --git a/tests/data/parser/inline/0013_unsafe_block_in_mod.rs b/tests/data/parser/inline/0013_unsafe_block_in_mod.rs new file mode 100644 index 0000000000..26141e9049 --- /dev/null +++ b/tests/data/parser/inline/0013_unsafe_block_in_mod.rs @@ -0,0 +1 @@ +fn foo(){} unsafe { } fn bar(){} diff --git a/tests/data/parser/inline/0013_unsafe_block_in_mod.txt b/tests/data/parser/inline/0013_unsafe_block_in_mod.txt new file mode 100644 index 0000000000..2e319be735 --- /dev/null +++ b/tests/data/parser/inline/0013_unsafe_block_in_mod.txt @@ -0,0 +1,27 @@ +FILE@[0; 33) + FN_ITEM@[0; 11) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + IDENT@[3; 6) "foo" + L_PAREN@[6; 7) + R_PAREN@[7; 8) + L_CURLY@[8; 9) + R_CURLY@[9; 10) + WHITESPACE@[10; 11) + UNSAFE_KW@[11; 17) + ERROR@[17; 22) + err: `expected `trait`, `impl` or `fn`` + WHITESPACE@[17; 18) + L_CURLY@[18; 19) + WHITESPACE@[19; 20) + R_CURLY@[20; 21) + WHITESPACE@[21; 22) + FN_ITEM@[22; 33) + FN_KW@[22; 24) + WHITESPACE@[24; 25) + IDENT@[25; 28) "bar" + L_PAREN@[28; 29) + R_PAREN@[29; 30) + L_CURLY@[30; 31) + R_CURLY@[31; 32) + WHITESPACE@[32; 33)