GHC's tct_closed flag is not being set correctly
The Note [Bindings with closed types] in TcEnv describes when a binding is "closed", which in turn affects generalisation. (See the Note for details.)
But the implementation doesn't follow the Note. Instead it uses this function in TcEnv:
isClosedLetBndr :: Id -> TopLevelFlag
-- See Note [Bindings with closed types] in TcRnTypes
-- Note that we decided if a let-bound variable is closed by
-- looking at its type, which is slightly more liberal, and a whole
-- lot easier to implement, than looking at its free variables
isClosedLetBndr id
| isEmptyVarSet (tyCoVarsOfType (idType id)) = TopLevel
| otherwise = NotTopLevel
It may be easier but it's also wrong. Consider
f x = ( let g y = x+y in ...
, x::Int)
Is g closed (which affects how definitions in ... are generalised)? Well if we typecheck the second element of the tuple first, we may "know" that x::Int by the time we are inferring a type for g, conclude that g has no free type variables, and say that it is closed.
But if we do the x::Int part second, so while type checking the let we think that x::alpha, then we'll say that g is open.
This looks nasty. I think we should do it the way the Note says.
Thanks to Facundo for pointing this out. Not urgent, but plainly wrong.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | facundominguez@gmail.com |
| Operating system | |
| Architecture |