Skip to content
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

Design Meeting Notes, 3/8/2019 #30279

Closed
DanielRosenwasser opened this issue Mar 8, 2019 · 0 comments
Closed

Design Meeting Notes, 3/8/2019 #30279

DanielRosenwasser opened this issue Mar 8, 2019 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

Higher order function type inference

#30215

Reference code

declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;
declare function invoke<A extends any[], R>(f: (...args: A) => R, ...args: A): R;

declare function box<T>(x: T): { value; T };
declare function list<T>(x: T): T[];
declare function map<T, U>(f: (t: T) => U): (a: T[]) => U[];
  • Seemed to get a lot of enthusiasm on this issue.
  • Builds on improvements to our inference - specifically, this does better when doing inference from other generic functions.
    • First, we added a change to make types with generic signatures contextually sensitive.

      • We have multiple rounds of inference, and marking arguments as contextually sensitive means we can defer inferring from them to later rounds.
        • This allows us to let types flow into function expressions to understand their output types.
      • This is important each pass of our inference process is fundamentally just a left-to-right process over provided arguments.
      • This example used to give {}[] before this change. Now list is contextually sensitive and we infer number for A, and the output type is number[].
        invoke(list, 42);
    • Another change is an extension of the last change - any invoked expression that has a generic call signature that can return a function is also contextually sensitive.

      // Would previously be `{}[]`, now is `number[]` because the `map` is generic and returns a function,
      // and is now considered contextually sensitive.
      invoke(map(x => x * 2), [1, 2, 3, 4]);
      
      invoke(list, identity(42));
    • The last big change is that if the output type of a signature is a non-generic single signature type, then any type parameters which had no inferences will be "promoted" to fresh type variables on a version of the output type that is generic.

      • Is this a problem for named type arguments?
        • Any change to an invocation can change the way the type arguments are named in output types.
      • In a sense, these fresh type variables get observed as existential types.
    • Is there a way to opt out of this behavior?

      • No.
      • What if you specify a type parameter list on the output type?
        • Yes.
          • Can I specify an empty type parameter list?
            • No.
              • Huh.
                • Anders: I feel relatively confident in the change; observed differences seem to have been questionable anyway.
    • Only user test suite code that saw changes is RxJS, fp-ts, and Ramda.

      • RxJS: Looks like fixes. (@benlesh)
      • fp-ts: Better errors, fixes. One .d.ts file changed by creating a generic output type(!) (@gcanti)
      • Ramda: In some cases, better types. In a few, it's just people putting type parameters in the wrong place.
    • Infra: we didn't need the stupid excludeArguments array in overload resolution.

      • "That constellation of weird hacks was just weird."
  • Limitations
    • We haven't changed anything for unannotated function expressions

      declare function box<T>(a: T): { value: T };
      pipe(x => [x], box); // this is (x: any) => { value: any[] }

      In other words, we don't try to infer type parameters for x.

Cross-compilation incremental builds

#29813

  • High level idea: serializing the information we have in --watch mode to disk to get way faster subsequent compiles.
  • New flag called: --incremental
    • Turned on by default for all composite projects, and defaults to a file called .tsbuildinfo.
    • But can be turned on for all projects!
  • Works best for files with modules
  • outFile may need some changes because something will always need to cha
  • What's the .tsbuildinfo file look like?
    • Here's the schema:

      export interface SourceFileInfo {
          // List of helpers in own source files emitted if no prepend is present
          helpers?: string[];
          prologues?: SourceFilePrologueInfo[];
      }
      
      export interface BundleFileInfo {
          sections: BundleFileSection[];
          sources?: SourceFileInfo;
      }
      
      export interface BundleBuildInfo {
          js?: BundleFileInfo;
          dts?: BundleFileInfo;
          commonSourceDirectory: string;
          sourceFiles: ReadonlyArray<string>;
      }
      
      export interface ProgramBuildInfo {
          fileInfos: MapLike<BuilderState.FileInfo>;
          options: CompilerOptions;
          referencedMap?: MapLike<string[]>;
          exportedModulesMap?: MapLike<string[]>;
          semanticDiagnosticsPerFile?: string[];
      }
      
      export interface BuildInfo {
          bundle?: BundleBuildInfo;
          program?: ProgramBuildInfo;
      }
  • You can just delete this and everything should be fine, right?
    • Yes.
    • Though, there's an open question of whether deleting the file should trigger a full rebuild in either --watch or --build?
      • Seems like yes.
  • Can MSBuild take advantage of this stuff?
    • Talk about this offline.
  • .tsbuildinfo.json so tooling can understand it?
    • Well, do we want people to be able to consume this file?
      • No, but it's useful and people will.
        • But we can't provide guarantees about this.
      • What's the versioning story?
        • Do these files need some sort of versioning?
        • Maybe the the compiler can track this?
          • The compiler needs to know what versions it's compatible with, so then why not a format version?
        • Easier to just say that no version of TypeScript is compatible with .tsbuildinfo files from other compilations.
          • Resolution: Version number in file.
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Mar 8, 2019
@DanielRosenwasser DanielRosenwasser changed the title Design Meeting Notes 3/8/2019 Design Meeting Notes, 3/8/2019 Mar 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

1 participant