Syntactically permit unsafety on mods

This commit is contained in:
David Tolnay 2020-08-23 03:42:19 -07:00
parent 25b2f48612
commit fd4dd00dde
No known key found for this signature in database
GPG key ID: F9BA143B95FF6D82
17 changed files with 284 additions and 37 deletions

View file

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}

View file

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}

View file

@ -0,0 +1,9 @@
unsafe extern {
//~^ ERROR extern block cannot be declared unsafe
}
unsafe extern "C" {
//~^ ERROR extern block cannot be declared unsafe
}
fn main() {}

View file

@ -0,0 +1,14 @@
error: extern block cannot be declared unsafe
--> $DIR/unsafe-foreign-mod.rs:1:1
|
LL | unsafe extern {
| ^^^^^^
error: extern block cannot be declared unsafe
--> $DIR/unsafe-foreign-mod.rs:5:1
|
LL | unsafe extern "C" {
| ^^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,9 @@
unsafe mod m {
//~^ ERROR module cannot be declared unsafe
}
unsafe mod n;
//~^ ERROR module cannot be declared unsafe
//~^^ ERROR file not found for module `n`
fn main() {}

View file

@ -0,0 +1,23 @@
error[E0583]: file not found for module `n`
--> $DIR/unsafe-mod.rs:5:1
|
LL | unsafe mod n;
| ^^^^^^^^^^^^^
|
= help: to create the module `n`, create file "$DIR/n.rs"
error: module cannot be declared unsafe
--> $DIR/unsafe-mod.rs:1:1
|
LL | unsafe mod m {
| ^^^^^^
error: module cannot be declared unsafe
--> $DIR/unsafe-mod.rs:5:1
|
LL | unsafe mod n;
| ^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0583`.

View file

@ -0,0 +1,89 @@
// force-host
// no-prefer-dynamic
// These are tests for syntax that is accepted by the Rust parser but
// unconditionally rejected semantically after macro expansion. Attribute macros
// are permitted to accept such syntax as long as they replace it with something
// that makes sense to Rust.
//
// We also inspect some of the spans to verify the syntax is not triggering the
// lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081).
#![crate_type = "proc-macro"]
#![feature(proc_macro_span)]
extern crate proc_macro;
use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree};
use std::path::Component;
// unsafe mod m {
// pub unsafe mod inner;
// }
#[proc_macro_attribute]
pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let tokens = &mut input.into_iter();
expect(tokens, "unsafe");
expect(tokens, "mod");
expect(tokens, "m");
let tokens = &mut expect_brace(tokens);
expect(tokens, "pub");
expect(tokens, "unsafe");
expect(tokens, "mod");
let ident = expect(tokens, "inner");
expect(tokens, ";");
check_useful_span(ident, "unsafe-mod.rs");
TokenStream::new()
}
// unsafe extern {
// type T;
// }
#[proc_macro_attribute]
pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let tokens = &mut input.into_iter();
expect(tokens, "unsafe");
expect(tokens, "extern");
let tokens = &mut expect_brace(tokens);
expect(tokens, "type");
let ident = expect(tokens, "T");
expect(tokens, ";");
check_useful_span(ident, "unsafe-foreign-mod.rs");
TokenStream::new()
}
// unsafe extern "C++" {}
#[proc_macro_attribute]
pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let tokens = &mut input.into_iter();
expect(tokens, "unsafe");
expect(tokens, "extern");
let abi = expect(tokens, "\"C++\"");
expect_brace(tokens);
check_useful_span(abi, "unsafe-foreign-mod.rs");
TokenStream::new()
}
fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree {
match tokens.next() {
Some(token) if token.to_string() == expected => token,
wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected),
}
}
fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter {
match tokens.next() {
Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => {
group.stream().into_iter()
}
wrong => panic!("unexpected token: {:?}, expected `{{`", wrong),
}
}
fn check_useful_span(token: TokenTree, expected_filename: &str) {
let span = token.span();
assert!(span.start().column < span.end().column);
let source_path = span.source_file().path();
let filename = source_path.components().last().unwrap();
assert_eq!(filename, Component::Normal(expected_filename.as_ref()));
}

View file

@ -0,0 +1,14 @@
// run-pass
// aux-build:macro-only-syntax.rs
extern crate macro_only_syntax;
#[macro_only_syntax::expect_unsafe_foreign_mod]
unsafe extern {
type T;
}
#[macro_only_syntax::expect_unsafe_extern_cpp_mod]
unsafe extern "C++" {}
fn main() {}

View file

@ -0,0 +1,13 @@
// run-pass
// aux-build:macro-only-syntax.rs
#![feature(proc_macro_hygiene)]
extern crate macro_only_syntax;
#[macro_only_syntax::expect_unsafe_mod]
unsafe mod m {
pub unsafe mod inner;
}
fn main() {}