Skip to content

Commit

Permalink
Merge pull request #1318 from demergent-labs/fix_recursive_types
Browse files Browse the repository at this point in the history
allow recursive types to be any by default
  • Loading branch information
lastmjs authored Oct 1, 2023
2 parents b4cdbcb + 0fdec36 commit f9c46fa
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 54 deletions.
3 changes: 1 addition & 2 deletions examples/composite_queries/src/canister1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ const CompQueryCanister = Canister({
}),
// Composite query calling queries on the same canister
incCanister1: query([], nat, async () => {
// TODO This is not an ideal solution but will work for now
const self: any = CompQueryCanister(ic.id());

counter += 1n;

const canister1AResult: any = await ic.call(self.incCounter);
const canister1AResult = await ic.call(self.incCounter);
const canister1BResult = await ic.call(self.incCounter);

return counter + canister1AResult + canister1BResult;
Expand Down
2 changes: 1 addition & 1 deletion examples/motoko_examples/whoami/src/index.did
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ service: (principal) -> {
idQuick: () -> (principal) query;
installer: () -> (principal) query;
whoami: () -> (principal);
}
}
80 changes: 38 additions & 42 deletions examples/motoko_examples/whoami/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,51 @@ import {
postUpgrade,
Principal,
query,
Recursive,
update,
Void
update
} from 'azle';

// We use the zero principal but any principal could be used.
let install: Principal = Principal.fromText('aaaaa-aa');
let someone: Principal = Principal.fromText('aaaaa-aa');

const WhoAmI = Recursive(() =>
Canister({
// Manually save the calling principal and argument for later access.
init: init([Principal], (somebody) => {
install = ic.caller();
someone = somebody;
}),
// Manually re-save these variables after new deploys.
postUpgrade: postUpgrade([Principal], (somebody) => {
install = ic.caller();
someone = somebody;
}),
// Return the principal identifier of the wallet canister that installed this
// canister.
installer: query([], Principal, () => {
return install;
}),
// Return the principal identifier that was provided as an installation
// argument to this canister.
argument: query([], Principal, () => {
return someone;
}),
// Return the principal identifier of the caller of this method.
whoami: update([], Principal, () => {
return ic.caller();
}),
// Return the principal identifier of this canister.
id: update([], Principal, async () => {
const self = WhoAmI(ic.id());
const WhoAmI = Canister({
// Manually save the calling principal and argument for later access.
init: init([Principal], (somebody) => {
install = ic.caller();
someone = somebody;
}),
// Manually re-save these variables after new deploys.
postUpgrade: postUpgrade([Principal], (somebody) => {
install = ic.caller();
someone = somebody;
}),
// Return the principal identifier of the wallet canister that installed this
// canister.
installer: query([], Principal, () => {
return install;
}),
// Return the principal identifier that was provided as an installation
// argument to this canister.
argument: query([], Principal, () => {
return someone;
}),
// Return the principal identifier of the caller of this method.
whoami: update([], Principal, () => {
return ic.caller();
}),
// Return the principal identifier of this canister.
id: update([], Principal, async () => {
const self: any = WhoAmI(ic.id());

return await ic.call(self.whoami);
}),
// Return the principal identifier of this canister via the global `ic` object.
// This is much quicker than `id()` above because it isn't making a cross-
// canister call to itself. Additionally, it can now be a `Query` which means it
// doesn't have to go through consensus.
idQuick: query([], Principal, () => {
return ic.id();
})
return await ic.call(self.whoami);
}),
// Return the principal identifier of this canister via the global `ic` object.
// This is much quicker than `id()` above because it isn't making a cross-
// canister call to itself. Additionally, it can now be a `Query` which means it
// doesn't have to go through consensus.
idQuick: query([], Principal, () => {
return ic.id();
})
);
});

export default WhoAmI;
4 changes: 2 additions & 2 deletions examples/recursion/src/recursion/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import MyFullCanister from '../recursive_canister';
// These are the types that can be recursive
// Record
// Record can't be recursive by itself. It needs something to be able to terminate it. It needs to work with Variants, Opts, and Vec
const varRecord = Recursive(() => Record({ myVar: myVar }));
const varRecord = Recursive(() => Record({ myVar }));
const vecRecord = Recursive(() => Record({ myVecRecords: Vec(vecRecord) }));
const optRecord = Recursive(() => Record({ myOpt: Opt(optRecord) }));
const myVar = Variant({ num: int8, varRec: varRecord });
Expand All @@ -33,7 +33,7 @@ const recVariant = Recursive(() =>
const optTuple = Recursive(() => Tuple(Opt(optTuple), Opt(optTuple)));
const vecTuple = Recursive(() => Tuple(Vec(vecTuple), Vec(vecTuple)));
const varTuple = Recursive(() => Tuple(myTupleVar, myTupleVar));
const myTupleVar = Variant({ num: int8, varTuple: varTuple });
const myTupleVar = Variant({ num: int8, varTuple });
// Vec
// Vec can't be recursive by itself. At the end of it all it needs to have a concrete type.
// Opt
Expand Down
2 changes: 1 addition & 1 deletion src/lib_functional/candid/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export type TypeMapping<T> = T extends () => any
: T extends AzleVoid
? void
: T extends AzleTuple<infer U>
? { [K in keyof U]: TypeMapping<U[K]> }
? { [K in keyof U]: U[K] extends any ? any : TypeMapping<U[K]> }
: T extends AzleVec<infer U>
? TypeMapping<U>[]
: T extends AzleOpt<infer U>
Expand Down
2 changes: 1 addition & 1 deletion src/lib_functional/candid/reference/recursive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { v4 } from 'uuid';
import { IDL } from '@dfinity/candid';
import { Parent } from '../../../lib_new/utils';

export function Recursive<T extends () => any>(idlCallback: T): T {
export function Recursive(idlCallback: any): any {
const name = v4();

let result = (...args: any[]) => {
Expand Down
7 changes: 5 additions & 2 deletions src/lib_functional/canister_methods/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IDL } from '../../lib_new/index';
import { ic } from '../../lib_new/ic';
import { TypeMapping } from '..';
import { CandidType, TypeMapping } from '..';
import {
DecodeVisitor,
EncodeVisitor
Expand Down Expand Up @@ -33,7 +33,10 @@ export type CanisterMethodInfo<T extends ReadonlyArray<any>, K> = {
guard: (() => any) | undefined;
};

export type Callback<Params extends ReadonlyArray<any>, Return> = (
export type Callback<
Params extends ReadonlyArray<CandidType>,
Return extends CandidType
> = (
...args: { [K in keyof Params]: TypeMapping<Params[K]> }
) => TypeMapping<Return> | Promise<TypeMapping<Return>>;

Expand Down
2 changes: 1 addition & 1 deletion src/lib_functional/canister_methods/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
createParents,
executeMethod
} from '.';
import { CandidType, RecursiveType, TypeMapping } from '../candid';
import { CandidType, TypeMapping } from '../candid';
import { toParamIDLTypes, toReturnIDLType } from '../../lib_new/utils';

export function query<
Expand Down
4 changes: 2 additions & 2 deletions src/lib_new/ic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ type Ic = {
trap: (message: string) => never;
};

type ArgsType<T> = T extends (...args: infer U) => any ? U : never;
type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;
type ArgsType<T> = T extends (...args: infer U) => any ? U : any;
type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : any;
type ReturnTypeOfPromise<T> = T extends (...args: any[]) => infer R
? Promise<R>
: never;
Expand Down

0 comments on commit f9c46fa

Please sign in to comment.