Snap for 10453563 from f21458e6efac9710bd5f73473cb47856a7020803 to mainline-media-swcodec-release

Change-Id: I32a3cfcfc55c3c1e61bc04f6a08199f31a712e20
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 @@
 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/[email protected]
       - 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
diff --git a/Android.bp b/Android.bp
index f56a6fd..c3aed71 100644
--- a/Android.bp
+++ b/Android.bp
@@ -41,7 +41,7 @@
     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 @@
         "libsyn",
     ],
     compile_multilib: "first",
+    product_available: true,
+    vendor_available: true,
 }
diff --git a/Cargo.toml b/Cargo.toml
index 0a7ae1e..a183443 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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 <[email protected]>"]
 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 @@
 [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 <[email protected]>"]
+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 @@
 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 @@
    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.
diff --git a/METADATA b/METADATA
index 5416245..18ed219 100644
--- a/METADATA
+++ b/METADATA
@@ -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 @@
   }
   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
   }
 }
diff --git a/README.md b/README.md
index a1c09fb..33dc3cd 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/src/lib.rs b/src/lib.rs
index 2c9bd77..d0be8b4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)
+}
 
-    let mut function = parse_macro_input!(function as ItemFn);
+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))]
+        _ => {}
+    }
+}
+
+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 @@
 
     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 @@
         __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 @@
         .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 @@
         }
     }
 
-    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 @@
             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();
+  |           ^