text:
Invalid URL in README

The link "Short animated video introducing BB84 protocol" results in a "Video unavailable" on YouTube.

Thank you for reporting! Looks like our broken links checker didn't recognize it, since it's not a 404 page. Let me remove the link.

authors: haavardw tcNickolas

repo: microsoft/QuantumKatas


text:
[EN DateTimeV2] Revise ImplicitDate

.NET only for now. Pending performance test.

Add test
Support cases like "1st week of Oct. on Friday"

Draft due to performance drop.

This is currently blocked as perf was it, right @Grey0202? @LionbridgeCSII, could you take a look and try other approach to solve the source issue?

@tellarin, a simpler approach would be to include the new pattern directly into WeekDayOfMonthRegex, in this way there is no need to modify the base code.
I could not see any performance issue using this method, but maybe I am missing something, do you have any guidelines on how analyse performance?

Closing as it was replaced by #2120.

source: gharchive/pull-request

authors: Grey0202 LionbridgeCSII tellarin

repo: microsoft/Recognizers-Text

license: MIT

license_type: permissive

license_source: github-api


text:
Choosing the Ciphertext Modulus for BFV

I am trying to choose the minimum ciphertext modulus for a given plaintext modulus in BFV. Could someone advise me on this? I would only like to perform a single plaintext-ciphertext multiplication, and then ciphertext-ciphertext addition.
My guess is that to decrypt an exact result, I require that the noise budget is slightly larger |e|x|p| for my plaintext space Zp? How much larger should it be for me to be ensured that I will not encounter any decryption errors? Is 1 bit enough, since from what I understand the error is ternary, thus my error  is bounded by 2x|e|x|p| <= 2|p|?
Am I right to say that this analysis changes for public key crypto to having |e| = 2, plus an additional 1 bit error during decryption, so 2x|e|x|p| <= 4|p|, so I need 2+1 = 3 bits?

Also, am I right to say that because during the encoding phase, we are using a geometrical embedding (canonical ring embedding), if the values represented are small, the coefficients of the plaintext polynomial will also be small?

choose the minimum ciphertext modulus for a given plaintext modulus in BFV
The computation described does not even consume any level. Try choose the smallest parameter given by BFV default parameters.

the error is ternary
The error is discrete Gaussian, not ternary.

slightly larger |e|x|p|
Not always. If batching is used, plaintext is a polynomial, then there should be a factor of $\sqrt{n}$.

if the values represented are small, the coefficients of the plaintext polynomial will also be small?
Encoding is performed mod p. If there is no overflow mod p during encoding, your statement can be correct.

source: gharchive/issue

authors: WeiDaiWD jon-chuang

repo: microsoft/SEAL


text:
SEAL3.3 CKKS save and load

I use the save function to save the Ciphertext to the file , and then use the load function to read the Ciphertext from the file , but I found that the decrypted Ciphertext was different from the original value.
I found that only the uncomputed Ciphertext could be decrypted to the same value as the original.
so how can I get the true Ciphertext from the file?

Do you see this issue using any of the newer versions of SEAL? Note that 3.3.x are pretty old; for example, the entire serialization system was totally rewritten for 3.4.0. Is there some particular reason you need to use SEAL 3.3?


text:
Get public and secret keys as a string

Is there a clean way, like a getter function, to get the public and secret keys as a std::string?
I would like not to use save and load from file for this.
(I would use this mainly for testing)

@lorepieri8 the save() methods output to a stream, but in binary form. To view them, you would need to encode it to a human readable format such as a base64 string. Of course, this depends on your use-case. You could wrap the call with something that looks like this:
std::ostringstream buffer;
<public/secret key>.save(buffer, compr_mode);
std::string contents = buffer.str();
std::string encoded = b64encode(contents); // Transform binary string to base64 encoded string.
return encoded;

You can find many base64 encode/decode implementations on the web. This will completely buffer the string in memory (which can be large, especially for Galois keys), but it works.
Hope this helps!


text:
remove the unnecessary inv_ntt calls in mod_switch

For the ckks rescale function, we only need one inv_ntt on the last moduli,
since the core computation qk^(-1) * ((ct mod qi) - (ct mod qk)) is doable in both
NTT domain and power-basis domain.

Thanks for the PR, we sincerely appreciate your contributions! This particular issue we have already fixed internally and will be releasing it in a new version (3.5.0) very shortly.

authors: fionser kimlaine


text:
Fix missing URLs in dev.md

This adds missing URLs in dev.md.

 Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.:x: Calinou sign nowYou have signed the CLA already but the status is still pending? Let us recheck it.

Thanks! 🍻

authors: Calinou danmarshall msftclas

repo: microsoft/SandDance


text:
matrix is being deprecated from numpy

This causes an error everywhere that np.asmatrix() is called.
See this so post for details.

Done

Turns out matrix.dot() does matrix multiplication whereas array.dot() does element wise multiplication, which is a problem, hence can't just replace asmatrix() to float64() and get the right answer...

repo: microsoft/SparseSC


text:
Error while deploying APIs to dev space

While trying to deploy all the APIs of backend and web to dev space, the process starts but hangs at " Waiting for container image build". The process terminates after about an hour and shows the below message -
Waiting for container image build...Streaming build container logs for service 'tt-coupons' failed with: Server timeout (30000.00ms) elapsed without receiving a message from the server. 4m 57s
Oops... An unexpected error has occurred. A report of the error will be sent to Microsoft.
For diagnostic information, see Azure Dev Spaces logs at 'C:\Users\abc\AppData\Local\Temp\Azure Dev Spaces'.
Please include the following Request ID when contacting support: 3d5b48b9-0e19-4f22-b000-07c43df8f7e8

Thanks,
Hoysala

Hi,
This is probably because you have not deployed de ttsa service account on the namespace (dev in your screenshot):
Before the azds up type:
kubectl apply -f helm\ttsa.yaml -n dev`

This need to be done only once.

The command helped move past the error..
The instruction in the paragraph - "All deployments of Tailwind Traders run under Kubernetes ttsa service account. You need to create manually this service account in the dev namespace. Just type kubectl apply -f ttsa.yaml. Please note that the ttsa.yaml file is in the /Deploy/helm folder, so run this from that folder or use a relative path.' has missed out  "-n dev" at the end.
Thank you!

authors: eiximenis hgaruda

repo: microsoft/TailwindTraders-Backend


text:
documentation or guidence on connecting backend

When deploying the web portion the readme says:
When you deploy this website to Azure you can define the Backend you want to use in case you have deploy your own backend. By defaults it is configured the public Backend environment provided by Microsoft.
Im having an issue finding documentation or guidance on how exactly you connect the website to the backend. I have both successfully deployed just need specifics on how to connect them.

Hi @scautomation
I updated the documentation and fixed the default values to production backend DNS. Documentation changes are at pull request #53.

authors: OriolBonjoch scautomation

repo: microsoft/TailwindTraders-Website


text:
NullReferenceException in Columnar Mode

The following code throws a null reference exception when running in columnar mode.
It seems to occur whenever I add the nested GroupApply, is there a known limitation there am I doing something wrong in the code?
The error occurs in the code generated by Trill on the following line:
    public unsafe void OnNext(StreamMessage<CompoundGroupKey<Microsoft.StreamProcessing.CompoundGroupKey<Microsoft.StreamProcessing.Empty, System.String>, System.String>, System.Double> batch)
    {
        GeneratedBatch_2 inputBatch = batch as GeneratedBatch_2;

        StreamMessage<Microsoft.StreamProcessing.CompoundGroupKey<Microsoft.StreamProcessing.Empty, System.String>, System.Double> tmp; // Need this type to call Get with so the right subtype will be returned
        outPool.Get(out tmp);

        ...

        var srckey = batch.key.col;
        var destkey = tmp.key.col; // <== key is null

Reproduction
public struct Payload
{
    public string Name;
    public string GroupId;
    public int Reading;
}

public struct Result
{
    public string Name;
    public double Average;
}

public void Run()
{
    var array = new Payload[]
    {
        new Payload { GroupId = "GA", Name = "A", Reading = 1 },
        new Payload { GroupId = "GA", Name = "B", Reading = 2 },
        new Payload { GroupId = "GA", Name = "C", Reading = 3 },
    };

    Observable
        .Interval(TimeSpan.FromMilliseconds(500))
        .Select(i => array[i])
        .Take(array.Length)
        .ToAtemporalStreamable(TimelinePolicy.WallClock())
        .GroupApply(
            e => e.GroupId,
            byGroup => byGroup.GroupApply(
                            b => b.Name,
                            byName => byName
                                    .TumblingWindowLifetime(TimeSpan.FromSeconds(3).Ticks)
                                    .Average(e => e.Reading)),
            (g, avg) => new Result { Name = g.Key, Average = avg })
        .ToStreamEventObservable()
        .Where(e => e.IsData)
        .Subscribe(b =>
        {
            Console.WriteLine($"Kind: {b.Kind}, Time: {new DateTime(b.StartTime):hh:mm:ss}, Name: {b.Payload.Name}, Average: {b.Payload.Average}");
        });
}

This is now fixed

@wassim-k Here you go: https://www.nuget.org/packages/Trill/2020.12.1.2

authors: peterfreiling wassim-k

repo: microsoft/Trill


text:
derived tuple type not working as rest parameter

TypeScript Version:  3.7.5 | 3.8.2

Search Terms:
Code
type ValuesPick<TProps, TKeys extends Readonly<Array<keyof TProps>>> = {
  [I in keyof TKeys]: TKeys[I] extends keyof TProps ? TProps[TKeys[I]] : unknown;
};

interface SomeObject {
  a: string,
  b: number,
  c: boolean,
}

const keys = ["a", "b"] as const;

type Values = ValuesPick<SomeObject, typeof keys> // got type `readonly [string, number]` as expected;

// same as declaration
// type Values = readonly [string, number]

// working as value
const values: Values = [
  1, // error as expected
  2,
];

// break as rest parameter
const fn: (...params: Values) => void = (
  a, // expect `string` but got `string | number`
  b, // expect `number` but got `string | number`
) => {

};

// working with tuple directly
const fn: (...params: readonly [string, number]) => void = (
  a, // got type `string` as expected
  b, // got type `number` as expected
) => {

};

Expected behavior:
as comments in code
Actual behavior:
as comments in code
Playground Link:
Related Issues:

I'm not seeing the described behavior:

@RyanCavanaugh
Sorry，I report the issue to the wrong place. it is a IDE display issue.

type ValuesPick<TProps, TKeys extends Readonly<Array<keyof TProps>>> = {
  [I in keyof TKeys]: TKeys[I] extends keyof TProps ? TProps[TKeys[I]] : unknown;
};

export const from = <TProps extends object>() => {
  return <TOutput, TKeys extends Readonly<Array<keyof TProps>>>(
    keys: TKeys,
    valuer: (...args: ValuesPick<TProps, TKeys>) => TOutput,
  ) => {
    return [keys, valuer] as const;
  };
};

interface SomeObject {
  a: string,
  b: number,
  c: boolean,
}

const pick = from<SomeObject>();

pick(["a", "b"] as const /* for convert to tuple */, (a, b) => {
  return a + b
});

on more question,
some case like above，is there better way to write a tuple type without as const ?

authors: RyanCavanaugh morlay

repo: microsoft/TypeScript


text:
Allow importModuleSpecifier: "relative" to be overridden for explicitly configured "paths" in a jsconfig/tsconfig

This is a follow-up issue of https://github.com/microsoft/TypeScript/issues/40139
As per the docs, once you've imported a variable somewhere, vscode knows where to find it (bypassing the issue above).
I want all my code to be imported with relative imports everywhere for consistency. so I set "javascript.preferences.importModuleSpecifier": "relative". However, I don't want relative paths to be used when importing from a module declared in tsconfig's paths, as I specifically put it there so it can be resolved as an absolute import for convenience.
Clearly these 2 settings are conflicting, but I wonder if the current compromise is the best one (i.e. settings.json wins over tsconfig)?
I would expect to be able to auto-import variables from my paths module absolutely, even though I want everything else to import relatively.

VSCode Version: Insiders
OS Version: macOS 10.15.6

Steps to Reproduce:

Clone this repo: https://github.com/Floriferous/paths-resolution
Go to branch absolute-import-paths
Notice test2.js imports someVar properly
Open test.js, try to auto-import someVar, notice intellisense only suggests a relative import

Does this issue occur when all extensions are disabled?: Yes

This is currently the designed behavior. I've updated the issue title to make it clear this is a feature request for new behavior with how importModuleSpecifier and paths
Note that the same also happens for  "javascript.preferences.importModuleSpecifier": "auto"

authors: Floriferous mjbvz


text:
type-only import prevents declaration of a value with the same name

TypeScript Version:  4.1.0-dev.20200915
Search Terms: ts1361 type-only import type 'Foo' cannot be used as a value because it was imported using 'import type'.
Code
import type { Foo } from "./Foo";

function Foo(): Foo {
  return {
    name: "index.ts"
  };
}

Foo(); // 'Foo' cannot be used as a value because it was imported using 'import type'.ts(1361)

Expected behavior: Since the import type only creates a symbol in the type realm, I expect to be able to create the same symbol in the value realm without conflict. Especially since it's possible to declare the same symbol as both a type and value from within a single file.
Actual behavior: An error is raised: 'Foo' cannot be used as a value because it was imported using 'import type'.ts(1361), which makes this behavior seem very much intended, though that seems to violate the feature's stated intent. From the description of the feature's Type semantics from #35200:

If the symbol does have a value side, name resolution for that symbol will see only the type side.

Playground Link: https://codesandbox.io/s/wizardly-chatelet-h8zkg?file=/src/index.ts
Related Issues: #35200
cc: @andrewbranch

This is correct, Foo still potentially refers to a value which can only be used in non-emitted positions. If you want to separate the two, consider
import type { Foo as _Foo } from "./Foo";

type Foo = _Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

or
type Foo = import("./Foo").Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

Letting @andrewbranch correct me if I'm mistaken though

You got it right 👍

This is correct, Foo still potentially refers to a value which can only be used in non-emitted positions. If you want to separate the two, consider
import type { Foo as _Foo } from "./Foo";

type Foo = _Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

or
type Foo = import("./Foo").Foo;
function Foo(): Foo {
  return {
    name: "index.ts"
  };
}
Foo();

Sorry for bringing this up after four years, but I'm interested in what way can Foo still be a value if we've explicitly imported it as a type, and there's no e.g. value of the same name as the type in the imported module?

The best way to understand this is that the correct interpretation isn't "Import the type meaning of Foo", it's "Import Foo for use in type positions". For example, let's say you have a class exported in one file
// foo.ts
export class Foo {
  static x = "bar";
}

You can import it elsewhere and use it as a value, in type positions:
import type { Foo } from "./foo.js";
function something(f: typeof Foo) { // <- *value* reference on Foo
  return f.x;
}

Aha. So this is more a feature for avoiding unnecessary imports in the built code. If I want to use a value Foo just to get it's type, then I use import type and I can use the value only on the type position, and this value won't actually be included in the final built JS.

authors: 1000hz DanielRosenwasser RyanCavanaugh andrewbranch mastarija


text:
Properties should be inferred to exist on object after "in" expression

Suggestion

🔍 Search Terms

in any unknown property access exist infer
✅ Viability Checklist

My suggestion meets these guidelines:

[x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
[x] This wouldn't change the runtime behavior of existing JavaScript code
[x] This could be implemented without emitting different JS based on the types of the expressions
[x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
[x] This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion
Accessing a property in a block where an in expression involving the property name is guaranteed to be true shouldn't give a typecheck error.
📃 Motivating Example

I have a function that checks any object for something.
I'd like to avoid using any as the argument type, because it completely disables typechecking.
If I do this:
function foo(x: object): boolean {
    if ("m" in x) {
        return typeof x.m === "object"
    } else {
        return false
    }
}

this is viewed as invalid by TS.
With this new feature, it's valid, because "m" in x being true guarantees that x.m won't fail.
💻 Use Cases

Type guards for some types that don't use any.

Duplicate of #21732.

@MartinJohns
Thanks!

authors: MartinJohns schuelermine


text:
Type incorrectly narrowed down to null when using forEach

Bug Report
let a: number | null = null;
[1].forEach(() => {
    a = 1;
});
a // incorrectly inferred to null

Expected - type is inferred to number | null.
Actual - type us narrowed down to null
The "for const of" version works correctly.
🔎 Search Terms
forEach, null, type narrowing
🕗 Version & Regression Information
This started happening when trying to migrate from 4.2.3 to 4.3.5
⏯ Playground Link
Playground link with relevant code

Another duplicate of #9998.

authors: MartinJohns patrickszmucer


text:
v4.5 regression: The inferred type of '…' cannot be named without a reference to '…'

Bug Report

🔎 Search Terms

rxjs
re-export
declaration
composite
project references

🕗 Version & Regression Information

This changed between versions 4.4.4 and 4.5.1-rc

⏯ Playground Link
N/A
💻 Code
package.json:
{
  "dependencies": {
    "rxjs": "^7.4.0",
    "typescript": "^4.5.1-rc"
  }
}

tsconfig.json:
{
    "compilerOptions": {
        "target": "ESNext",
        "module": "CommonJS",
        "declaration": true,
        "outDir": "./target/"
    },
    "files": ["./src/main.ts"],
}

src/facade.ts:
export { connectable, EMPTY } from 'rxjs';

src/main.ts:
import * as Rx from './facade';

export const myConnectable = Rx.connectable(Rx.EMPTY);

Steps to reproduce:

Run yarn
Run tsc

🙁 Actual behavior
No error, as it behaved in 4.4.4.
🙂 Expected behavior
Error:
$ tsc
src/main.ts:3:14 - error TS2742: The inferred type of 'myConnectable' cannot be named without a reference to '../node_modules/rxjs/dist/types'. This is likely not portable. A type annotation is necessary.

3 export const myConnectable = Rx.connectable(Rx.EMPTY);
               ~~~~~~~~~~~~~

Found 1 error.

I am able to workaround this by modifying src/facade.ts like so:
 export { connectable, EMPTY } from 'rxjs';
+export * from 'rxjs/internal/types'

Note also that the error doesn't reproduce if we import directly from rxjs:
src/main.ts:
import { EMPTY, connectable } from 'rxjs';

export const myConnectable = connectable(EMPTY);

Sounds like https://github.com/microsoft/TypeScript/issues/46452#issuecomment-954879475 which would be expected for RxJS in node12/nodenext resolution mode, but you’re not in that mode 🤔

It looks like module resolution ignores export maps in --moduleResolution node (expected at least for back compat—we would really break the world if we changed this), but module specifier resolution always looks at export maps.

authors: OliverJAsh andrewbranch


text:
new.target type is too narrow

Bug Report
🔎 Search Terms
new.target, narrow
🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about new.target

⏯ Playground Link
Playground link with relevant code
💻 Code
class AssertionError extends Error {
    name = "AssertionError";
}

function assert(
    boolean: boolean,
    message: string = "Assertion failed",
): asserts boolean {
    if (!boolean) {
        throw new AssertionError(message);
    }
}

type PathInit = {
    isRooted: boolean,
    parts: ReadonlyArray<string>,
};

type AbsolutePathLike = AbsolutePath | `/${ string }`;
type PathLike = Path | string;

abstract class Path {
    static parse(path: `/${ string }`): AbsolutePath;
    static parse(path: string): AbsolutePath | RelativePath;
    static parse(path: string): AbsolutePath | RelativePath {
        const isRooted = path.startsWith("/");
        if (isRooted) {
            return new AbsolutePath(path.slice(1).split("/"));
        }
        return new RelativePath(path.split("/"));
    }
    static from(path: AbsolutePathLike): AbsolutePath;
    static from(path: RelativePath): RelativePath;
    static from(path: PathLike): AbsolutePath | RelativePath;
    static from(path: PathLike): AbsolutePath | RelativePath {
        if (typeof path === "string") {
            return Path.parse(path);
        }
        return path;
    }
    static join(
        first: RelativePath,
        ...paths: Array<PathLike>
    ): RelativePath;
    static join(
        first: AbsolutePathLike,
        ...paths: Array<PathLike>
    ): AbsolutePath;
    static join(
        first: PathLike,
        ...paths: Array<PathLike>
    ): AbsolutePath | RelativePath;
    static join(
        first: PathLike,
        ...paths: Array<PathLike>
    ): AbsolutePath | RelativePath {
        first = Path.from(first);
        const allPaths = [first, ...paths].map((path) => Path.from(path));
        if (first.isAbsolute()) {
            return new AbsolutePath(
                allPaths.flatMap((path) => path.#parts),
            );
        }
        assert(first.isRelative());
        return new RelativePath(
            allPaths.flatMap((path) => path.#parts),
        );
    }
    readonly #isRooted: boolean;
    readonly #parts: ReadonlyArray<string>;
    constructor({
        isRooted,
        parts,
    }: PathInit) {
        if (new.target !== AbsolutePath
        && new.target !== RelativePath) {
            throw new TypeError("Path should not be constructed directly");
        }
        const realParts: Array<string> = [];
        for (const part of parts) {
            if (part.includes("/")) {
                throw new RangeError(`path segments may not contain "/" characters`);
            } else if (part === "." || part === "") {
                continue;
            } else {
                realParts.push(part);
            }
        }
        this.#isRooted = isRooted;
        this.#parts = Object.freeze(realParts);
    }
    isAbsolute(): this is AbsolutePath {
        return this.#isRooted;
    }
    isRelative(): this is RelativePath {
        return !this.#isRooted;
    }
    #toString(): string {
        let path = this.#parts.join("/");
        if (this.#isRooted) {
            path = `/${ path }`;
        }
        return path;
    }
    get path(): string {
        return this.#toString();
    }
    get parts(): ReadonlyArray<string> {
        return this.#parts;
    }
}
class RelativePath extends Path {
    constructor(parts: ReadonlyArray<string>) {
        super({
            isRooted: false,
            parts,
        });
    }
}
class AbsolutePath extends Path {
    constructor(parts: ReadonlyArray<string>) {
        super({
            isRooted: true,
            parts,
        });
    }
    get fileURL(): string {
        const url = new URL("file://");
        url.pathname = `/${ this.parts.map((part) => encodeURIComponent(part)).join("/") }`;
        return url.href;
    }
}

🙁 Actual behavior
The value of new.target is too narrow as it does not actually allow proper subclasses to assume the value of new.target despite this being entirely possible. This is because, in this case, typeof Path has an incompatible construct signature with typeof AbsolutePath/RelativePath.
🙂 Expected behavior
In general subclasses can be expected to change the signature of the constructor, this is a core part of class-based OO, hence new.target type is overspecified.
I think the simplest resolution would be to simply widen new.target to new (...args: any[]) => this, as the only thing guaranteed about a subclass signature is that it will return an instance of this.

Smaller example that's not as motivating, but it demonstrates the issue in a minimal way:
class Class {
    constructor(x: number) {
        // This condition will always return 'false' since the types 'typeof Class' and 'typeof Subclass' have no overlap.
        if (new.target === Subclass) {

        }
    }
}

class Subclass extends Class {
    constructor(arg: [number, number]) {
        super(arg[0]);
    }
}

Just for the record, this works:
if (new.target !== Class) {}

which is probably how I would write it anyway, since as you hinted at in the OP, unless you control the entire hierarchy, your class doesn't know what its subclasses are going to do or even what all of them are.

From TypeScript's perspective, there's nothing different between this code and the "obviously-wrong" comparison Path === AbsolutePath. The only theoretically-grounded fix would be to make all constructors secretly generic so we could introduce a hidden constrained type parameter to represent the type of new.target, but the performance implications of this would be quite expensive. The upside - avoiding one type assertion - isn't particularly high given how often this comes up.
That said, we might be able to tweak the "can you compare X to Y" rule to allow this. @DanielRosenwasser , any thoughts?

The only theoretically-grounded fix would be to make all constructors secretly generic so we could introduce a hidden constrained type parameter to represent the type of new.target

I'm confused as to why one couldn't just set new.target equal to the type new (...args: any[]) => this (or perhaps even the wider type new (...args: any[]) => Path. This doesn't seem like it should require any hidden generic, just a redefinition of what new.target.
Like we can already define the type itself within the constructor:
class Path {
    constructor() {
        type NewTarget = new (...args: any[]) => this;
    }
}

The fix would just be to set new.target to this type, rather than to the current class.

Actually I realise the correct type is actually just new (...args: any[]) => Path, not even requiring the ``thiscostraint. THis is because in general you don't know what subtype you'll be getting fromnew.target` alone.

this in that position is effectively a hidden generic - that's how this parameters are implemented

Actually I realise the correct type is actually just new (...args: any[]) => Path

new.target.staticMember should be legal. The type is (an arbitrary subtype, sort of, of)-typeof Path

new.target.staticMember should be legal. The type is (an arbitrary subtype, sort of, of)-typeof Path

Admittedly I had never noticed that subclasses overriding static members with unrelated types is an error (I suppose because I've never done it). Given this though, doesn't our type just become:
type Base__NewTarget = {
    // This obliterates the construct signature from (typeof Base), admittedly I do not
    // know if there is an easier way to remove the call/construct signatures
    [K in keyof typeof Base]: (typeof Base)[K]
} & {
    new (...args: any[]): Base;
};

class Base {
    static isBase(value: any): value is Base {
        return #tag in value;
    }

    readonly #tag = true;

    constructor(arg: number) {
        // fine
        const newTarget: Base__NewTarget = new.target;

        // Allowed
        newTarget === Sub;

        // works
        newTarget.isBase(3);
    }
}

class Sub extends Base {
    constructor(arg: string /* incompatible with Base's arg */) {
        super(Number(arg));
    }
}

I dunno how the internals of TS work, but this type is again already definable so it feels like TypeScript should be able to define new.target equivalently.

We could maybe imagine something like that. Another approach is to say that instead of checking for a some form of compatibility from each type (a relationship check that we call comparability today), we could try another approach where we just check whether the intersection of both sides of a type form a non-empty type. I think @ahejlsberg and @weswigham have brought up in the past.
The problem with that is that almost every single object type ruins this. An object type forms a non-empty intersection with almost everything.
To start, here's a questionable example:
interface Equalalable {
    equals(other: unknown): boolean;
}

interface Barkable {
    bark(): void;
}

declare const dog: Barkable;
declare const horse: Equalalable;

function foo(dog: Barkable, horse: Equalalable) {
    // Not allowed today, would be allowed under intersection rules.
    if (dog === horse) {
        // ...
    }
}

This produces runnable JavaScript, but questionable. The object hierarchies theoretically overlap, but this has the chance to catch logic errors today across unrelated types.
Here's a severely questionable example.
interface TrafficLight {
    state: "red" | "green" | "yellow"
}

function drive(trafficLight: TrafficLight) {
    // Not allowed today, would be allowed under intersection rules.
    if (trafficLight !== "red") {
        // ...
    }
}

This also produces runnable JavaScript, but the if block will always run. That's because the intersection of "red" and TrafficLight is considered non-vacuous. We assume "red" & TrafficLight is a type that can exist (and while it technically can, we all know that's bogus for all practical purposes).
So I think intersection takes us to the other extreme of having no guarantees in === checks.
Maybe we could

vary this behavior on a strict-mode flag? (seems questionable)
special-case how literals form intersections for this operation?

Both seem like areas we could experiment in.

authors: DanielRosenwasser Jamesernator RyanCavanaugh fatcerberus


text:
Index type not recognised as string when the value type has a generic function argument

Bug Report

🔎 Search Terms

generic
index signature
🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about index signatures

⏯ Playground Link

Playground link with relevant code
💻 Code

interface Test<T> {
  t: (t: T) => void;
}

interface Tests {
  [key: string]: Test<unknown>
}

type StringTest = Test<string>;

interface APP extends Tests {
  key: StringTest;
}

🙁 Actual behavior
Getting the error Property 'key' of type 'StringTest' is not assignable to 'string' index type 'Test<unknown>'.
If the generic T is moved from being an argument to being the return type, the error disappears.
🙂 Expected behavior
The error should not appear, as I don't believe whether a generic is used in the function argument or not should affect the indexing.

This is a correct error. Test<string> is not assignable to Test<unknown> because type parameter T is used in a contravariant position (t: T) => void.

This is a correct error. Test<string> is not assignable to Test<unknown> because type parameter T is used in a contravariant position (t: T) => void.

If that is the case then why is replacing t: (t: T) => void with t: T or t: () => T negating the error?

Just for good measure, in case the reason for the contravariance is not obvious: Test<unknown>, by type, is a function which can be called with any value.  You can’t substitute a function that only accepts strings.

@mi-col Because by moving the type parameter to the return type, it becomes covariant. See my comment above.

authors: fatcerberus mi-col whzx5byb


text:
augmenting a module when not using any import or export statements overwrites the module instead of extending it

Bug Report
when augmenting a module and not using any import or export statements (except the dynamic import one which i guess doesn't count), it overwrites the existing module instead of extending it

🔎 Search Terms
augment module overwrite

🕗 Version & Regression Information
4.8.0-dev.20220524
⏯ Playground Link
can't seem to reproduce it in the playground for some reason https://www.typescriptlang.org/play?strict=false&noImplicitAny=false&strictNullChecks=false&strictFunctionTypes=false&strictPropertyInitialization=false&strictBindCallApply=false&noImplicitThis=false&noImplicitReturns=false&alwaysStrict=false&esModuleInterop=false&declaration=false&experimentalDecorators=false&emitDecoratorMetadata=false&jsx=0&module=1&isolatedModules=false&ts=4.8.0-dev.20220523#code/CYUwxgNghgTiAEBbA9sArhBByADsgzgC6JQB2AtGMhJmIQJbKlbwDeAvgLABQPA9H3ilk8EDBjIYAGngAjNIXiEAFgnxRECKqFHjJ+ePVJLl9AzgkArcIQBc8ZYUI58tgQHN6KtLIB0VRD4AERBCKDBlAAkQKGA+QgBPHBB8MBh6HEJyYVBLfHILZGs6eLgQPjN8NBAAfThCnlBIWC0mIngAM2Rke3pEPBhCAApcAmIySmpaBiYsAEpfADVYeihZTABlKmSgA
but here is a repro project https://github.com/DetachHead/typescript-nodejs-project/tree/issue_repro
💻 Code

declare module 'postman-collection' {}

// TS2694: Namespace '"postman-collection"' has no exported member 'VariableScope'.
declare const foo: import('postman-collection').VariableScope

🙁 Actual behavior

TS2694: Namespace '"postman-collection"' has no exported member 'VariableScope'.

🙂 Expected behavior
no error as the module is extended, not overwritten

Yes, it is awful, but this is the difference between an ambient module declaration and a module augmentation.

In that case do you know why I can't seem to recreate this behaviour in the playground?

Hmm... I have no idea 😅

authors: DetachHead andrewbranch


text:
Import module specifier breaks when folder name starts with $

Does this issue occur when all extensions are disabled?: Yes

VS Code Version: 1.78.2
OS Version: macOS 13.2.1

Steps to Reproduce:

Have a typescript module in an import path that contains a folder starting with $, such as "~/routes/trpc+/$trpc/instance"
Try to import that module using the auto complete feature
Observe that the import path becomes "~/routes/trpc+//instance"

Looks like a duplicate of https://github.com/microsoft/TypeScript/issues/53290

Thanks, that does look like a closely related issue. I tried upgrading to 5.1.0-beta (which should contain the fix) in my project but it was still showing the same problem. Is it correct to assume that the LSP should be using the typescript version I have installed? Or is it going to be running its own version?

It uses a bundled copy by default.  You have to tell it to use your local TS version by clicking the {} in the status bar next to “TypeScript”.

Great, thanks. Can confirm 5.1.0-beta fixes it.

authors: WesleyYue fatcerberus


text:
Better error message for using outdated moduleResolution: node(10)

Suggestion
🔍 Search Terms
moduleResolution node node10 eol esm commonjs cannot find types
✅ Viability Checklist
My suggestion meets these guidelines:

[x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
[x] This wouldn't change the runtime behavior of existing JavaScript code
[x] This could be implemented without emitting different JS based on the types of the expressions
[x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
[x] This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion
When a TSConfig is using "moduleResolution": "node" or "node10" and an import resolves to an npm package whose types declarations that doesn't support Node < 16, the error message in tsc is very general:
Cannot find module '...' or its corresponding type declarations.

Same in VS Code:

Could we please have a secondary message added suggesting that the project be switched to using a more modern "moduleResolution"?
This message needs bikeshedding, but a starting proposal:
Cannot find module '...' or its corresponding type declarations.
    Consider upgrading your "moduleResolution" compiler option. See aka.ms/tsconfig#moduleResolution for details.

📃 Motivating Example
This has been a point of confusion in at least https://github.com/typescript-eslint/typescript-eslint/issues/7284. We've gotten a few duplicate reports.
💻 Use Cases
Same as ☝, I think. I can't think of anything more specific.

People are going to come here and complain if we issue that message and it turns out that the module really isn't there under any setting, and I don't really see a way we could determinatively detect which (if any) other resolution settings would work.

Hmm. Maybe it can just link to aka.ms/tsconfig#moduleResolution then?

detect which (if any) other resolution settings would work

Also, I'm realizing now I meant to suggest in the OP that this message should only be there if any other resolution setting would work. 😬

Under different module resolution settings, we could even have entirely different source files under analysis, rendering the original import moot. It's not tractable in the general case IMO

Could we just have node10 do the same thing node16 does and specially handle the error where they would have diverged?

Or something more naive where we keep track of whether exports was specified anywhere where we checked.

@DanielRosenwasser is it possible to use ambiguous language in the presence of “exports”? For example, “This package may be resolvable using (…) because we found type module and exports declared in the package”?
I’ve only converted a few packages I maintain to be ESM so far, but every time I do I get a ton of issues like https://github.com/blakeembrey/change-case/issues/304. The current message isn’t adequate to show the issue is in user configuration and not the package.

We use "may" a lot of the time, so I'm okay with that.

Coming back to this - this is a pretty persistent pain-point for users of @typescript-eslint.
We've found that a lot of users don't know that:

moduleResolution: node actually means node10
node16 exists
node10 is different to node16
they're using a module resolution that doesn't match their runtime (our minimum supported node version is 16).

We've had to keep this pinned issue up and open to give people docs on how to fix the unclear error message, or else they file an issue with us saying our package is broken.
I'm sure there are a lot of packages out there who continue to include a types field in their package.json solely to stave-off the support burden of users who are still (usually erroneously) using node10 resolution.
We could do this also - but it does seem "smelly" that we would consider changing our config to avoid support burden from an unclear TS error message.
I 110% get that we can't make the error message say something so absolute like "you're using node10 but this package doesn't have a types field declared, but it has an exports field, you must use node16 instead" because, well, it's a different module resolution and that advice may not even be correct!
But as @blakeembrey suggested maybe there's a way we can help nudge the user in the right direction for this specific case? Or at least suggest something that might help them try something else and self-service fix their problem, rather than having to reach for stackoverflow / github issues / discord messages in order to even learn about the 2 character config change that could fix their problem.
For example, would this rough logic be acceptable?
"if TS finds a package that has no types field but has an exports field with a nested types field, then append This package may be resolvable using (…) because we found typed exports declared in the package. to the error message"

@andrewbranch does the above sound like something we can do?

Yes 👍

authors: DanielRosenwasser JoshuaKGoldberg RyanCavanaugh andrewbranch blakeembrey bradzacher


text:
Improve type inference for nullish coalescing (??) after null checks on multiple variables

🔍 Search Terms
"narrowing multiple conditions", "control flow analysis", "nullish coalescing", "type narrowing after null check"
✅ Viability Checklist

[X] This wouldn't be a breaking change in existing TypeScript/JavaScript code
[X] This wouldn't change the runtime behavior of existing JavaScript code
[X] This could be implemented without emitting different JS based on the types of the expressions
[X] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
[X] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
[X] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ Suggestion
Currently, TypeScript doesn’t correctly infer types when using the nullish coalescing operator (??) after null checks involving multiple nullable variables. This requires additional code to handle permutations of nullable values, making the code less concise.
Consider the following example:
function test(a: string | null, b: string | null): string {
  if (!a && !b) {
    throw Error("Need either a or b");
  }

  return a ?? b;  // TypeScript error: Type 'string | null' is not assignable to type 'string'
}

After the if (!a && !b) check, it’s guaranteed that at least one of a or b is a string, yet TypeScript still raises an error for the a ?? b expression, assuming that both values could still be null.
Expected Behavior:
I expect TypeScript to infer that at least one of a or b is a non-null string after the if (!a && !b) check. Therefore, a ?? b should not throw a type error since it’s guaranteed to return a non-null string.
Actual Behavior:
TypeScript throws the following error:
Type 'string | null' is not assignable to type 'string'.

Despite the null check ensuring that at least one of a or b is non-null, TypeScript doesn’t infer that a ?? b will always return a string.
📃 Motivating Example
In TypeScript, handling nullable values often requires extra checks or verbose code. With this improvement, TypeScript’s type inference is now smarter when using the nullish coalescing operator (??) after null checks.
For example, in this code:
function test(a: string | null, b: string | null): string {
  if (!a && !b) {
    throw Error("Need either a or b");
  }

  return a ?? b;  // Now correctly inferred as 'string'
}

TypeScript now understands that after checking both a and b are not null, a ?? b will always return a non-null string. This makes the code more concise and eliminates the need for redundant if blocks or temporary variables.
As the number of nullable variables increases, this becomes more useful. Without it, handling multiple nullable variables would require increasingly verbose checks.
💻 Use Cases

What do you want to use this for?
General TypeScript usage.

What shortcomings exist with current approaches?
Non-null assertion is needed, when it shouldn't be.

What workarounds are you using in the meantime?
Using non-null assertion. Eg.

function test(a: string | null, b: string | null): string {
  if (!a && !b) {
    throw Error("Need either a or b")
  }

  return (a ?? b )!
}

Duplicate of #49452.

authors: MartinJohns hkfi


text:
Incorrectly inferred call signature

🔎 Search Terms
call signature, overloaded call
🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about call signature

⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.7.0-dev.20241101#code/JYOwLgpgTgZghgYwgAgGIHt3IN4ChnIAUAHgFzICMAlOQEz5FnK03IDMuAvrrmAJ4AHFAGE4AGzEBlYAHMQcMAFcoEADwAVAHzIAvMnXIIxSCAAmAZyIA6GwPKgY0ZAAUqu7Q6cAlZAH5rtuSu7sg+5Oq8gigA6lDoIDLqUbrIohLScgrKahjo2gD0+Yx0bjrabEA
💻 Code
interface Foo {
  (x: 1): 2
  (x: 2): 3
}

type CallSignature<T> = T extends (...p: infer P) => infer R ? (...p: P) => R : T
type WrongType = CallSignature<Foo> // (x: 2) => 3

🙁 Actual behavior
The inferred type is not compatible with actual type
🙂 Expected behavior
The inferred type should (at minimum) be compatible with actual type (ideally { (x: 1) => 2; (x: 2) => 3 }).
Additional information about the issue
No response

This is working as intended / a design limitation. See the documentation: Inferring Within Conditional Types

When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types.

see #26591 and other issues

authors: MartinJohns boris-kolar jcalz


text:
fix(25155): insertSpaceBeforeTypeAnnotation doesn't work with optional parameters / properties

Fixes #25155

@DanielRosenwasser ?


text:
Small fix in getIsContextSensitiveAssignmentOrContextType

Test that parentSymbol.valueDeclaration exists.
Fixes #38532

I'm not sure about the name of the test file...


text:
Don't re-alias top-level type aliases with local type aliases

Fixes #43622.

I did not add the repro from #43622 as a test since it requires React and other libraries. I have manually verified that #43622 is fixed by this PR, and we already have a test that verifies the new local type alias behavior (see the baseline changes).

Is there anything specific you wanted me to test/check?

Not really. I suppose the debatable part is whether we just want to point users at the workaround (i.e. changing xxx to [xxx][0]) and not actually merge this PR.

Is there anything specific you wanted me to test/check?

Not really. I suppose the debatable part is whether we just want to point users at the workaround (i.e. changing xxx to [xxx][0]) and not actually merge this PR.

Is there some way we could supplement tracing to make it clear when a bad expansion happens so that we can at least point users to the relevant type declarations?  If we can't assist users in finding where to apply that workaround, I'd be pretty reluctant to recommend they do so.

@typescript-bot perf test this faster

Is there some way we could supplement tracing to make it clear when a bad expansion happens so that we can at least point users to the relevant type declarations?

I can't think of any. If we preserved all possible type aliases then perhaps, but in that case we'd probably just add logic to pick the first accessible alias. But as we discussed in the design meeting, I don't think the additional complexity is merited.
Overall, I think we're better off with the behavior in this PR so I'll merge it.

authors: DanielRosenwasser ahejlsberg amcasey


text:
Use missingType in --noUncheckedIndexedAccess mode

This implements what I discuss here.
Fixes #43614.

@typescript-bot test this
@typescript-bot user test this inline
@typescript-bot run dt
@typescript-bot perf test faster
@typescript-bot test top100

I love it when „in the next day or two” means „in the next half an hour” 😉

authors: Andarist ahejlsberg


text:
Only pad initializer types for parameters without annotations and contextual signatures

fixes https://github.com/microsoft/TypeScript/issues/59936

@typescript-bot test it

@typescript-bot test it

@typescript-bot pack this

Maybe I'm misunderstanding it, but isn't this sorta kinda a revert of https://github.com/microsoft/TypeScript/pull/59183 but only in the parameter case? Is this too targeted? Or am I misunderstanding?

It's not a revert. Previously object literal types were contextually-typed by their corresponding patterns.
So in a situation like this:
function test({ a = 1 } = {}) {}

The type of this {} ended up to be { a?: number }. Since #59183 that's no longer the case - its type stays as {}. This fact/difference isn't particularly observable to the user but the signature computed based on it can be quite different. The signature is meant to be (_: { a?: number }) => void.
Since the type of the initializer expressions changed in #59183, Anders introduced "object padding" for those initializer types - a way to go from the initializer type to a parameter type using the available binding pattern information. Such mechanism was already used for tuple types. So this was a way to unify the algorithm for both object and array patterns in parameter positions.
That new object padding introduced regressions but only because it didn't cover some cases (see https://github.com/microsoft/TypeScript/pull/59924 ) and because it's too eager in some other cases (like this one here).
TLDR: it's not a revert, it's just an extension of those changes

authors: Andarist jakebailey


text:
Have CMake generate pkg-config file for library

So that various build processes can query for compiler and linker flags in Linux, MSYS2, and CygWin.

/azp run UVAtlas-GitHub-CMake,UVAtlas-GitHub-CMake-Dev17,UVAtlas-GitHub-MinGW,UVAtlas-GitHub-WSL,UVAtlas-GitHub-WSL-11

/azp run UVAtlas-GitHub-CMake,UVAtlas-GitHub-CMake-Dev17,UVAtlas-GitHub-MinGW,UVAtlas-GitHub-WSL,UVAtlas-GitHub-WSL-11

authors: JPeterMugaas walbourn

repo: microsoft/UVAtlas


text:
issue in installing, WslRegisterDistribution failed with error: 0x8007023e Error: 0x8007023e {Application Error}

Windows Version
22H2 19045.4651
WSL Version
0.0.0.0
Are you using WSL 1 or WSL 2?

[X] WSL 2
[ ] WSL 1

Kernel Version
5.10.16
Distro Version
24.04
Other Software
Docker Desktop
Repro Steps
.
Expected Behavior
.
Actual Behavior

C:\Users\ali>wsl.exe
Windows Subsystem for Linux has no installed distributions.
Distributions can be installed by visiting the Microsoft Store:
https://aka.ms/wslstore

C:\Users\ali>wsl --install
Copyright (c) Microsoft Corporation. All rights reserved.

Usage: wsl.exe [Argument] [Options...] [CommandLine]

Arguments for running Linux binaries:

    If no command line is provided, wsl.exe launches the default shell.

    --exec, -e <CommandLine>
        Execute the specified command without using the default Linux shell.

    --
        Pass the remaining command line as is.

Options:
    --cd <Directory>
        Sets the specified directory as the current working directory.
        If ~ is used the Linux user's home path will be used. If the path begins
        with a / character, it will be interpreted as an absolute Linux path.
        Otherwise, the value must be an absolute Windows path.

    --distribution, -d <Distro>
        Run the specified distribution.

    --user, -u <UserName>
        Run as the specified user.

Arguments for managing Windows Subsystem for Linux:

    --help
        Display usage information.

    --install [Options]
        Install additional Windows Subsystem for Linux distributions.
        For a list of valid distributions, use 'wsl --list --online'.

        Options:
            --distribution, -d [Argument]
                Downloads and installs a distribution by name.

                Arguments:
                    A valid distribution name (not case sensitive).

                Examples:
                    wsl --install -d Ubuntu
                    wsl --install --distribution Debian

    --set-default-version <Version>
        Changes the default install version for new distributions.

    --shutdown
        Immediately terminates all running distributions and the WSL 2
        lightweight utility virtual machine.

    --status
        Show the status of Windows Subsystem for Linux.

    --update [Options]
        If no options are specified, the WSL 2 kernel will be updated
        to the latest version.

        Options:
            --rollback
                Revert to the previous version of the WSL 2 kernel.

            --inbox
                Only update the inbox WSL 2 kernel. Do not install WSL from the Microsoft Store.

            --web-download
                Download the most recent version of WSL from the internet instead of the Microsoft Store.

Arguments for managing distributions in Windows Subsystem for Linux:

    --export <Distro> <FileName>
        Exports the distribution to a tar file.
        The filename can be - for standard output.

    --import <Distro> <InstallLocation> <FileName> [Options]
        Imports the specified tar file as a new distribution.
        The filename can be - for standard input.

        Options:
            --version <Version>
                Specifies the version to use for the new distribution.

    --list, -l [Options]
        Lists distributions.

        Options:
            --all
                List all distributions, including distributions that are
                currently being installed or uninstalled.

            --running
                List only distributions that are currently running.

            --quiet, -q
                Only show distribution names.

            --verbose, -v
                Show detailed information about all distributions.

            --online, -o
                Displays a list of available distributions for install with 'wsl --install'.

    --set-default, -s <Distro>
        Sets the distribution as the default.

    --set-version <Distro> <Version>
        Changes the version of the specified distribution.

    --terminate, -t <Distro>
        Terminates the specified distribution.

    --unregister <Distro>
        Unregisters the distribution and deletes the root filesystem.

C:\Users\ali>wsl --install -d Ubuntu
Installing: Ubuntu
Ubuntu has been installed.
Launching Ubuntu...

Installing, this may take a few minutes...
WslRegisterDistribution failed with error: 0x8007023e
Error: 0x8007023e {Application Error}
The exception s (0x
Press any key to continue...

     ```

### Diagnostic Logs

_No response_

deploying WSL2 distributions
ensuring main distro is deployed: deploying "docker-desktop": importing WSL distro "Failed to configure network (networkingMode Nat). To disable networking, set wsl2.networkingMode=None in C:\Users\ali.sharify\.wslconfig\r\nError code: Wsl/Service/RegisterDistro/CreateVm/ConfigureNetworking/HNS/ERROR_UNHANDLED_EXCEPTION\r\n" output="docker-desktop": exit code: 4294967295: running WSL command wsl.exe C:\Windows\System32\wsl.exe --import docker-desktop \AppData\Local\Docker\wsl\main C:\Program Files\Docker\Docker\resources\wsl\wsl-bootstrap.tar --version 2: Failed to configure network (networkingMode Nat). To disable networking, set wsl2.networkingMode=None in .wslconfig
Error code: Wsl/Service/RegisterDistro/CreateVm/ConfigureNetworking/HNS/ERROR_UNHANDLED_EXCEPTION
: exit status 0xffffffff
checking if isocache exists: CreateFile \wsl$\docker-desktop-data\isocache: The network name cannot be found.

repo: microsoft/WSL


text:
binfmt_misc/binfmt-support not working as expected

Windows Build Number
Microsoft Windows [Version 10.0.19043.1110]
WSL Version

[X] WSL 2
[ ] WSL 1

Kernel Version
Linux version 5.4.72-microsoft-standard-WSL2 (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 SMP Wed Oct 28 23:40:43 UTC 2020
Distro Version
Ubuntu 20.04
Other Software
qemu
qemu-user-static
binfmt-support
Repro Steps
I don't know what I did to get my system into this state. It was working fine. I think I rebooted with a Windows Update, but not sure.
sudo apt-get reinstall binfmt-support

Expected Behavior
/proc/sys/fs/binfmt_misc/ to be filled with qemu-* files. Like this:
cameron@uberfall:~$ ls -l /proc/sys/fs/binfmt_misc/
total 0
-rw-r--r-- 1 root root 0 Jun 24 09:01 python2.7
-rw-r--r-- 1 root root 0 Jul  1 06:07 python3.8
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-aarch64
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-alpha
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-arm
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-armeb
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-cris
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-hppa
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-m68k
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-microblaze
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-mips
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-mips64
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-mips64el
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-mipsel
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-mipsn32
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-mipsn32el
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-ppc
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-ppc64
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-ppc64abi32
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-ppc64le
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-riscv32
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-riscv64
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-s390x
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-sh4
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-sh4eb
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-sparc
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-sparc32plus
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-sparc64
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-xtensa
-rw-r--r-- 1 root root 0 Jun 24 09:01 qemu-xtensaeb
--w------- 1 root root 0 Jul  1 06:07 register
-rw-r--r-- 1 root root 0 Jul  1 06:07 status

Actual Behavior
$ ls -l /proc/sys/fs/binfmt_misc/
total 0

Diagnostic Logs
Fresh boot of wsl (after wsl --shutdown)
cameron@Nook:~$ uptime -p
up 0 minutes

Some binfmt is loaded, missing qemu.
cameron@Nook:~$ ls -l /proc/sys/fs/binfmt_misc/
total 0
-rw-r--r-- 1 root root 0 Jul 14 15:09 WSLInterop
--w------- 1 root root 0 Jul 14 15:09 register
-rw-r--r-- 1 root root 0 Jul 14 15:09 status

It is mounted as expected
cameron@Nook:~$ mount | grep binfmt
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)

Cleaning installed version (with RUNLEVEL=1 fix for runlevel detection)
cameron@Nook:~$ sudo RUNLEVEL=1 apt -y remove --purge binfmt-support
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be REMOVED:
  binfmt-support*
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
After this operation, 246 kB disk space will be freed.
(Reading database ... 32683 files and directories currently installed.)
Removing binfmt-support (2.2.0-2) ...
 * Disabling additional executable binary formats binfmt-support                                                                                [ OK ]
Processing triggers for man-db (2.9.1-1) ...
(Reading database ... 32672 files and directories currently installed.)
Purging configuration files for binfmt-support (2.2.0-2) ...
Processing triggers for systemd (245.4-4ubuntu3.7) ...

No binfmt (as expected)
cameron@Nook:~$ ls -l /proc/sys/fs/binfmt_misc/
total 0

Not mounted either (as expected)
cameron@Nook:~$ mount | grep binfmt

Reinstall (with RUNLEVEL=1 fix for runlevel detection)
cameron@Nook:~$ sudo RUNLEVEL=1 apt install binfmt-support
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  binfmt-support
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/58.2 kB of archives.
After this operation, 246 kB of additional disk space will be used.
Selecting previously unselected package binfmt-support.
(Reading database ... 32670 files and directories currently installed.)
Preparing to unpack .../binfmt-support_2.2.0-2_amd64.deb ...
Unpacking binfmt-support (2.2.0-2) ...
Setting up binfmt-support (2.2.0-2) ...
Created symlink /etc/systemd/system/multi-user.target.wants/binfmt-support.service → /lib/systemd/system/binfmt-support.service.
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for systemd (245.4-4ubuntu3.7) ...

Still empty 😕
cameron@Nook:~$ ls -l /proc/sys/fs/binfmt_misc/
total 0

Not mounted 😕
cameron@Nook:~$ mount | grep binfmt

umount fails... now during apt reinstall ....
cameron@Nook:~$ sudo RUNLEVEL=1 apt reinstall binfmt-support
Reading package lists... Done
Building dependency tree
Reading state information... Done
0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 0 not upgraded.
Need to get 0 B/58.2 kB of archives.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 32683 files and directories currently installed.)
Preparing to unpack .../binfmt-support_2.2.0-2_amd64.deb ...
 * Disabling additional executable binary formats binfmt-support                                                                                umount: /proc/sys/fs/binfmt_misc: not mounted.
update-binfmts: warning: Couldn't unmount the binfmt_misc filesystem from /proc/sys/fs/binfmt_misc.
                                                                                [ OK ]
Unpacking binfmt-support (2.2.0-2) over (2.2.0-2) ...
Setting up binfmt-support (2.2.0-2) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for systemd (245.4-4ubuntu3.7) ...

I have also tried reinstalling qemu and qemu-user-static.
Related

#2103
#2620 Says "binfmt flags support is complete in WSL2" so I assume it should all just work. It also did for a while...

Since WSL doesn't run systemd / init scripts the qemu binfmt interpreter will have to be re-registered when you restart your VM.  I believe there is probably a script you can run to accomplish this, but I'm not familiar.

@benhillis Good catch. I'd missed the Systemd reference.
Looking in /etc/systemd/system/multi-user.target.wants/binfmt-support.service I see the start script.
Running:
``bash
sudo update-binfmts --enable
Seems to have fixed it! Thanks!

----

This leads to the bigger question I guess. How to make it so I don't need to run `update-binfmts --enable`... How do packages that expect to have SystemD setup and working in WSL2?

@cinderblock in general you can use commands like sudo service docker start to interact with services in WSL, for example the docker daemon and ssh daemon can be started this way instead of using systemd.
I'll close this issue out for our bookkeeping since it looks like you're resolved and this can be accrued to the feature of adding systemd support to WSL! Thanks for filing!

Related to https://github.com/microsoft/WSL/issues/994

I realize this bug is closed but I wanted to document a related failure mode: after installing qemu-user-static for the first time I get this error when running wslview
grep: /proc/sys/fs/binfmt_misc/WSLInterop: No such file or directory
WSL Interopability is disabled. Please enable it before using WSL.

I'm guessing something in the install process of these packages removes the WSLInterop entry. Rebooting fixes WSL but you're still left with the QEMU problem update-binfmts fixes.
Did anyone file a bug with the upstream QEMU packages? I'm not even sure it's appropriate; they rely on systemd to work and systemd just isn't present here. It seems like a general limitation of WSL.

I'm suffering the same problem. There's no proc/sys/fs/binfmt_misc/WSLInterop in my WSL2 instance.

Configurations of /etc/wsl.conf
10:51:50 ~/Code 101ms $ cat /etc/wsl.conf
[user]
# This instance is exported from official Ubuntu instance.
# I export it to "D:\\" and re-import into WSL2 else where.
default = dragon1573

[boot]
systemd = true

[interop]
enabled = true
appendWindowsPath = false

Launch Windows browser
10:51:41 ~/Code 2ms $ wslview https://cn.bing.com/
grep: /proc/sys/fs/binfmt_misc/WSLInterop: No such file or directory
WSL Interopability is disabled. Please enable it before using WSL.
grep: /proc/sys/fs/binfmt_misc/WSLInterop: No such file or directory
[error] WSL Interoperability is disabled. Please enable it before using WSL.
/usr/bin/wslview: line 216: /mnt/c/Windows/System32/reg.exe: cannot execute binary file: Exec format error
/usr/bin/wslview: line 149: /mnt/c/Windows/System32/chcp.com: cannot execute binary file: Exec format error
/usr/bin/wslview: line 156: /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe: cannot execute binary file: Exec format error
/usr/bin/wslview: line 149: /mnt/c/Windows/System32/chcp.com: cannot execute binary file: Exec format error

What's inside /proc/sys/fs/binfmt_misc/
10:51:59 ~/Code 1ms $ tree /proc/sys/fs/binfmt_misc/
/proc/sys/fs/binfmt_misc/
├── jar
├── llvm-15-runtime.binfmt
├── python3.10
├── register
└── status

0 directories, 5 files

Is my WSL2 instance (the *.vhdx) broken? Shall I unregister and reinstall a brand new offical Ubuntu instance?

I think this is due to https://github.com/systemd/systemd/blob/b9b0f338be2f63af96d295e4eaf9e8a8889190bb/src/binfmt/binfmt.c#L246-L251 -- effectively, systemd-binfmt assumes it must be managing all of the registrations for the system, which seems like a problem even for systemd-nspawn, for example. :sweat_smile:
I used sudo systemctl mask systemd-binfmt.service to fix this (telling systemd explicitly to no longer assume it manages this).  The consequence of this is that packages like qemu-user-static that also will try to register might not do so, but I'm also running Docker Desktop so I don't need that (what helped me figure this out is that its QEMU rules also get wiped out by this).

I use sudo update-binfmts --enable to add llvm-17-runtime.binfmt  python3.11  python3.12 to /proc/sys/fs/binfmt_misc/.
Details
┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ lsmod | grep binfmt

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ ls /proc/sys/fs/binfmt_misc/
register  status  WSLInterop

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ ll /etc/systemd/system/multi-user.target.wants/binfmt-support.service
ls: cannot access '/etc/systemd/system/multi-user.target.wants/binfmt-support.service': No such file or directory

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ update-binfmts --enable
Command 'update-binfmts' not found, but can be installed with:
sudo apt install binfmt-support

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ sudo apt install binfmt-support
Installing:
  binfmt-support

Summary:
  Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 69
  Download size: 64.3 kB
  Space needed: 214 kB / 1,018 GB available

Get:1 https://mirrors.tuna.tsinghua.edu.cn/kali kali-last-snapshot/main amd64 binfmt-support amd64 2.2.2-7 [64.3 kB]
Fetched 64.3 kB in 1s (121 kB/s)
Selecting previously unselected package binfmt-support.
(Reading database ... 203549 files and directories currently installed.)
Preparing to unpack .../binfmt-support_2.2.2-7_amd64.deb ...
Unpacking binfmt-support (2.2.2-7) ...
Setting up binfmt-support (2.2.2-7) ...
invoke-rc.d: could not determine current runlevel
Created symlink /etc/systemd/system/multi-user.target.wants/binfmt-support.service → /usr/lib/systemd/system/binfmt-support.service.
Processing triggers for man-db (2.12.1-2) ...
Processing triggers for kali-menu (2024.3.1) ...

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ ll /etc/systemd/system/multi-user.target.wants/binfmt-support.service
lrwxrwxrwx 1 root root 46 Oct 29 09:39 /etc/systemd/system/multi-user.target.wants/binfmt-support.service -> /usr/lib/systemd/system/binfmt-support.service

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ sudo update-binfmts --enable

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ ll /proc/sys/fs/binfmt_misc/status
-rw-r--r-- 1 root root 0 Oct 29 09:39 /proc/sys/fs/binfmt_misc/status

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ cat /proc/sys/fs/binfmt_misc/status
enabled

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ modprobe binfmt_misc

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ ls /proc/sys/fs/binfmt_misc/
llvm-17-runtime.binfmt  python3.11  python3.12  register  status  WSLInterop

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ qemu-i386 stack_overflow_32
Welcome to the CTF challenge!
Enter your input: aaa
You entered: aaa

Goodbye!

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ qemu-arm64 stack_overflow_arm64
qemu-arm64: Could not open '/lib/ld-linux-aarch64.so.1': No such file or directory

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ qemu-arm64 -L /usr/aarch64-linux-gnu/ stack_overflow_arm64
Welcome to the CTF challenge!
Enter your input: aaa
You entered: aaa

Goodbye!

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ qemu-arm -L /usr/arm-linux-gnueabi stack_overflow_arm7
Welcome to the CTF challenge!
Enter your input: aaa
You entered: aaa

Goodbye!

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$ qemu-armhf -L /usr/arm-linux-gnueabihf stack_overflow_arm7hf
Welcome to the CTF challenge!
Enter your input: aaa
You entered: aaa

Goodbye!

┌──(liudonghua㉿LDH-DESKTOP)-[~/ctf]
└─$

authors: Dragon1573 NelsonMinar benhillis cinderblock craigloewen-msft liudonghua123 tianon trallnag


text:
perf/builtin-sched.c:673:13 error: comparison of distinct pointer types [-Werror,-Wcompare-distinct-pointer-types]

Version
Microsoft Windows [Version 10.0.19043.1706]
WSL Version

[X] WSL 2
[ ] WSL 1

Kernel Version
5.10.y
Distro Version
Ubuntu 22.04 LTS
Other Software
Software in WSL2:
tools/perf, see builtin-sched.c line 673
clang version 1:14.0-55~exp2
Repro Steps
In WSL2:
export CC=clang

git clone --depth=1 https://github.com/microsoft/WSL2-Linux-Kernel.git
cd WSL2-Linux-Kernel/tools/perf
make

Expected Behavior
I expected perf to compile flawlessly.
Actual Behavior
WSL2-Linux-Kernel/tools/perf/builtin-sched.c breaks at the line 673, character 13, due to a warning that is actually an error (-Werror).
The warning is -Wcompare-distinct-pointer-types.
The type of the expression & (16 * 2014) is int *.
The type of the expression (__sysconf(75)) is long *.
The macro max(_max1, _max2) from WSL2-Linux-Kernel/tools/include/linux/kernel.h:43:17 compares both expressions and thus a warning is emitted.
Diagnostic Logs
builtin-sched.c:673:13: error: comparison of distinct pointer types ('typeof (16 * 1024) *' (aka 'int *') and 'typeof (__sysconf(75)) *' (aka 'long *')) [-Werror,-Wcompare-distinct-pointer-types]
                        (size_t) max(16 * 1024, PTHREAD_STACK_MIN));
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WSL2-Linux-Kernel/tools/include/linux/kernel.h:43:17: note: expanded from macro 'max'
        (void) (&_max1 == &_max2);              \
                ~~~~~~ ^  ~~~~~~
  CC       builtin-report.o

Please make a PR on the other repo.

I encountered the same problem as you did. I resolved the issue by updating WSL2.
In powershell:
wsl --update

Then in WSL2 do your Repro Steps：
export KERNEL_VERSION=$(uname -r | cut -d'-' -f1)
git clone --depth 1 --single-branch --branch=linux-msft-wsl-${KERNEL_VERSION} https://github.com/microsoft/WSL2-Linux-Kernel.git
cd WSL2-Linux-Kernel/tools/perf
make

authors: benoit-dubreuil iwonder1996 pmartincic