summaryrefslogtreecommitdiffstats
path: root/third_party/rust/inherent
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/inherent
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/inherent')
-rw-r--r--third_party/rust/inherent/.cargo-checksum.json1
-rw-r--r--third_party/rust/inherent/Cargo.toml49
-rw-r--r--third_party/rust/inherent/LICENSE-APACHE176
-rw-r--r--third_party/rust/inherent/LICENSE-MIT23
-rw-r--r--third_party/rust/inherent/README.md86
-rw-r--r--third_party/rust/inherent/src/expand.rs128
-rw-r--r--third_party/rust/inherent/src/lib.rs97
-rw-r--r--third_party/rust/inherent/src/parse.rs69
-rw-r--r--third_party/rust/inherent/tests/compiletest.rs7
-rw-r--r--third_party/rust/inherent/tests/test.rs25
-rw-r--r--third_party/rust/inherent/tests/ui/blanket-impl.rs12
-rw-r--r--third_party/rust/inherent/tests/ui/blanket-impl.stderr7
-rw-r--r--third_party/rust/inherent/tests/ui/not-trait-impl.rs10
-rw-r--r--third_party/rust/inherent/tests/ui/not-trait-impl.stderr7
-rw-r--r--third_party/rust/inherent/tests/ui/not-visible.rs18
-rw-r--r--third_party/rust/inherent/tests/ui/not-visible.stderr8
16 files changed, 723 insertions, 0 deletions
diff --git a/third_party/rust/inherent/.cargo-checksum.json b/third_party/rust/inherent/.cargo-checksum.json
new file mode 100644
index 0000000000..73af0431e0
--- /dev/null
+++ b/third_party/rust/inherent/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"c9005651a132b1a38e3fb98035bbe23fc1a87cbf4ebfc0ade0c9c954d9aa5490","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"c26da74954caf861f3446c6e3499807097c319478885ed286df16a22f21a48ec","src/expand.rs":"d9141b9f7e65b405dff04a11605d6ced32febbd1500ad749892093ff2b3a078d","src/lib.rs":"f4bca344e759a502e314c69cdb7f34393f558e19ccefe0c22850916e54edd620","src/parse.rs":"5478cff1e20ac6dc2c95772eaecfa8b8ec557effe689b536d865287c0b0b89ce","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"d4cbe55331c9f3e971e3c96ad773441a8106d3f5bff5e54859c8a789ab38917b","tests/ui/blanket-impl.rs":"2c9f50f15deba611a53b00285bf6c8867da15ae1527d96f7cba72fe0b23cac3a","tests/ui/blanket-impl.stderr":"726b558c91610587473cc6ada6e00f6c69fdb171c79fa1e3604efb1f2f036650","tests/ui/not-trait-impl.rs":"e99aba255dc75c498d43098c496a2b349631de74ca51b6fdcd90fc744a4fcc94","tests/ui/not-trait-impl.stderr":"56f5e23c71975bc5d9747db7444f9d385881ba8a889a5282be77479b5abdbcf6","tests/ui/not-visible.rs":"ee9c08bf412b0ce2b077ab53a2ad4c98ada104c48721b484bfe79ebb2bc36230","tests/ui/not-visible.stderr":"83812840392c4ab0f250db02fe5e778d6e33c7c180076cc8e5ee94f242d07a66"},"package":"cb659d59c4af6c9dc568b13db431174ab5fa961aa53f5aad7f42fb710c06bc46"} \ No newline at end of file
diff --git a/third_party/rust/inherent/Cargo.toml b/third_party/rust/inherent/Cargo.toml
new file mode 100644
index 0000000000..df15969a8a
--- /dev/null
+++ b/third_party/rust/inherent/Cargo.toml
@@ -0,0 +1,49 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# 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.
+#
+# 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 = "inherent"
+version = "1.0.4"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+description = "Make trait methods callable without the trait in scope"
+documentation = "https://docs.rs/inherent"
+readme = "README.md"
+categories = [
+ "rust-patterns",
+ "no-std",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/inherent"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[lib]
+proc-macro = true
+
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0.75"
+features = ["full"]
+
+[dev-dependencies.rustversion]
+version = "1.0"
+
+[dev-dependencies.trybuild]
+version = "1.0.49"
+features = ["diff"]
diff --git a/third_party/rust/inherent/LICENSE-APACHE b/third_party/rust/inherent/LICENSE-APACHE
new file mode 100644
index 0000000000..1b5ec8b78e
--- /dev/null
+++ b/third_party/rust/inherent/LICENSE-APACHE
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
diff --git a/third_party/rust/inherent/LICENSE-MIT b/third_party/rust/inherent/LICENSE-MIT
new file mode 100644
index 0000000000..31aa79387f
--- /dev/null
+++ b/third_party/rust/inherent/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/inherent/README.md b/third_party/rust/inherent/README.md
new file mode 100644
index 0000000000..8921d595ab
--- /dev/null
+++ b/third_party/rust/inherent/README.md
@@ -0,0 +1,86 @@
+\#\[inherent\]
+==============
+
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/inherent-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/inherent)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/inherent.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/inherent)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-inherent-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/inherent)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/inherent/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/inherent/actions?query=branch%3Amaster)
+
+This crate provides an attribute macro to make trait methods callable without
+the trait in scope.
+
+```toml
+[dependencies]
+inherent = "1.0"
+```
+
+## Example
+
+```rust
+mod types {
+ use inherent::inherent;
+
+ trait Trait {
+ fn f(self);
+ }
+
+ pub struct Struct;
+
+ #[inherent]
+ impl Trait for Struct {
+ pub fn f(self) {}
+ }
+}
+
+fn main() {
+ // types::Trait is not in scope, but method can be called.
+ types::Struct.f();
+}
+```
+
+Without the `inherent` macro on the trait impl, this would have failed with the
+following error:
+
+```console
+error[E0599]: no method named `f` found for type `types::Struct` in the current scope
+ --> src/main.rs:18:19
+ |
+8 | pub struct Struct;
+ | ------------------ method `f` not found for this
+...
+18 | types::Struct.f();
+ | ^
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `f`, perhaps you need to implement it:
+ candidate #1: `types::Trait`
+```
+
+The `inherent` macro expands to inherent methods on the `Self` type of the trait
+impl that forward to the trait methods. In the case above, the generated code
+would be:
+
+```rust
+impl Struct {
+ pub fn f(self) {
+ <Self as Trait>::f(self)
+ }
+}
+```
+
+<br>
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/third_party/rust/inherent/src/expand.rs b/third_party/rust/inherent/src/expand.rs
new file mode 100644
index 0000000000..1e3ce2142f
--- /dev/null
+++ b/third_party/rust/inherent/src/expand.rs
@@ -0,0 +1,128 @@
+use crate::parse::TraitImpl;
+use proc_macro2::{Span, TokenStream, TokenTree};
+use quote::{quote, quote_spanned};
+use syn::{FnArg, Ident, ImplItem, ImplItemMethod, Item, Pat, Path, Stmt, Visibility};
+
+pub fn inherent(mut input: TraitImpl) -> TokenStream {
+ let impl_token = &input.impl_token;
+ let generics = &input.generics;
+ let where_clause = &input.generics.where_clause;
+ let trait_ = &input.trait_;
+ let ty = &input.self_ty;
+
+ let fwd_methods: Vec<_> = input
+ .items
+ .iter()
+ .filter_map(|item| match item {
+ ImplItem::Method(method) => Some(fwd_method(trait_, method)),
+ _ => None,
+ })
+ .collect();
+
+ input.items = input
+ .items
+ .into_iter()
+ .filter_map(|item| match item {
+ ImplItem::Method(mut method) => {
+ if inherit_default_implementation(&method) {
+ None
+ } else {
+ method.vis = Visibility::Inherited;
+ Some(ImplItem::Method(method))
+ }
+ }
+ item => Some(item),
+ })
+ .collect();
+
+ let body = quote_spanned!(input.brace_token.span=> { #(#fwd_methods)* });
+
+ quote! {
+ #impl_token #generics #ty #where_clause #body
+
+ #input
+ }
+}
+
+fn fwd_method(trait_: &Path, method: &ImplItemMethod) -> TokenStream {
+ let attrs = &method.attrs;
+ let vis = &method.vis;
+ let constness = &method.sig.constness;
+ let asyncness = &method.sig.asyncness;
+ let unsafety = &method.sig.unsafety;
+ let abi = &method.sig.abi;
+ let fn_token = method.sig.fn_token;
+ let ident = &method.sig.ident;
+ let generics = &method.sig.generics;
+ let output = &method.sig.output;
+ let where_clause = &method.sig.generics.where_clause;
+
+ let (arg_pat, arg_val): (Vec<_>, Vec<_>) = method
+ .sig
+ .inputs
+ .pairs()
+ .enumerate()
+ .map(|(i, pair)| {
+ let (input, comma_token) = pair.into_tuple();
+ match input {
+ FnArg::Receiver(receiver) => {
+ let self_token = receiver.self_token;
+ if receiver.reference.is_some() {
+ (quote!(#receiver #comma_token), quote!(#self_token))
+ } else {
+ (quote!(#self_token #comma_token), quote!(#self_token))
+ }
+ }
+ FnArg::Typed(arg) => {
+ let var = match arg.pat.as_ref() {
+ Pat::Ident(pat) => pat.ident.clone(),
+ _ => Ident::new(&format!("__arg{}", i), Span::call_site()),
+ };
+ let colon_token = arg.colon_token;
+ let ty = &arg.ty;
+ (quote!(#var #colon_token #ty #comma_token), quote!(#var))
+ }
+ }
+ })
+ .unzip();
+
+ let types = generics.type_params().map(|param| &param.ident);
+ let body = quote!(<Self as #trait_>::#ident::<#(#types,)*>(#(#arg_val,)*));
+ let block = quote_spanned!(method.block.brace_token.span=> { #body });
+ let args = quote_spanned!(method.sig.paren_token.span=> (#(#arg_pat)*));
+
+ let has_doc = attrs.iter().any(|attr| attr.path.is_ident("doc"));
+ let default_doc = if has_doc {
+ None
+ } else {
+ let mut link = String::new();
+ for segment in &trait_.segments {
+ link += &segment.ident.to_string();
+ link += "::";
+ }
+ let msg = format!("See [`{}{}`]", link, ident);
+ Some(quote!(#[doc = #msg]))
+ };
+
+ quote! {
+ #(#attrs)*
+ #default_doc
+ #vis #constness #asyncness #unsafety #abi #fn_token #ident #generics #args #output #where_clause #block
+ }
+}
+
+fn inherit_default_implementation(method: &ImplItemMethod) -> bool {
+ method.block.stmts.len() == 1
+ && match &method.block.stmts[0] {
+ Stmt::Item(Item::Verbatim(verbatim)) => {
+ let mut iter = verbatim.clone().into_iter();
+ match iter.next() {
+ Some(TokenTree::Punct(punct)) => {
+ punct.as_char() == ';' && iter.next().is_none()
+ }
+ _ => false,
+ }
+ }
+ _ => false,
+ }
+}
diff --git a/third_party/rust/inherent/src/lib.rs b/third_party/rust/inherent/src/lib.rs
new file mode 100644
index 0000000000..a04f8f6690
--- /dev/null
+++ b/third_party/rust/inherent/src/lib.rs
@@ -0,0 +1,97 @@
+//! [![github]](https://github.com/dtolnay/inherent)&ensp;[![crates-io]](https://crates.io/crates/inherent)&ensp;[![docs-rs]](https://docs.rs/inherent)
+//!
+//! [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&logo=docs.rs
+//!
+//! <br>
+//!
+//! ##### An attribute macro to make trait methods callable without the trait in scope.
+//!
+//! # Example
+//!
+//! ```rust
+//! mod types {
+//! use inherent::inherent;
+//!
+//! trait Trait {
+//! fn f(self);
+//! }
+//!
+//! pub struct Struct;
+//!
+//! #[inherent]
+//! impl Trait for Struct {
+//! pub fn f(self) {}
+//! }
+//! }
+//!
+//! fn main() {
+//! // types::Trait is not in scope, but method can be called.
+//! types::Struct.f();
+//! }
+//! ```
+//!
+//! Without the `inherent` macro on the trait impl, this would have failed with the
+//! following error:
+//!
+//! ```console
+//! error[E0599]: no method named `f` found for type `types::Struct` in the current scope
+//! --> src/main.rs:18:19
+//! |
+//! 8 | pub struct Struct;
+//! | ------------------ method `f` not found for this
+//! ...
+//! 18 | types::Struct.f();
+//! | ^
+//! |
+//! = help: items from traits can only be used if the trait is implemented and in scope
+//! = note: the following trait defines an item `f`, perhaps you need to implement it:
+//! candidate #1: `types::Trait`
+//! ```
+//!
+//! The `inherent` macro expands to inherent methods on the `Self` type of the trait
+//! impl that forward to the trait methods. In the case above, the generated code
+//! would be:
+//!
+//! ```rust
+//! # trait Trait {
+//! # fn f(self);
+//! # }
+//! #
+//! # pub struct Struct;
+//! #
+//! # impl Trait for Struct {
+//! # fn f(self) {}
+//! # }
+//! #
+//! impl Struct {
+//! pub fn f(self) {
+//! <Self as Trait>::f(self)
+//! }
+//! }
+//! ```
+
+#![allow(
+ clippy::default_trait_access,
+ clippy::needless_doctest_main,
+ clippy::needless_pass_by_value
+)]
+
+extern crate proc_macro;
+
+mod expand;
+mod parse;
+
+use proc_macro::TokenStream;
+use syn::parse::Nothing;
+use syn::parse_macro_input;
+
+use crate::parse::TraitImpl;
+
+#[proc_macro_attribute]
+pub fn inherent(args: TokenStream, input: TokenStream) -> TokenStream {
+ parse_macro_input!(args as Nothing);
+ let input = parse_macro_input!(input as TraitImpl);
+ expand::inherent(input).into()
+}
diff --git a/third_party/rust/inherent/src/parse.rs b/third_party/rust/inherent/src/parse.rs
new file mode 100644
index 0000000000..92a91f624b
--- /dev/null
+++ b/third_party/rust/inherent/src/parse.rs
@@ -0,0 +1,69 @@
+use proc_macro2::{Span, TokenStream};
+use quote::ToTokens;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::token::Brace;
+use syn::{Attribute, Generics, ImplItem, ItemImpl, Path, Token, Type};
+
+#[derive(Clone)]
+pub struct TraitImpl {
+ pub attrs: Vec<Attribute>,
+ pub defaultness: Option<Token![default]>,
+ pub unsafety: Option<Token![unsafe]>,
+ pub impl_token: Token![impl],
+ pub generics: Generics,
+ pub trait_: Path,
+ pub for_token: Token![for],
+ pub self_ty: Type,
+ pub brace_token: Brace,
+ pub items: Vec<ImplItem>,
+}
+
+impl Parse for TraitImpl {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let imp: ItemImpl = input.parse()?;
+
+ let (trait_, for_token) = match imp.trait_ {
+ Some((_bang_token, trait_, for_token)) => (trait_, for_token),
+ None => {
+ return Err(Error::new(
+ Span::call_site(),
+ "must be placed on a trait impl",
+ ))
+ }
+ };
+
+ Ok(TraitImpl {
+ attrs: imp.attrs,
+ defaultness: imp.defaultness,
+ unsafety: imp.unsafety,
+ impl_token: imp.impl_token,
+ generics: imp.generics,
+ trait_,
+ for_token,
+ self_ty: *imp.self_ty,
+ brace_token: imp.brace_token,
+ items: imp.items,
+ })
+ }
+}
+
+impl ToTokens for TraitImpl {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let imp = self.clone();
+
+ ItemImpl::to_tokens(
+ &ItemImpl {
+ attrs: imp.attrs,
+ defaultness: imp.defaultness,
+ unsafety: imp.unsafety,
+ impl_token: imp.impl_token,
+ generics: imp.generics,
+ trait_: Some((None, imp.trait_, imp.for_token)),
+ self_ty: Box::new(imp.self_ty),
+ brace_token: imp.brace_token,
+ items: imp.items,
+ },
+ tokens,
+ );
+ }
+}
diff --git a/third_party/rust/inherent/tests/compiletest.rs b/third_party/rust/inherent/tests/compiletest.rs
new file mode 100644
index 0000000000..7974a6249e
--- /dev/null
+++ b/third_party/rust/inherent/tests/compiletest.rs
@@ -0,0 +1,7 @@
+#[rustversion::attr(not(nightly), ignore)]
+#[cfg_attr(miri, ignore)]
+#[test]
+fn ui() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/*.rs");
+}
diff --git a/third_party/rust/inherent/tests/test.rs b/third_party/rust/inherent/tests/test.rs
new file mode 100644
index 0000000000..801b1c1165
--- /dev/null
+++ b/third_party/rust/inherent/tests/test.rs
@@ -0,0 +1,25 @@
+mod types {
+ use inherent::inherent;
+
+ trait Trait {
+ fn f<T: ?Sized>(self);
+ // A default method
+ fn g(&self) {}
+ }
+
+ pub struct Struct;
+
+ #[inherent]
+ impl Trait for Struct {
+ pub fn f<T: ?Sized>(self) {}
+ pub fn g(&self);
+ }
+}
+
+#[test]
+fn test() {
+ // types::Trait is not in scope.
+ let s = types::Struct;
+ s.g();
+ s.f::<str>();
+}
diff --git a/third_party/rust/inherent/tests/ui/blanket-impl.rs b/third_party/rust/inherent/tests/ui/blanket-impl.rs
new file mode 100644
index 0000000000..d775c5e937
--- /dev/null
+++ b/third_party/rust/inherent/tests/ui/blanket-impl.rs
@@ -0,0 +1,12 @@
+use inherent::inherent;
+
+trait A {
+ fn a(&self);
+}
+
+#[inherent]
+impl<T> A for T {
+ fn a(&self) {}
+}
+
+fn main() {}
diff --git a/third_party/rust/inherent/tests/ui/blanket-impl.stderr b/third_party/rust/inherent/tests/ui/blanket-impl.stderr
new file mode 100644
index 0000000000..986641cea2
--- /dev/null
+++ b/third_party/rust/inherent/tests/ui/blanket-impl.stderr
@@ -0,0 +1,7 @@
+error[E0118]: no nominal type found for inherent implementation
+ --> tests/ui/blanket-impl.rs:8:1
+ |
+8 | impl<T> A for T {
+ | ^^^^^^^^^^^^^^^ impl requires a nominal type
+ |
+ = note: either implement a trait on it or create a newtype to wrap it instead
diff --git a/third_party/rust/inherent/tests/ui/not-trait-impl.rs b/third_party/rust/inherent/tests/ui/not-trait-impl.rs
new file mode 100644
index 0000000000..a9a6a11628
--- /dev/null
+++ b/third_party/rust/inherent/tests/ui/not-trait-impl.rs
@@ -0,0 +1,10 @@
+use inherent::inherent;
+
+struct Struct;
+
+#[inherent]
+impl Struct {
+ fn f() {}
+}
+
+fn main() {}
diff --git a/third_party/rust/inherent/tests/ui/not-trait-impl.stderr b/third_party/rust/inherent/tests/ui/not-trait-impl.stderr
new file mode 100644
index 0000000000..ea723e86b0
--- /dev/null
+++ b/third_party/rust/inherent/tests/ui/not-trait-impl.stderr
@@ -0,0 +1,7 @@
+error: must be placed on a trait impl
+ --> tests/ui/not-trait-impl.rs:5:1
+ |
+5 | #[inherent]
+ | ^^^^^^^^^^^
+ |
+ = note: this error originates in the attribute macro `inherent` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/inherent/tests/ui/not-visible.rs b/third_party/rust/inherent/tests/ui/not-visible.rs
new file mode 100644
index 0000000000..faccf90ff4
--- /dev/null
+++ b/third_party/rust/inherent/tests/ui/not-visible.rs
@@ -0,0 +1,18 @@
+mod types {
+ use inherent::inherent;
+
+ trait Trait {
+ fn f();
+ }
+
+ pub struct Struct;
+
+ #[inherent]
+ impl Trait for Struct {
+ fn f() {}
+ }
+}
+
+fn main() {
+ types::Struct::f();
+}
diff --git a/third_party/rust/inherent/tests/ui/not-visible.stderr b/third_party/rust/inherent/tests/ui/not-visible.stderr
new file mode 100644
index 0000000000..9fb9d7b892
--- /dev/null
+++ b/third_party/rust/inherent/tests/ui/not-visible.stderr
@@ -0,0 +1,8 @@
+error[E0624]: associated function `f` is private
+ --> tests/ui/not-visible.rs:17:20
+ |
+12 | fn f() {}
+ | ------ private associated function defined here
+...
+17 | types::Struct::f();
+ | ^ private associated function