What version are you using?
main with experimental_spec_shaking_v2.
What did you do?
Enabled experimental_spec_shaking_v2 and used export = false on a spec-bearing type:
#[cfg(feature = "experimental_spec_shaking_v2")]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[contracttype(export = false)]
pub struct Hidden {
pub x: u32,
}
The same problem can occur indirectly when a workspace enables soroban-sdk/experimental_spec_shaking_v2 and also builds helper crates such as soroban-token-spec or stellar-asset-spec that contain #[contractevent(..., export = false)].
What did you expect to see?
Spec shaking v2 should derive the final contract spec from reachable contract functions, events, errors, and referenced types. A type reachable from the contract boundary should either participate in shaking or produce a clear diagnostic if the annotation is unsupported.
What did you see instead?
export = false suppresses spec emission, so v2 marker generation is skipped for that type and reachable boundary types can fail trait-bound checks at compile time. export = true is also misleading under v2 because post-build shaking can still remove entries that are not reachable. Helper spec crates with export = false can fail to compile when the SDK macro dependency is unified with the v2 feature.
Alternatives
If we still see a need to allow developers to insert entries into the contractspecv0, we could add a flag or attribute that emits a keep-alive marker regardless of if the spec is reachable. Keeping export as the flag to use would mean we still need to error when export = false, or document that this is not recommended behavior and could result in incorrect specs.
What version are you using?
mainwithexperimental_spec_shaking_v2.What did you do?
Enabled
experimental_spec_shaking_v2and usedexport = falseon a spec-bearing type:The same problem can occur indirectly when a workspace enables
soroban-sdk/experimental_spec_shaking_v2and also builds helper crates such assoroban-token-specorstellar-asset-specthat contain#[contractevent(..., export = false)].What did you expect to see?
Spec shaking v2 should derive the final contract spec from reachable contract functions, events, errors, and referenced types. A type reachable from the contract boundary should either participate in shaking or produce a clear diagnostic if the annotation is unsupported.
What did you see instead?
export = falsesuppresses spec emission, so v2 marker generation is skipped for that type and reachable boundary types can fail trait-bound checks at compile time.export = trueis also misleading under v2 because post-build shaking can still remove entries that are not reachable. Helper spec crates withexport = falsecan fail to compile when the SDK macro dependency is unified with the v2 feature.Alternatives
If we still see a need to allow developers to insert entries into the
contractspecv0, we could add a flag or attribute that emits a keep-alive marker regardless of if the spec is reachable. Keepingexportas the flag to use would mean we still need to error whenexport = false, or document that this is not recommended behavior and could result in incorrect specs.