Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify in error messages, where exactly two Actor objects differ #4571

Open
vporton opened this issue Jun 11, 2024 · 1 comment
Open

Specify in error messages, where exactly two Actor objects differ #4571

vporton opened this issue Jun 11, 2024 · 1 comment

Comments

@vporton
Copy link

vporton commented Jun 11, 2024

It is very inconvenient, when I receive a long message of two Actor classes differing. I want the message to show where (which methods with their signatures) is the point(s) of difference.

I adopted to copy the error message, extract from it two Actor classes manually and compare them with wdiff command to find what's wrong. But that's inconvenient.

cannot implicitly instantiate function of type
  <K, V>(Tree<K, V>, (K, K) -> Order, K) -> ?V
to argument of type
  ({
     #leaf;
     #node :
       (Color, Tree<(Partition__1, OuterSubDBKey), GUID__2>,
        ((Partition__1, OuterSubDBKey), ?GUID__2),
        Tree<(Partition__1, OuterSubDBKey), GUID__2>)
   },
   ((Partition__1, OuterSubDBKey), (Partition__1, OuterSubDBKey)) ->
     {#equal; #greater; #less},
   (actor {
      createOuter :
        shared {
                 innerKey : InnerSubDBKey;
                 outerKey : OuterSubDBKey;
                 part : Principal
               } ->
          async
            {
              inner : {canister : Principal; key : InnerSubDBKey};
              outer : {canister : Principal; key : OuterSubDBKey}
            };
      deleteInner : shared {innerKey : InnerSubDBKey; sk : SK} -> async ();
      deleteSubDBInner : shared {innerKey : InnerSubDBKey} -> async ();
      deleteSubDBOuter : shared {outerKey : OuterSubDBKey} -> async ();
      getByInner :
        shared query {innerKey : InnerSubDBKey; sk : SK} ->
          async ?AttributeValue;
      getByOuter :
        shared {outerKey : OuterSubDBKey; sk : SK} -> async ?AttributeValue;
      getInner :
        shared query {outerKey : OuterSubDBKey} ->
          async ?{canister : Principal; key : InnerSubDBKey};
      getSubDBUserDataInner :
        shared {innerKey : InnerSubDBKey} -> async ?Text;
      getSubDBUserDataOuter :
        shared {outerKey : OuterSubDBKey} -> async ?Text;
      hasByInner :
        shared query {innerKey : InnerSubDBKey; sk : SK} -> async Bool;
      hasByOuter : shared {outerKey : OuterSubDBKey; sk : SK} -> async Bool;
      hasSubDBByInner : shared query {innerKey : InnerSubDBKey} -> async Bool;
      hasSubDBByOuter : shared {outerKey : OuterSubDBKey} -> async Bool;
      isOverflowed : shared query () -> async Bool;
      putLocation :
        shared {
                 innerCanister : Principal;
                 innerKey : InnerSubDBKey;
                 outerKey : OuterSubDBKey
               } ->
          async ();
      rawDeleteSubDB : shared {innerKey : InnerSubDBKey} -> async ();
      rawGetSubDB :
        shared query {innerKey : InnerSubDBKey} ->
          async ?{map : [(SK, AttributeValue)]; userData : Text};
      rawInsertSubDB :
        shared {
                 hardCap : ?Nat;
                 innerKey : ?InnerSubDBKey;
                 map : [(SK, AttributeValue)];
                 userData : Text
               } ->
          async {innerKey : InnerSubDBKey};
      rawInsertSubDBAndSetOuter :
        shared {
                 hardCap : ?Nat;
                 keys : ?{innerKey : InnerSubDBKey; outerKey : OuterSubDBKey};
                 map : [(SK, AttributeValue)];
                 userData : Text
               } ->
          async {innerKey : InnerSubDBKey; outerKey : OuterSubDBKey};
      scanLimitInner :
        shared query {
                       dir : Direction__1;
                       innerKey : InnerSubDBKey;
                       limit : Nat;
                       lowerBound : SK;
                       upperBound : SK
                     } ->
          async ScanLimitResult__1<Text, AttributeValue>;
      scanLimitOuter :
        shared {
                 dir : Direction__1;
                 limit : Nat;
                 lowerBound : SK;
                 outerKey : OuterSubDBKey;
                 upperBound : SK
               } ->
          async ScanLimitResult__1<Text, AttributeValue>;
      scanSubDBs :
        shared query () ->
          async
            [(OuterSubDBKey, {canister : Principal; key : InnerSubDBKey})];
      startInsertingImpl :
        shared {innerKey : InnerSubDBKey; sk : SK; value : AttributeValue} ->
          async ();
      subDBSizeByInner :
        shared query {innerKey : InnerSubDBKey} -> async ?Nat;
      subDBSizeByOuter : shared {outerKey : OuterSubDBKey} -> async ?Nat;
      subDBSizeOuterImpl : shared {outerKey : OuterSubDBKey} -> async ?Nat;
      superDBSize : shared query () -> async Nat
    }, Nat))
because implicit instantiation of type parameter K is over-constrained with
  (actor {
     createOuter :
       shared {
                innerKey : InnerSubDBKey;
                outerKey : OuterSubDBKey;
                part : Principal
              } ->
         async
           {
             inner : {canister : Principal; key : InnerSubDBKey};
             outer : {canister : Principal; key : OuterSubDBKey}
           };
     deleteInner : shared {innerKey : InnerSubDBKey; sk : SK} -> async ();
     deleteSubDBInner : shared {innerKey : InnerSubDBKey} -> async ();
     deleteSubDBOuter : shared {outerKey : OuterSubDBKey} -> async ();
     getByInner :
       shared query {innerKey : InnerSubDBKey; sk : SK} ->
         async ?AttributeValue;
     getByOuter :
       shared {outerKey : OuterSubDBKey; sk : SK} -> async ?AttributeValue;
     getInner :
       shared query {outerKey : OuterSubDBKey} ->
         async ?{canister : Principal; key : InnerSubDBKey};
     getSubDBUserDataInner : shared {innerKey : InnerSubDBKey} -> async ?Text;
     getSubDBUserDataOuter : shared {outerKey : OuterSubDBKey} -> async ?Text;
     hasByInner :
       shared query {innerKey : InnerSubDBKey; sk : SK} -> async Bool;
     hasByOuter : shared {outerKey : OuterSubDBKey; sk : SK} -> async Bool;
     hasSubDBByInner : shared query {innerKey : InnerSubDBKey} -> async Bool;
     hasSubDBByOuter : shared {outerKey : OuterSubDBKey} -> async Bool;
     isOverflowed : shared query () -> async Bool;
     putLocation :
       shared {
                innerCanister : Principal;
                innerKey : InnerSubDBKey;
                outerKey : OuterSubDBKey
              } ->
         async ();
     rawDeleteSubDB : shared {innerKey : InnerSubDBKey} -> async ();
     rawGetSubDB :
       shared query {innerKey : InnerSubDBKey} ->
         async ?{map : [(SK, AttributeValue)]; userData : Text};
     rawInsertSubDB :
       shared {
                hardCap : ?Nat;
                innerKey : ?InnerSubDBKey;
                map : [(SK, AttributeValue)];
                userData : Text
              } ->
         async {innerKey : InnerSubDBKey};
     rawInsertSubDBAndSetOuter :
       shared {
                hardCap : ?Nat;
                keys : ?{innerKey : InnerSubDBKey; outerKey : OuterSubDBKey};
                map : [(SK, AttributeValue)];
                userData : Text
              } ->
         async {innerKey : InnerSubDBKey; outerKey : OuterSubDBKey};
     scanLimitInner :
       shared query {
                      dir : Direction__1;
                      innerKey : InnerSubDBKey;
                      limit : Nat;
                      lowerBound : SK;
                      upperBound : SK
                    } ->
         async ScanLimitResult__1<Text, AttributeValue>;
     scanLimitOuter :
       shared {
                dir : Direction__1;
                limit : Nat;
                lowerBound : SK;
                outerKey : OuterSubDBKey;
                upperBound : SK
              } ->
         async ScanLimitResult__1<Text, AttributeValue>;
     scanSubDBs :
       shared query () ->
         async [(OuterSubDBKey, {canister : Principal; key : InnerSubDBKey})];
     startInsertingImpl :
       shared {innerKey : InnerSubDBKey; sk : SK; value : AttributeValue} ->
         async ();
     subDBSizeByInner : shared query {innerKey : InnerSubDBKey} -> async ?Nat;
     subDBSizeByOuter : shared {outerKey : OuterSubDBKey} -> async ?Nat;
     subDBSizeOuterImpl : shared {outerKey : OuterSubDBKey} -> async ?Nat;
     superDBSize : shared query () -> async Nat
   }, OuterSubDBKey)  <: 
    K  <:  (Partition__1, OuterSubDBKey)
where
  (actor {
     createOuter :
       shared {
                innerKey : InnerSubDBKey;
                outerKey : OuterSubDBKey;
                part : Principal
              } ->
         async
           {
             inner : {canister : Principal; key : InnerSubDBKey};
             outer : {canister : Principal; key : OuterSubDBKey}
           };
     deleteInner : shared {innerKey : InnerSubDBKey; sk : SK} -> async ();
     deleteSubDBInner : shared {innerKey : InnerSubDBKey} -> async ();
     deleteSubDBOuter : shared {outerKey : OuterSubDBKey} -> async ();
     getByInner :
       shared query {innerKey : InnerSubDBKey; sk : SK} ->
         async ?AttributeValue;
     getByOuter :
       shared {outerKey : OuterSubDBKey; sk : SK} -> async ?AttributeValue;
     getInner :
       shared query {outerKey : OuterSubDBKey} ->
         async ?{canister : Principal; key : InnerSubDBKey};
     getSubDBUserDataInner : shared {innerKey : InnerSubDBKey} -> async ?Text;
     getSubDBUserDataOuter : shared {outerKey : OuterSubDBKey} -> async ?Text;
     hasByInner :
       shared query {innerKey : InnerSubDBKey; sk : SK} -> async Bool;
     hasByOuter : shared {outerKey : OuterSubDBKey; sk : SK} -> async Bool;
     hasSubDBByInner : shared query {innerKey : InnerSubDBKey} -> async Bool;
     hasSubDBByOuter : shared {outerKey : OuterSubDBKey} -> async Bool;
     isOverflowed : shared query () -> async Bool;
     putLocation :
       shared {
                innerCanister : Principal;
                innerKey : InnerSubDBKey;
                outerKey : OuterSubDBKey
              } ->
         async ();
     rawDeleteSubDB : shared {innerKey : InnerSubDBKey} -> async ();
     rawGetSubDB :
       shared query {innerKey : InnerSubDBKey} ->
         async ?{map : [(SK, AttributeValue)]; userData : Text};
     rawInsertSubDB :
       shared {
                hardCap : ?Nat;
                innerKey : ?InnerSubDBKey;
                map : [(SK, AttributeValue)];
                userData : Text
              } ->
         async {innerKey : InnerSubDBKey};
     rawInsertSubDBAndSetOuter :
       shared {
                hardCap : ?Nat;
                keys : ?{innerKey : InnerSubDBKey; outerKey : OuterSubDBKey};
                map : [(SK, AttributeValue)];
                userData : Text
              } ->
         async {innerKey : InnerSubDBKey; outerKey : OuterSubDBKey};
     scanLimitInner :
       shared query {
                      dir : Direction__1;
                      innerKey : InnerSubDBKey;
                      limit : Nat;
                      lowerBound : SK;
                      upperBound : SK
                    } ->
         async ScanLimitResult__1<Text, AttributeValue>;
     scanLimitOuter :
       shared {
                dir : Direction__1;
                limit : Nat;
                lowerBound : SK;
                outerKey : OuterSubDBKey;
                upperBound : SK
              } ->
         async ScanLimitResult__1<Text, AttributeValue>;
     scanSubDBs :
       shared query () ->
         async [(OuterSubDBKey, {canister : Principal; key : InnerSubDBKey})];
     startInsertingImpl :
       shared {innerKey : InnerSubDBKey; sk : SK; value : AttributeValue} ->
         async ();
     subDBSizeByInner : shared query {innerKey : InnerSubDBKey} -> async ?Nat;
     subDBSizeByOuter : shared {outerKey : OuterSubDBKey} -> async ?Nat;
     subDBSizeOuterImpl : shared {outerKey : OuterSubDBKey} -> async ?Nat;
     superDBSize : shared query () -> async Nat
   }, OuterSubDBKey)  </: 
    (Partition__1, OuterSubDBKey)
so that no valid instantiation exists
@crusso
Copy link
Contributor

crusso commented Jun 17, 2024

I feel your pain.

(Note to self: to address this properly we have to extend our subtyping check to not just return a bool but, in the failure case, a path indicating which subgoal during subtying failed. Moscow ML does something similar at the module level.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants