diff options
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | .clippy.toml | 1 | ||||
-rw-r--r-- | .github/workflows/ci.yml | 69 | ||||
-rw-r--r-- | Android.bp | 4 | ||||
-rw-r--r-- | Cargo.toml | 22 | ||||
-rw-r--r-- | Cargo.toml.orig | 10 | ||||
-rw-r--r-- | LICENSE-APACHE | 25 | ||||
-rw-r--r-- | METADATA | 14 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/lib.rs | 103 | ||||
-rw-r--r-- | tests/compiletest/mod.rs | 6 | ||||
-rw-r--r-- | tests/test.rs | 88 | ||||
-rw-r--r-- | tests/ui/async-fn.rs | 10 | ||||
-rw-r--r-- | tests/ui/async-fn.stderr | 7 | ||||
-rw-r--r-- | tests/ui/trait-fn.rs | 12 | ||||
-rw-r--r-- | tests/ui/trait-fn.stderr | 5 |
16 files changed, 323 insertions, 64 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index a244221..341a73b 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,6 @@ { "git": { - "sha1": "bd3461a31006e0c46f76970db07d4054c12e9928" - } -} + "sha1": "b5c6d7e1df7e423a9543ee9317f63339660743a6" + }, + "path_in_vcs": "" +}
\ No newline at end of file diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 0000000..3d30690 --- /dev/null +++ b/.clippy.toml @@ -0,0 +1 @@ +msrv = "1.31.0" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 921c271..650b0e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,27 +3,90 @@ name: CI on: push: pull_request: + workflow_dispatch: schedule: [cron: "40 1 * * *"] +permissions: + contents: read + +env: + RUSTFLAGS: -Dwarnings + jobs: + pre_ci: + uses: dtolnay/.github/.github/workflows/pre_ci.yml@master + test: name: Rust ${{matrix.rust}} + needs: pre_ci + if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest strategy: fail-fast: false matrix: - rust: [nightly, beta, stable, 1.32.0] + rust: [nightly, beta, stable, 1.56.0] + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} + - name: Enable deny(non_exhaustive_omitted_patterns) + run: echo RUSTFLAGS=$(RUSTFLAGS)\ --cfg=exhaustive >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV + if: matrix.rust == 'nightly' + - run: cargo test + + xplat: + name: ${{matrix.name}} + needs: pre_ci + if: needs.pre_ci.outputs.continue + runs-on: ${{matrix.os}}-latest + strategy: + fail-fast: false + matrix: + include: + - name: macOS + os: macos + - name: Windows + os: windows + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + - name: Enable type layout randomization + run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV - run: cargo test msrv: name: Rust 1.31.0 + needs: pre_ci + if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@1.31.0 - run: cargo build + + clippy: + name: Clippy + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@clippy + - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --exit-code 1 @@ -41,7 +41,7 @@ rust_proc_macro { name: "libno_panic", crate_name: "no_panic", cargo_env_compat: true, - cargo_pkg_version: "0.1.15", + cargo_pkg_version: "0.1.21", srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ @@ -50,4 +50,6 @@ rust_proc_macro { "libsyn", ], compile_multilib: "first", + product_available: true, + vendor_available: true, } @@ -3,28 +3,30 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" +rust-version = "1.31" name = "no-panic" -version = "0.1.15" +version = "0.1.21" authors = ["David Tolnay <dtolnay@gmail.com>"] description = "Attribute macro to require that the compiler prove a function can't ever panic." documentation = "https://docs.rs/no-panic" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/no-panic" + [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [lib] proc-macro = true + [dependencies.proc-macro2] version = "1.0" @@ -34,5 +36,13 @@ version = "1.0" [dependencies.syn] version = "1.0" features = ["full"] + +[dev-dependencies.rustversion] +version = "1.0.9" + [dev-dependencies.tempfile] version = "3.0" + +[dev-dependencies.trybuild] +version = "1.0.69" +features = ["diff"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index f32a7f2..98bf79c 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,13 +1,13 @@ [package] name = "no-panic" -version = "0.1.15" +version = "0.1.21" authors = ["David Tolnay <dtolnay@gmail.com>"] +description = "Attribute macro to require that the compiler prove a function can't ever panic." +documentation = "https://docs.rs/no-panic" edition = "2018" license = "MIT OR Apache-2.0" -description = "Attribute macro to require that the compiler prove a function can't ever panic." repository = "https://github.com/dtolnay/no-panic" -documentation = "https://docs.rs/no-panic" -readme = "README.md" +rust-version = "1.31" [lib] proc-macro = true @@ -18,7 +18,9 @@ quote = "1.0" syn = { version = "1.0", features = ["full"] } [dev-dependencies] +rustversion = "1.0.9" tempfile = "3.0" +trybuild = { version = "1.0.69", features = ["diff"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 16fe87b..1b5ec8b 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/no-panic +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "no-panic" description: "Attribute macro to require that the compiler prove a function can\'t ever panic." third_party { @@ -7,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/no-panic/no-panic-0.1.15.crate" + value: "https://static.crates.io/crates/no-panic/no-panic-0.1.21.crate" } - version: "0.1.15" + version: "0.1.21" license_type: NOTICE last_upgrade_date { - year: 2020 - month: 12 - day: 29 + year: 2023 + month: 3 + day: 6 } } @@ -3,8 +3,8 @@ [<img alt="github" src="https://img.shields.io/badge/github-dtolnay/no--panic-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/no-panic) [<img alt="crates.io" src="https://img.shields.io/crates/v/no-panic.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/no-panic) -[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-no--panic-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/no-panic) -[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/no-panic/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/no-panic/actions?query=branch%3Amaster) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-no--panic-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/no-panic) +[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/no-panic/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/no-panic/actions?query=branch%3Amaster) A Rust attribute macro to require that the compiler prove a function can't ever panic. @@ -2,7 +2,7 @@ //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust -//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //! <br> //! @@ -119,31 +119,110 @@ //! [Kixunil]: https://github.com/Kixunil //! [`dont_panic`]: https://github.com/Kixunil/dont_panic +#![doc(html_root_url = "https://docs.rs/no-panic/0.1.21")] +#![allow( + clippy::doc_markdown, + clippy::match_same_arms, + clippy::missing_panics_doc +)] +#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))] + extern crate proc_macro; use proc_macro::TokenStream; -use proc_macro2::Span; +use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{parse_macro_input, parse_quote, Attribute, FnArg, Ident, ItemFn, PatType, ReturnType}; +use syn::parse::{Error, Nothing, Result}; +use syn::{ + parse_quote, Attribute, FnArg, GenericArgument, Ident, ItemFn, Pat, PatType, Path, + PathArguments, ReturnType, Token, Type, TypeInfer, TypeParamBound, +}; #[proc_macro_attribute] -pub fn no_panic(args: TokenStream, function: TokenStream) -> TokenStream { - assert!(args.is_empty()); +pub fn no_panic(args: TokenStream, input: TokenStream) -> TokenStream { + let args = TokenStream2::from(args); + let input = TokenStream2::from(input); + let expanded = match parse(args, input.clone()) { + Ok(function) => expand_no_panic(function), + Err(parse_error) => { + let compile_error = parse_error.to_compile_error(); + quote!(#compile_error #input) + } + }; + TokenStream::from(expanded) +} + +fn parse(args: TokenStream2, input: TokenStream2) -> Result<ItemFn> { + let function: ItemFn = syn::parse2(input)?; + let _: Nothing = syn::parse2::<Nothing>(args)?; + if function.sig.asyncness.is_some() { + return Err(Error::new( + Span::call_site(), + "no_panic attribute on async fn is not supported", + )); + } + Ok(function) +} + +// Convert `Path<impl Trait>` to `Path<_>` +fn make_impl_trait_wild(ret: &mut Type) { + match ret { + Type::ImplTrait(impl_trait) => { + *ret = Type::Infer(TypeInfer { + underscore_token: Token![_](impl_trait.impl_token.span), + }); + } + Type::Array(ret) => make_impl_trait_wild(&mut ret.elem), + Type::Group(ret) => make_impl_trait_wild(&mut ret.elem), + Type::Paren(ret) => make_impl_trait_wild(&mut ret.elem), + Type::Path(ret) => make_impl_trait_wild_in_path(&mut ret.path), + Type::Ptr(ret) => make_impl_trait_wild(&mut ret.elem), + Type::Reference(ret) => make_impl_trait_wild(&mut ret.elem), + Type::Slice(ret) => make_impl_trait_wild(&mut ret.elem), + Type::TraitObject(ret) => { + for bound in &mut ret.bounds { + if let TypeParamBound::Trait(bound) = bound { + make_impl_trait_wild_in_path(&mut bound.path); + } + } + } + Type::Tuple(ret) => ret.elems.iter_mut().for_each(make_impl_trait_wild), + Type::BareFn(_) | Type::Infer(_) | Type::Macro(_) | Type::Never(_) | Type::Verbatim(_) => {} + #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] + _ => {} + } +} - let mut function = parse_macro_input!(function as ItemFn); +fn make_impl_trait_wild_in_path(path: &mut Path) { + for segment in &mut path.segments { + if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments { + for arg in &mut bracketed.args { + if let GenericArgument::Type(arg) = arg { + make_impl_trait_wild(arg); + } + } + } + } +} +fn expand_no_panic(mut function: ItemFn) -> TokenStream2 { let mut move_self = None; let mut arg_pat = Vec::new(); let mut arg_val = Vec::new(); for (i, input) in function.sig.inputs.iter_mut().enumerate() { let numbered = Ident::new(&format!("__arg{}", i), Span::call_site()); match input { - FnArg::Typed(PatType { pat, .. }) => { + FnArg::Typed(PatType { pat, .. }) + if match pat.as_ref() { + Pat::Ident(pat) => pat.ident != "self", + _ => true, + } => + { arg_pat.push(quote!(#pat)); arg_val.push(quote!(#numbered)); *pat = parse_quote!(mut #numbered); } - FnArg::Receiver(_) => { + FnArg::Typed(_) | FnArg::Receiver(_) => { move_self = Some(quote! { if false { loop {} @@ -168,7 +247,11 @@ pub fn no_panic(args: TokenStream, function: TokenStream) -> TokenStream { let ret = match &function.sig.output { ReturnType::Default => quote!(-> ()), - output @ ReturnType::Type(..) => quote!(#output), + ReturnType::Type(arrow, output) => { + let mut output = output.clone(); + make_impl_trait_wild(&mut output); + quote!(#arrow #output) + } }; let stmts = function.block.stmts; let message = format!( @@ -200,5 +283,5 @@ pub fn no_panic(args: TokenStream, function: TokenStream) -> TokenStream { __result })); - TokenStream::from(quote!(#function)) + quote!(#function) } diff --git a/tests/compiletest/mod.rs b/tests/compiletest/mod.rs index f4e26c1..cc3632d 100644 --- a/tests/compiletest/mod.rs +++ b/tests/compiletest/mod.rs @@ -34,7 +34,11 @@ pub fn contains_panic(name: &str, code: &str) -> bool { .arg("--out-dir") .arg(tempdir.path()) .arg("--extern") - .arg("no_panic=target/debug/libno_panic.so") + .arg(format!( + "no_panic=target/debug/{prefix}no_panic.{extension}", + prefix = std::env::consts::DLL_PREFIX, + extension = std::env::consts::DLL_EXTENSION, + )) .status() .expect("failed to execute rustc"); assert!(status.success()); diff --git a/tests/test.rs b/tests/test.rs index a7da4d4..c65a08c 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,6 +1,13 @@ #[macro_use] mod compiletest; +#[rustversion::attr(not(nightly), ignore)] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} + assert_no_panic! { mod test_readme { #[no_panic] @@ -119,21 +126,27 @@ assert_no_panic! { } } - mod test_self_in_vec { + mod test_self_in_macro { struct S { data: usize, } + macro_rules! id { + ($expr:expr) => { + $expr + }; + } + impl S { #[no_panic] - fn get_mut(&mut self) -> Vec<usize> { - vec![self.data] + fn get_mut(&mut self) -> usize { + id![self.data] } } fn main() { let mut s = S { data: 0 }; - println!("{}", s.get_mut()[0]); + println!("{}", s.get_mut()); } } @@ -165,6 +178,73 @@ assert_no_panic! { println!("{}", s.get_mut()); } } + + mod test_self_with_std_pin { + use std::pin::Pin; + + pub struct S; + + impl S { + #[no_panic] + fn f(mut self: Pin<&mut Self>) { + let _ = self.as_mut(); + } + } + + fn main() {} + } + + mod test_deref_coercion { + #[no_panic] + pub fn f(s: &str) -> &str { + &s + } + + fn main() {} + } + + mod test_return_impl_trait { + use std::io; + + #[no_panic] + pub fn f() -> io::Result<impl io::Write> { + Ok(Vec::new()) + } + + fn main() {} + } + + mod test_conditional_return { + #[no_panic] + pub fn f(i: i32) { + if i < 0 { + return; + } + } + + fn main() { + println!("{:?}", f(-1)); + } + } + + mod test_conditional_return_macro { + macro_rules! return_if_negative { + ($e:expr) => { + if $e < 0 { + return; + } + } + } + + #[no_panic] + pub fn f(i: i32) { + return_if_negative!(i); + } + + fn main() { + println!("{:?}", f(-1)); + } + } } assert_link_error! { diff --git a/tests/ui/async-fn.rs b/tests/ui/async-fn.rs new file mode 100644 index 0000000..65deada --- /dev/null +++ b/tests/ui/async-fn.rs @@ -0,0 +1,10 @@ +use no_panic::no_panic; + +#[no_panic] +async fn f() { + g().await; +} + +async fn g() {} + +fn main() {} diff --git a/tests/ui/async-fn.stderr b/tests/ui/async-fn.stderr new file mode 100644 index 0000000..ad06ecc --- /dev/null +++ b/tests/ui/async-fn.stderr @@ -0,0 +1,7 @@ +error: no_panic attribute on async fn is not supported + --> tests/ui/async-fn.rs:3:1 + | +3 | #[no_panic] + | ^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `no_panic` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/trait-fn.rs b/tests/ui/trait-fn.rs new file mode 100644 index 0000000..d2c650f --- /dev/null +++ b/tests/ui/trait-fn.rs @@ -0,0 +1,12 @@ +use no_panic::no_panic; + +trait Trait { + #[no_panic] + fn f(); +} + +impl Trait for i32 { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/trait-fn.stderr b/tests/ui/trait-fn.stderr new file mode 100644 index 0000000..b4215c8 --- /dev/null +++ b/tests/ui/trait-fn.stderr @@ -0,0 +1,5 @@ +error: expected curly braces + --> tests/ui/trait-fn.rs:5:11 + | +5 | fn f(); + | ^ |