Skip to content

NamedFieldPuns should allow "ambiguous" field names

Consider the following example:

{-# LANGUAGE NamedFieldPuns #-}

import DupType

data A = A { field :: Int }

f :: A -> Int
f A { field } = field

with

module DupType where

data B = B { field :: Int }

This results in the following error:

A.hs:8:7: error:
    Ambiguous occurrence ‘field’
    It could refer to either ‘DupType.field’,
                             imported from ‘DupType’ at A.hs:3:1-14
                             (and originally defined at DupType.hs:3:14-18)
                          or ‘Main.field’, defined at A.hs:5:14
  |
8 | f A { field } = field
  |       ^^^^^

This seems like poor behavior, because since a particular constructor is used, it is unambiguous which field is intended. In particular, this is inconsistent with RecordWildCards. Consider that f A { .. } = field compiles perfectly fine.

I actually encountered this issue in a bit of a different usecase. I was using NamedFieldPuns along with DuplicateFieldNames. However, I got the constructor name wrong. After the scope error in the output, there was an ambiguous field name error. This was quite confusing because DuplicateFieldNames was on, so ambiguity should be fine! Took me a while to realize that the scope error was the root issue. With the constructor name fixed, the code compiled. If the constructor was used to resolve field names, then the 2nd error wouldn't have been emitted.

I realize that broadening the code allowed by NamedFieldPuns could lead to issues where code written for newer GHC versions does not work with older GHC versions. This certainly will not change the meaning of older code. What's the policy on this?

Edited by Michael Sloan
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information