summaryrefslogtreecommitdiffstats
path: root/third_party/rust/inherent/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/inherent/src
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/inherent/src')
-rw-r--r--third_party/rust/inherent/src/expand.rs138
-rw-r--r--third_party/rust/inherent/src/lib.rs100
-rw-r--r--third_party/rust/inherent/src/parse.rs69
-rw-r--r--third_party/rust/inherent/src/verbatim.rs34
4 files changed, 341 insertions, 0 deletions
diff --git a/third_party/rust/inherent/src/expand.rs b/third_party/rust/inherent/src/expand.rs
new file mode 100644
index 0000000000..c840123dee
--- /dev/null
+++ b/third_party/rust/inherent/src/expand.rs
@@ -0,0 +1,138 @@
+use crate::parse::TraitImpl;
+use crate::verbatim::VerbatimFn;
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, quote_spanned};
+use syn::{Attribute, FnArg, Ident, ImplItem, Pat, Path, Signature, 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::Fn(method) => Some(fwd_method(
+ trait_,
+ &method.attrs,
+ &method.vis,
+ &method.sig,
+ method.block.brace_token.span.join(),
+ )),
+ ImplItem::Verbatim(tokens) => {
+ if let Ok(method) = syn::parse2::<VerbatimFn>(tokens.clone()) {
+ Some(fwd_method(
+ trait_,
+ &method.attrs,
+ &method.vis,
+ &method.sig,
+ method.semi_token.span,
+ ))
+ } else {
+ None
+ }
+ }
+ _ => None,
+ })
+ .collect();
+
+ input.items = input
+ .items
+ .into_iter()
+ .filter_map(|item| match item {
+ ImplItem::Fn(mut method) => {
+ method.vis = Visibility::Inherited;
+ Some(ImplItem::Fn(method))
+ }
+ ImplItem::Verbatim(tokens) => {
+ if syn::parse2::<VerbatimFn>(tokens.clone()).is_ok() {
+ None
+ } else {
+ Some(ImplItem::Verbatim(tokens))
+ }
+ }
+ 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,
+ attrs: &[Attribute],
+ vis: &Visibility,
+ sig: &Signature,
+ body_span: Span,
+) -> TokenStream {
+ let constness = &sig.constness;
+ let asyncness = &sig.asyncness;
+ let unsafety = &sig.unsafety;
+ let abi = &sig.abi;
+ let fn_token = sig.fn_token;
+ let ident = &sig.ident;
+ let generics = &sig.generics;
+ let output = &sig.output;
+ let where_clause = &sig.generics.where_clause;
+
+ let (arg_pat, arg_val): (Vec<_>, Vec<_>) = 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!(body_span=> { #body });
+ let args = quote_spanned!(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
+ }
+}
diff --git a/third_party/rust/inherent/src/lib.rs b/third_party/rust/inherent/src/lib.rs
new file mode 100644
index 0000000000..4a334666f7
--- /dev/null
+++ b/third_party/rust/inherent/src/lib.rs
@@ -0,0 +1,100 @@
+//! [![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)
+//! }
+//! }
+//! ```
+
+#![doc(html_root_url = "https://docs.rs/inherent/1.0.7")]
+#![allow(
+ clippy::default_trait_access,
+ clippy::module_name_repetitions,
+ clippy::needless_doctest_main,
+ clippy::needless_pass_by_value
+)]
+
+extern crate proc_macro;
+
+mod expand;
+mod parse;
+mod verbatim;
+
+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/src/verbatim.rs b/third_party/rust/inherent/src/verbatim.rs
new file mode 100644
index 0000000000..d064f6ee1f
--- /dev/null
+++ b/third_party/rust/inherent/src/verbatim.rs
@@ -0,0 +1,34 @@
+use proc_macro2::TokenStream;
+use quote::{ToTokens, TokenStreamExt};
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{Attribute, Signature, Token, Visibility};
+
+pub struct VerbatimFn {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: Option<Token![default]>,
+ pub sig: Signature,
+ pub semi_token: Token![;],
+}
+
+impl Parse for VerbatimFn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(VerbatimFn {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ defaultness: input.parse()?,
+ sig: input.parse()?,
+ semi_token: input.parse()?,
+ })
+ }
+}
+
+impl ToTokens for VerbatimFn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(&self.attrs);
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ self.sig.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+}