mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-25 06:24:27 +08:00
Instantiate generics with a literal undefined argument
`id(undefined)` binds T = undefined, which the type mapper answers as VOID (the return convention), so the instance's parameter was refused (SC2001) although a declared `v: undefined` parameter compiles. Instantiated parameters are value positions and now take the unit-only slot, as declared ones do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
dd0c255fa7
commit
cd63b935e0
@@ -13,7 +13,12 @@ import {
|
||||
typeEquals,
|
||||
} from "../../ir/ir.js";
|
||||
import { isJsSourceFile, isNodeEsmFile } from "../program.js";
|
||||
import { genResultRecord, jsOpenObjectType } from "../type-mapper.js";
|
||||
import {
|
||||
genResultRecord,
|
||||
isUnitOnlyTsType,
|
||||
jsOpenObjectType,
|
||||
unitOnlyUnion,
|
||||
} from "../type-mapper.js";
|
||||
import { dynFallbackType } from "./lowerer.js";
|
||||
import { builtinModuleFnOf } from "./surfaces.js";
|
||||
import { mixinFnShapeOf } from "./lower-mixins.js";
|
||||
@@ -373,7 +378,7 @@ export function paramShapes(
|
||||
const tsType = symbol
|
||||
? lowerer.checker.getTypeOfSymbol(symbol)
|
||||
: lowerer.typeOf(declParam.name);
|
||||
const mapped = jsOpenObjectType(
|
||||
let mapped = jsOpenObjectType(
|
||||
declParam,
|
||||
lowerer.runtimeOptionalBindingType(
|
||||
declParam.name,
|
||||
@@ -382,6 +387,11 @@ export function paramShapes(
|
||||
lowerer.shapes,
|
||||
lowerer.unions,
|
||||
);
|
||||
// An instantiation with a literal `undefined` argument (`id(undefined)`
|
||||
// binds T = undefined): standalone undefined maps to VOID (the return
|
||||
// convention), and a parameter is a value position, so it takes the
|
||||
// unit-only slot like a declared `v: undefined` parameter.
|
||||
if (mapped?.kind === "void" && isUnitOnlyTsType(tsType)) mapped = unitOnlyUnion(lowerer.unions);
|
||||
if (!mapped || mapped.kind === "void")
|
||||
lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
|
||||
if (declParam.dotDotDotToken) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// A generic call with a literal `undefined` argument binds T = undefined;
|
||||
// the parameter holds undefined like a declared `v: undefined` parameter.
|
||||
function kind<T>(v: T): string {
|
||||
return typeof v;
|
||||
}
|
||||
console.log(kind(undefined), kind(null), kind(1), kind("s"));
|
||||
function same<T>(a: T, b: T): boolean {
|
||||
return a === b;
|
||||
}
|
||||
console.log(same(undefined, undefined));
|
||||
function wrap<T>(v: T): { v: T } {
|
||||
return { v };
|
||||
}
|
||||
const w = wrap(undefined);
|
||||
console.log(JSON.stringify(w), w.v === undefined, "v" in w);
|
||||
function describe<T>(label: string, v: T): string {
|
||||
return `${label}=${String(v)}`;
|
||||
}
|
||||
console.log(describe("u", undefined));
|
||||
Reference in New Issue
Block a user