
#16288: Core Lint error: Occurrence is GlobalId, but binding is LocalId -------------------------------------+------------------------------------- Reporter: monoidal | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash or panic | Test Case: Blocked By: | Blocking: 15840 Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): OK I see what is happening. First, read `OccurAnal` * `Note [Binder swap]` * `Note [Binder swap on GlobalId scrutinees]`. (This case happens in the program concerned, with scrutinee `pretV`.) The trouble is that the binder-swap, done by the occurrence analyser, transforms {{{ case A.foo{r872} of bar { K x -> ...(A.foo{r872})... } ===> case A.foo{r872} of bar { K x -> let foo{r872} = bar in ...(A.foo{r872})... }}} where `A.foo{r872}` is a `GlobalId` with unique `r872`. In the binder- swap we make a `LocalId` for `foo{r872}` ''with the same unique'', which deliberately shadows the global binding. After the simplifer substitutes it out we'll get {{{ case A.foo{r872} of bar { K x -> ...(bar)... }}} which is what we want. Alas, the intermediate form does not satisfy Lint's rules, because a `GlobalId` occurrence is bound by a `LocalId` binding. Mostly this does not show up, because we run the simplifier before linting. But ''unfoldings'' are occurrence-analysed (so that they are all ready for inlining) so the linter sees the occurrence-analysed form and barfs. ----------- What to do? A quick fix is simply not to do the binder-swap when occurrence analysing unfoldings. Replace the calls to `occurAnalyseExpr` in `CoreUnfold` with `occurAnalyseExpr_NoBinderSwap`. But that just makes things yet a bit more complicated. An alternative, and I think nicer, solution is to make the occcurrence analyser do the binder-swap substitution as it goes. Instead of adding a let-binding (as now) and doing some fancy footwork to gather the right occurrence info (as now -- e.g. `occ_gbl_scruts`), we can simply carry a substitution, and apply it to every variable. I'm not completely sure of the best path here. Maybe try both? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16288#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler