-
-
Notifications
You must be signed in to change notification settings - Fork 389
Consider HsExpanded
expressions during SYB traversal
#3579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting the patch out so quickly!
@@ -347,14 +354,19 @@ collectRecords = everything (<>) (maybeToList . (Nothing `mkQ` getRecPatterns `e | |||
collectNames :: GenericQ (UniqFM Name [Name]) | |||
collectNames = everything (plusUFM_C (<>)) (emptyUFM `mkQ` (\x -> unitUFM x [x])) | |||
|
|||
getRecCons :: LHsExpr (GhcPass 'Renamed) -> Maybe RecordInfo | |||
getRecCons :: LHsExpr (GhcPass 'Renamed) -> (Maybe RecordInfo, Bool) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with returning a Maybe instead of a List here is that you can only return one match from within the HsExpanded expression, even though there could be multiple matches. This example showcases this.
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Construction where
data MyRec = MyRec
{ foo :: Int
, bar :: Int
, baz :: Char
}
data YourRec = YourRec
{ foo2 :: MyRec
, bar2 :: Int
, baz2 :: Char
}
myRecExample = MyRec {..}
where
foo = 5
bar = 6
baz = 'a'
yourRecExample = YourRec {..}
where
foo2 = myRecExample
bar2 = 5
baz2 = 'a'
convertMe :: () -> Int
convertMe _ =
(let MyRec{..} = myRecExample
YourRec{..} = yourRecExample
in foo2).foo
In this case, your code, would only offer to rewrite the first matched wildcard instead of both.
This example is very constructed, however, HsExpansion could possibly be used for more cases in the future, which would cause these sorts of edge cases to also appear more often.
where | ||
mkRecInfo :: LHsExpr (GhcPass 'Renamed) -> Maybe RecordInfo | ||
mkRecInfo expr = listToMaybe | ||
[ RecordInfoCon realSpan' (unLoc expr) | RealSrcSpan realSpan' _ <- [ getLoc expr ]] | ||
getRecCons _ = Nothing | ||
getRecCons _ = (Nothing, False) | ||
|
||
getRecPatterns :: LPat (GhcPass 'Renamed) -> Maybe RecordInfo | ||
getRecPatterns conPat@(conPatDetails . unLoc -> Just (RecCon flds)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConPat can also occur inside an HsExpanded expression. For example, the constructed example above uses ConPat (because the wildcards occur in the let binding)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually thinking about it though, you shouldn't need to change this, because getRecCon
should already, by calling collectRecords
, return both RecordCon
and ConPat
matches. May want to point that out in the comments though.
Closed. Completed in #3750 . |
Fixes #3574. Implements the proposed solution and adds the given reproduction steps as a test case.