Likely, the constraint comes from following config in callee/Cargo.toml:
[lib]
crate-type = ["cdylib"]
This is crucial for building target wasm. But it also make the crate not a rust lib anymore. Then it cannot be depended by other crates.
For data structures to be used by multiple canisters, it’s better to move them into a non-cdylib crate.
And let each canister crate depend on that crate.
This is indeed what you achieved with the utils crate.
Oh well, would have preferred to be able to do that, for the sake of colocating types, but as I read more, I understand this is a Rust limitation, not an IC limitation.
I also had trouble importing from a canister crate marked cdylib. After consulting with Claude I found that one can add rlib to the Cargo.toml in a canister crate like this