oxalica / nil

NIx Language server, an incremental analysis assistant for writing in Nix.
Apache License 2.0
1.35k stars 40 forks source link

Type system and attributes analysis #14

Open oxalica opened 2 years ago

oxalica commented 2 years ago

Previously mentioned in,

Without some kinds of "evaluation" going on, it's not possible to complete any meaningful attributes after . or ?. The most obvious thought is to introduce a type system with inference.

For a typical file from nixpkgs,

{ lib, stdenv, fetchurl, foo }:
stdenv.mkDerivation rec {
  pname = "hello";
  src = fetchurl {
    url = "...";
    sha256 = "...";
  };
  buildInputs = lib.optional condition foo;
  # ...
}

We have these main goals:

Since the file itself doesn't provide any information about the types of its parameter. We should somehow figure out how it is expected to be called, by either,

  1. Tracking all reference sites (via path) of this file. Then somehow do top-down type inference.
  2. Assume the top-level parameter is a subset of nixpkgs.legacyPackages.<system>. Guess parameter types by evaluating corresponding attributes via Nix invocation.

I think we'll go method (2) since it's much simpler and works in most cases.

If anyone has more ideas on this, please comments here.

LunNova commented 2 years ago

Since 2 is easy and mostly works, if there are cases where it's not sufficient a way to annotate (a comment after the arg?) the correct type could be useful.

I like the idea of for flakes being able to evaluate the flake and its outputs and record the types things had during that evaluation so they're guaranteed to be right. Could even record multiple types when something has different types depending on where it's called. That also sounds really hard.

lf- commented 1 year ago

An idea I have about this issue is to possibly use type annotations or otherwise say where the things going into some lambda come from, since it will be different in NixOS modules (regrettably).

Like:

# @type callPackage
{ hello, stdenv }: ....
oxalica commented 1 year ago

The initial implementation of type system is included in 2022-11-07. Currently type inference is done in individual files and have no information input. Polymorphism is also not implemented yet. But it already improved the completion experience a lot.

oxalica commented 1 year ago

Type schema of flake.nix is implemented since d044c9c5b4241975ff64f7e1ee4ad0b26c036fea. Completion of inputs and known input fields like outPath, modifiedDate work now. But since we don't evaluate flakes yet, their real output cannot be completed. Screenshot_20230203_032552

Flake output fields also work, but only when a direct Attrset literal is given in the output. If you use other wrappers like flake-utils, it will not work currently.

Screenshot_20230203_032525

ModProg commented 1 year ago

Ideally this could be extended to even provide diagnostics.

I thought, one could start with typing all builtins and maybe nixpkgs.lib and then inferring every time there is a guaranteed type conflict, i.e. when someone swaps the arguments of map.

anna328p commented 4 days ago

Are there plans to add support for type annotations?