Closed mcintyre94 closed 1 year ago
Does this still allow .key()
to be used in non-seed contexts?
Oops looks like this needs a bit more work, I added this instruction:
@instruction
def hello(payer: Signer, user: User, another: Empty[Another]):
a = another.init(payer, seeds=[user.key()])
k = user.key()
print(k)
And got this error:
anchor build -p seahorse_seeds failed:
Compiling seahorse_seeds v0.1.0 (/Users/callum/scratch/seahorse_seeds/programs/seahorse_seeds)
error[E0599]: no method named `key` found for struct `seahorse_util::Mutable<LoadedUser<'info, '_>>` in the current scope
--> programs/seahorse_seeds/src/dot/program.rs:85:22
|
85 | let mut k = user.key();
| ^^^ method not found in `seahorse_util::Mutable<LoadedUser<'info, '_>>`
|
::: programs/seahorse_seeds/src/lib.rs:25:5
|
25 | pub struct Mutable<T>(Rc<RefCell<T>>);
| -------------------------------------- method `key` not found for this
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `key`, perhaps you need to implement it:
candidate #1: `anchor_lang::Key`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `seahorse_seeds` due to previous error
Marked this as draft, I'll take another look at this
Just adding some thoughts, I think the very general problem here is that the AST (in the build step) is built bottom-up. This means that expressions like [account.key()]
are completely built without any regard for the context that they're in, which might be a "normal" expression (keys = [account.key()]
) or a "special" expression (my_account.init(seeds = [account.key()], ...
).
So a full solution to this might require some real compiler rework. Maybe just pass down a context object to enable/disable certain behaviors and use that info to build up the AST?
I think it would need to be something like that, not sure exactly how that'd look though! IIRC didn't 0.1 have some special handling for seeds, where they'd be rendered specifically? I guess a generalised and more flexible version of that would be nice!
@ameliatastic I've refactored this, could you review please?
key()
from the check stage, it's just returned as the existing expression there nowaccount.borrow().__account__.key()
when used not in seeds. Other attributes (eg class fields), and key()
in a seed are just compiled as normaltests/test-cases
which is intended for stuff that's worth having tests for but doesn't make sense to put in an example. Behaves exactly the same as examples in the CI, they get compiled and there's an error if there's any mismatch. I'm keen not to limit our tests to things that can double as useful documentation, which examples was forcing us into a bit. Hey, really sorry I missed this, didn't realize you had brought this PR out of draft. Looking at it now!
The code we were generating was
user . borrow () . __account__ . key () . as_ref ()
. Butborrow()
didn't exist on the boxed accounts that we end up with in the accounts struct.Instead we can just use
user.key().as_ref()
directly.Closes #62