I tried to figure out where in the 8.0.2 branch this regression was introduced. Unfortunately, I wasn't able to isolate an exact commit, because the range of commits in which it was introduced doesn't build. However, I know for sure it was introduced between:
From cc02156b859159eff7d86043f67826c17f2bd170 Mon Sep 17 00:00:00 2001From: Bartosz Nitka <niteria@gmail.com>Date: Mon, 18 Apr 2016 07:32:03 -0700Subject: [PATCH] Make benign non-determinism in pretty-printing more obviousThis change takes us one step closer to being able to remove`varSetElemsWellScoped`. The end goal is to make every sourceof non-determinism obvious at the source level, so that whenwe achieve determinism it doesn't get broken accidentally.Test Plan: compile GHCReviewers: simonmar, goldfire, simonpj, austin, bgamariReviewed By: simonpjSubscribers: thomieDifferential Revision: https://phabricator.haskell.org/D2123GHC Trac Issues: #4012(cherry picked from commit 0f96686b10fd36d479a54c71a6e1753193e85347)
From ae94a31e7f162b4a3ef6b6f837bd6006a98f639a Mon Sep 17 00:00:00 2001From: Simon Peyton Jones <simonpj@microsoft.com>Date: Fri, 22 Apr 2016 10:47:14 +0100Subject: [PATCH] Refactor free tyvars on LHS of rulesA RULE can have unbound meta-tyvars on the LHS. Consider data T a = C foo :: T a -> Int foo C = 1 {-# RULES "myrule" foo C = 1 #-}After type checking the LHS becomes (foo alpha (C alpah)) and we donot want to zap the unbound meta-tyvar 'alpha' to Any, because thatlimits the applicability of the rule. Instead, we want to quantifyover it!Previously there was a rather clunky implementation of thisquantification, buried in the zonker in TcHsSyn (zonkTvCollecting).This patch refactors it so that the zonker just turns the meta-tyvarinto a skolem, and the desugarer adds the quantification. See DsBindsNote [Free tyvars on rule LHS]. As it happened, the desugarer wasalready doing something similar for dictionaries. See DsBindsNote [Free dictionaries on rule LHS]No change in functionality, but less cruft.(cherry picked from commit 6ad2b42f866fa718855cc5c850e3549bc1428b3c)
I doubt that ae94a31e was responsible, since it seems to only touch rewrite RULES. Furthermore, niteria authored all commits between cc02156b and that point. Do you have a hunch what might be happening here, niteria?
Actually, compiling these commits from the HEAD branch (instead of the 8.0.2 branch) turned out to be more fruitful. I discovered that the commit which introduced this regression is c9bcaf31:
From c9bcaf3165586ac214fa694e61c55eb45eb131ab Mon Sep 17 00:00:00 2001From: Bartosz Nitka <niteria@gmail.com>Date: Tue, 26 Apr 2016 05:58:24 -0700Subject: [PATCH] Kill varSetElemsWellScoped in quantifyTyVarsvarSetElemsWellScoped introduces unnecessary non-determinism ininferred type signatures.Removing this instance required changing the representation ofTcDepVars to use deterministic sets.This is the last occurence of varSetElemsWellScoped, allowing me tofinally remove it.Test Plan:./validateI will update the expected outputs when commiting, some reorderingof type variables in types is expected.
This appears to be another case of unspoken assumptions about the order.
On top of c9bcaf31 it suffices to make this change:
--- a/compiler/typecheck/TcMType.hs+++ b/compiler/typecheck/TcMType.hs@@ -874,7 +874,7 @@ quantifyZonkedTyVars gbl_tvs (DV{ dv_kvs = dep_tkvs, dv_tvs = nondep_tkvs }) -- closeOverKinds all_cvs: do not quantify over coercion -- variables, or any any tvs that a covar depends on- nondep_tvs = dVarSetElems $+ nondep_tvs = varSetElems . dVarSetToVarSet $ nondep_tkvs `dVarSetMinusVarSet` gbl_tvs -- No worry about dependent covars here; they are -- all in dep_tkvs
to make the problem go away. It also fixes the problem on HEAD, except you have to use nonDetEltsUFM instead of varSetElems.
I think this has been broken since 67465497.
Running before c9bcaf31 with -dunique-increment=-1 reproduces the problem.
It appears that when we growThetaTyVarsDSet we add some kind variables to the nondependent type var set, but the vars inside depend on the newly added kind var. We then linearize without any regard for dependencies, because there shouldn't be any.