Helper macros: autoimpl, impl_scope

Related tags

Utilities impl-tools
Overview

Impl-tools

A set of helper macros

Macros

Autoimpl

#[autoimpl] is a variant of #[derive], supporting:

  • explicit generic parameter bounds
  • ignored fields
  • traits defined using a primary field
  • generic re-implementations for traits
use impl_tools::autoimpl;
use std::fmt::Debug;

#[autoimpl(for<'a, T: trait + ?Sized> Box<T>)]
// Generates: impl<'a, T: Animal + ?Sized> Animal for Box<T> { .. }
trait Animal {
    fn number_of_legs(&self) -> u32;
}

#[autoimpl(Debug ignore self.animal where T: Debug)]
// Generates: impl<T, A: Animal> std::fmt::Debug for Named<A> where T: Debug { .. }
#[autoimpl(Deref, DerefMut using self.animal)]
// Generates: impl<T, A: Animal> std::ops::Deref for Named<A> { .. }
// Generates: impl<T, A: Animal> std::ops::DerefMut for Named<A> { .. }
struct Named<T, A: Animal> {
    name: T,
    animal: A,
}

fn main() {
    struct Fish;
    impl Animal for Fish {
        fn number_of_legs(&self) -> u32 {
            0
        }
    }

    let my_fish = Named {
        name: "Nemo",
        animal: Box::new(Fish),
    };

    assert_eq!(
        format!("{my_fish:?} has {} legs!", my_fish.number_of_legs()),
        r#"Named { name: "Nemo", .. } has 0 legs!"#
    );
}

Impl Default

#[impl_default] implements std::default::Default:

use impl_tools::{impl_default, impl_scope};

#[impl_default(Tree::Ash)]
enum Tree { Ash, Beech, Birch, Willow }

impl_scope! {
    #[impl_default]
    struct Copse {
        tree_type: Tree,
        number: u32 = 7,
    }
}

Impl Scope

impl_scope! is a function-like macro used to define a type plus its implementations. It supports impl Self syntax:

use impl_tools::impl_scope;
use std::fmt::Display;

impl_scope! {
    /// I don't know why this exists
    pub struct NamedThing<T: Display, F> {
        name: T,
        func: F,
    }

    // Repeats generic parameters of type
    impl Self {
        fn format_name(&self) -> String {
            format!("{}", self.name)
        }
    }

    // Merges generic parameters of type
    impl<O> Self where F: Fn(&str) -> O {
        fn invoke(&self) -> O {
            (self.func)(&self.format_name())
        }
    }
}

Supported Rust Versions

The MSRV is 1.56.0 (first to support Edition 2021).

Using a nightly compiler will improve diagnostics.

Copyright and Licence

The COPYRIGHT file includes a list of contributors who claim copyright on this project. This list may be incomplete; new contributors may optionally add themselves to this list.

The impl-tools library is published under the terms of the Apache License, Version 2.0. You may obtain a copy of this licence from the LICENSE file or on the following webpage: https://www.apache.org/licenses/LICENSE-2.0

Comments
  • Auto Impl trait for `struct Newtype(Arc<dyn Trait + Send + Sync + 'static>);` etc.?

    Auto Impl trait for `struct Newtype(Arc);` etc.?

    I'm researching best approach for writing business app code like typically done in JVM languages etc. I'm not a fan of OOP, and I really dislike SpringBoot style automagic DI. However abstracting away external components behind an interface, and constructor-passing DI are really great for larger apps.

    In the past when doing trait as an interface for multiple implementations for DI, I would go for type SharedConnection = Arc<dyn Connection + Send + Sync + 'static>) kind of thing, and I'm happy to finally find a crate that can get rid of some of that boilerplate.

    However not long ago, I've read https://jmmv.dev/2022/04/rust-traits-and-dependency-injection.html#good-solution-newtype, and I think a NewType is even better, it's just I never wanted to put an effort writting out all that stuff.

    Would supporting this pattern fall under the goals of this crate?

    Going even further, I wonder if supporting things like struct Newtype(Arc<RwLock<dyn Trait + Send + Sync + 'static>>) would be possible.

    opened by dpc 15
  • Improving the error message from autoimpl when type isn't `Deref`

    Improving the error message from autoimpl when type isn't `Deref`

    I tried the following with autoimpl. Note that MyGreatType doesn't implement Deref.

    use impl_tools::autoimpl;
    
    struct MyGreatType<T: ?Sized>(Box<T>);
    
    #[autoimpl(for<T: trait + ?Sized> MyGreatType<T>)]
    trait MyGreatTrait {
        fn my_great_method(&self);
    }
    

    I got the following error:

    or[E0308]: mismatched types
     --> src/main.rs:7:25
      |
    5 | #[autoimpl(for<T: trait + ?Sized> MyGreatType<T>)]
      | --------------------------------------------------
      | |              |
      | |              this type parameter
      | arguments to this function are incorrect
    6 | trait MyGreatTrait {
    7 |     fn my_great_method(&self);
      |                         ^^^^ expected type parameter `T`, found struct `MyGreatType`
      |
      = note: expected reference `&T`
                 found reference `&MyGreatType<T>`
    note: associated function defined here
     --> src/main.rs:7:8
      |
    7 |     fn my_great_method(&self);
      |        ^^^^^^^^^^^^^^^
    

    While this is far from the worst error message you could give here, I think it could be better. For example, when rustc encounters a missing trait bound, like here:

    use std::ops::Deref;
    
    struct MyGreatType<T: ?Sized>(Box<T>);
    
    trait RequiresDeref: Deref {}
    
    impl<T> RequiresDeref for MyGreatType<T> {}
    

    It gives a super helpful error message:

    error[E0277]: the trait bound `MyGreatType<T>: Deref` is not satisfied
     --> src/main.rs:7:9
      |
    7 | impl<T> RequiresDeref for MyGreatType<T> {}
      |         ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `MyGreatType<T>`
      |
    note: required by a bound in `RequiresDeref`
     --> src/main.rs:5:22
      |
    5 | trait RequiresDeref: Deref {}
      |                      ^^^^^ required by this bound in `RequiresDeref`
    

    It'd be great if autoimpl could report something like that.

    opened by nsunderland1 4
  • autoimpl trait re-implementation should copy `cfg` attrs

    autoimpl trait re-implementation should copy `cfg` attrs

    Summary The #[cfg(..)] attr is used to conditionally compile something. If a trait item is conditional, then its re-implementation should be too.

    Are there any other attrs which should be forwarded?

    To Reproduce

    #[impl_tools::autoimpl(for<T: trait> &T)]
    trait MyTrait {
        #[cfg(feature = "foo")]
        fn do_foo(&self);
    }
    
    opened by dhardy 2
  • Support `using = self.inner` for `Debug`

    Support `using = self.inner` for `Debug`

    There are instances in the std library where a Debug implementation forwards to a single field, e.g. the impl for File. We don't currently support forwarding for Debug, but I think we could support this, e.g.:

    # use impl_tools::autoimpl;
    #[autoimpl(Debug using self.0)]
    struct Thing<T: std::fmt::Debug>(T);
    
    opened by dhardy 1
  • Prepare 0.2.0

    Prepare 0.2.0

    PR adds:

    • Attrs expanded by impl_scope now require an explicit grouping token, just like #[proc_macro_attribute]
    • impl_default now supports a where clause

    Changelog for 0.2.0:

    • Added impl_scope!
    • Added #[impl_default]
    opened by dhardy 1
  • 0.5.2: add singleton! macro

    0.5.2: add singleton! macro

    A new macro ported from kas-macros:

    use std::fmt;
    fn main() {
        let world = "world";
        let says_hello_world = impl_tools::singleton! {
            struct(&'static str = world);
            impl fmt::Display for Self {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    write!(f, "hello {}", self.0)
                }
            }
        };
        assert_eq!(format!("{}", says_hello_world), "hello world");
    }
    
    opened by dhardy 0
  • 0.5.1 - for_deref: do not copy attributes from trait items

    0.5.1 - for_deref: do not copy attributes from trait items

    Something like this:

    #[autoimpl(for<T: trait> &T)]
    trait Foo {
        /// A useless method
        fn foo();
    }
    

    previously expanded to this:

    #[automatically_derived]
    impl<T: Foo> Foo for &T {
        /// A useless method
        fn foo() {
            <T as Foo>::foo()
        }
    }
    

    The doc-comment should definitely not be copied to the impl, nor should other attributes such as #[inline].

    opened by dhardy 0
  • 0.4.1: support GATs

    0.4.1: support GATs

    Generic associated types are merged into rustc nightly, and assuming no further issues will reach stable at 1.65.0.

    This PR fixes support for GATs (and also attributes on trait consts/methods/types). This PR does not depend on nightly or 1.65.0, but adds an extra test which is only run on rustc ≥ 1.65.0.

    opened by dhardy 0
  • v0.3 part 2: Extensibility for autoimpl

    v0.3 part 2: Extensibility for autoimpl

    #[autoimpl] is revised for extensibility. Some revisions to extensibility of impl_scope!.

    README and CHANGELOG updated.

    Pending some testing, this is ready to go for v0.3.

    opened by dhardy 0
  • v0.3 is extensibilty: impl-tools-lib sub-crate

    v0.3 is extensibilty: impl-tools-lib sub-crate

    This is part 1 of 2 (part 2 will revise #[autoimpl]). Changes:

    • Move implementation to a new crate, impl-tools-lib, and revise the API slightly. This allows users to write their own versions of impl-tools to supporting whichever #[autoimpl] trait rules and impl_scope! attribute rules they choose.
    • New ScopeAttr trait as the basis for impl_scope! attribute rule plug-ins.
    • More documentation.
    opened by dhardy 0
  • Add #[impl_default]

    Add #[impl_default]

    This does not use valid Rust syntax for field initialisers, nevertheless it works within impl_scope:

    impl_scope! {
        #[impl_default]
        struct Person {
            name: String = "Jane Doe".to_string(),
            age: u32 = 72,
            occupation: String,
        }
    }
    

    TODO: some tidy up of this PR before merging.

    opened by dhardy 0
  • Support #[autoimpl] on enums?

    Support #[autoimpl] on enums?

    Currently #[autoimpl] supports three modes of operation:

    1. On structs, impl traits targetting many fields (e.g. Clone, Debug)
    2. On structs, impl traits targetting one field (e.g. Deref)
    3. On traits, impl for certain types supporting Deref to another type which supports the trait

    Each has special syntax: (1) supports ignore self.a, self.b; (2) supports using self.foo; (3) supports for<'a, T>.

    Now, derive(Clone) etc. supports enums. This has nothing to do with derive and everything to do with the impl for Clone, which uses a low level interface. #[autoimpl] uses a much higher-level interface, such that we parse the target struct/trait and confirm fields mentioned by ignore / using exist before even touching code specific to Clone, Deref etc.

    So, the question is, if we let #[autoimpl] support enums, then what syntax should be supported and what restrictions should we have?

    E.g. should we support ignoring like this?

    #[autoimpl(Debug ignore self.1)]
    enum X {
        A(i32, ()),
        B(f32, ()),
    }
    

    If so, should we require that each enum variant has a tuple form such that self.1 is valid?

    Should we support this, where fields mentioned by ignore may not apply to all variants?

    #[autoimpl(Debug ignore self.x, self.y)]
    enum E {
        A,
        B(i32),
        C { a: i8, x: () }
        D { a: u8, y: () }
    }
    

    Should we allow this?

    #[autoimpl(Deref using self.foo)]
    enum Y {
        A { foo: Foo },
        B { foo: Foo, x: f32 },
    }
    

    And thus this (custom Target syntax is supported by #26):

    #[autoimpl(Deref<Target = Foo> using self.foo)]
    enum Y {
        A { foo: A }, // require: A: Foo
        B { foo: B, x: f32 }, // require: B: Foo
    }
    
    opened by dhardy 1
Releases(0.6.2)
  • 0.6.2(Dec 16, 2022)

  • 0.6.1(Dec 1, 2022)

    • Better diagnostics for trait-redefinition: require Deref bound (#28)
    • Document Deref with custom Target type

    impl-tools-lib has breaking changes and therefore a higher version number (0.7.0):

    • Replace free function impl_generics with method Generics::impl_generics
    • Add method Generics::ty_generics

    Note: next breaking release for impl-tools should bump version to match -lib.

    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(Nov 18, 2022)

  • 0.5.2(Oct 6, 2022)

    [0.5.2] — 2022-10-06

    • Add singleton! macro (#25)
    use std::fmt;
    fn main() {
        let world = "world";
        let says_hello_world = impl_tools::singleton! {
            struct(&'static str = world);
            impl fmt::Display for Self {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    write!(f, "hello {}", self.0)
                }
            }
        };
        assert_eq!(format!("{}", says_hello_world), "hello world");
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 0.5.1(Sep 23, 2022)

  • 0.5.0(Sep 22, 2022)

    • #[autoimpl] on traits now merges trait generics with macro generics (#21)
    • lib::autoimpl::struct_items returns the trait path in addition to impl items (#22)
    • Add lib::autoimpl::ImplArgs::for_fields, for_fields_iter (#22)
    • Add autoimpl support for Copy, AsRef, AsMut, Borrow, BorrowMut, PartialEq, Eq, PartialOrd, Ord, Hash (#22)
    • Add #[automatically_derived] annotation to generated impls (#22)
    Source code(tar.gz)
    Source code(zip)
  • 0.4.4(Sep 19, 2022)

  • 0.4.3(Sep 18, 2022)

  • 0.4.2(Sep 17, 2022)

    • Correct release of 0.4.1 (which bumped the version of impl-tools without bumping impl-tools-lib) (#18)
    • Fix #[autoimpl] on traits for GATs and attributes on trait const/method/type items (#17)
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Aug 19, 2022)

  • 0.3.2(Aug 19, 2022)

  • 0.3.0(Aug 19, 2022)

    The library now supports extensibility. Most code has been moved to a new crate, impl-tools-lib. Users may replace impl-tools with their own front-end proc-macro crate, adding/removing the traits supported by #[autoimpl] and the attributes supported by impl_scope!.

    • Extensibility for impl_scope!
    • Extensibility for #[autoimpl]
    • Permit path arguments in #[autoimpl]
    • Bug-fix for #[autoimpl(Debug)] on tuple and unit structs
    • Lots of internal code revision
    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Aug 19, 2022)

  • 0.1.0(Aug 19, 2022)

Owner
null
Simple and fast git helper functions

Simple and fast git helper functions

LongYinan 126 Dec 11, 2022
A Self-Reference Helper For Rust.

Self-Reference A Self-Refernece Helper (Inspired From Selfie) this crate provides safe access to its self-reference. the main idea is not initializing

Jun Ryung Ju 6 Sep 7, 2022
Rust derive macros for automating the boring stuff.

derived: Macros for automating the boring stuff The derived crate provides macros that can simplify all the boring stuff, like writing constructors fo

Sayan 7 Oct 4, 2021
An experimental transpiler to bring tailwind macros to SWC 🚀

stailwc (speedy tailwind compiler) This is an experimental SWC transpiler to bring compile time tailwind macros to SWC (and nextjs) a-la twin macro. T

Alexander Lyon 139 Dec 20, 2022
Simple procedural macros `tnconst![...]`, `pconst![...]`, `nconst![...]` and `uconst![...]` that returns the type level integer from `typenum` crate.

typenum-consts Procedural macros that take a literal integer (or the result of an evaluation of simple mathematical expressions or an environment vari

Jim Chng 3 Mar 30, 2024
Js-macros - Quickly prototype Rust procedural macros using JavaScript or TypeScript!

js-macros Quickly prototype Rust procedural macros using JavaScript or TypeScript! Have you ever thought "this would be a great use case for a procedu

null 15 Jun 17, 2022
microtemplate - A fast, microscopic helper crate for runtime string interpolation.

microtemplate A fast, microscopic helper crate for runtime string interpolation. Design Goals Very lightweight: I want microtemplate to do exactly one

_iPhoenix_ 13 Jan 31, 2022
Windows game hack helper utilities in rust.

⚗️ toy-arms Windows game hack helper utilities in rust. This crate has some useful macros, functions and traits. ?? How to use this crate? With this c

s3pt3mb3r 100 Jan 1, 2023
Helper library for interacting with Terra assets (SDK coins and CW20 tokens)

terra-asset Helpers for interacting with Terra assets, including native coins and CW20 tokens Usage This crate contains two struct types: AssetInfo st

larry 9 Jan 3, 2022
Yay - Yet another Yogurt - An AUR Helper written in Go

Yay Yet Another Yogurt - An AUR Helper Written in Go Help translate yay: Transifex Features Advanced dependency solving PKGBUILD downloading from ABS

J Guerreiro 8.6k Jan 1, 2023
Paru is your standard pacman wrapping AUR helper with lots of features and minimal interaction.

Paru Feature packed AUR helper Description Paru is your standard pacman wrapping AUR helper with lots of features and minimal interaction. Installatio

Lulu 4k Jan 9, 2023
Simple and fast git helper functions

Simple and fast git helper functions

LongYinan 126 Dec 11, 2022
Helper functions and structs for working with 2D space in Bevy.

About Baffled by quaternions? Want to accelerate an object in 2D? Wish that there was a simple way to work with grids? Just want to know if two axis-a

Leafwing Studios 11 May 9, 2022
🐳 📦 Bringing docker containers to your AUR helper since 2022

zeus Releases | CI | Issues | Installing | Building Zeus. A simple AUR helper which utilizes docker containers allowing developers and users alike to

1337 16 Dec 17, 2022
Obvious Unified Compression Helper is a CLI tool to help you compress and decompress files of several formats

Ouch! ouch stands for Obvious Unified Compression Helper and is a CLI tool to help you compress and decompress files of several formats. Features Usag

null 734 Dec 30, 2022
Figma Agent for Linux (a.k.a. Font Helper)

Figma Agent for Linux (a.k.a. Font Helper)

Neetly 32 Dec 25, 2022
A Self-Reference Helper For Rust.

Self-Reference A Self-Refernece Helper (Inspired From Selfie) this crate provides safe access to its self-reference. the main idea is not initializing

Jun Ryung Ju 6 Sep 7, 2022
Git FIDO Helper - Sign your Git commits with multiple resident SSH keys

gfh Git FIDO helper, or God Fucking Help me. gfh is a tool for helping you sign your commits in Git with resident SSH keys stored on multiple FIDO dev

Michael Mitchell 16 Nov 30, 2022
A helper bevy plugin to handle downloading OpenStreetMap-compliant slippy tiles

Bevy Slippy Tiles A helper bevy plugin to handle downloading OpenStreetMap-compliant slippy tiles. [DownloadSlippyTilesEvent] can be fired to request

Edouard Poitras 4 Jan 25, 2023
A simple helper for spawning objects in Bevy.

Spew A simple helper for spawning objects in Bevy. Usage First, create an enum that holds objects you might want to spawn: #[derive(Debug, Eq, Partial

Jan Hohenheim 6 Mar 20, 2023