Get Actor (not class) canister principal in non-async context

How do I allow for a self reference to an actor to get its principal when not directly in an async/shared method
The example below is run through an http router and eventually is called, but the compiler gives me an error definedness error [M0016], cannot use Actor before Actor has been defined
but is fine if that Actor is referenced in the http_request/_update
@claudio @ggreif

Even if i switch it to an actor class and use this, it gives me the error definedness error [M0016], cannot use get before this has been defined on the |> _.getAsync("/hash", getCanisterHashAsync)

actor Actor {
    private func get(_ : Route.RouteContext) : async* Route.RouteResult {
        let ic = actor ("aaaaa-aa") : IC;
        let result = await ic.canister_info({
            canister_id = Principal.fromActor(Actor); // error - definedness error [M0016], cannot use Actor before Actor has been defined
            num_requested_changes = ?0;
        });
       ...
    };

    let pipeline = HttpPipeline.empty()
    // Router
    |> HttpRouter.use(
        _,
        HttpRouter.RouterBuilder()
        |> _.getAsync("/hash", get)
        |> _.build(),
    )
    |> HttpPipeline.build(_);

    public query func http_request(request : Http.RawQueryHttpRequest) : async Http.RawQueryHttpResponse {
        pipeline.http_request(request);
    };

    public func http_request_update(req : Http.RawUpdateHttpRequest) : async Http.RawUpdateHttpResponse {
        await* pipeline.http_request_update(req);
    };

};
2 Likes

I stripped it down to

import Principal "mo:base/Principal";

actor Actor {
    let canister_id = Principal.fromActor(Actor);

    private func get(_ : Int) : async* () {
        let result = {
            canister_id;
            num_requested_changes = ?0;
        };
    };
};

Which moc do you use? It works in the Playground.

1 Like

im using dfx v0.24.3

1 Like

When i copy/paste this in instead of mine I still get the erro

Stderr:
/home/gekctek/git/motoko_http/examples/basic/main.mo:138.18-138.21: warning [M0194], unused identifier get (delete or rename to wildcard `_` or `_get`)
/home/gekctek/git/motoko_http/examples/basic/main.mo:139.13-139.19: warning [M0194], unused identifier result (delete or rename to wildcard `_` or `_result`)
/home/gekctek/git/motoko_http/examples/basic/main.mo:135.1-144.2: definedness error [M0016], cannot use Actor before Actor has been defined
2 Likes

That is moc 0.13.4 IIRC. So the above is available since 0.13.2. You can do that workaround too. But upon reflecting, there might be a bug still lurking, as your code is morally fine. Can you strip it down and file an issue? Then we’ll look into it.

2 Likes

What does $(dfx cache show)/moc --version say? (You might want do dfx cache install beforehand…)

1 Like

❯ $(dfx cache show)/moc --version
Motoko compiler 0.13.4 (source cphia92h-ww0hpm9k-jlgzh3ln-3mnqdwxq)

1 Like

So, im not sure whats going on here, but i commented out the mops dependencies one by one and when i comment out the dev dependency test it compiles just fine

[package]
name = "http"
version = "0.0.1"
description = "A collection of HTTP tools to make http requests easy to use"
repository = "https://github.com/edjcase/motoko_http"
keywords = ["http", "router", "parser", "middleware", "web", "pipeline"]
license = "MIT"

[dependencies]
base = "0.14.0"
itertools = "0.2.2"
json = "1.0.0"
xtended-text = "1.0.0"
xtended-numbers = "0.3.1"
glob = "0.0.1"

[dev-dependencies]
# test = "2.0.0"

@ZenVoich any thoughts on why this would be a thing?

1 Like

That would be weird. I did

$ dfxvm default 0.24.3
info: using existing install for dfx 0.24.3
info: set default version to dfx 0.24.3

$(dfx cache show)/moc --version
Motoko compiler 0.13.4 (source dbxci4cq-zk2bhl2g-gxc564v5-ilxpj21z)

$ cat test.mo
import Principal "mo:base/Principal";

actor Actor {
    let canister_id = Principal.fromActor(Actor);

    private func get(_ : Int) : async* () {
        let result = {
            canister_id;
            num_requested_changes = ?0;
        };
    };
};

$(dfx cache show)/moc -c test.mo --package base $(dfx cache show)/base
test.mo:6.18-6.21: warning [M0194], unused identifier get (delete or rename to wildcard `_` or `_get`)
test.mo:7.13-7.19: warning [M0194], unused identifier result (delete or rename to wildcard `_` or `_result`)

… and it compiles!

1 Like

I bet it is a moc-wrapper-related issue. Please check echo $DFX_MOC_PATH.

1 Like

There it is
When I comment out test = "2.0.0" I get 0.13.4
When i uncomment test = "2.0.0" I get 0.12.1

3 Likes

Updating MOPS to the latest version fixed the issue

@ZenVoich What does mops do?
Is it if there are any dev-dependencies something changes?

1 Like

Mops caches resolved moc path to .mops/moc-<os>-<mops.tom-hash> file to reduce overhead reading config and detecting required moc version. So I suppose you updated dfx, but mops do not know that cache must be invalidated, and when you removed test mops computed a new cache file because <mops.tom-hash> changed.

I’ll consider including the dfx version in the cache file name.

For now you can just remove .mops folder or .mops/moc-* files.

Or you can specify moc version in [toolchain] section:

[toolchain]
moc = '0.13.4'
2 Likes