Skip to content

Commit

Permalink
Fix bug with postqualified imports and qualifiedStyle=unrestricted (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ulidtko authored and shayne-fletcher committed Oct 13, 2023
1 parent 2cb667e commit 2fa5e9f
Show file tree
Hide file tree
Showing 16 changed files with 122 additions and 42 deletions.
2 changes: 2 additions & 0 deletions data/import_style.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
- {name: HypotheticalModule3, importStyle: qualified}
- {name: 'HypotheticalModule3.*', importStyle: unqualified}
- {name: 'HypotheticalModule3.OtherSubModule', importStyle: unrestricted, qualifiedStyle: post}
- {name: HypotheticalModule4, importStyle: qualified, as: HM4, asRequired: true}
- {name: HypotheticalModule5, importStyle: qualified, qualifiedStyle: post}
8 changes: 4 additions & 4 deletions hlint.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ library
deriving-aeson >= 0.2,
filepattern >= 0.1.1

if !flag(ghc-lib) && impl(ghc >= 9.6.1) && impl(ghc < 9.7.0)
if !flag(ghc-lib) && impl(ghc >= 9.8.1) && impl(ghc < 9.9.0)
build-depends:
ghc == 9.6.*,
ghc == 9.8.*,
ghc-boot-th,
ghc-boot
else
build-depends:
ghc-lib-parser == 9.6.*
ghc-lib-parser == 9.8.*
build-depends:
ghc-lib-parser-ex >= 9.6.0.2 && < 9.6.1
ghc-lib-parser-ex >= 9.8.0.0 && < 9.8.1

if flag(gpl)
build-depends: hscolour >= 1.21
Expand Down
2 changes: 1 addition & 1 deletion src/Config/Yaml.hs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ parseFail (Val focus path) msg = fail $
-- aim to show a smallish but relevant context
dotDot (fromMaybe (encode focus) $ listToMaybe $ dropWhile (\x -> BS.length x > 250) $ map encode contexts)
where
(steps, contexts) = unzip $ reverse path
(steps, contexts) = Prelude.unzip $ reverse path
dotDot x = let (a,b) = BS.splitAt 250 x in BS.unpack a ++ (if BS.null b then "" else "...")

parseArray :: Val -> Parser [Val]
Expand Down
6 changes: 3 additions & 3 deletions src/GHC/Util/FreeVars.hs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ instance FreeVars (LocatedA (HsExpr GhcPs)) where
freeVars (L _ (RecordCon _ _ (HsRecFields flds _))) = Set.unions $ map freeVars flds -- Record construction.
freeVars (L _ (RecordUpd _ e flds)) =
case flds of
Left fs -> Set.unions $ freeVars e : map freeVars fs
Right ps -> Set.unions $ freeVars e : map freeVars ps
RegularRecUpdFields _ fs -> Set.unions $ freeVars e : map freeVars fs
OverloadedRecUpdFields _ ps -> Set.unions $ freeVars e : map freeVars ps
freeVars (L _ (HsMultiIf _ grhss)) = free (allVars grhss) -- Multi-way if.
freeVars (L _ (HsTypedBracket _ e)) = freeVars e
freeVars (L _ (HsUntypedBracket _ (ExpBr _ e))) = freeVars e
Expand Down Expand Up @@ -174,7 +174,7 @@ instance FreeVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (FieldOcc GhcPs)) (
freeVars o@(L _ (HsFieldBind _ _ x _)) = freeVars x

instance FreeVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (AmbiguousFieldOcc GhcPs)) (LocatedA (HsExpr GhcPs)))) where
freeVars (L _ (HsFieldBind _ x _ True)) = Set.singleton $ rdrNameOcc $ rdrNameAmbiguousFieldOcc $ unLoc x -- a pun
freeVars (L _ (HsFieldBind _ x _ True)) = Set.singleton $ rdrNameOcc $ ambiguousFieldOccRdrName $ unLoc x -- a pun
freeVars (L _ (HsFieldBind _ _ x _)) = freeVars x

instance FreeVars (LocatedA (HsFieldBind (LocatedAn NoEpAnns (FieldLabelStrings GhcPs)) (LocatedA (HsExpr GhcPs)))) where
Expand Down
6 changes: 3 additions & 3 deletions src/GHC/Util/HsExpr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ dotApps (x : xs) = dotApp x (dotApps xs)

-- | @lambda [p0, p1..pn] body@ makes @\p1 p1 .. pn -> body@
lambda :: [LPat GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs
lambda vs body = noLocA $ HsLam noExtField (MG Generated (noLocA [noLocA $ Match EpAnnNotUsed LambdaExpr vs (GRHSs emptyComments [noLocA $ GRHS EpAnnNotUsed [] body] (EmptyLocalBinds noExtField))]))
lambda vs body = noLocA $ HsLam noExtField (MG (Generated DoPmc) (noLocA [noLocA $ Match EpAnnNotUsed LambdaExpr vs (GRHSs emptyComments [noLocA $ GRHS EpAnnNotUsed [] body] (EmptyLocalBinds noExtField))]))

-- | 'paren e' wraps 'e' in parens if 'e' is non-atomic.
paren :: LHsExpr GhcPs -> LHsExpr GhcPs
Expand Down Expand Up @@ -242,7 +242,7 @@ niceLambdaR ss e =
let grhs = noLocA $ GRHS EpAnnNotUsed [] e :: LGRHS GhcPs (LHsExpr GhcPs)
grhss = GRHSs {grhssExt = emptyComments, grhssGRHSs=[grhs], grhssLocalBinds=EmptyLocalBinds noExtField}
match = noLocA $ Match {m_ext=EpAnnNotUsed, m_ctxt=LambdaExpr, m_pats=map strToPat ss, m_grhss=grhss} :: LMatch GhcPs (LHsExpr GhcPs)
matchGroup = MG {mg_ext=Generated, mg_alts=noLocA [match]}
matchGroup = MG {mg_ext=Generated DoPmc, mg_alts=noLocA [match]}
in (noLocA $ HsLam noExtField matchGroup, const [])


Expand All @@ -252,7 +252,7 @@ replaceBranches :: LHsExpr GhcPs -> ([LHsExpr GhcPs], [LHsExpr GhcPs] -> LHsExpr
replaceBranches (L l (HsIf _ a b c)) = ([b, c], \[b, c] -> L l (HsIf EpAnnNotUsed a b c))

replaceBranches (L s (HsCase _ a (MG FromSource (L l bs)))) =
(concatMap f bs, L s . HsCase EpAnnNotUsed a . MG Generated . L l . g bs)
(concatMap f bs, L s . HsCase EpAnnNotUsed a . MG (Generated DoPmc). L l . g bs)
where
f :: LMatch GhcPs (LHsExpr GhcPs) -> [LHsExpr GhcPs]
f (L _ (Match _ CaseAlt _ (GRHSs _ xs _))) = [x | (L _ (GRHS _ _ x)) <- xs]
Expand Down
4 changes: 2 additions & 2 deletions src/Hint/Export.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import GHC.Types.Name.Reader
exportHint :: ModuHint
exportHint _ (ModuleEx (L s m@HsModule {hsmodName = Just name, hsmodExports = exports}) )
| Nothing <- exports =
let r = o{ hsmodExports = Just (noLocA [noLocA (IEModuleContents EpAnnNotUsed name)] )} in
let r = o{ hsmodExports = Just (noLocA [noLocA (IEModuleContents (Nothing, EpAnnNotUsed) name)] )} in
[(ignore "Use module export list" (L s o) (noLoc r) []){ideaNote = [Note "an explicit list is usually better"]}]
| Just (L _ xs) <- exports
, mods <- [x | x <- xs, isMod x]
Expand All @@ -32,7 +32,7 @@ exportHint _ (ModuleEx (L s m@HsModule {hsmodName = Just name, hsmodExports = ex
, exports' <- [x | x <- xs, not (matchesModName modName x)]
, modName `elem` names =
let dots = mkRdrUnqual (mkVarOcc " ... ")
r = o{ hsmodExports = Just (noLocA (noLocA (IEVar noExtField (noLocA (IEName noExtField (noLocA dots)))) : exports') )}
r = o{ hsmodExports = Just (noLocA (noLocA (IEVar Nothing (noLocA (IEName noExtField (noLocA dots)))) : exports') )}
in
[ignore "Use explicit module export list" (L s o) (noLoc r) []]
where
Expand Down
5 changes: 3 additions & 2 deletions src/Hint/Extensions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ import Refact.Types
import Data.Set qualified as Set
import Data.Map qualified as Map

import GHC.Data.FastString
import GHC.Types.SrcLoc
import GHC.Types.SourceText
import GHC.Hs
Expand Down Expand Up @@ -492,8 +493,8 @@ used MultiWayIf = hasS isMultiIf
used NumericUnderscores = hasS f
where
f :: OverLitVal -> Bool
f (HsIntegral (IL (SourceText t) _ _)) = '_' `elem` t
f (HsFractional (FL (SourceText t) _ _ _ _)) = '_' `elem` t
f (HsIntegral (IL (SourceText t) _ _)) = '_' `elem` unpackFS t
f (HsFractional (FL (SourceText t) _ _ _ _)) = '_' `elem` unpackFS t
f _ = False

used LambdaCase = hasS isLCase
Expand Down
2 changes: 1 addition & 1 deletion src/Hint/Lambda.hs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ lambdaBind
where
reform :: [LPat GhcPs] -> LHsExpr GhcPs -> Located (HsDecl GhcPs)
reform ps b = L (combineSrcSpans (locA loc1) (locA loc2)) $ ValD noExtField $
origBind {fun_matches = MG Generated (noLocA [noLocA $ Match EpAnnNotUsed ctxt ps $ GRHSs emptyComments [noLocA $ GRHS EpAnnNotUsed [] b] $ EmptyLocalBinds noExtField])}
origBind {fun_matches = MG (Generated DoPmc) (noLocA [noLocA $ Match EpAnnNotUsed ctxt ps $ GRHSs emptyComments [noLocA $ GRHS EpAnnNotUsed [] b] $ EmptyLocalBinds noExtField])}

mkSubtsAndTpl newPats newBody = (sub, tpl)
where
Expand Down
2 changes: 1 addition & 1 deletion src/Hint/ListRec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ findCase x = do
gRHS e = noLocA $ GRHS EpAnnNotUsed [] e :: LGRHS GhcPs (LHsExpr GhcPs) -- Guarded rhs.
gRHSSs e = GRHSs emptyComments [gRHS e] emptyLocalBinds -- Guarded rhs set.
match e = Match{m_ext=EpAnnNotUsed,m_pats=ps12, m_grhss=gRHSSs e, ..} -- Match.
matchGroup e = MG{mg_alts=noLocA [noLocA $ match e], mg_ext=Generated, ..} -- Match group.
matchGroup e = MG{mg_alts=noLocA [noLocA $ match e], mg_ext=Generated DoPmc, ..} -- Match group.
funBind e = FunBind {fun_matches=matchGroup e, ..} :: HsBindLR GhcPs GhcPs -- Fun bind.

pure (ListCase ps b1 (x, xs, b2), noLocA . ValD noExtField . funBind)
Expand Down
2 changes: 1 addition & 1 deletion src/Hint/Monad.hs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ monadLet xs = mapMaybe mkLet xs
grhs = noLocA (GRHS EpAnnNotUsed [] rhs)
grhss = GRHSs emptyComments [grhs] (EmptyLocalBinds noExtField)
match = noLocA $ Match EpAnnNotUsed (FunRhs p Prefix NoSrcStrict) [] grhss
fb = noLocA $ FunBind noExtField p (MG Generated (noLocA [match]))
fb = noLocA $ FunBind noExtField p (MG (Generated DoPmc) (noLocA [match]))
binds = unitBag fb
valBinds = ValBinds NoAnnSortKey binds []
localBinds = HsValBinds EpAnnNotUsed valBinds
Expand Down
2 changes: 1 addition & 1 deletion src/Hint/Naming.hs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ shortenLGRHS (L locGRHS (GRHS ttg0 guards (L locExpr _))) =
L locGRHS (GRHS ttg0 guards (L locExpr dots))
where
dots :: HsExpr GhcPs
dots = HsLit EpAnnNotUsed (HsString (SourceText "...") (mkFastString "..."))
dots = HsLit EpAnnNotUsed (HsString (SourceText (fsLit "...")) (fsLit "..."))

getNames :: LHsDecl GhcPs -> [String]
getNames decl = maybeToList (declName decl) ++ getConstructorNames (unLoc decl)
Expand Down
13 changes: 7 additions & 6 deletions src/Hint/NumLiteral.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
module Hint.NumLiteral (numLiteralHint) where

import GHC.Hs
import GHC.Data.FastString
import GHC.LanguageExtensions.Type (Extension (..))
import GHC.Types.SrcLoc
import GHC.Types.SourceText
Expand Down Expand Up @@ -49,18 +50,18 @@ numLiteralHint _ modu =

suggestUnderscore :: LHsExpr GhcPs -> [Idea]
suggestUnderscore x@(L _ (HsOverLit _ ol@(OverLit _ (HsIntegral intLit@(IL (SourceText srcTxt) _ _))))) =
[ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` srcTxt, srcTxt /= underscoredSrcTxt ]
[ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` unpackFS srcTxt, unpackFS srcTxt /= underscoredSrcTxt ]
where
underscoredSrcTxt = addUnderscore srcTxt
underscoredSrcTxt = addUnderscore (unpackFS srcTxt)
y :: LocatedAn an (HsExpr GhcPs)
y = noLocA $ HsOverLit EpAnnNotUsed $ ol{ol_val = HsIntegral intLit{il_text = SourceText underscoredSrcTxt}}
y = noLocA $ HsOverLit EpAnnNotUsed $ ol{ol_val = HsIntegral intLit{il_text = SourceText (fsLit underscoredSrcTxt)}}
r = Replace Expr (toSSA x) [("a", toSSA y)] "a"
suggestUnderscore x@(L _ (HsOverLit _ ol@(OverLit _ (HsFractional fracLit@(FL (SourceText srcTxt) _ _ _ _))))) =
[ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` srcTxt, srcTxt /= underscoredSrcTxt ]
[ suggest "Use underscore" (reLoc x) (reLoc y) [r] | '_' `notElem` unpackFS srcTxt, unpackFS srcTxt /= underscoredSrcTxt ]
where
underscoredSrcTxt = addUnderscore srcTxt
underscoredSrcTxt = addUnderscore (unpackFS srcTxt)
y :: LocatedAn an (HsExpr GhcPs)
y = noLocA $ HsOverLit EpAnnNotUsed $ ol{ol_val = HsFractional fracLit{fl_text = SourceText underscoredSrcTxt}}
y = noLocA $ HsOverLit EpAnnNotUsed $ ol{ol_val = HsFractional fracLit{fl_text = SourceText (fsLit underscoredSrcTxt)}}
r = Replace Expr (toSSA x) [("a", toSSA y)] "a"
suggestUnderscore _ = mempty

Expand Down
35 changes: 24 additions & 11 deletions src/Hint/Restrict.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import Data.Set qualified as Set
import Data.Map qualified as Map
import Data.List.Extra
import Data.List.NonEmpty (nonEmpty)
import Data.Either
import Data.Maybe
import Data.Monoid
import Data.Semigroup
Expand Down Expand Up @@ -157,6 +158,11 @@ checkPragmas modu flags exts mps =
, not $ null bad]
isGood def mp x = maybe def (within modu "" . riWithin) $ Map.lookup x mp


-- | Extension to GHC's 'ImportDeclQualifiedStyle', expressing @qualifiedStyle: unrestricted@,
-- i.e. the preference of "either pre- or post-, but qualified" in a rule.
data QualifiedPostOrPre = QualifiedPostOrPre deriving Eq

checkImports :: String -> [LImportDecl GhcPs] -> (Bool, Map.Map String RestrictItem) -> [Idea]
checkImports modu lImportDecls (def, mp) = mapMaybe getImportHint lImportDecls
where
Expand Down Expand Up @@ -190,30 +196,37 @@ checkImports modu lImportDecls (def, mp) = mapMaybe getImportHint lImportDecls
case fromMaybe ImportStyleUnrestricted $ getAlt riImportStyle of
ImportStyleUnrestricted
| NotQualified <- ideclQualified -> (Nothing, Nothing)
| otherwise -> (second (<> " or unqualified") <$> expectedQualStyle, Nothing)
ImportStyleQualified -> (expectedQualStyleDef, Nothing)
| otherwise -> (Just $ second (<> " or unqualified") expectedQualStyle, Nothing)
ImportStyleQualified -> (Just expectedQualStyle, Nothing)
ImportStyleExplicitOrQualified
| Just (False, _) <- first (== EverythingBut) <$> ideclImportList -> (Nothing, Nothing)
| otherwise ->
( second (<> " or with an explicit import list") <$> expectedQualStyleDef
( Just $ second (<> " or with an explicit import list") expectedQualStyle
, Nothing )
ImportStyleExplicit
| Just (False, _) <- first (== EverythingBut) <$> ideclImportList -> (Nothing, Nothing)
| otherwise ->
( Just (NotQualified, "unqualified")
( Just (Right NotQualified, "unqualified")
, Just $ Just (Exactly, noLocA []) )
ImportStyleUnqualified -> (Just (NotQualified, "unqualified"), Nothing)
expectedQualStyleDef = expectedQualStyle <|> Just (QualifiedPre, "qualified")
ImportStyleUnqualified -> (Just (Right NotQualified, "unqualified"), Nothing)
expectedQualStyle =
case fromMaybe QualifiedStyleUnrestricted $ getAlt riQualifiedStyle of
QualifiedStyleUnrestricted -> Nothing
QualifiedStylePost -> Just (QualifiedPost, "post-qualified")
QualifiedStylePre -> Just (QualifiedPre, "pre-qualified")
QualifiedStyleUnrestricted -> (Left QualifiedPostOrPre, "qualified")
QualifiedStylePost -> (Right QualifiedPost, "post-qualified")
QualifiedStylePre -> (Right QualifiedPre, "pre-qualified")
-- unless expectedQual is Nothing, it holds the Idea (hint) to ultimately emit,
-- except in these cases when the rule's requirements are fulfilled in-source:
qualIdea
| Just ideclQualified == (fst <$> expectedQual) = Nothing
-- the rule demands a particular importStyle, and the decl obeys exactly
| Just (Right ideclQualified) == (fst <$> expectedQual) = Nothing
-- the rule demands a QualifiedPostOrPre import, and the decl does either
| Just (Left QualifiedPostOrPre) == (fst <$> expectedQual)
&& ideclQualified `elem` [QualifiedPost, QualifiedPre] = Nothing
-- otherwise, expectedQual gets converted into a warning below (or is Nothing)
| otherwise = expectedQual
whenJust qualIdea $ \(qual, hint) -> do
let i' = noLoc $ (unLoc i){ ideclQualified = qual
-- convert non-Nothing qualIdea into hlint's refactoring Idea
let i' = noLoc $ (unLoc i){ ideclQualified = fromRight QualifiedPre qual
, ideclImportList = fromMaybe ideclImportList expectedHiding }
msg = moduleNameString (unLoc ideclName) <> " should be imported " <> hint
Left $ warn msg (reLoc i) i' []
Expand Down
6 changes: 4 additions & 2 deletions src/Hint/Unsafe.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ unsafeHint _ (ModuleEx (L _ m)) = \ld@(L loc d) ->
-- 'x' is not marked 'NOINLINE'.
, x `notElem` noinline]
where
noInline = fsLit $ '{' : '-' : '#' : " NOINLINE"

gen :: OccName -> LHsDecl GhcPs
gen x = noLocA $
SigD noExtField (InlineSig EpAnnNotUsed (noLocA (mkRdrUnqual x))
(InlinePragma (SourceText "{-# NOINLINE") (NoInline (SourceText "{-# NOINLINE")) Nothing NeverActive FunLike))
(InlinePragma (SourceText noInline) (NoInline (SourceText noInline)) Nothing NeverActive FunLike))
noinline :: [OccName]
noinline = [q | L _(SigD _ (InlineSig _ (L _ (Unqual q))
(InlinePragma _ (NoInline (SourceText "{-# NOINLINE")) Nothing NeverActive FunLike))
(InlinePragma _ (NoInline (SourceText noInline)) Nothing NeverActive FunLike))
) <- hsmodDecls m]

isUnsafeDecl :: HsDecl GhcPs -> Bool
Expand Down
8 changes: 4 additions & 4 deletions stack.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# For hlint/ghc-9.6.*, the minimum build compiler is ghc-9.2.2 (ghc-9.2.1 was a broken release). 9.2.2 exhibits the "'ffitarget_x86.h' file not found" problem on macOS. in this case, build with invoke `C_INCLUDE_PATH="$(xcrun --show-sdk-path)"/usr/include/ffi stack build`.
resolver: nightly-2023-04-02 # ghc-9.4.4
# For hlint/ghc-9.8.*, the minimum build compiler is ghc-9.4.1.
resolver: lts-21.6 # ghc-9.4.5

packages:
- .

extra-deps:
- ghc-lib-parser-9.6.2.20230523
- ghc-lib-parser-ex-9.6.0.2
- ghc-lib-parser-9.8.1.20231009
- ghc-lib-parser-ex-9.8.0.0
# To test hlint against experimental builds of ghc-lib-parser-ex,
# modify extra-deps like this:
# - archive: /users/shayne/project/ghc-lib-parser-ex/ghc-lib-parser-ex-8.10.0.18.tar.gz
Expand Down
61 changes: 61 additions & 0 deletions tests/import_style.test
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,64 @@ OUTPUT
No hints

---------------------------------------------------------------------
RUN tests/importStyle-postqual-pos.hs --hint=data/import_style.yaml -XImportQualifiedPost
FILE tests/importStyle-postqual-pos.hs
import HypotheticalModule1 qualified as HM1
import HypotheticalModule2 qualified
import HypotheticalModule2 qualified as Arbitrary
import HypotheticalModule3 qualified
import HypotheticalModule3 qualified as Arbitrary
import HypotheticalModule4 qualified as HM4
import HypotheticalModule5 qualified
import HypotheticalModule5 qualified as HM5
OUTPUT
No hints

---------------------------------------------------------------------
RUN tests/importStyle-postqual-neg.hs --hint=data/import_style.yaml -XImportQualifiedPost
FILE tests/importStyle-postqual-neg.hs
import HypotheticalModule1 qualified
import qualified HypotheticalModule4
import qualified HypotheticalModule4 as Verbotten
import qualified HypotheticalModule4 as HM4
import HypotheticalModule5 as HM5
import qualified HypotheticalModule5

OUTPUT
tests/importStyle-postqual-neg.hs:1:1-36: Warning: Avoid restricted alias
Found:
import HypotheticalModule1 qualified
Perhaps:
import HypotheticalModule1 qualified as HM1
Note: may break the code

tests/importStyle-postqual-neg.hs:2:1-36: Warning: Avoid restricted alias
Found:
import qualified HypotheticalModule4
Perhaps:
import qualified HypotheticalModule4 as HM4
Note: may break the code

tests/importStyle-postqual-neg.hs:3:1-49: Warning: Avoid restricted alias
Found:
import qualified HypotheticalModule4 as Verbotten
Perhaps:
import qualified HypotheticalModule4 as HM4
Note: may break the code

tests/importStyle-postqual-neg.hs:5:1-33: Warning: HypotheticalModule5 should be imported post-qualified
Found:
import HypotheticalModule5 as HM5
Perhaps:
import HypotheticalModule5 qualified as HM5
Note: may break the code

tests/importStyle-postqual-neg.hs:6:1-36: Warning: HypotheticalModule5 should be imported post-qualified
Found:
import qualified HypotheticalModule5
Perhaps:
import HypotheticalModule5 qualified
Note: may break the code

5 hints
---------------------------------------------------------------------

0 comments on commit 2fa5e9f

Please sign in to comment.