Suspicious uses of lookupExactOrOrig_maybe wrt field selectors
The current implementation of rnExpr (HsVar ...)
looks something like (slightly simplified):
rnExpr (HsVar _ (L l v))
= do { mb_name <- lookupExprOccRn v
; case mb_name of
{ Nothing
-> rnUnboundVar v
; Just (NormalGreName name)
-> return (HsVar noExtField (L l name), unitFV name)
; Just (FieldGreName fl)
-> do { let sel_name = flSelector fl
; return (HsRecSel noExtField (FieldOcc sel_name (L l v) ), unitFV sel_name) } }
My point here being that we do something different for field selectors, returning an HsRecSel
instead of an HsVar
.
However, if you look at the implementation of lookupExprOccRn
, it ends up going through (among other things) lookupGlobalOccRn_overloaded
:
lookupGlobalOccRn_overloaded :: DuplicateRecordFields -> FieldsOrSelectors -> RdrName
-> RnM (Maybe AmbiguousResult)
lookupGlobalOccRn_overloaded dup_fields_ok fos rdr_name =
lookupExactOrOrig_maybe rdr_name (fmap (UnambiguousGre . NormalGreName)) $
do { res <- lookupGreRn_helper fos rdr_name
; case res of
GreNotFound -> fmap UnambiguousGre <$> lookupOneQualifiedNameGHCi fos rdr_name
OneNameMatch gre -> return $ Just (UnambiguousGre (gre_name gre))
MultipleNames gres
| all isRecFldGRE gres
, dup_fields_ok == DuplicateRecordFields -> return $ Just AmbiguousFields
| otherwise -> do
addNameClashErrRn rdr_name gres
return (Just (UnambiguousGre (gre_name (NE.head gres)))) }
The above code shows that we first try to look up an Orig
or Exact
Name
in which case we always return a non-field GreName
, and if that fails we go to the normal path which might return a field GRE or not.
This seems completely wrong to me: what if we have the exact name of a field selector? We should then surely return a field GreName
? If we don't, then rnExpr
will return an HsVar
instead of an HsRecSel
.
I'm attempting to fix this in !8686 (merged). It seems that lookupExactOrOrig_maybe
should not return just a Name
, but something which has more information (in particular, enough information to distinguish fields from non-fields). I'm not sure how to engineer this however, especially with Orig
names which just correspond to Name
s in the NameCache
, and I don't know how we can extract more information out of them.