-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Regression causes Function top-type to be callable with no arguments #48840
Comments
π Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript. Issue body code block by @webstrand π Compiled Historical Information
|
@typescript-bot bisect good v3.8.3 bad v3.9.7 |
I think this aliasing unsoundness is actually unrelated to whether |
The change between v3.8.3 and v3.9.7 occurred at 0e15b9f. |
I've always considered this to be the distinction between |
declare let foo: (...args: never[]) => void;
foo = (x: string) => {}; makes sense, fundementally, because |
Well, |
For real-world use, this most commonly shows up in my code like function foo<T extends (...args: never) => unknown>(fn: T) {
fn(); // no error
} or const registry = new Map<(...args: never) => unknown, unknown[]>();
for(const [fn, data] of registry) {
fn(); // no error
} |
Actually I found a counterexample from AnyhowStep by reading around #48840 (comment): https://www.typescriptlang.org/play?#code/PQKhCgAIUhlBDAZgUwE6QG5oM4EsD2AdpPopAAYBiAroQMYAuBh5kA7gBa50eTYf5qAGwAmkQvgaQARskh14QochEA6KDACiWVAE9IiWo2Z8BwsbMjxseAOaF405ZAb4XXbABoZ1KQw+mgqLikjJy1nYOTnKukMg6+ob0TETq0MDgyAAeAA74qH66OXIAgoS6NMkmALyQABSqjfCottgAXOLxaADaALoAlJDVAHyY+LgiANzg4EnGRAb4+AA8ACpxWQzIhCLYVuV9w3WDAN5QkBd0RNhSiIQAjB0NjajINx2rgyNjE0P1jaoAPpfUYnAC+0wul2ut0IACYOmUKkYUsRand7pBgMA4qhUPlwGCgA |
But let x: (...args: never[]) => unknown = () => {}
const y: (...args: ["one arg"]) => unknown = (x) => alert(x.charCodeAt(0))
x = y;
try {
x() // throws
} catch(e) {
alert(e)
} I think it is just broken that |
So can we confirm that this is a bug and not just "needs investigation" anymore, given the discussion in #35438 ? |
It seems there are two different unsoundnesses being discussed here: declare let foo: (...args: never) => void;
foo(); // should error (`[]` isn't assignable to `never`), but does not declare let foo: (...args: never[]) => void;
foo = (x: string) => {}; // should error (`never[]` isn't assignable to `[string]`), but does not Both of these unsoundnesses relate to a top function type being callable; however, the correct fix for the former is to make the type |
We shouldn't even let you write The second assignment isn't unsound per our definition of rest args being assumed to have sufficient arity (or more accurately, it's unsound in the way that all rest args / finite parameter lists are unsound) |
Are you saying that the type
Ah, good point. |
Upon further reflection, I think you're right about |
So, just running into this again, presumably Right now both types are callable with no arguments and both of these are considered top types for functions. Which of these can we fix without breaking everyone? |
I've been using and teaching |
Would it break the universe if we stopped |
Bug Report
π Search Terms
function top type callable spread never regression
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
foo()
was permitted.π Expected behavior
foo()
should not be permitted because it is unsafe.(...args: never) => unknown
behaves as the top-type for all functions; all function types are assignable to it. So calling it will lead to unsafe behavior by functions expecting 1 or more arguments.The text was updated successfully, but these errors were encountered: