1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-29 02:29:06 -05:00

fix(dts/ffi): non-exact types break FFI inference (#14968)

This commit is contained in:
Carter Snook 2022-06-27 07:41:58 -05:00 committed by David Sherret
parent 1bd024f546
commit cbe9d79f56
2 changed files with 143 additions and 30 deletions

View file

@ -362,48 +362,59 @@ declare namespace Deno {
export type NativeResultType = NativeType | NativeVoidType; export type NativeResultType = NativeType | NativeVoidType;
type ToNativeTypeMap =
& Record<NativeNumberType, number>
& Record<NativeBigIntType, bigint | number>
& Record<NativePointerType, TypedArray | bigint | null>
& Record<NativeFunctionType, bigint | null>;
/** Type conversion for foreign symbol parameters and unsafe callback return types */ /** Type conversion for foreign symbol parameters and unsafe callback return types */
type ToNativeType<T extends NativeType = NativeType> = T extends type ToNativeType<T extends NativeType = NativeType> = ToNativeTypeMap[T];
NativeNumberType ? number
: T extends NativeBigIntType ? bigint | number type ToNativeResultTypeMap = ToNativeTypeMap & Record<NativeVoidType, void>;
: T extends NativePointerType ? TypedArray | bigint | null
: T extends NativeFunctionType ? bigint | null
: never;
/** Type conversion for unsafe callback return types */ /** Type conversion for unsafe callback return types */
type ToNativeResultType<T extends NativeResultType = NativeResultType> = type ToNativeResultType<T extends NativeResultType = NativeResultType> =
T extends NativeType ? ToNativeType<T> ToNativeResultTypeMap[T];
: T extends NativeVoidType ? void
type ToNativeParameterTypes<T extends readonly NativeType[]> =
//
[(T[number])[]] extends [T] ? ToNativeType<T[number]>[]
: [readonly (T[number])[]] extends [T]
? readonly ToNativeType<T[number]>[]
: T extends readonly [...NativeType[]] ? {
[K in keyof T]: ToNativeType<T[K]>;
}
: never; : never;
type ToNativeParameterTypes<T extends readonly NativeType[]> = T extends type FromNativeTypeMap =
readonly [] ? [] & Record<NativeNumberType, number>
: T extends readonly [ & Record<NativeBigIntType, bigint>
infer U extends NativeType, & Record<NativePointerType, bigint>
...(infer V extends NativeType[]), & Record<NativeFunctionType, bigint>;
] ? [ToNativeType<U>, ...ToNativeParameterTypes<V>]
: never;
/** Type conversion for foreign symbol return types and unsafe callback parameters */ /** Type conversion for foreign symbol return types and unsafe callback parameters */
type FromNativeType<T extends NativeType = NativeType> = T extends type FromNativeType<T extends NativeType = NativeType> = FromNativeTypeMap[T];
NativeNumberType ? number
: T extends NativeBigIntType | NativePointerType | NativeFunctionType type FromNativeResultTypeMap =
? bigint & FromNativeTypeMap
: never; & Record<NativeVoidType, void>;
/** Type conversion for foregin symbol return types */ /** Type conversion for foregin symbol return types */
type FromNativeResultType<T extends NativeResultType = NativeResultType> = type FromNativeResultType<T extends NativeResultType = NativeResultType> =
T extends NativeType ? FromNativeType<T> FromNativeResultTypeMap[T];
: T extends NativeVoidType ? void
: never;
type FromNativeParameterTypes<T extends readonly NativeType[]> = T extends type FromNativeParameterTypes<
readonly [] ? [] T extends readonly NativeType[],
: T extends readonly [ > =
infer U extends NativeType, //
...(infer V extends NativeType[]), [(T[number])[]] extends [T] ? FromNativeType<T[number]>[]
] ? [FromNativeType<U>, ...FromNativeParameterTypes<V>] : [readonly (T[number])[]] extends [T]
: never; ? readonly FromNativeType<T[number]>[]
: T extends readonly [...NativeType[]] ? {
[K in keyof T]: FromNativeType<T[K]>;
}
: never;
/** A foreign function as defined by its parameter and result types */ /** A foreign function as defined by its parameter and result types */
export interface ForeignFunction< export interface ForeignFunction<

View file

@ -285,3 +285,105 @@ const static13_right: number = remote.symbols.static13;
// @ts-expect-error: Invalid member type // @ts-expect-error: Invalid member type
const static14_wrong: null = remote.symbols.static14; const static14_wrong: null = remote.symbols.static14;
const static14_right: number = remote.symbols.static14; const static14_right: number = remote.symbols.static14;
// Adapted from https://stackoverflow.com/a/53808212/10873797
type Equal<T, U> = (<G>() => G extends T ? 1 : 2) extends
(<G>() => G extends U ? 1 : 2) ? true
: false;
type AssertEqual<
Expected extends $,
Got extends $$,
$ = [Equal<Got, Expected>] extends [true] ? Expected
: ([Expected] extends [Got] ? never : Got),
$$ = [Equal<Expected, Got>] extends [true] ? Got
: ([Got] extends [Expected] ? never : Got),
> = never;
type AssertNotEqual<
Expected extends $,
Got,
$ = [Equal<Expected, Got>] extends [true] ? never : Expected,
> = never;
type TypedArray =
| Int8Array
| Uint8Array
| Int16Array
| Uint16Array
| Int32Array
| Uint32Array
| Uint8ClampedArray
| Float32Array
| Float64Array
| BigInt64Array
| BigUint64Array;
type __Tests__ = [
empty: AssertEqual<
{ symbols: Record<never, never>; close(): void },
Deno.DynamicLibrary<Record<never, never>>
>,
basic: AssertEqual<
{ symbols: { add: (n1: number, n2: number) => number }; close(): void },
Deno.DynamicLibrary<{ add: { parameters: ["i32", "u8"]; result: "i32" } }>
>,
higher_order_params: AssertEqual<
{
symbols: {
pushBuf: (ptr: bigint | TypedArray | null, func: bigint | null) => void;
};
close(): void;
},
Deno.DynamicLibrary<
{ pushBuf: { parameters: ["pointer", "function"]; result: "void" } }
>
>,
higher_order_returns: AssertEqual<
{
symbols: {
pushBuf: (
ptr: bigint | TypedArray | null,
func: bigint | null,
) => bigint;
};
close(): void;
},
Deno.DynamicLibrary<
{ pushBuf: { parameters: ["pointer", "function"]; result: "pointer" } }
>
>,
non_exact_params: AssertEqual<
{
symbols: {
foo: (...args: (number | bigint | TypedArray | null)[]) => bigint;
};
close(): void;
},
Deno.DynamicLibrary<
{ foo: { parameters: ("i32" | "pointer")[]; result: "u64" } }
>
>,
non_exact_params_empty: AssertEqual<
{
symbols: {
foo: () => number;
};
close(): void;
},
Deno.DynamicLibrary<
{ foo: { parameters: []; result: "i32" } }
>
>,
non_exact_params_empty: AssertNotEqual<
{
symbols: {
foo: (a: number) => number;
};
close(): void;
},
Deno.DynamicLibrary<
{ foo: { parameters: []; result: "i32" } }
>
>,
];