colin-kiegel / rust-derive-builder

derive builder implementation for rust structs
https://colin-kiegel.github.io/rust-derive-builder/
Apache License 2.0
1.28k stars 82 forks source link

Can't compile v0.10.0 in the `no_std` environment #201

Closed toku-sa-n closed 3 years ago

toku-sa-n commented 3 years ago

The following code compiles with the derive_builder crate v0.9.0:

#![no_std]

#[macro_use]
extern crate derive_builder;

extern crate alloc;

#[derive(Builder)]
#[builder(no_std)]
struct Foo {
    bar: i32,
}

However, it can't compile with v0.10.0, even without the default features, emitting the following errors:

   Compiling foo v0.1.0 (/tmp/tmp.obTGIdHacx/foo)
error[E0433]: failed to resolve: use of undeclared crate or module `std`
 --> src/lib.rs:8:10
  |
8 | #[derive(Builder)]
  |          ^^^^^^^ use of undeclared crate or module `std`
  |
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0412]: cannot find type `String` in this scope
 --> src/lib.rs:8:10
  |
8 | #[derive(Builder)]
  |          ^^^^^^^ not found in this scope
  |
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider importing this struct
  |
9 | use alloc::string::String;
  |

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0412, E0433.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `foo`

To learn more, run the command again with --verbose.

Something depends on the std crate.

TedDriggs commented 3 years ago

I believe the error is coming from the FooBuilderError generated here, which includes a String as a field in one of its enum variants.

On the crate side, there appear to be three things going on here:

  1. We shouldn't generate the ValidationError(String) variant for a builder without a user-provided validation function.
  2. We shouldn't assume that String will mean String
  3. I'm not sure we even need #[builder(no_std)] any more; we might want to deprecate it.

@toku-sa-n if you want to get rid of the compile error without waiting for 0.10.1, you should be able to set #[builder(build_fn(error = "YourOwnType"))] as shown in this example. That would bypass the generation of the problematic error enum altogether.

@andy128k is there a reason we unconditionally emit the ValidationError variant? It seems that we could gate that on the inclusion of a build_fn(validate = "...") being set.

andy128k commented 3 years ago

Fallible defaults set via #[builder(default = "self.default_field()?")] is a reason why it is hard to detect if ValidationError is even needed.

toku-sa-n commented 3 years ago

Still, this problem doesn't seem to be solved. See https://stackoverflow.com/questions/67189725/why-can-my-no-std-program-compile-even-if-it-depends-on-std-somehow. From the comment by Masklinn

here derive-builder (core) depends on darling which depends on darling_core which depends on ident_case.. which depends on std. Therefore cargo tries to pull in std.

TedDriggs commented 3 years ago

I believe I've figured out the root cause.

In 0.9.0, derive_builder was itself the proc-macro crate, and it depended on derive_builder_core which did most of the work and relied on std being present. In the move to 0.10.0, we created derive_builder_macro to be the proc-macro crate so that derive_builder could export other things (e.g. UninitializedFieldError). Our mistake was leaving a direct dependency from derive_builder to derive_builder_core.

Assuming that's correct, the fix is to move UninitializedFieldError out of derive_builder_core, so that derive_builder only depends on derive_builder_macro. Testing this locally, that does seem to work.

@toku-sa-n, I couldn't get rustup target add x86_64_unknown_uefi to work on my Mac so I tested with armv7a-none-eabi Can you please try a build using the Cargo.toml dependency line below and let me know if it works?

derive_builder = { git = "https://github.com/colin-kiegel/rust-derive-builder", branch = "no_std" }
toku-sa-n commented 3 years ago

I'm happy to say that I can build my project with the derive_builder crate on the no_std branch (and default-features = false).

TedDriggs commented 3 years ago

Excellent! I'd like to keep the test @andy128k added, but I can't figure out why it worked in CI when he published it and now causes the build to fail. I may need to temporarily remove it to get v0.10.2 live so you can stop using a branch dependency.

chanced commented 1 year ago

I'm running into this in 0.12.0

For example, https://github.com/chanced/navajo/blob/v0.0.1/navajo/src/jose/claims.rs

error[E0433]: failed to resolve: use of undeclared crate or module `std`
 --> navajo/src/jose/claims.rs:8:63
  |
8 | #[derive(Debug, PartialEq, Eq, Serialize, Clone, Deserialize, Builder, Default)]
  |                                                               ^^^^^^^ use of undeclared crate or module `std`
  |
  = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info)
#[derive(Debug, PartialEq, Eq, Serialize, Clone, Deserialize, Builder, Default)]
pub struct Claims {
    /// The "iss" (issuer) claim identifies the principal that issued the
    /// JWT.  The processing of this claim is generally application specific.
    /// The `"iss"` value is a case-sensitive string containing a StringOrURI
    /// value.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// <https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1>
    #[serde(rename = "iss", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub issuer: Option<String>,

    /// The `"sub"` (subject) claim identifies the principal that is the
    /// subject of the JWT. The claims in a JWT are normally statements
    /// about the subject. The subject value MUST either be scoped to be
    /// locally unique in the context of the issuer or be globally unique.
    /// The processing of this claim is generally application specific. The
    /// `"sub"` value is a case-sensitive string containing a StringOrURI
    /// value.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// <https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2>
    #[serde(rename = "sub", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub subject: Option<String>,

    /// The `"aud"` (audience) claim identifies the recipients that the JWT is
    /// intended for. Each principal intended to process the JWT MUST
    /// identify itself with a value in the audience claim. If the principal
    /// processing the claim does not identify itself with a value in the
    /// "aud" claim when this claim is present, then the JWT MUST be
    /// rejected. In the general case, the `"aud"` value is an array of case-
    /// sensitive strings, each containing a StringOrURI value.  In the
    /// special case when the JWT has one audience, the `"aud"` value MAY be a
    /// single case-sensitive string containing a StringOrURI value.  The
    /// interpretation of audience values is generally application specific.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// <https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3
    #[serde(rename = "aud", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub audience: Option<StringOrStrings>,

    /// The `"exp"` (expiration time) claim identifies the expiration time on
    /// or after which the JWT MUST NOT be accepted for processing. The
    /// processing of the `"exp"` claim requires that the current date/time
    /// MUST be before the expiration date/time listed in the `"exp"` claim.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4
    #[serde(rename = "exp", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub expiration_time: Option<NumericDate>,

    /// The `"nbf"` (not before) claim identifies the time before which the JWT
    /// MUST NOT be accepted for processing.  The processing of the `"nbf"`
    /// claim requires that the current date/time MUST be after or equal to
    /// the not-before date/time listed in the `"nbf"` claim.  Implementers MAY
    /// provide for some small leeway, usually no more than a few minutes, to
    /// account for clock skew.  Its value MUST be a number containing a
    /// NumericDate value.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// <https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5>
    #[serde(rename = "nbf", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub not_before: Option<NumericDate>,

    /// The `"iat"` (issued at) claim identifies the time at which the JWT was
    /// issued. This claim can be used to determine the age of the JWT.  Its
    /// value MUST be a number containing a NumericDate value.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// <https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6>
    #[serde(rename = "iat", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub issued_at: Option<NumericDate>,

    /// The `"jti"` (JWT ID) claim provides a unique identifier for the JWT.
    /// The identifier value MUST be assigned in a manner that ensures that
    /// there is a negligible probability that the same value will be
    /// accidentally assigned to a different data object; if the application
    /// uses multiple issuers, collisions MUST be prevented among values
    /// produced by different issuers as well.  The "jti" claim can be used
    /// to prevent the JWT from being replayed.  The "jti" value is a case-
    /// sensitive string.
    ///
    /// Use of this claim is OPTIONAL.
    ///
    /// <https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7>
    #[serde(rename = "jti", skip_serializing_if = "Option::is_none")]
    #[builder(default, setter(into, strip_option))]
    pub jwt_id: Option<String>,

    #[serde(flatten)]
    #[builder(default, try_setter, setter)]
    pub additional_claims: serde_json::Map<String, Value>,
}
chanced commented 1 year ago

Would it be better if I created a new issue rather than resurrecting this one?

I can't expand the macro:

 cargo expand -p navajo jose::Claims
    Checking navajo v0.0.1 (/Users/chance/dev/navajo/navajo)
error[E0433]: failed to resolve: use of undeclared crate or module `std`
 --> navajo/src/jose/claims.rs:8:63
  |
8 | #[derive(Debug, PartialEq, Eq, Serialize, Clone, Deserialize, Builder, Default)]
  |                                                               ^^^^^^^ use of undeclared crate or module `std`
  |
  = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0433]: failed to resolve: use of undeclared crate or module `std`
  --> navajo/src/jose/validator.rs:12:24
   |
12 | #[derive(Debug, Clone, Builder)]
   |                        ^^^^^^^ use of undeclared crate or module `std`
   |
   = note: this error originates in the derive macro `Builder` (in Nightly builds, run with -Z macro-backtrace for more info)
TedDriggs commented 1 year ago

Would it be better if I created a new issue rather than resurrecting this one?

Yes.

TedDriggs commented 1 year ago

A new issue would be better.


From: Chance @.> Sent: Wednesday, April 5, 2023 8:09:18 AM To: colin-kiegel/rust-derive-builder @.> Cc: Ted Driggs @.>; State change @.> Subject: Re: [colin-kiegel/rust-derive-builder] Can't compile v0.10.0 in the no_std environment (#201)

Would it be better if I created a new issue rather than resurrecting this one?

I can't expand the macro:

cargo expand -p navajo jose::Claims Checking navajo v0.0.1 (/Users/chance/dev/navajo/navajo) error[E0433]: failed to resolve: use of undeclared crate or module std --> navajo/src/jose/claims.rs:8:63 8 #[derive(Debug, PartialEq, Eq, Serialize, Clone, Deserialize, Builder, Default)] ^^^^^^^ use of undeclared crate or module std
= note: this error originates in the derive macro Builder (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module std --> navajo/src/jose/validator.rs:12:24 12 #[derive(Debug, Clone, Builder)] ^^^^^^^ use of undeclared crate or module std

= note: this error originates in the derive macro Builder (in Nightly builds, run with -Z macro-backtrace for more info)

— Reply to this email directly, view it on GitHubhttps://github.com/colin-kiegel/rust-derive-builder/issues/201#issuecomment-1497653004, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ABEVHRYXRVCXMQ5GGD5JRQLW7WDJ5ANCNFSM42GUWEZQ. You are receiving this because you modified the open/close state.Message ID: @.***>

chanced commented 1 year ago

A new issue would be better.

285