Motoko - Multiple Canister Imports - Compile Error

I am running into an issue with the Motoko compiler (dfx 0.8.4) when importing two canisters and calling functions on each.

Canister A imports canisters B and C.

import B "canister:B”;
import C "canister:C”;

When calling a function of B, the compiler incorrectly expects a different return type that only exists in a function of C.

When inspecting B.did and C.did, the return type of the function I am calling in B has the same autogenerated type name (Result_2) as the return type in C that the compiler is expecting.

B.did

type Result_2 = 
 variant {
   err: text;
   ok: text;
 };

C.did

type Result_2 = 
 variant {
   err: text;
   ok: opt vec SomeType;
 };

Error:

Stderr:
/src/Post/main.mo:196.59-196.146: type error [M0096], expression of type
  Result_2 = {#err : Text; #ok : ?[SomeType]}
cannot produce expected type
  {#err : Text; #ok : Text}

So, with multiple canister imports, it appears that the compiler is expecting the incorrect return types of functions when they have the same autogenerate type names in the did files.

I should also mention that I started using Text as the error type because I ran into the same issue with multiple variant types for defining errors.

This is currently a roadblock and the only solution I know of is to remove one of the canister imports. If anyone knows of another solution, please advise me. Thank you!

1 Like

After writing this, I realized that the autogenerated type name is causing the collision with the compiler, so I tried creating a custom type for the function return types to remove the naming collision, and that worked!

Example:

type MyCustomResult = Result.Result<Text, Text>;

public func SomeFunction() : async MyCustomResult {...}

The did file now uses the custom type name instead of the autogenerated name:

type MyCustomResult = 
 variant {
   err: text;
   ok: text;
 };

So, the compiler is running into type naming collisions across multiple canisters due to the autogenerated type names in the did files. By defining custom types for function results, these naming collisions can be avoided.

4 Likes

This might be interesting for @chenyan

1 Like

Thanks for the report. There is no namespace in candid imports, which will certainly cause problems with multiple imports. I will file a bug: https://github.com/dfinity/motoko/issues/3103.

The current workaround is indeed to write custom type definitions to avoid the collision. A slightly more automatic approach is to use didc to generate the type bindings with didc bind a.did -t mo. Then you can import A "./a"; import B "./b" in Motoko and use A.Result_2 and B.Result_2 to avoid name collisions.

3 Likes