Skip to content

Conversation

@ChrisPenner
Copy link
Member

@ChrisPenner ChrisPenner commented Dec 5, 2025

Overview

We've noticed that since let-rec bindings, constructors, and ability lists are all ordered by hash, they sometimes jump around when you make changes; this means the diffs also get much worse since the bindings might have completely re-ordered in-between changes.

internal ticket

There's no real need for these to be printed in hash-order, since the parser will re-order them according to hash on ingestion anyways.

This changes the printer to put things in a consistent order by name rather than hash.

Implementation approach and notes

Add some sorts in the printer modules.

Test coverage

  • See the new print-ordering.md transcript tests; as well as all the re-rendered existing transcripts

@ChrisPenner ChrisPenner changed the title Cp/ordered printing Human-centric let-rec, constructor and ability orderings Dec 5, 2025
@ChrisPenner ChrisPenner marked this pull request as ready for review December 5, 2025 20:42
@ChrisPenner
Copy link
Member Author

Q before merging, @aryairani @mitchellwrosen ,
If I re-order a structural type on printing from structural type Bool = True | False into structural type Bool = False | True is that going to swap every True and False 😓 ?

Maybe I should not do this for structural types just to be sure?
Or does it still apply for non-structural types? I've gotta think about it a bit.

@ChrisPenner ChrisPenner requested a review from hojberg December 5, 2025 20:46
@ChrisPenner ChrisPenner marked this pull request as draft December 5, 2025 20:46
@pchiusano
Copy link
Member

@ChrisPenner did you see #5893 it gives the safe criteria you can use for sorting

@aryairani
Copy link
Contributor

Q before merging, @aryairani @mitchellwrosen , If I re-order a structural type on printing from structural type Bool = True | False into structural type Bool = False | True is that going to swap every True and False 😓 ?

Maybe I should not do this for structural types just to be sure? Or does it still apply for non-structural types? I've gotta think about it a bit.

I'm going to do a quick transcript for this, but one answer is that structural type Bool = True | False would be better of an error anyway, since it's a structural type and the constructors are not structurally distinct.

Now what about for unique types? Do we not have the same problem?

@aryairani
Copy link
Contributor

aryairani commented Dec 5, 2025

@ChrisPenner
Okay, so it's basically the worst possible outcome:

structural type SBool = SFalse | STrue
> add

  Done.

> names STrue SFalse

  'STrue':
  Hash            Kind   Names
  #6kbe32g06n#1   Term   SBool.STrue

  'SFalse':
  Hash            Kind   Names
  #6kbe32g06n#0   Term   SBool.SFalse

0 = False; 1 = True

structural type SBool = STrue | SFalse
  Loading changes detected in scratch.u.

  No changes found.

Oh good, nothing's changed.

> add

  Done.

> names STrue SFalse

  'STrue':
  Hash            Kind   Names
  #6kbe32g06n#0   Term   SBool.STrue

  'SFalse':
  Hash            Kind   Names
  #6kbe32g06n#1   Term   SBool.SFalse

Oh just kidding, it actually did change. 0 is True and 1 is False. It doesn't break any code, but it may break your mind.

unique type UBool = UFalse | UTrue
> add

  Done.

> names UFalse UTrue

  'UFalse':
  Hash            Kind   Names
  #5l0gnirl3n#0   Term   UBool.UFalse

  'UTrue':
  Hash            Kind   Names
  #5l0gnirl3n#1   Term   UBool.UTrue
unique type UBool = UTrue | UFalse
  Loading changes detected in scratch.u.

  No changes found.
> add

  Done.

> names UFalse UTrue

  'UFalse':
  Hash            Kind   Names
  #5l0gnirl3n#1   Term   UBool.UFalse

  'UTrue':
  Hash            Kind   Names
  #5l0gnirl3n#0   Term   UBool.UTrue

Same issue here, possibly less surprising.

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