Skip to content

Conversation

@dolio
Copy link
Contributor

@dolio dolio commented Oct 23, 2025

This PR introduces more variance tracking into the type checker. As far as type checking goes, this isn't a huge change. The type checker can be given a collection of variance info for types, and it will be used in the right spot when checking.

The rest is mostly the variance inference for data types, and the plumbing necessary to perform that inference and get the information into the type checker. The inference classifies each parameter of a data type in one of four ways:

  1. Phantom (T A ~ T B for all A and B)
  2. Covariant (T A <= T B when A <= B)
  3. Contravariant (T A <= T B when A >= B)
  4. Invariant (T A = T B when A = B)

The inference starts with some basic information about wired-in types (like lists), and builds up the information by checking groups of mutually defined data types in dependency order.

The new subtyping possibilities changed how some errors present, so I tried to tweak the error reporting to maintain relatively good messages.

At the moment, no type declarations are variance checked. However,
basic variance information is available for lists an immutable arrays.
There is a procedure for inferring variance, and the type checking
method should work for whatever variance information is provided.
Most types will simply have no information available currently, meaning
they are treated as invariant.
- Freshen variables in declarations before solving. This avoids
  accidentally conflating variables from separate separate
  declarations based on name.
- Adjust some defaulting behavior for unknown variables (assume
  invariant for safety, because the phantom case should be ensured for
  valid variables via other means).
Copy link
Member

@pchiusano pchiusano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!!

I think phantom we may want to keep as invariant, unless I am misunderstanding. The reason is we just don't know what the user's intent was.

Like if you exchange a value for a Hashed Nat (a phantom-typed hash), you don't want that to be cast to a Hashed Text automatically. You want to have to take explicit action there.

Ideally we could just have kind annotations but in the absence of that I'm thinking phantom type parameters are treated as invariant. WDYT?

@dolio
Copy link
Contributor Author

dolio commented Oct 24, 2025

Yeah, I was wondering about that myself. As you say, there are uses of phantom types where you don't actually want anything to vary.

I can just make phantom things behave as invariant, or map phantoms to invariants for now.

@pchiusano
Copy link
Member

I can just make phantom things behave as invariant, or map phantoms to invariants for now.

@dolio yup sounds good to me.

@dolio
Copy link
Contributor Author

dolio commented Oct 27, 2025

I don't really understand the ormolu problem. It seems to be dying on import Foo qualified ..., but we've been using those for a while. And some of its complaints were already there before I touched the file in question.

dolio and others added 4 commits October 27, 2025 15:21
I believe this should have already been removed via a merge with trunk,
but something about the merge kept it around.
@aryairani aryairani merged commit 481c806 into trunk Oct 28, 2025
32 checks passed
@aryairani aryairani deleted the topic/variance branch October 28, 2025 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants