Skip to content

hiver-aop README/API example does not compile from downstream crates #60

@zjarlin

Description

@zjarlin

Summary

hiver-aop 0.1.0-alpha.6 cannot be used from a downstream crate with the current README/API shape.

I found three separate problems while trying to compile the documented example:

  1. The README imports and uses Aspect, Before, After, and Around, but the proc-macro crate exports lowercase attribute macros: aspect, before, after, and around.
  2. Runtime types such as JoinPoint are not available to downstream crates because this is a proc-macro = true crate, and the runtime re-export is gated out.
  3. Even after switching to the lowercase macro names, applying #[before], #[after], or #[around] to methods inside an impl block fails because the macro expansion generates an invalid impl for a function name.

There is also a documentation/model mismatch: the pointcut examples use Java/Spring package patterns such as com.example..*.*(..). That may be familiar for AspectJ users, but Rust users need either Rust path semantics (crate::service::..., module paths, attributes, traits, etc.) or clear documentation explaining what those strings actually match in Rust.

Version

hiver-aop = 0.1.0-alpha.6
rustc 1.95.0 (59807616e 2026-04-14)
cargo 1.95.0 (f2d3ce0bd 2026-03-21)

cargo info hiver-aop reports:

version: 0.1.0-alpha.6
rust-version: 1.87
repository: https://github.com/ViewWay/hiver

Reproduction 1: README example does not compile

cargo new --bin hiver-aop-readme-smoke
cd hiver-aop-readme-smoke
cargo add hiver-aop

Use the README-style code:

use hiver_aop::{After, Around, Aspect, Before};

#[Aspect]
struct LoggingAspect;

impl LoggingAspect {
    #[Before("execution(* com.example..*.*(..))")]
    fn log_before(&self, join_point: &JoinPoint) {
        println!("Entering: {}", join_point.method_name());
    }
}

fn main() {}

Then run:

cargo check

Actual result:

error[E0432]: unresolved imports `hiver_aop::After`, `hiver_aop::Around`, `hiver_aop::Aspect`, `hiver_aop::Before`
  |
  | use hiver_aop::{After, Around, Aspect, Before};
  |                 ^^^^^  ^^^^^^  ^^^^^^  ^^^^^^ no `Before` in the root

Reproduction 2: lowercase macro names still fail

cargo new --bin hiver-aop-real-smoke
cd hiver-aop-real-smoke
cargo add hiver-aop anyhow

Use the actually exported macro names:

use hiver_aop::{after, around, aspect, before};

#[aspect]
struct LoggingAspect;

impl LoggingAspect {
    #[before("execution(* crate::service::*::*(..))")]
    fn log_before(&self, join_point: &hiver_aop::JoinPoint) {
        println!("Entering: {}", join_point.method_name());
    }

    #[after("execution(* crate::service::*::*(..))")]
    fn log_after(&self, join_point: &hiver_aop::JoinPoint) {
        println!("Exiting: {}", join_point.method_name());
    }

    #[around("execution(* crate::service::*::*(..))")]
    fn log_around(&self, join_point: hiver_aop::JoinPoint) -> Result<(), anyhow::Error> {
        println!("Before: {}", join_point.method_name());
        let result = join_point.proceed()?;
        println!("After: {}", join_point.method_name());
        Ok(result)
    }
}

fn main() {}

Then run:

cargo check

Actual result:

error: implementation is not supported in `trait`s or `impl`s
 --> src/main.rs:7:5
  |
7 |     #[before("execution(* crate::service::*::*(..))")]
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in the attribute macro `before`

And the runtime type is not exported:

error[E0425]: cannot find type `JoinPoint` in crate `hiver_aop`
  |
  |     fn log_before(&self, join_point: &hiver_aop::JoinPoint) {
  |                                                  ^^^^^^^^^ not found in `hiver_aop`
  |
note: found an item that was configured out
  |
  | #[cfg(not(proc_macro))]
  |          ------------ the item is gated here

Suspected cause

In hiver-aop/src/lib.rs, the crate is a proc-macro crate and the runtime re-export is gated:

#[cfg(not(proc_macro))]
pub use runtime::{
    AdviceChain, AdviceType, AspectRegistry, JoinPoint, PointcutExpression, ProceedingJoinPoint,
    global_registry,
};

That means downstream crates cannot import hiver_aop::JoinPoint.

The advice macro implementation also appears to generate invalid Rust. For example, before parses the annotated item as ItemFn, then expands to something shaped like this:

fn log_before(...) { ... }

impl log_before {
    const POINTCUT: &str = "...";
}

log_before is a function item, not a type, so this cannot compile. When the attribute is used inside an impl block, the generated nested impl also triggers:

implementation is not supported in `trait`s or `impl`s

Expected behavior

One of these should be true:

  • The README example compiles as written, including exported macro names and runtime types; or
  • The README is updated to the real Rust API shape, with a working downstream compile test; and
  • Runtime types are moved to a normal library crate such as hiver-aop-runtime, while the proc macros live in a separate macro crate; and
  • Pointcut documentation explains how Rust paths/modules/attributes/traits are matched, instead of only showing Java/Spring com.example package patterns.

Extra verification

Running the crate's own tests compiles:

cargo check --manifest-path ~/.cargo/registry/src/index.crates.io-*/hiver-aop-0.1.0-alpha.6/Cargo.toml --tests

But those tests do not appear to cover the downstream README usage, so this issue is only visible from a real consumer crate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions