idanarye / rust-typed-builder

Compile-time type-checked builder derive

Home Page:https://crates.io/crates/typed-builder

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Undocumented breaking Change in v0.15?

Overdash opened this issue · comments

commented

Been using this library for a while.

Tried to bump my code to the latest version 0.15 and started getting compilation errors (without any other changes):

error[E0433]: failed to resolve: could not find `typed_builder` in the list of imported crates
  --> my_project/file.rs
   |
11 | #[derive(sqlx::FromRow, Serialize, Deserialize, TypedBuilder, Debug)]
   |                                                 ^^^^^^^^^^^^ could not find `typed_builder` in the list of imported crates
   |
   = note: this error originates in the derive macro `TypedBuilder` (in Nightly builds, run with -Z macro-backtrace for more info)

Reverting to version 0.14.0 works fine without any tweaks, leading me to believe there's an undocumented change in the CHANGELOG

commented

I can not reproduce it :/

Can you please delete the /target directory and try to compile again?

Can you please show the whole struct with its field attributes?

Did you rename the crate in Cargo.toml?

commented

Can you please delete the /target directory and try to compile again?

Yes, I tried this - it's also failing in the same way in my GH Actions. Tried to search through cargo tree to check for any version conflicts, saw none.

Can you please show the whole struct with its field attributes?

#[derive(sqlx::FromRow, Serialize, Deserialize, TypedBuilder, Debug)]
pub struct Account {
    #[builder(default = Uuid::new_v4())]
    pub account_id: Uuid,
    pub phone_number: String,
    pub full_name: String,
    #[serde(skip_serializing)]
    pub security_pin: String,
    pub country_code: String,
    #[builder(default)]
    pub email: Option<String>,
    #[builder(default = AccountType::Unverified)]
    pub account_type: AccountType,
    #[builder(default, setter(strip_option))]
    pub account_state: Option<EntityState>,
    #[builder(default = Utc::now())]
    created_at: DateTime<Utc>,
}

Also, no, I did not rename the crate :/ @idanarye

I won't ask you for the full source, but can I at least see your Cargo.toml?

I tried replicating it with:

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use typed_builder::TypedBuilder;
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize)]
pub enum AccountType {
    Unverified,
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct EntityState;

#[derive(sqlx::FromRow, Serialize, Deserialize, TypedBuilder, Debug)]
pub struct Account {
    #[builder(default = Uuid::new_v4())]
    pub account_id: Uuid,
    pub phone_number: String,
    pub full_name: String,
    #[serde(skip_serializing)]
    pub security_pin: String,
    pub country_code: String,
    #[builder(default)]
    pub email: Option<String>,
    #[builder(default = AccountType::Unverified)]
    pub account_type: AccountType,
    #[builder(default, setter(strip_option))]
    pub account_state: Option<EntityState>,
    #[builder(default = Utc::now())]
    created_at: DateTime<Utc>,
}

fn main() {}

With this Cargo.toml:

[package]
name = "app"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
chrono = { version = "0.4.26", features = ["serde"] }
serde = "1.0.167"
sqlx = "0.7.0"
typed-builder = "0.15.0"
uuid = { version = "1.4.0", features = ["v4", "serde"] }

And was able to build it just fine.

commented

Hmm this is odd. I'm running a Monorepo so I have multiple Cargo.toml - one at the root as a workspace. But typed-builder is only exposed in 1 of the submodules:

[package]
name = "toolbox"
version = "0.1.0"
edition = "2021"

[lib]
path = "src/lib.rs"
doctest = false

[dependencies]
# General Utils
chrono = { version = "0", features = ["serde"] }
strum = { version = "0", features = ["derive"] }
typed-builder = { version = "0.14" }
uuid = { version = "1", features = ["v4", "serde"] }

(Omitted other dependencies for brevity).
This toolbox library exposes typed-builder:
pub use typed_builder;

and is then used by another sub-crate which actually invokes the TypedBuilder macro:
use toolbox::typed_builder::TypedBuilder;

It's possible the issue is the almost roundabout way I'm importing TypedBuilder, but this worked in 0.14.0 so I'm unsure what changed 🤔

(I will clear all my caches later and close this issue if that fixed it)

The thing that changed is that this crate was split into two - a procmacro crate and a regular crate that reexports the procmacro and also adds some types (that the procmacro uses). The procmacro expects the regular crate to exist as a simple typed_builder.

This is a weakness of procmacros, which I'm not sure there is a way around...

commented

Ah I see. So it's only really breaking this particular use-case.

This is a weakness of procmacros, which I'm not sure there is a way around...

Yeah unfortunately there's no work around that. Other proc-macro rich packages have a similar weakness (e.g. SQLx)

If anyone else experiences this issue: you'll have to add the typed-builder crate as a dependency in any sub-crate that's using it to fix this.

I'll close this issue. This is a weird edge-case, so I doubt you'd want to add it to the CHANGELOG (?)

Adding an entry to the CHANGELOG may not be such a bad idea. Yes, this is a common pitfall, but since it previous versions of Typed Builder did not suffer from it it may confuse people who upgrade (like it confused you)

Because it really is that common, I'm not going to add it to the README or the to the docs, so I don't even need to release a new version.