Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
29 changed files:
- compiler/GHC/Core/ConLike.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/HsToCore/Pmc/Utils.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Unbound.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26480.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26480.stderr
- + testsuite/tests/overloadedrecflds/should_fail/T26480_aux1.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26480_aux2.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26480b.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26480b.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/overloadedrecflds/should_fail/hasfieldfail01.stderr
- testsuite/tests/overloadedrecflds/should_fail/hasfieldfail02.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail11.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail8.hs
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail8.stderr
- testsuite/tests/rename/should_fail/T19843h.stderr
Changes:
| ... | ... | @@ -26,6 +26,8 @@ module GHC.Core.ConLike ( |
| 26 | 26 | , conLikeFieldType
|
| 27 | 27 | , conLikeIsInfix
|
| 28 | 28 | , conLikeHasBuilder
|
| 29 | + |
|
| 30 | + , isExistentialRecordField
|
|
| 29 | 31 | ) where
|
| 30 | 32 | |
| 31 | 33 | import GHC.Prelude
|
| ... | ... | @@ -35,7 +37,7 @@ import GHC.Core.Multiplicity |
| 35 | 37 | import GHC.Core.PatSyn
|
| 36 | 38 | import GHC.Core.TyCo.Rep (Type, ThetaType)
|
| 37 | 39 | import GHC.Core.TyCon (tyConDataCons)
|
| 38 | -import GHC.Core.Type(mkTyConApp)
|
|
| 40 | +import GHC.Core.Type(mkTyConApp, tyCoVarsOfType)
|
|
| 39 | 41 | import GHC.Types.Unique
|
| 40 | 42 | import GHC.Types.Name
|
| 41 | 43 | import GHC.Types.Name.Reader
|
| ... | ... | @@ -43,6 +45,7 @@ import GHC.Types.Basic |
| 43 | 45 | |
| 44 | 46 | import GHC.Types.GREInfo
|
| 45 | 47 | import GHC.Types.Var
|
| 48 | +import GHC.Types.Var.Set
|
|
| 46 | 49 | import GHC.Utils.Misc
|
| 47 | 50 | import GHC.Utils.Outputable
|
| 48 | 51 | |
| ... | ... | @@ -239,3 +242,23 @@ conLikeFieldType (RealDataCon dc) label = dataConFieldType dc label |
| 239 | 242 | conLikeIsInfix :: ConLike -> Bool
|
| 240 | 243 | conLikeIsInfix (RealDataCon dc) = dataConIsInfix dc
|
| 241 | 244 | conLikeIsInfix (PatSynCon ps) = patSynIsInfix ps
|
| 245 | + |
|
| 246 | +-- | Is this record field a naughty record field due to the presence of
|
|
| 247 | +-- existential type variables?
|
|
| 248 | +--
|
|
| 249 | +-- Different from 'isNaughtyRecordSelector' because the latter is also true
|
|
| 250 | +-- in the presence of @-XNoFieldSelectors@.
|
|
| 251 | +--
|
|
| 252 | +-- See Note [Naughty record selectors] in GHC.Tc.TyCl.Utils.
|
|
| 253 | +isExistentialRecordField :: Type -> ConLike -> Bool
|
|
| 254 | +isExistentialRecordField field_ty con =
|
|
| 255 | + case con of
|
|
| 256 | + RealDataCon {} -> not $ field_ty_tvs `subVarSet` res_ty_tvs
|
|
| 257 | + PatSynCon {} -> not $ field_ty_tvs `subVarSet` mkVarSet univ_tvs
|
|
| 258 | + -- In the PatSynCon case, the selector type is (data_ty -> field_ty), but
|
|
| 259 | + -- fvs(data_ty) are all universals (see Note [Pattern synonym result type] in
|
|
| 260 | + -- GHC.Core.PatSyn, so no need to check them.
|
|
| 261 | + where
|
|
| 262 | + field_ty_tvs = tyCoVarsOfType field_ty
|
|
| 263 | + res_ty_tvs = tyCoVarsOfType data_ty
|
|
| 264 | + (univ_tvs, _, _, _, _, _, data_ty) = conLikeFullSig con |
| ... | ... | @@ -1898,7 +1898,7 @@ matchSeparator PatBindRhs = text "=" |
| 1898 | 1898 | matchSeparator PatBindGuards = text "="
|
| 1899 | 1899 | matchSeparator StmtCtxt{} = text "<-"
|
| 1900 | 1900 | matchSeparator RecUpd = text "=" -- This can be printed by the pattern
|
| 1901 | -matchSeparator PatSyn = text "<-" -- match checker trace
|
|
| 1901 | +matchSeparator PatSynCtx = text "<-" -- match checker trace
|
|
| 1902 | 1902 | matchSeparator LazyPatCtx = panic "unused"
|
| 1903 | 1903 | matchSeparator ThPatSplice = panic "unused"
|
| 1904 | 1904 | matchSeparator ThPatQuote = panic "unused"
|
| ... | ... | @@ -2494,7 +2494,7 @@ instance Outputable fn => Outputable (HsMatchContext fn) where |
| 2494 | 2494 | ppr (StmtCtxt _) = text "StmtCtxt _"
|
| 2495 | 2495 | ppr ThPatSplice = text "ThPatSplice"
|
| 2496 | 2496 | ppr ThPatQuote = text "ThPatQuote"
|
| 2497 | - ppr PatSyn = text "PatSyn"
|
|
| 2497 | + ppr PatSynCtx = text "PatSynCtx"
|
|
| 2498 | 2498 | ppr LazyPatCtx = text "LazyPatCtx"
|
| 2499 | 2499 | |
| 2500 | 2500 | instance Outputable HsLamVariant where
|
| ... | ... | @@ -2538,7 +2538,7 @@ matchContextErrString RecUpd = text "record update" |
| 2538 | 2538 | matchContextErrString (ArrowMatchCtxt c) = matchArrowContextErrString c
|
| 2539 | 2539 | matchContextErrString ThPatSplice = panic "matchContextErrString" -- Not used at runtime
|
| 2540 | 2540 | matchContextErrString ThPatQuote = panic "matchContextErrString" -- Not used at runtime
|
| 2541 | -matchContextErrString PatSyn = text "pattern synonym"
|
|
| 2541 | +matchContextErrString PatSynCtx = text "pattern synonym"
|
|
| 2542 | 2542 | matchContextErrString (StmtCtxt (ParStmtCtxt c)) = matchContextErrString (StmtCtxt c)
|
| 2543 | 2543 | matchContextErrString (StmtCtxt (TransStmtCtxt c)) = matchContextErrString (StmtCtxt c)
|
| 2544 | 2544 | matchContextErrString (StmtCtxt (PatGuard _)) = text "pattern guard"
|
| ... | ... | @@ -2613,7 +2613,7 @@ pprMatchContextNoun PatBindGuards = text "pattern binding guards" |
| 2613 | 2613 | pprMatchContextNoun (ArrowMatchCtxt c) = pprArrowMatchContextNoun c
|
| 2614 | 2614 | pprMatchContextNoun (StmtCtxt ctxt) = text "pattern binding in"
|
| 2615 | 2615 | $$ pprAStmtContext ctxt
|
| 2616 | -pprMatchContextNoun PatSyn = text "pattern synonym declaration"
|
|
| 2616 | +pprMatchContextNoun PatSynCtx = text "pattern synonym declaration"
|
|
| 2617 | 2617 | pprMatchContextNoun LazyPatCtx = text "irrefutable pattern"
|
| 2618 | 2618 | |
| 2619 | 2619 | pprMatchContextNouns :: Outputable fn => HsMatchContext fn -> SDoc
|
| ... | ... | @@ -93,7 +93,7 @@ exhaustiveWarningFlag (ArrowMatchCtxt c) = arrowMatchContextExhaustiveWarningFla |
| 93 | 93 | exhaustiveWarningFlag RecUpd = Just Opt_WarnIncompletePatternsRecUpd
|
| 94 | 94 | exhaustiveWarningFlag LazyPatCtx = Just Opt_WarnIncompleteUniPatterns
|
| 95 | 95 | exhaustiveWarningFlag ThPatSplice = Nothing
|
| 96 | -exhaustiveWarningFlag PatSyn = Nothing
|
|
| 96 | +exhaustiveWarningFlag PatSynCtx = Nothing
|
|
| 97 | 97 | exhaustiveWarningFlag ThPatQuote = Nothing
|
| 98 | 98 | -- Don't warn about incomplete patterns in list comprehensions, pattern guards
|
| 99 | 99 | -- etc. They are often *supposed* to be incomplete
|
| ... | ... | @@ -763,7 +763,7 @@ rnPatSynBind sig_fn bind@(PSB { psb_id = L l name |
| 763 | 763 | ; let scoped_tvs = sig_fn name
|
| 764 | 764 | |
| 765 | 765 | ; ((pat', details'), fvs1) <- bindSigTyVarsFV scoped_tvs $
|
| 766 | - rnPat PatSyn pat $ \pat' ->
|
|
| 766 | + rnPat PatSynCtx pat $ \pat' ->
|
|
| 767 | 767 | -- We check the 'RdrName's instead of the 'Name's
|
| 768 | 768 | -- so that the binding locations are reported
|
| 769 | 769 | -- from the left-hand side
|
| ... | ... | @@ -2453,8 +2453,8 @@ badImportItemErr iface decl_spec ie sub avails = do |
| 2453 | 2453 | -- Only keep imported items, and set the "HowInScope" to
|
| 2454 | 2454 | -- "Nothing" to avoid printing "imported from..." in the suggestion
|
| 2455 | 2455 | -- error message.
|
| 2456 | - imported_item (SimilarRdrName rdr_name (Just (ImportedBy {})))
|
|
| 2457 | - = Just (SimilarRdrName rdr_name Nothing)
|
|
| 2456 | + imported_item (SimilarRdrName rdr_name gre (Just (ImportedBy {})))
|
|
| 2457 | + = Just (SimilarRdrName rdr_name gre Nothing)
|
|
| 2458 | 2458 | imported_item _ = Nothing
|
| 2459 | 2459 | |
| 2460 | 2460 | checkIfDataCon = checkIfAvailMatches isDataConName
|
| ... | ... | @@ -18,6 +18,7 @@ module GHC.Rename.Unbound |
| 18 | 18 | , unknownNameSuggestionsMessage
|
| 19 | 19 | , similarNameSuggestions
|
| 20 | 20 | , fieldSelectorSuggestions
|
| 21 | + , anyQualImportSuggestions
|
|
| 21 | 22 | , WhatLooking(..)
|
| 22 | 23 | , WhereLooking(..)
|
| 23 | 24 | , LookingFor(..)
|
| ... | ... | @@ -215,7 +216,7 @@ unknownNameSuggestions_ looking_for dflags hpt curr_mod global_env local_env |
| 215 | 216 | , map (ImportSuggestion $ rdrNameOcc tried_rdr_name) imp_suggs
|
| 216 | 217 | , extensionSuggestions tried_rdr_name
|
| 217 | 218 | , fieldSelectorSuggestions global_env tried_rdr_name ]
|
| 218 | - (imp_errs, imp_suggs) = importSuggestions looking_for hpt curr_mod imports tried_rdr_name
|
|
| 219 | + (imp_errs, imp_suggs) = sameQualImportSuggestions looking_for hpt curr_mod imports tried_rdr_name
|
|
| 219 | 220 | |
| 220 | 221 | if_ne :: (NonEmpty a -> b) -> [a] -> [b]
|
| 221 | 222 | if_ne _ [] = []
|
| ... | ... | @@ -242,7 +243,7 @@ similarNameSuggestions looking_for@(LF what_look where_look) dflags global_env |
| 242 | 243 | all_possibilities :: [(String, SimilarName)]
|
| 243 | 244 | all_possibilities = case what_look of
|
| 244 | 245 | WL_None -> []
|
| 245 | - _ -> [ (showPpr dflags r, SimilarRdrName r (Just $ LocallyBoundAt loc))
|
|
| 246 | + _ -> [ (showPpr dflags r, SimilarRdrName r Nothing (Just $ LocallyBoundAt loc))
|
|
| 246 | 247 | | (r,loc) <- local_possibilities local_env ]
|
| 247 | 248 | ++ [ (showPpr dflags r, rp) | (r, rp) <- global_possibilities global_env ]
|
| 248 | 249 | |
| ... | ... | @@ -273,7 +274,7 @@ similarNameSuggestions looking_for@(LF what_look where_look) dflags global_env |
| 273 | 274 | |
| 274 | 275 | global_possibilities :: GlobalRdrEnv -> [(RdrName, SimilarName)]
|
| 275 | 276 | global_possibilities global_env
|
| 276 | - | tried_is_qual = [ (rdr_qual, SimilarRdrName rdr_qual (Just how))
|
|
| 277 | + | tried_is_qual = [ (rdr_qual, SimilarRdrName rdr_qual (Just gre) (Just how))
|
|
| 277 | 278 | | gre <- globalRdrEnvElts global_env
|
| 278 | 279 | , isGreOk looking_for gre
|
| 279 | 280 | , let occ = greOccName gre
|
| ... | ... | @@ -288,7 +289,7 @@ similarNameSuggestions looking_for@(LF what_look where_look) dflags global_env |
| 288 | 289 | rdr_unqual = mkRdrUnqual occ
|
| 289 | 290 | , is_relevant occ
|
| 290 | 291 | , sim <- case (unquals_in_scope gre, quals_only gre) of
|
| 291 | - (how:_, _) -> [ SimilarRdrName rdr_unqual (Just how) ]
|
|
| 292 | + (how:_, _) -> [ SimilarRdrName rdr_unqual (Just gre) (Just how) ]
|
|
| 292 | 293 | ([], pr:_) -> [ pr ] -- See Note [Only-quals]
|
| 293 | 294 | ([], []) -> [] ]
|
| 294 | 295 | |
| ... | ... | @@ -316,45 +317,74 @@ similarNameSuggestions looking_for@(LF what_look where_look) dflags global_env |
| 316 | 317 | quals_only :: GlobalRdrElt -> [SimilarName]
|
| 317 | 318 | -- Ones for which *only* the qualified version is in scope
|
| 318 | 319 | quals_only (gre@GRE { gre_imp = is })
|
| 319 | - = [ (SimilarRdrName (mkRdrQual (is_as ispec) (greOccName gre)) (Just $ ImportedBy ispec))
|
|
| 320 | + = [ (SimilarRdrName (mkRdrQual (is_as ispec) (greOccName gre)) (Just gre) (Just $ ImportedBy ispec))
|
|
| 320 | 321 | | i <- bagToList is, let ispec = is_decl i, is_qual ispec ]
|
| 321 | 322 | |
| 323 | +-- | Provide import suggestions, without filtering by module qualification.
|
|
| 324 | +-- Used to suggest imports for 'HasField', which doesn't care about whether a
|
|
| 325 | +-- name is imported qualified or unqualified.
|
|
| 326 | +--
|
|
| 327 | +-- For example:
|
|
| 328 | +--
|
|
| 329 | +-- > import M1 () -- M1 exports fld1
|
|
| 330 | +-- > import qualified M2 hiding ( fld2 )
|
|
| 331 | +-- > x r = r.fld1 -- suggest adding 'fld1' to M1 import
|
|
| 332 | +-- > y r = getField @"fld2" r -- suggest unhiding 'fld' from M2 import
|
|
| 333 | +anyQualImportSuggestions :: LookingFor -> LookupGRE GREInfo -> TcM [ImportSuggestion]
|
|
| 334 | +anyQualImportSuggestions looking_for lookup_gre =
|
|
| 335 | + do { imp_info <- getImports
|
|
| 336 | + ; let interesting_imports = interestingImports imp_info (const True)
|
|
| 337 | + ; return $
|
|
| 338 | + importSuggestions_ looking_for interesting_imports lookup_gre
|
|
| 339 | + }
|
|
| 322 | 340 | |
| 323 | --- | Generate errors and helpful suggestions if a qualified name Mod.foo is not in scope.
|
|
| 324 | -importSuggestions :: LookingFor
|
|
| 325 | - -> InteractiveContext -> Module
|
|
| 326 | - -> ImportAvails -> RdrName -> ([ImportError], [ImportSuggestion])
|
|
| 327 | -importSuggestions looking_for ic currMod imports rdr_name
|
|
| 328 | - | WL_LocalOnly <- lf_where looking_for = ([], [])
|
|
| 329 | - | WL_LocalTop <- lf_where looking_for = ([], [])
|
|
| 341 | +-- | The given 'RdrName' is not in scope. Try to find out why that is by looking
|
|
| 342 | +-- at the import list, to suggest e.g. changing the import list somehow.
|
|
| 343 | +--
|
|
| 344 | +-- For example:
|
|
| 345 | +--
|
|
| 346 | +-- > import qualified M1 hiding ( blah1 )
|
|
| 347 | +-- > x = M1.blah -- suggest unhiding blah1
|
|
| 348 | +-- > y = XX.blah1 -- import error: no imports provide the XX qualification prefix
|
|
| 349 | +sameQualImportSuggestions
|
|
| 350 | + :: LookingFor
|
|
| 351 | + -> InteractiveContext
|
|
| 352 | + -> Module
|
|
| 353 | + -> ImportAvails
|
|
| 354 | + -> RdrName
|
|
| 355 | + -> ([ImportError], [ImportSuggestion])
|
|
| 356 | +sameQualImportSuggestions looking_for ic currMod imports rdr_name
|
|
| 330 | 357 | | not (isQual rdr_name || isUnqual rdr_name) = ([], [])
|
| 331 | - | Just name <- mod_name
|
|
| 332 | - , show_not_imported_line name
|
|
| 333 | - = ([MissingModule name], [])
|
|
| 358 | + | Just rdr_mod_name <- mb_rdr_mod_name
|
|
| 359 | + , show_not_imported_line rdr_mod_name
|
|
| 360 | + = ([MissingModule rdr_mod_name], [])
|
|
| 334 | 361 | | is_qualified
|
| 335 | - , null helpful_imports
|
|
| 362 | + , null import_suggs
|
|
| 336 | 363 | , (mod : mods) <- map fst interesting_imports
|
| 337 | 364 | = ([ModulesDoNotExport (mod :| mods) (lf_which looking_for) occ_name], [])
|
| 338 | - | mod : mods <- helpful_imports_non_hiding
|
|
| 339 | - = ([], [CouldImportFrom (mod :| mods)])
|
|
| 340 | - | mod : mods <- helpful_imports_hiding
|
|
| 341 | - = ([], [CouldUnhideFrom (mod :| mods)])
|
|
| 342 | 365 | | otherwise
|
| 343 | - = ([], [])
|
|
| 344 | - where
|
|
| 366 | + = ([], import_suggs)
|
|
| 367 | + where
|
|
| 368 | + |
|
| 369 | + interesting_imports = interestingImports imports right_qual_import
|
|
| 370 | + |
|
| 371 | + import_suggs =
|
|
| 372 | + importSuggestions_ looking_for interesting_imports $
|
|
| 373 | + (LookupOccName (rdrNameOcc rdr_name) $ RelevantGREsFOS WantNormal)
|
|
| 374 | + |
|
| 345 | 375 | is_qualified = isQual rdr_name
|
| 346 | - (mod_name, occ_name) = case rdr_name of
|
|
| 376 | + (mb_rdr_mod_name, occ_name) = case rdr_name of
|
|
| 347 | 377 | Unqual occ_name -> (Nothing, occ_name)
|
| 348 | 378 | Qual mod_name occ_name -> (Just mod_name, occ_name)
|
| 349 | - _ -> panic "importSuggestions: dead code"
|
|
| 350 | - |
|
| 379 | + _ -> panic "sameQualImportSuggestions: dead code"
|
|
| 351 | 380 | |
| 352 | - -- What import statements provide "Mod" at all
|
|
| 353 | - -- or, if this is an unqualified name, are not qualified imports
|
|
| 354 | - interesting_imports = [ (mod, imp)
|
|
| 355 | - | (mod, mod_imports) <- M.toList (imp_mods imports)
|
|
| 356 | - , Just imp <- return $ pick (importedByUser mod_imports)
|
|
| 357 | - ]
|
|
| 381 | + -- See Note [When to show/hide the module-not-imported line]
|
|
| 382 | + show_not_imported_line :: ModuleName -> Bool -- #15611
|
|
| 383 | + show_not_imported_line modnam
|
|
| 384 | + | not (null interactive_imports) = False -- 1 (interactive context)
|
|
| 385 | + | not (null interesting_imports) = False -- 1 (normal module import)
|
|
| 386 | + | moduleName currMod == modnam = False -- 2
|
|
| 387 | + | otherwise = True
|
|
| 358 | 388 | |
| 359 | 389 | -- Choose the imports from the interactive context which might have provided
|
| 360 | 390 | -- a module.
|
| ... | ... | @@ -362,18 +392,52 @@ importSuggestions looking_for ic currMod imports rdr_name |
| 362 | 392 | filter pick_interactive (ic_imports ic)
|
| 363 | 393 | |
| 364 | 394 | pick_interactive :: InteractiveImport -> Bool
|
| 365 | - pick_interactive (IIDecl d) | mod_name == Just (unLoc (ideclName d)) = True
|
|
| 366 | - | mod_name == fmap unLoc (ideclAs d) = True
|
|
| 367 | - pick_interactive (IIModule m) | mod_name == Just (moduleName m) = True
|
|
| 395 | + pick_interactive (IIDecl d) | mb_rdr_mod_name == Just (unLoc (ideclName d)) = True
|
|
| 396 | + | mb_rdr_mod_name == fmap unLoc (ideclAs d) = True
|
|
| 397 | + pick_interactive (IIModule m) | mb_rdr_mod_name == Just (moduleName m) = True
|
|
| 368 | 398 | pick_interactive _ = False
|
| 369 | 399 | |
| 400 | + right_qual_import imv =
|
|
| 401 | + case mb_rdr_mod_name of
|
|
| 402 | + -- Qual RdrName: only want qualified imports with the same module name
|
|
| 403 | + Just rdr_mod_name -> imv_name imv == rdr_mod_name
|
|
| 404 | + -- UnQual RdrName: import must be unqualified
|
|
| 405 | + Nothing -> not (imv_qualified imv)
|
|
| 406 | + |
|
| 407 | +-- | What import statements are relevant?
|
|
| 408 | +--
|
|
| 409 | +-- - If we are looking for a qualified name @Mod.blah@, which imports provide @Mod@ at all,
|
|
| 410 | +-- - If we are looking for an unqualified name, which imports are themselves unqualified.
|
|
| 411 | +interestingImports :: ImportAvails -> (ImportedModsVal -> Bool) -> [(Module, ImportedModsVal)]
|
|
| 412 | +interestingImports imports ok_mod_name =
|
|
| 413 | + [ (mod, imp)
|
|
| 414 | + | (mod, mod_imports) <- M.toList (imp_mods imports)
|
|
| 415 | + , Just imp <- return $ pick (importedByUser mod_imports)
|
|
| 416 | + ]
|
|
| 417 | + |
|
| 418 | + where
|
|
| 370 | 419 | -- We want to keep only one for each original module; preferably one with an
|
| 371 | 420 | -- explicit import list (for no particularly good reason)
|
| 372 | 421 | pick :: [ImportedModsVal] -> Maybe ImportedModsVal
|
| 373 | - pick = listToMaybe . sortBy cmp . filter select
|
|
| 374 | - where select imv = case mod_name of Just name -> imv_name imv == name
|
|
| 375 | - Nothing -> not (imv_qualified imv)
|
|
| 376 | - cmp = on compare imv_is_hiding S.<> on SrcLoc.leftmost_smallest imv_span
|
|
| 422 | + pick = listToMaybe . sortBy cmp . filter ok_mod_name
|
|
| 423 | + where
|
|
| 424 | + cmp = on compare imv_is_hiding S.<> on SrcLoc.leftmost_smallest imv_span
|
|
| 425 | + |
|
| 426 | +importSuggestions_
|
|
| 427 | + :: LookingFor
|
|
| 428 | + -> [(Module, ImportedModsVal)]
|
|
| 429 | + -> LookupGRE GREInfo
|
|
| 430 | + -> [ImportSuggestion]
|
|
| 431 | +importSuggestions_ looking_for interesting_imports lookup_gre
|
|
| 432 | + | WL_LocalOnly <- lf_where looking_for = []
|
|
| 433 | + | WL_LocalTop <- lf_where looking_for = []
|
|
| 434 | + | mod : mods <- helpful_imports_non_hiding
|
|
| 435 | + = [CouldImportFrom (mod :| mods)]
|
|
| 436 | + | mod : mods <- helpful_imports_hiding
|
|
| 437 | + = [CouldUnhideFrom (mod :| mods)]
|
|
| 438 | + | otherwise
|
|
| 439 | + = []
|
|
| 440 | + where
|
|
| 377 | 441 | |
| 378 | 442 | -- Which of these would export a 'foo'
|
| 379 | 443 | -- (all of these are restricted imports, because if they were not, we
|
| ... | ... | @@ -382,21 +446,13 @@ importSuggestions looking_for ic currMod imports rdr_name |
| 382 | 446 | where helpful (_,imv)
|
| 383 | 447 | = any (isGreOk looking_for) $
|
| 384 | 448 | lookupGRE (imv_all_exports imv)
|
| 385 | - (LookupOccName occ_name $ RelevantGREsFOS WantNormal)
|
|
| 449 | + lookup_gre
|
|
| 386 | 450 | |
| 387 | 451 | -- Which of these do that because of an explicit hiding list resp. an
|
| 388 | 452 | -- explicit import list
|
| 389 | 453 | (helpful_imports_hiding, helpful_imports_non_hiding)
|
| 390 | 454 | = partition (imv_is_hiding . snd) helpful_imports
|
| 391 | 455 | |
| 392 | - -- See Note [When to show/hide the module-not-imported line]
|
|
| 393 | - show_not_imported_line :: ModuleName -> Bool -- #15611
|
|
| 394 | - show_not_imported_line modnam
|
|
| 395 | - | not (null interactive_imports) = False -- 1 (interactive context)
|
|
| 396 | - | not (null interesting_imports) = False -- 1 (normal module import)
|
|
| 397 | - | moduleName currMod == modnam = False -- 2
|
|
| 398 | - | otherwise = True
|
|
| 399 | - |
|
| 400 | 456 | extensionSuggestions :: RdrName -> [GhcHint]
|
| 401 | 457 | extensionSuggestions rdrName
|
| 402 | 458 | | rdrName == mkUnqual varName (fsLit "mdo") ||
|
| ... | ... | @@ -17,6 +17,8 @@ module GHC.Tc.Errors( |
| 17 | 17 | |
| 18 | 18 | import GHC.Prelude
|
| 19 | 19 | |
| 20 | +import GHC.Builtin.Names (hasFieldClassName)
|
|
| 21 | + |
|
| 20 | 22 | import GHC.Driver.Env (hsc_units)
|
| 21 | 23 | import GHC.Driver.DynFlags
|
| 22 | 24 | import GHC.Driver.Ppr
|
| ... | ... | @@ -31,6 +33,7 @@ import GHC.Tc.Errors.Ppr |
| 31 | 33 | import GHC.Tc.Types.Constraint
|
| 32 | 34 | import GHC.Tc.Types.CtLoc
|
| 33 | 35 | import GHC.Tc.Utils.TcMType
|
| 36 | +import GHC.Tc.Utils.Env (tcLookupId, tcLookupDataCon)
|
|
| 34 | 37 | import GHC.Tc.Zonk.Type
|
| 35 | 38 | import GHC.Tc.Utils.TcType
|
| 36 | 39 | import GHC.Tc.Zonk.TcType
|
| ... | ... | @@ -43,6 +46,7 @@ import {-# SOURCE #-} GHC.Tc.Errors.Hole ( findValidHoleFits, getHoleFitDispConf |
| 43 | 46 | import GHC.Types.Name
|
| 44 | 47 | import GHC.Types.Name.Reader
|
| 45 | 48 | import GHC.Types.Id
|
| 49 | +import GHC.Types.Id.Info (IdDetails(..), RecSelParent (..))
|
|
| 46 | 50 | import GHC.Types.Var
|
| 47 | 51 | import GHC.Types.Var.Set
|
| 48 | 52 | import GHC.Types.Var.Env
|
| ... | ... | @@ -50,13 +54,18 @@ import GHC.Types.Name.Env |
| 50 | 54 | import GHC.Types.SrcLoc
|
| 51 | 55 | import GHC.Types.Basic
|
| 52 | 56 | import GHC.Types.Error
|
| 57 | +import GHC.Types.Hint (SimilarName (..))
|
|
| 53 | 58 | import qualified GHC.Types.Unique.Map as UM
|
| 59 | +import GHC.Types.Unique.Set (nonDetEltsUniqSet)
|
|
| 54 | 60 | |
| 55 | 61 | import GHC.Unit.Module
|
| 56 | 62 | import qualified GHC.LanguageExtensions as LangExt
|
| 57 | 63 | |
| 64 | +import GHC.Core.PatSyn (PatSyn)
|
|
| 58 | 65 | import GHC.Core.Predicate
|
| 59 | 66 | import GHC.Core.Type
|
| 67 | +import GHC.Core.Class (className)
|
|
| 68 | +import GHC.Core.ConLike (isExistentialRecordField, ConLike (..))
|
|
| 60 | 69 | import GHC.Core.Coercion
|
| 61 | 70 | import GHC.Core.TyCo.Ppr ( pprTyVars )
|
| 62 | 71 | import GHC.Core.TyCo.Tidy
|
| ... | ... | @@ -75,13 +84,18 @@ import GHC.Data.List.SetOps ( equivClasses, nubOrdBy ) |
| 75 | 84 | import GHC.Data.Maybe
|
| 76 | 85 | import qualified GHC.Data.Strict as Strict
|
| 77 | 86 | |
| 87 | + |
|
| 88 | +import Language.Haskell.Syntax.Basic (FieldLabelString(..))
|
|
| 89 | + |
|
| 78 | 90 | import Control.Monad ( unless, when, foldM, forM_ )
|
| 91 | +import Data.Bifunctor ( bimap )
|
|
| 79 | 92 | import Data.Foldable ( toList )
|
| 80 | 93 | import Data.Function ( on )
|
| 81 | 94 | import Data.List ( partition, union, sort, sortBy )
|
| 82 | 95 | import Data.List.NonEmpty ( NonEmpty(..), nonEmpty )
|
| 83 | 96 | import qualified Data.List.NonEmpty as NE
|
| 84 | 97 | import Data.Ord ( comparing )
|
| 98 | +import Data.Either (partitionEithers)
|
|
| 85 | 99 | |
| 86 | 100 | {-
|
| 87 | 101 | ************************************************************************
|
| ... | ... | @@ -1470,8 +1484,8 @@ coercion. |
| 1470 | 1484 | mkIrredErr :: SolverReportErrCtxt -> NonEmpty ErrorItem -> TcM SolverReport
|
| 1471 | 1485 | mkIrredErr ctxt items
|
| 1472 | 1486 | = do { (ctxt, binds, item1) <- relevantBindings True ctxt item1
|
| 1473 | - ; let msg = important ctxt $ mkPlainMismatchMsg $
|
|
| 1474 | - CouldNotDeduce (getUserGivens ctxt) (item1 :| others) Nothing
|
|
| 1487 | + ; couldNotDeduceErr <- mkCouldNotDeduceErr (getUserGivens ctxt) (item1 :| others) Nothing
|
|
| 1488 | + ; let msg = important ctxt $ mkPlainMismatchMsg couldNotDeduceErr
|
|
| 1475 | 1489 | ; return $ add_relevant_bindings binds msg }
|
| 1476 | 1490 | where
|
| 1477 | 1491 | item1:|others = tryFilter (not . ei_suppress) items
|
| ... | ... | @@ -1851,6 +1865,7 @@ reportEqErr :: SolverReportErrCtxt |
| 1851 | 1865 | -> TcM TcSolverReportMsg
|
| 1852 | 1866 | reportEqErr ctxt item ty1 ty2
|
| 1853 | 1867 | = do
|
| 1868 | + mismatch <- misMatchOrCND ctxt item ty1 ty2
|
|
| 1854 | 1869 | mb_coercible_info <- if errorItemEqRel item == ReprEq
|
| 1855 | 1870 | then coercible_msg ty1 ty2
|
| 1856 | 1871 | else return Nothing
|
| ... | ... | @@ -1862,7 +1877,6 @@ reportEqErr ctxt item ty1 ty2 |
| 1862 | 1877 | , mismatchAmbiguityInfo = eqInfos
|
| 1863 | 1878 | , mismatchCoercibleInfo = mb_coercible_info }
|
| 1864 | 1879 | where
|
| 1865 | - mismatch = misMatchOrCND ctxt item ty1 ty2
|
|
| 1866 | 1880 | eqInfos = eqInfoMsgs ty1 ty2
|
| 1867 | 1881 | |
| 1868 | 1882 | coercible_msg :: TcType -> TcType -> TcM (Maybe CoercibleMsg)
|
| ... | ... | @@ -1894,6 +1908,7 @@ mkTyVarEqErr' ctxt item tv1 ty2 |
| 1894 | 1908 | -- try it before anything more complicated.
|
| 1895 | 1909 | | check_eq_result `cterHasProblem` cteImpredicative
|
| 1896 | 1910 | = do
|
| 1911 | + headline_msg <- misMatchOrCND ctxt item ty1 ty2
|
|
| 1897 | 1912 | tyvar_eq_info <- extraTyVarEqInfo (tv1, Nothing) ty2
|
| 1898 | 1913 | let
|
| 1899 | 1914 | poly_msg = CannotUnifyWithPolytype item tv1 ty2 mb_tv_info
|
| ... | ... | @@ -1917,6 +1932,7 @@ mkTyVarEqErr' ctxt item tv1 ty2 |
| 1917 | 1932 | || errorItemEqRel item == ReprEq
|
| 1918 | 1933 | -- The cases below don't really apply to ReprEq (except occurs check)
|
| 1919 | 1934 | = do
|
| 1935 | + headline_msg <- misMatchOrCND ctxt item ty1 ty2
|
|
| 1920 | 1936 | tv_extra <- extraTyVarEqInfo (tv1, Nothing) ty2
|
| 1921 | 1937 | reason <- if errorItemEqRel item == ReprEq
|
| 1922 | 1938 | then RepresentationalEq tv_extra <$> coercible_msg ty1 ty2
|
| ... | ... | @@ -1933,23 +1949,24 @@ mkTyVarEqErr' ctxt item tv1 ty2 |
| 1933 | 1949 | --
|
| 1934 | 1950 | -- Use tyCoVarsOfType because it might have begun as the canonical
|
| 1935 | 1951 | -- constraint (Dual (Dual a)) ~ a, and been swizzled by mkEqnErr_help
|
| 1936 | - = let ambiguity_infos = eqInfoMsgs ty1 ty2
|
|
| 1952 | + = do headline_msg <- misMatchOrCND ctxt item ty1 ty2
|
|
| 1953 | + let ambiguity_infos = eqInfoMsgs ty1 ty2
|
|
| 1937 | 1954 | |
| 1938 | - interesting_tyvars = filter (not . noFreeVarsOfType . tyVarKind) $
|
|
| 1939 | - filter isTyVar $
|
|
| 1940 | - fvVarList $
|
|
| 1941 | - tyCoFVsOfType ty1 `unionFV` tyCoFVsOfType ty2
|
|
| 1955 | + interesting_tyvars = filter (not . noFreeVarsOfType . tyVarKind) $
|
|
| 1956 | + filter isTyVar $
|
|
| 1957 | + fvVarList $
|
|
| 1958 | + tyCoFVsOfType ty1 `unionFV` tyCoFVsOfType ty2
|
|
| 1942 | 1959 | |
| 1943 | - occurs_err =
|
|
| 1944 | - OccursCheck
|
|
| 1945 | - { occursCheckInterestingTyVars = interesting_tyvars
|
|
| 1946 | - , occursCheckAmbiguityInfos = ambiguity_infos }
|
|
| 1947 | - main_msg =
|
|
| 1948 | - CannotUnifyVariable
|
|
| 1949 | - { mismatchMsg = headline_msg
|
|
| 1950 | - , cannotUnifyReason = occurs_err }
|
|
| 1960 | + occurs_err =
|
|
| 1961 | + OccursCheck
|
|
| 1962 | + { occursCheckInterestingTyVars = interesting_tyvars
|
|
| 1963 | + , occursCheckAmbiguityInfos = ambiguity_infos }
|
|
| 1964 | + main_msg =
|
|
| 1965 | + CannotUnifyVariable
|
|
| 1966 | + { mismatchMsg = headline_msg
|
|
| 1967 | + , cannotUnifyReason = occurs_err }
|
|
| 1951 | 1968 | |
| 1952 | - in return main_msg
|
|
| 1969 | + return main_msg
|
|
| 1953 | 1970 | |
| 1954 | 1971 | -- If the immediately-enclosing implication has 'tv' a skolem, and
|
| 1955 | 1972 | -- we know by now its an InferSkol kind of skolem, then presumably
|
| ... | ... | @@ -2005,7 +2022,6 @@ mkTyVarEqErr' ctxt item tv1 ty2 |
| 2005 | 2022 | -- Consider an ambiguous top-level constraint (a ~ F a)
|
| 2006 | 2023 | -- Not an occurs check, because F is a type function.
|
| 2007 | 2024 | where
|
| 2008 | - headline_msg = misMatchOrCND ctxt item ty1 ty2
|
|
| 2009 | 2025 | mismatch_msg = mkMismatchMsg item ty1 ty2
|
| 2010 | 2026 | |
| 2011 | 2027 | -- The following doesn't use the cterHasProblem mechanism because
|
| ... | ... | @@ -2073,7 +2089,7 @@ eqInfoMsgs ty1 ty2 |
| 2073 | 2089 | = Nothing
|
| 2074 | 2090 | |
| 2075 | 2091 | misMatchOrCND :: SolverReportErrCtxt -> ErrorItem
|
| 2076 | - -> TcType -> TcType -> MismatchMsg
|
|
| 2092 | + -> TcType -> TcType -> TcM MismatchMsg
|
|
| 2077 | 2093 | -- If oriented then ty1 is actual, ty2 is expected
|
| 2078 | 2094 | misMatchOrCND ctxt item ty1 ty2
|
| 2079 | 2095 | | insoluble_item -- See Note [Insoluble mis-match]
|
| ... | ... | @@ -2082,10 +2098,10 @@ misMatchOrCND ctxt item ty1 ty2 |
| 2082 | 2098 | || null givens
|
| 2083 | 2099 | = -- If the equality is unconditionally insoluble
|
| 2084 | 2100 | -- or there is no context, don't report the context
|
| 2085 | - mkMismatchMsg item ty1 ty2
|
|
| 2101 | + return $ mkMismatchMsg item ty1 ty2
|
|
| 2086 | 2102 | |
| 2087 | 2103 | | otherwise
|
| 2088 | - = CouldNotDeduce givens (item :| []) (Just $ CND_Extra level ty1 ty2)
|
|
| 2104 | + = mkCouldNotDeduceErr givens (item :| []) (Just $ CND_ExpectedActual level ty1 ty2)
|
|
| 2089 | 2105 | |
| 2090 | 2106 | where
|
| 2091 | 2107 | insoluble_item = case ei_m_reason item of
|
| ... | ... | @@ -2275,9 +2291,8 @@ mkQCErr :: HasDebugCallStack => SolverReportErrCtxt -> NonEmpty ErrorItem -> TcM |
| 2275 | 2291 | mkQCErr ctxt items
|
| 2276 | 2292 | | item1 :| _ <- tryFilter (not . ei_suppress) items
|
| 2277 | 2293 | -- Ignore multiple qc-errors on the same line
|
| 2278 | - = do { let msg = mkPlainMismatchMsg $
|
|
| 2279 | - CouldNotDeduce (getUserGivens ctxt) (item1 :| []) Nothing
|
|
| 2280 | - ; return $ important ctxt msg }
|
|
| 2294 | + = do { couldNotDeduceErr <- mkCouldNotDeduceErr (getUserGivens ctxt) (item1 :| []) Nothing
|
|
| 2295 | + ; return $ important ctxt $ mkPlainMismatchMsg couldNotDeduceErr }
|
|
| 2281 | 2296 | |
| 2282 | 2297 | |
| 2283 | 2298 | mkDictErr :: HasDebugCallStack => SolverReportErrCtxt -> NonEmpty ErrorItem -> TcM SolverReport
|
| ... | ... | @@ -2292,16 +2307,9 @@ mkDictErr ctxt orig_items |
| 2292 | 2307 | -- But we report only one of them (hence 'head') because they all
|
| 2293 | 2308 | -- have the same source-location origin, to try avoid a cascade
|
| 2294 | 2309 | -- of error from one location
|
| 2295 | - ; ( err, (imp_errs, hints) ) <-
|
|
| 2296 | - mk_dict_err ctxt (head (no_inst_items ++ overlap_items))
|
|
| 2297 | - ; return $
|
|
| 2298 | - SolverReport
|
|
| 2299 | - { sr_important_msg = SolverReportWithCtxt ctxt err
|
|
| 2300 | - , sr_supplementary = [ SupplementaryImportErrors imps
|
|
| 2301 | - | imps <- maybeToList (NE.nonEmpty imp_errs) ]
|
|
| 2302 | - , sr_hints = hints
|
|
| 2303 | - }
|
|
| 2304 | - }
|
|
| 2310 | + ; err <- mk_dict_err ctxt (head (no_inst_items ++ overlap_items))
|
|
| 2311 | + ; return $ important ctxt err
|
|
| 2312 | + }
|
|
| 2305 | 2313 | where
|
| 2306 | 2314 | items = tryFilter (not . ei_suppress) orig_items
|
| 2307 | 2315 | |
| ... | ... | @@ -2335,28 +2343,29 @@ mkDictErr ctxt orig_items |
| 2335 | 2343 | -- matching and unifying instances, and say "The choice depends on the instantion of ...,
|
| 2336 | 2344 | -- and the result of evaluating ...".
|
| 2337 | 2345 | mk_dict_err :: HasCallStack => SolverReportErrCtxt -> (ErrorItem, ClsInstLookupResult)
|
| 2338 | - -> TcM ( TcSolverReportMsg, ([ImportError], [GhcHint]) )
|
|
| 2346 | + -> TcM TcSolverReportMsg
|
|
| 2339 | 2347 | mk_dict_err ctxt (item, (matches, pot_unifiers, unsafe_overlapped))
|
| 2340 | 2348 | = case (NE.nonEmpty matches, NE.nonEmpty unsafe_overlapped) of
|
| 2341 | 2349 | (Nothing, _) -> do -- No matches but perhaps several unifiers
|
| 2342 | 2350 | { (_, rel_binds, item) <- relevantBindings True ctxt item
|
| 2343 | 2351 | ; candidate_insts <- get_candidate_instances
|
| 2344 | - ; (imp_errs, field_suggestions) <- record_field_suggestions item
|
|
| 2345 | - ; return (CannotResolveInstance item unifiers candidate_insts rel_binds, (imp_errs, field_suggestions)) }
|
|
| 2352 | + ; mb_noBuiltinInst_msg <- getNoBuiltinInstMsg item
|
|
| 2353 | + ; return $
|
|
| 2354 | + CannotResolveInstance item unifiers candidate_insts rel_binds mb_noBuiltinInst_msg
|
|
| 2355 | + }
|
|
| 2346 | 2356 | |
| 2347 | 2357 | -- Some matches => overlap errors
|
| 2348 | 2358 | (Just matchesNE, Nothing) -> return $
|
| 2349 | - ( OverlappingInstances item (NE.map fst matchesNE) unifiers, ([], []))
|
|
| 2359 | + OverlappingInstances item (NE.map fst matchesNE) unifiers
|
|
| 2350 | 2360 | |
| 2351 | 2361 | (Just (match :| []), Just unsafe_overlappedNE) -> return $
|
| 2352 | - ( UnsafeOverlap item (fst match) (NE.map fst unsafe_overlappedNE), ([], []))
|
|
| 2362 | + UnsafeOverlap item (fst match) (NE.map fst unsafe_overlappedNE)
|
|
| 2353 | 2363 | (Just matches@(_ :| _), Just overlaps) ->
|
| 2354 | 2364 | pprPanic "mk_dict_err: multiple matches with overlap" $
|
| 2355 | 2365 | vcat [ text "matches:" <+> ppr matches
|
| 2356 | 2366 | , text "overlaps:" <+> ppr overlaps
|
| 2357 | 2367 | ]
|
| 2358 | 2368 | where
|
| 2359 | - orig = errorItemOrigin item
|
|
| 2360 | 2369 | pred = errorItemPred item
|
| 2361 | 2370 | (clas, tys) = getClassPredTys pred
|
| 2362 | 2371 | unifiers = getCoherentUnifiers pot_unifiers
|
| ... | ... | @@ -2381,43 +2390,6 @@ mk_dict_err ctxt (item, (matches, pot_unifiers, unsafe_overlapped)) |
| 2381 | 2390 | in different_names && same_occ_names
|
| 2382 | 2391 | | otherwise = False
|
| 2383 | 2392 | |
| 2384 | - -- See Note [Out-of-scope fields with -XOverloadedRecordDot]
|
|
| 2385 | - record_field_suggestions :: ErrorItem -> TcM ([ImportError], [GhcHint])
|
|
| 2386 | - record_field_suggestions item = flip (maybe $ return ([], noHints)) record_field $ \name ->
|
|
| 2387 | - do { glb_env <- getGlobalRdrEnv
|
|
| 2388 | - ; lcl_env <- getLocalRdrEnv
|
|
| 2389 | - ; let field_name_hints = report_no_fieldnames item
|
|
| 2390 | - ; (errs, hints) <- if occ_name_in_scope glb_env lcl_env name
|
|
| 2391 | - then return ([], noHints)
|
|
| 2392 | - else unknownNameSuggestions emptyLocalRdrEnv WL_RecField (mkRdrUnqual name)
|
|
| 2393 | - ; pure (errs, hints ++ field_name_hints)
|
|
| 2394 | - }
|
|
| 2395 | - |
|
| 2396 | - -- get type names from instance
|
|
| 2397 | - -- resolve the type - if it's in scope is it a record?
|
|
| 2398 | - -- if it's a record, report an error - the record name + the field that could not be found
|
|
| 2399 | - report_no_fieldnames :: ErrorItem -> [GhcHint]
|
|
| 2400 | - report_no_fieldnames item
|
|
| 2401 | - | Just (EvVarDest evvar) <- ei_evdest item
|
|
| 2402 | - -- we can assume that here we have a `HasField @Symbol x r a` instance
|
|
| 2403 | - -- because of GetFieldOrigin in record_field
|
|
| 2404 | - , Just (_, [_symbol, x, r, a]) <- tcSplitTyConApp_maybe (varType evvar)
|
|
| 2405 | - , Just (r_tycon, _) <- tcSplitTyConApp_maybe r
|
|
| 2406 | - , Just x_name <- isStrLitTy x
|
|
| 2407 | - -- we check that this is a record type by checking whether it has any
|
|
| 2408 | - -- fields (in scope)
|
|
| 2409 | - , not . null $ tyConFieldLabels r_tycon
|
|
| 2410 | - = [RemindRecordMissingField x_name r a]
|
|
| 2411 | - | otherwise = []
|
|
| 2412 | - |
|
| 2413 | - occ_name_in_scope glb_env lcl_env occ_name = not $
|
|
| 2414 | - null (lookupGRE glb_env (LookupOccName occ_name (RelevantGREsFOS WantNormal))) &&
|
|
| 2415 | - isNothing (lookupLocalRdrOcc lcl_env occ_name)
|
|
| 2416 | - |
|
| 2417 | - record_field = case orig of
|
|
| 2418 | - GetFieldOrigin name -> Just (mkVarOccFS name)
|
|
| 2419 | - _ -> Nothing
|
|
| 2420 | - |
|
| 2421 | 2393 | {- Note [Report candidate instances]
|
| 2422 | 2394 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 2423 | 2395 | If we have an unsolved (Num Int), where `Int` is not the Prelude Int,
|
| ... | ... | @@ -2475,6 +2447,245 @@ results in |
| 2475 | 2447 | in the import of ‘Data.Monoid’
|
| 2476 | 2448 | -}
|
| 2477 | 2449 | |
| 2450 | +mkCouldNotDeduceErr
|
|
| 2451 | + :: [UserGiven]
|
|
| 2452 | + -> NonEmpty ErrorItem
|
|
| 2453 | + -> Maybe CND_ExpectedActual
|
|
| 2454 | + -> TcM MismatchMsg
|
|
| 2455 | +mkCouldNotDeduceErr user_givens items@(item :| _) mb_ea
|
|
| 2456 | + = do { mb_noBuiltinInst_info <- getNoBuiltinInstMsg item
|
|
| 2457 | + ; return $ CouldNotDeduce user_givens items mb_ea mb_noBuiltinInst_info }
|
|
| 2458 | + |
|
| 2459 | +getNoBuiltinInstMsg :: ErrorItem -> TcM (Maybe NoBuiltinInstanceMsg)
|
|
| 2460 | +getNoBuiltinInstMsg item =
|
|
| 2461 | + do { rdr_env <- getGlobalRdrEnv
|
|
| 2462 | + ; fam_envs <- tcGetFamInstEnvs
|
|
| 2463 | + ; mbNoHasFieldMsg <- hasFieldInfo_maybe rdr_env fam_envs item
|
|
| 2464 | + ; return $ fmap NoBuiltinHasFieldMsg mbNoHasFieldMsg
|
|
| 2465 | + }
|
|
| 2466 | + |
|
| 2467 | +{- Note [Error messages for unsolved HasField constraints]
|
|
| 2468 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 2469 | +The HasField type-class has special instance solving logic, implemented in
|
|
| 2470 | +'GHC.Tc.Instance.Class.{matchHasField,lookupHasFieldLabel}'. This logic is a
|
|
| 2471 | +bit complex, so it's useful to explain to the user why GHC might have failed to
|
|
| 2472 | +solve a 'HasField' constraint. GHC will emit the following error messages for
|
|
| 2473 | +an unsolved constraint of the form 'HasField fld_name rec_ty fld_ty'.
|
|
| 2474 | +These come in two flavours
|
|
| 2475 | + |
|
| 2476 | + HF1.
|
|
| 2477 | + Actionable hints: suggest similarly named fields (in case of mis-spelling)
|
|
| 2478 | + or provide import suggestions (e.g. out of scope field).
|
|
| 2479 | + See 'GHC.Tc.Errors.Ppr.hasFieldMsgHints' which takes the returned
|
|
| 2480 | + 'HasFieldMsg' and produces the hints we display to the user.
|
|
| 2481 | + |
|
| 2482 | + This depends on whether 'rec_ty' is a known fixed TyCon or not.
|
|
| 2483 | + |
|
| 2484 | + HF1a. If 'rec_ty' is a known record TyCon:
|
|
| 2485 | + - If 'fld_name' is a record field of that TyCon, but it's not in scope,
|
|
| 2486 | + then suggest importing it.
|
|
| 2487 | + - Otherwise, we suggest similarly named fields, prioritising similar
|
|
| 2488 | + name suggestions for record fields from that same TyCon.
|
|
| 2489 | + |
|
| 2490 | + HF1b. If 'rec_ty' is not a fixed TyCon (e.g. it's a metavariable):
|
|
| 2491 | + - If 'fld_name' is an in-scope record field, don't suggest anything.
|
|
| 2492 | + - Otherwise, suggest similar names.
|
|
| 2493 | + |
|
| 2494 | + HF2. Observations. GHC points out a fact to the user which might help them
|
|
| 2495 | + understand the problem:
|
|
| 2496 | + |
|
| 2497 | + HF2a. 'fld_name' is not a string literal.
|
|
| 2498 | + This is useful when the user has forgotten the quotes, e.g. they
|
|
| 2499 | + have written 'getField @myFieldName' instead of 'getField @"myFieldName"'.
|
|
| 2500 | + |
|
| 2501 | + HF2b. 'rec_ty' is a TyCon without any fields, e.g. 'Int' or 'Bool'.
|
|
| 2502 | + |
|
| 2503 | + HF2c. The record field type 'fld_ty' contains existentials variables
|
|
| 2504 | + or foralls. In the former case GHC doesn't generate a field selector
|
|
| 2505 | + at all (it's a naughty record selector), while in the latter GHC
|
|
| 2506 | + doesn't solve the constraint, because class instance arguments
|
|
| 2507 | + can't contain foralls.
|
|
| 2508 | + |
|
| 2509 | + HF2d. The record field is a pattern synonym record field.
|
|
| 2510 | + GHC does not generate 'HasField' instances for pattern synonym fields.
|
|
| 2511 | + |
|
| 2512 | + HF2e. The user is using -XRebindableSyntax, and this is not actually the
|
|
| 2513 | + built-in HasField which GHC has special solving logic for.
|
|
| 2514 | + |
|
| 2515 | + This can happen rather easily, because the current usage of
|
|
| 2516 | + -XOverloadedRecordUpdate requires enabling -XRebindableSyntax and
|
|
| 2517 | + defining a custom 'setField' function.
|
|
| 2518 | +-}
|
|
| 2519 | + |
|
| 2520 | +-- | Try to produce an explanatory message for why GHC was not able to use
|
|
| 2521 | +-- a built-in instance to solve a 'HasField' constraint.
|
|
| 2522 | +--
|
|
| 2523 | +-- See Note [Error messages for unsolved HasField constraints]
|
|
| 2524 | +hasFieldInfo_maybe :: GlobalRdrEnv -> FamInstEnvs -> ErrorItem -> TcM (Maybe HasFieldMsg)
|
|
| 2525 | +hasFieldInfo_maybe rdr_env fam_inst_envs item
|
|
| 2526 | + | Just (x_ty, rec_ty, _wanted_field_ty) <- hasField_maybe (errorItemPred item)
|
|
| 2527 | + |
|
| 2528 | + -- This function largely replicates the logic
|
|
| 2529 | + -- of 'GHC.Tc.Instance.Class.{matchHasField,lookupHasFieldLabel}'.
|
|
| 2530 | + --
|
|
| 2531 | + -- When that function fails to return a built-in HasField instance,
|
|
| 2532 | + -- this function should generate an appropriate message which can be
|
|
| 2533 | + -- displayed to the user as a hint.
|
|
| 2534 | + |
|
| 2535 | + = case isStrLitTy x_ty of
|
|
| 2536 | + { Nothing ->
|
|
| 2537 | + -- (HF2a) Field label is not a literal string.
|
|
| 2538 | + return $ Just $ NotALiteralFieldName x_ty
|
|
| 2539 | + ; Just x ->
|
|
| 2540 | + do { dflags <- getDynFlags
|
|
| 2541 | + ; let x_fl = FieldLabelString x
|
|
| 2542 | + looking_for_field = LF WL_RecField WL_Global
|
|
| 2543 | + fld_var_occ = mkVarOccFS x
|
|
| 2544 | + lkup_fld_occ = LookupOccName fld_var_occ (RelevantGREsFOS WantField)
|
|
| 2545 | + similar_names =
|
|
| 2546 | + similarNameSuggestions looking_for_field
|
|
| 2547 | + dflags rdr_env emptyLocalRdrEnv (mkRdrUnqual fld_var_occ)
|
|
| 2548 | + ; (patsyns, suggs) <- partitionEithers <$> mapMaybeM with_parent similar_names
|
|
| 2549 | + ; imp_suggs <- anyQualImportSuggestions looking_for_field lkup_fld_occ
|
|
| 2550 | + ; case splitTyConApp_maybe rec_ty of
|
|
| 2551 | + { Nothing -> do
|
|
| 2552 | + -- (HF1b) Similar name and import suggestions with unknown TyCon.
|
|
| 2553 | + --
|
|
| 2554 | + -- Don't say 'rec is not a record type' if 'rec' is e.g. a type variable.
|
|
| 2555 | + -- That's not really helpful, especially if 'rec' is a metavariable,
|
|
| 2556 | + -- in which case this is most likely an ambiguity issue.
|
|
| 2557 | + let gres = lookupGRE rdr_env lkup_fld_occ
|
|
| 2558 | + case gres of
|
|
| 2559 | + _:_ ->
|
|
| 2560 | + -- If the name was in scope, don't give "similar name" suggestions.
|
|
| 2561 | + return Nothing
|
|
| 2562 | + [] -> do
|
|
| 2563 | + return $ Just $
|
|
| 2564 | + SuggestSimilarFields Nothing x_fl suggs patsyns imp_suggs
|
|
| 2565 | + ; Just (rec_tc, rec_args)
|
|
| 2566 | + | let rec_rep_tc = fstOf3 (tcLookupDataFamInst fam_inst_envs rec_tc rec_args)
|
|
| 2567 | + ->
|
|
| 2568 | + if null $ tyConFieldLabels rec_rep_tc
|
|
| 2569 | + then
|
|
| 2570 | + -- (HF2b) Not a record TyCon
|
|
| 2571 | + return $ Just $ NotARecordType rec_ty
|
|
| 2572 | + else
|
|
| 2573 | + case lookupTyConFieldLabel x_fl rec_rep_tc of
|
|
| 2574 | + { Nothing -> do
|
|
| 2575 | + -- (HF1a) Similar name and import suggestions with known TyCon.
|
|
| 2576 | + return $ Just $
|
|
| 2577 | + SuggestSimilarFields (Just (rec_tc, rec_rep_tc)) x_fl suggs patsyns imp_suggs
|
|
| 2578 | + ; Just fl ->
|
|
| 2579 | + -- The TyCon does have the field, so the issue might be that
|
|
| 2580 | + -- it's not in scope or that the field is existential or higher-rank.
|
|
| 2581 | + case lookupGRE_FieldLabel rdr_env fl of
|
|
| 2582 | + { Nothing -> do
|
|
| 2583 | + -- (HF1a) Not in scope. Try to suggest importing the field.
|
|
| 2584 | + let lookup_gre =
|
|
| 2585 | + LookupExactName
|
|
| 2586 | + { lookupExactName = flSelector fl
|
|
| 2587 | + , lookInAllNameSpaces = False }
|
|
| 2588 | + imp_suggs <- anyQualImportSuggestions looking_for_field lookup_gre
|
|
| 2589 | + return $ Just $ OutOfScopeField rec_tc fl imp_suggs
|
|
| 2590 | + ; Just gre ->
|
|
| 2591 | + let con1_nm =
|
|
| 2592 | + case nonDetEltsUniqSet $ recFieldCons $ fieldGREInfo gre of
|
|
| 2593 | + n : _ -> n
|
|
| 2594 | + [] -> pprPanic "record field with no constructors" (ppr fl)
|
|
| 2595 | + in case con1_nm of
|
|
| 2596 | + { PatSynName {} ->
|
|
| 2597 | + -- 'lookupTyConFieldLabel' always returns a DataCon field
|
|
| 2598 | + pprPanic "hasFieldInfo_maybe: PatSyn" $
|
|
| 2599 | + vcat [ text "tc:" <+> ppr rec_tc
|
|
| 2600 | + , text "rep_tc:" <+> ppr rec_rep_tc
|
|
| 2601 | + , text "con1_nm:" <+> ppr con1_nm
|
|
| 2602 | + ]
|
|
| 2603 | + ; DataConName dc1_nm -> do
|
|
| 2604 | + dc1 <- tcLookupDataCon dc1_nm
|
|
| 2605 | + let orig_field_ty = dataConFieldType dc1 (flLabel fl)
|
|
| 2606 | + return $
|
|
| 2607 | + -- (HF2c) Existential or higher-rank field.
|
|
| 2608 | + -- See 'GHC.Tc.Instance.Class.matchHasField', which
|
|
| 2609 | + -- has these same two conditions.
|
|
| 2610 | + if | isExistentialRecordField orig_field_ty (RealDataCon dc1)
|
|
| 2611 | + -- NB: use 'orig_field_ty' and not 'idType sel_id',
|
|
| 2612 | + -- because the latter is 'unitTy' when there are existentials.
|
|
| 2613 | + -> Just $ FieldTooFancy rec_tc x_fl FieldHasExistential
|
|
| 2614 | + | not $ isTauTy orig_field_ty
|
|
| 2615 | + -> Just $ FieldTooFancy rec_tc x_fl FieldHasForAlls
|
|
| 2616 | + | otherwise
|
|
| 2617 | + -> Nothing
|
|
| 2618 | + -- Not sure what went wrong. Usually not a type error
|
|
| 2619 | + -- in the field type, because the functional dependency
|
|
| 2620 | + -- would cause a genuine equality error.
|
|
| 2621 | + }}}}}}
|
|
| 2622 | + |
|
| 2623 | + -- (HF2e) It's a custom HasField constraint, not the one from GHC.Records.
|
|
| 2624 | + | Just (tc, _) <- splitTyConApp_maybe (errorItemPred item)
|
|
| 2625 | + , getOccString tc == "HasField"
|
|
| 2626 | + , isHasFieldOrigin (errorItemOrigin item)
|
|
| 2627 | + = return $ Just $ CustomHasField tc
|
|
| 2628 | + |
|
| 2629 | + | otherwise
|
|
| 2630 | + = return Nothing
|
|
| 2631 | + |
|
| 2632 | + where
|
|
| 2633 | + |
|
| 2634 | + get_parent_nm :: Name -> TcM (Maybe (Either PatSyn TyCon))
|
|
| 2635 | + get_parent_nm nm =
|
|
| 2636 | + do { fld_id <- tcLookupId nm
|
|
| 2637 | + ; return $
|
|
| 2638 | + case idDetails fld_id of
|
|
| 2639 | + RecSelId { sel_tycon = parent } ->
|
|
| 2640 | + case parent of
|
|
| 2641 | + RecSelData tc ->
|
|
| 2642 | + Just $ Right tc
|
|
| 2643 | + RecSelPatSyn ps ->
|
|
| 2644 | + -- (HF2d) PatSyn record fields don't contribute 'HasField'
|
|
| 2645 | + -- instances, so tell the user about that.
|
|
| 2646 | + Just $ Left ps
|
|
| 2647 | + _ -> Nothing
|
|
| 2648 | + }
|
|
| 2649 | + |
|
| 2650 | + get_parent :: SimilarName -> TcM (Maybe (Either PatSyn TyCon))
|
|
| 2651 | + get_parent (SimilarName nm) = get_parent_nm nm
|
|
| 2652 | + get_parent (SimilarRdrName _ mb_gre _) =
|
|
| 2653 | + case mb_gre of
|
|
| 2654 | + Nothing -> return Nothing
|
|
| 2655 | + Just gre -> get_parent_nm $ greName gre
|
|
| 2656 | + |
|
| 2657 | + with_parent :: SimilarName
|
|
| 2658 | + -> TcM (Maybe (Either (PatSyn, SimilarName) (TyCon, SimilarName)))
|
|
| 2659 | + with_parent n = fmap (bimap (,n) (,n)) <$> get_parent n
|
|
| 2660 | + |
|
| 2661 | +-- | Is this constraint definitely 'HasField'?
|
|
| 2662 | +hasField_maybe :: PredType -> Maybe (Type, Type, Type)
|
|
| 2663 | +hasField_maybe pred =
|
|
| 2664 | + case classifyPredType pred of
|
|
| 2665 | + ClassPred cls tys
|
|
| 2666 | + | className cls == hasFieldClassName
|
|
| 2667 | + , [ _k, _rec_rep, _fld_rep, x_ty, rec_ty, fld_ty ] <- tys
|
|
| 2668 | + -> Just (x_ty, rec_ty, fld_ty)
|
|
| 2669 | + _ -> Nothing
|
|
| 2670 | + -- NB: we deliberately don't handle rebound 'HasField' (with -XRebindableSyntax),
|
|
| 2671 | + -- as GHC only has built-in instances for the built-in 'HasField' class.
|
|
| 2672 | + |
|
| 2673 | +-- | Does this constraint arise from GHC internal mechanisms that desugar to
|
|
| 2674 | +-- usage of the 'HasField' typeclass (e.g. OverloadedRecordDot, etc)?
|
|
| 2675 | +--
|
|
| 2676 | +-- Just used heuristically to decide whether to print an informative message to
|
|
| 2677 | +-- the user (see (H2e) in Note [Error messages for unsolved HasField constraints]).
|
|
| 2678 | +isHasFieldOrigin :: CtOrigin -> Bool
|
|
| 2679 | +isHasFieldOrigin = \case
|
|
| 2680 | + OccurrenceOf n ->
|
|
| 2681 | + -- A heuristic...
|
|
| 2682 | + getOccString n `elem` ["getField", "setField"]
|
|
| 2683 | + OccurrenceOfRecSel {} -> True
|
|
| 2684 | + RecordUpdOrigin {} -> True
|
|
| 2685 | + RecordFieldProjectionOrigin {} -> True
|
|
| 2686 | + GetFieldOrigin {} -> True
|
|
| 2687 | + _ -> False
|
|
| 2688 | + |
|
| 2478 | 2689 | -----------------------
|
| 2479 | 2690 | -- relevantBindings looks at the value environment and finds values whose
|
| 2480 | 2691 | -- types mention any of the offending type variables. It has to be
|
| ... | ... | @@ -63,7 +63,7 @@ import GHC.Core.InstEnv |
| 63 | 63 | import GHC.Core.TyCo.Rep (Type(..))
|
| 64 | 64 | import GHC.Core.TyCo.Ppr (pprWithInvisibleBitsWhen, pprSourceTyCon,
|
| 65 | 65 | pprTyVars, pprWithTYPE, pprTyVar, pprTidiedType, pprForAll)
|
| 66 | -import GHC.Core.PatSyn ( patSynName, pprPatSynType )
|
|
| 66 | +import GHC.Core.PatSyn ( patSynName, pprPatSynType, PatSyn )
|
|
| 67 | 67 | import GHC.Core.TyCo.Tidy
|
| 68 | 68 | import GHC.Core.Predicate
|
| 69 | 69 | import GHC.Core.Type
|
| ... | ... | @@ -90,7 +90,7 @@ import GHC.Types.DefaultEnv (ClassDefaults(ClassDefaults, cd_types, cd_provenanc |
| 90 | 90 | import GHC.Types.Error
|
| 91 | 91 | import GHC.Types.Error.Codes
|
| 92 | 92 | import GHC.Types.Hint
|
| 93 | -import GHC.Types.Hint.Ppr ( pprSigLike ) -- & Outputable GhcHint
|
|
| 93 | +import GHC.Types.Hint.Ppr ( pprSigLike )
|
|
| 94 | 94 | import GHC.Types.Basic
|
| 95 | 95 | import GHC.Types.Id
|
| 96 | 96 | import GHC.Types.Id.Info ( RecSelParent(..) )
|
| ... | ... | @@ -129,6 +129,9 @@ import qualified GHC.LanguageExtensions as LangExt |
| 129 | 129 | |
| 130 | 130 | import GHC.Data.BooleanFormula (pprBooleanFormulaNice)
|
| 131 | 131 | |
| 132 | +import Language.Haskell.Syntax.Basic (field_label, FieldLabelString (..))
|
|
| 133 | + |
|
| 134 | +import Control.Monad (guard)
|
|
| 132 | 135 | import qualified Data.Semigroup as S
|
| 133 | 136 | import Data.List.NonEmpty (NonEmpty(..))
|
| 134 | 137 | import qualified Data.List.NonEmpty as NE
|
| ... | ... | @@ -4114,7 +4117,13 @@ pprTcSolverReportMsg ctxt (UnboundImplicitParams (item :| items)) = |
| 4114 | 4117 | sep [ text "Unbound implicit parameter" <> plural preds
|
| 4115 | 4118 | , nest 2 (pprParendTheta preds) ]
|
| 4116 | 4119 | else
|
| 4117 | - let mismatch = CouldNotDeduce givens (item :| items) Nothing
|
|
| 4120 | + let mismatch =
|
|
| 4121 | + CouldNotDeduce
|
|
| 4122 | + { cnd_user_givens = givens
|
|
| 4123 | + , cnd_wanted = item :| items
|
|
| 4124 | + , cnd_ea = Nothing
|
|
| 4125 | + , cnd_noBuiltin_msg = Nothing
|
|
| 4126 | + }
|
|
| 4118 | 4127 | invis_bits = mismatchInvisibleBits mismatch
|
| 4119 | 4128 | ppr_msg = pprMismatchMsg ctxt mismatch
|
| 4120 | 4129 | in
|
| ... | ... | @@ -4127,7 +4136,7 @@ pprTcSolverReportMsg _ (AmbiguityPreventsSolvingCt item ambigs) = |
| 4127 | 4136 | text "prevents the constraint" <+> quotes (pprParendType $ errorItemPred item)
|
| 4128 | 4137 | <+> text "from being solved."
|
| 4129 | 4138 | pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics})
|
| 4130 | - (CannotResolveInstance item unifiers candidates rel_binds)
|
|
| 4139 | + (CannotResolveInstance item unifiers candidates rel_binds mb_HasField_msg)
|
|
| 4131 | 4140 | = pprWithInvisibleBits invis_bits $
|
| 4132 | 4141 | vcat
|
| 4133 | 4142 | [ no_inst_msg
|
| ... | ... | @@ -4171,10 +4180,10 @@ pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics}) |
| 4171 | 4180 | | lead_with_ambig
|
| 4172 | 4181 | = (Set.empty, pprTcSolverReportMsg ctxt $ AmbiguityPreventsSolvingCt item (ambig_kvs, ambig_tvs))
|
| 4173 | 4182 | | otherwise
|
| 4174 | - = let mismatch = CouldNotDeduce useful_givens (item :| []) Nothing
|
|
| 4183 | + = let mismatch = CouldNotDeduce useful_givens (item :| []) Nothing mb_HasField_msg
|
|
| 4175 | 4184 | in
|
| 4176 | 4185 | ( mismatchInvisibleBits mismatch
|
| 4177 | - , pprMismatchMsg ctxt $ CouldNotDeduce useful_givens (item :| []) Nothing
|
|
| 4186 | + , pprMismatchMsg ctxt mismatch
|
|
| 4178 | 4187 | )
|
| 4179 | 4188 | |
| 4180 | 4189 | -- Report "potential instances" only when the constraint arises
|
| ... | ... | @@ -4202,6 +4211,9 @@ pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics}) |
| 4202 | 4211 | | otherwise = Nothing
|
| 4203 | 4212 | |
| 4204 | 4213 | extra_note
|
| 4214 | + | Just {} <- mb_HasField_msg
|
|
| 4215 | + = empty
|
|
| 4216 | + |
|
| 4205 | 4217 | -- Flag up partially applied uses of (->)
|
| 4206 | 4218 | | any isFunTy (filterOutInvisibleTypes (classTyCon clas) tys)
|
| 4207 | 4219 | = text "(maybe you haven't applied a function to enough arguments?)"
|
| ... | ... | @@ -4417,10 +4429,10 @@ mismatchInvisibleBits |
| 4417 | 4429 | , teq_mismatch_ty1 = ty1
|
| 4418 | 4430 | , teq_mismatch_ty2 = ty2 })
|
| 4419 | 4431 | = shouldPprWithInvisibleBits ty1 ty2 (errorItemOrigin item)
|
| 4420 | -mismatchInvisibleBits (CouldNotDeduce { cnd_extra = mb_extra })
|
|
| 4421 | - = case mb_extra of
|
|
| 4432 | +mismatchInvisibleBits (CouldNotDeduce { cnd_ea = mb_ea })
|
|
| 4433 | + = case mb_ea of
|
|
| 4422 | 4434 | Nothing -> Set.empty
|
| 4423 | - Just (CND_Extra _ ty1 ty2) ->
|
|
| 4435 | + Just (CND_ExpectedActual _ ty1 ty2) ->
|
|
| 4424 | 4436 | mayLookIdentical ty1 ty2
|
| 4425 | 4437 | |
| 4426 | 4438 | -- | Turn a 'MismatchMsg' into an 'SDoc'.
|
| ... | ... | @@ -4612,9 +4624,14 @@ pprMismatchMsg ctxt |
| 4612 | 4624 | |
| 4613 | 4625 | starts_with_vowel (c:_) = c `elem` ("AEIOU" :: String)
|
| 4614 | 4626 | starts_with_vowel [] = False
|
| 4615 | - |
|
| 4616 | -pprMismatchMsg ctxt (CouldNotDeduce useful_givens (item :| others) mb_extra)
|
|
| 4627 | +pprMismatchMsg ctxt
|
|
| 4628 | + (CouldNotDeduce { cnd_user_givens = useful_givens
|
|
| 4629 | + , cnd_wanted = item :| others
|
|
| 4630 | + , cnd_ea = mb_ea
|
|
| 4631 | + , cnd_noBuiltin_msg = mb_NoBuiltin_msg
|
|
| 4632 | + })
|
|
| 4617 | 4633 | = vcat [ main_msg
|
| 4634 | + , maybe empty pprNoBuiltinInstanceMsg mb_NoBuiltin_msg
|
|
| 4618 | 4635 | , pprQCOriginExtra item
|
| 4619 | 4636 | , ea_supplementary ]
|
| 4620 | 4637 | where
|
| ... | ... | @@ -4623,9 +4640,10 @@ pprMismatchMsg ctxt (CouldNotDeduce useful_givens (item :| others) mb_extra) |
| 4623 | 4640 | | otherwise = vcat ( addArising ct_loc no_deduce_msg
|
| 4624 | 4641 | : pp_from_givens useful_givens)
|
| 4625 | 4642 | |
| 4626 | - ea_supplementary = case mb_extra of
|
|
| 4627 | - Nothing -> empty
|
|
| 4628 | - Just (CND_Extra level ty1 ty2) -> mk_supplementary_ea_msg ctxt level ty1 ty2 orig
|
|
| 4643 | + ea_supplementary = case mb_ea of
|
|
| 4644 | + Nothing -> empty
|
|
| 4645 | + Just (CND_ExpectedActual level ty1 ty2) ->
|
|
| 4646 | + mk_supplementary_ea_msg ctxt level ty1 ty2 orig
|
|
| 4629 | 4647 | |
| 4630 | 4648 | ct_loc = errorItemCtLoc item
|
| 4631 | 4649 | orig = ctLocOrigin ct_loc
|
| ... | ... | @@ -5022,6 +5040,87 @@ pprCoercibleMsg (OutOfScopeNewtypeConstructor tc dc) = |
| 5022 | 5040 | 2 (sep [ text "of newtype" <+> quotes (pprSourceTyCon tc)
|
| 5023 | 5041 | , text "is not in scope" ])
|
| 5024 | 5042 | |
| 5043 | +pprNoBuiltinInstanceMsg :: NoBuiltinInstanceMsg -> SDoc
|
|
| 5044 | +pprNoBuiltinInstanceMsg = \case
|
|
| 5045 | + NoBuiltinHasFieldMsg msg -> pprHasFieldMsg msg
|
|
| 5046 | + |
|
| 5047 | +pprHasFieldMsg :: HasFieldMsg -> SDoc
|
|
| 5048 | +pprHasFieldMsg = \case
|
|
| 5049 | + NotALiteralFieldName ty ->
|
|
| 5050 | + text "NB:" <+> quotes (ppr ty) <+> what
|
|
| 5051 | + where
|
|
| 5052 | + what
|
|
| 5053 | + | Just {} <- getCastedTyVar_maybe ty
|
|
| 5054 | + = text "is a type variable, not a string literal."
|
|
| 5055 | + | otherwise
|
|
| 5056 | + = text "is not a string literal."
|
|
| 5057 | + NotARecordType ty ->
|
|
| 5058 | + text "NB:" <+> quotes (ppr ty) <+> text "is not a record type."
|
|
| 5059 | + OutOfScopeField tc fld _import_suggs ->
|
|
| 5060 | + text "NB: the record field" <+> quotes (ppr fld) <+> text "of" <+> quotes (ppr tc) <+> text "is out of scope."
|
|
| 5061 | + FieldTooFancy tc fld rea ->
|
|
| 5062 | + case rea of
|
|
| 5063 | + FieldHasExistential ->
|
|
| 5064 | + text "NB: the record field" <+> quotes (ppr fld) <+> text "of" <+> quotes (ppr tc) <+> text "contains existential variables."
|
|
| 5065 | + FieldHasForAlls ->
|
|
| 5066 | + text "NB: the field type of the record field" <+> quotes (ppr fld) <+> text "of" <+> quotes (ppr tc) <+> text "is not a mono-type."
|
|
| 5067 | + CustomHasField custom_hasField ->
|
|
| 5068 | + text "NB:" <+> quotes (ppr custom_hasField) <+> text "is not the built-in"
|
|
| 5069 | + <+> quotes (ppr hasFieldClassName) <+> text "class."
|
|
| 5070 | + SuggestSimilarFields (Just (tc, rep_tc)) fld suggs pat_syns _imp_suggs ->
|
|
| 5071 | + vcat
|
|
| 5072 | + [ text "NB:" <+> quotes (ppr tc)
|
|
| 5073 | + <+> text "does not have a record field named"
|
|
| 5074 | + <+> quotes (ppr fld) <> dot
|
|
| 5075 | + , pprHasFieldPatSynMsg fld pat_syns
|
|
| 5076 | + , pprSameNameOtherTyCons (mapMaybe same_name_diff_tc suggs)
|
|
| 5077 | + -- NB: The actual suggestions are dealt with by
|
|
| 5078 | + -- GHC.Tc.Errors.hasFieldMsgHints. The logic here just covers
|
|
| 5079 | + -- information for which there is no actionable hint.
|
|
| 5080 | + ]
|
|
| 5081 | + where
|
|
| 5082 | + same_name_diff_tc (rep_tc', fld') = do
|
|
| 5083 | + let occ = case fld' of
|
|
| 5084 | + SimilarName n -> getOccFS n
|
|
| 5085 | + SimilarRdrName n _ _ -> occNameFS $ rdrNameOcc n
|
|
| 5086 | + guard $
|
|
| 5087 | + rep_tc' /= rep_tc
|
|
| 5088 | + &&
|
|
| 5089 | + (fld == FieldLabelString occ)
|
|
| 5090 | + return rep_tc'
|
|
| 5091 | + SuggestSimilarFields Nothing fld _suggs pat_syns _imp_suggs ->
|
|
| 5092 | + pprHasFieldPatSynMsg fld pat_syns
|
|
| 5093 | + -- Most of the error message only makes sense when we know the TyCon.
|
|
| 5094 | + -- In this "unknown TyCon" case, we only have:
|
|
| 5095 | + -- - the "PatSyns don't give HasField instances" message
|
|
| 5096 | + -- - the hints, which are handled separately (see 'hasFieldMsgHints').
|
|
| 5097 | + |
|
| 5098 | +pprSameNameOtherTyCons :: [TyCon] -> SDoc
|
|
| 5099 | +pprSameNameOtherTyCons [] = empty
|
|
| 5100 | +pprSameNameOtherTyCons tcs =
|
|
| 5101 | + other_types_have <+> text "a field of this name:"
|
|
| 5102 | + <+> pprWithCommas (quotes . ppr) tcs <> dot
|
|
| 5103 | + where
|
|
| 5104 | + other_types_have :: SDoc
|
|
| 5105 | + other_types_have = case tcs of
|
|
| 5106 | + _:_:_ -> "Other types have"
|
|
| 5107 | + _ -> "Another type has"
|
|
| 5108 | + |
|
| 5109 | +pprHasFieldPatSynMsg :: FieldLabelString -> [(PatSyn, SimilarName)] -> SDoc
|
|
| 5110 | +pprHasFieldPatSynMsg fld pat_syns =
|
|
| 5111 | + if any same_name pat_syns
|
|
| 5112 | + then
|
|
| 5113 | + text "Pattern synonym record fields do not contribute"
|
|
| 5114 | + <+> quotes (ppr hasFieldClassName) <+> text "instances."
|
|
| 5115 | + else empty
|
|
| 5116 | + where
|
|
| 5117 | + same_name (_,nm) =
|
|
| 5118 | + let occ = case nm of
|
|
| 5119 | + SimilarName n -> getOccFS n
|
|
| 5120 | + SimilarRdrName n _ _ -> occNameFS $ rdrNameOcc n
|
|
| 5121 | + in
|
|
| 5122 | + occ == field_label fld
|
|
| 5123 | + |
|
| 5025 | 5124 | pprWhenMatching :: SolverReportErrCtxt -> WhenMatching -> SDoc
|
| 5026 | 5125 | pprWhenMatching ctxt (WhenMatching cty1 cty2 sub_o mb_sub_t_or_k) =
|
| 5027 | 5126 | sdocOption sdocPrintExplicitCoercions $ \printExplicitCoercions ->
|
| ... | ... | @@ -5247,8 +5346,8 @@ tcSolverReportMsgHints ctxt = \case |
| 5247 | 5346 | -> noHints
|
| 5248 | 5347 | AmbiguityPreventsSolvingCt {}
|
| 5249 | 5348 | -> noHints
|
| 5250 | - CannotResolveInstance {}
|
|
| 5251 | - -> noHints
|
|
| 5349 | + CannotResolveInstance { cannotResolve_noBuiltinMsg = mb_noBuiltin }
|
|
| 5350 | + -> maybe noHints noBuiltinInstanceHints mb_noBuiltin
|
|
| 5252 | 5351 | OverlappingInstances {}
|
| 5253 | 5352 | -> noHints
|
| 5254 | 5353 | UnsafeOverlap {}
|
| ... | ... | @@ -5256,22 +5355,66 @@ tcSolverReportMsgHints ctxt = \case |
| 5256 | 5355 | MultiplicityCoercionsNotSupported {}
|
| 5257 | 5356 | -> noHints
|
| 5258 | 5357 | |
| 5358 | +noBuiltinInstanceHints :: NoBuiltinInstanceMsg -> [GhcHint]
|
|
| 5359 | +noBuiltinInstanceHints = \case
|
|
| 5360 | + NoBuiltinHasFieldMsg noHasFieldMsg -> hasFieldMsgHints noHasFieldMsg
|
|
| 5361 | + |
|
| 5362 | +hasFieldMsgHints :: HasFieldMsg -> [GhcHint]
|
|
| 5363 | +hasFieldMsgHints = \case
|
|
| 5364 | + NotALiteralFieldName {} -> noHints
|
|
| 5365 | + NotARecordType {} -> noHints
|
|
| 5366 | + FieldTooFancy {} -> noHints
|
|
| 5367 | + SuggestSimilarFields mb_orig_tc orig_fld suggs _patsyns imp_suggs ->
|
|
| 5368 | + map (ImportSuggestion fld_occ) imp_suggs ++ similar_suggs
|
|
| 5369 | + where
|
|
| 5370 | + fld_occ = mkVarOccFS $ field_label orig_fld
|
|
| 5371 | + similar_suggs =
|
|
| 5372 | + case NE.nonEmpty $ filter different_name suggs of
|
|
| 5373 | + Nothing -> noHints
|
|
| 5374 | + Just neSuggs ->
|
|
| 5375 | + case mb_orig_tc of
|
|
| 5376 | + Just (orig_tc, orig_rep_tc) ->
|
|
| 5377 | + -- We know the parent TyCon
|
|
| 5378 | + [SuggestSimilarSelectors orig_tc orig_rep_tc orig_fld neSuggs]
|
|
| 5379 | + Nothing ->
|
|
| 5380 | + -- We don't know the parent TyCon
|
|
| 5381 | + [ SuggestSimilarNames
|
|
| 5382 | + (mkRdrUnqual fld_occ)
|
|
| 5383 | + (fmap snd neSuggs)
|
|
| 5384 | + ]
|
|
| 5385 | + different_name ( _, nm ) =
|
|
| 5386 | + let occ = case nm of
|
|
| 5387 | + SimilarName n -> getOccFS n
|
|
| 5388 | + SimilarRdrName n _ _ -> occNameFS $ rdrNameOcc n
|
|
| 5389 | + in
|
|
| 5390 | + orig_fld /= FieldLabelString occ
|
|
| 5391 | + OutOfScopeField _tc fld import_suggs ->
|
|
| 5392 | + map (ImportSuggestion (nameOccName $ flSelector fld)) import_suggs
|
|
| 5393 | + CustomHasField {} -> noHints
|
|
| 5394 | + |
|
| 5259 | 5395 | mismatchMsgHints :: SolverReportErrCtxt -> MismatchMsg -> [GhcHint]
|
| 5260 | 5396 | mismatchMsgHints ctxt msg =
|
| 5397 | + mismatchMsgHasFieldHints msg ++
|
|
| 5261 | 5398 | maybeToList [ hint | (exp,act) <- mismatchMsg_ExpectedActuals msg
|
| 5262 | 5399 | , hint <- suggestAddSig ctxt exp act ]
|
| 5263 | 5400 | |
| 5401 | +mismatchMsgHasFieldHints :: MismatchMsg -> [GhcHint]
|
|
| 5402 | +mismatchMsgHasFieldHints
|
|
| 5403 | + (CouldNotDeduce { cnd_noBuiltin_msg = mb_noBuiltin }) =
|
|
| 5404 | + maybe noHints noBuiltinInstanceHints mb_noBuiltin
|
|
| 5405 | +mismatchMsgHasFieldHints (BasicMismatch{}) = []
|
|
| 5406 | +mismatchMsgHasFieldHints (TypeEqMismatch{}) = []
|
|
| 5407 | + |
|
| 5264 | 5408 | mismatchMsg_ExpectedActuals :: MismatchMsg -> Maybe (Type, Type)
|
| 5265 | 5409 | mismatchMsg_ExpectedActuals = \case
|
| 5266 | 5410 | BasicMismatch { mismatch_ty1 = exp, mismatch_ty2 = act } ->
|
| 5267 | 5411 | Just (exp, act)
|
| 5268 | 5412 | TypeEqMismatch { teq_mismatch_expected = exp, teq_mismatch_actual = act } ->
|
| 5269 | 5413 | Just (exp,act)
|
| 5270 | - CouldNotDeduce { cnd_extra = cnd_extra }
|
|
| 5271 | - | Just (CND_Extra _ exp act) <- cnd_extra
|
|
| 5272 | - -> Just (exp, act)
|
|
| 5273 | - | otherwise
|
|
| 5274 | - -> Nothing
|
|
| 5414 | + CouldNotDeduce { cnd_ea = mb_ea } ->
|
|
| 5415 | + case mb_ea of
|
|
| 5416 | + Just (CND_ExpectedActual _ exp act) -> Just (exp, act)
|
|
| 5417 | + Nothing -> Nothing
|
|
| 5275 | 5418 | |
| 5276 | 5419 | cannotUnifyVariableHints :: CannotUnifyVariableReason -> [GhcHint]
|
| 5277 | 5420 | cannotUnifyVariableHints = \case
|
| ... | ... | @@ -72,7 +72,7 @@ module GHC.Tc.Errors.Types ( |
| 72 | 72 | , ExpectedActualInfo(..)
|
| 73 | 73 | , TyVarInfo(..), SameOccInfo(..)
|
| 74 | 74 | , AmbiguityInfo(..)
|
| 75 | - , CND_Extra(..)
|
|
| 75 | + , CND_ExpectedActual(..)
|
|
| 76 | 76 | , FitsMbSuppressed(..)
|
| 77 | 77 | , ValidHoleFits(..), noValidHoleFits
|
| 78 | 78 | , HoleFitDispConfig(..)
|
| ... | ... | @@ -86,6 +86,9 @@ module GHC.Tc.Errors.Types ( |
| 86 | 86 | , lookingForSubordinate
|
| 87 | 87 | , HoleError(..)
|
| 88 | 88 | , CoercibleMsg(..)
|
| 89 | + , NoBuiltinInstanceMsg(..)
|
|
| 90 | + , HasFieldMsg(..)
|
|
| 91 | + , TooFancyField(..)
|
|
| 89 | 92 | , PotentialInstances(..)
|
| 90 | 93 | , UnsupportedCallConvention(..)
|
| 91 | 94 | , ExpectedBackends
|
| ... | ... | @@ -200,7 +203,7 @@ import GHC.Tc.Utils.TcType (TcType, TcSigmaType, TcPredType, |
| 200 | 203 | import GHC.Types.Basic
|
| 201 | 204 | import GHC.Types.Error
|
| 202 | 205 | import GHC.Types.Avail
|
| 203 | -import GHC.Types.Hint (UntickedPromotedThing(..), AssumedDerivingStrategy(..), SigLike)
|
|
| 206 | +import GHC.Types.Hint
|
|
| 204 | 207 | import GHC.Types.ForeignCall (CLabelString)
|
| 205 | 208 | import GHC.Types.Id.Info ( RecSelParent(..) )
|
| 206 | 209 | import GHC.Types.Name (NamedThing(..), Name, OccName, getSrcLoc, getSrcSpan)
|
| ... | ... | @@ -5615,6 +5618,7 @@ data TcSolverReportMsg |
| 5615 | 5618 | , cannotResolve_unifiers :: [ClsInst]
|
| 5616 | 5619 | , cannotResolve_candidates :: [ClsInst]
|
| 5617 | 5620 | , cannotResolve_relBinds :: RelevantBindings
|
| 5621 | + , cannotResolve_noBuiltinMsg :: Maybe NoBuiltinInstanceMsg
|
|
| 5618 | 5622 | }
|
| 5619 | 5623 | |
| 5620 | 5624 | -- | Could not solve a constraint using available instances
|
| ... | ... | @@ -5675,15 +5679,20 @@ data MismatchMsg |
| 5675 | 5679 | -- Used for messages such as @"No instance for ..."@ and
|
| 5676 | 5680 | -- @"Could not deduce ... from"@.
|
| 5677 | 5681 | | CouldNotDeduce
|
| 5678 | - { cnd_user_givens :: [Implication]
|
|
| 5682 | + { cnd_user_givens :: [Implication]
|
|
| 5679 | 5683 | -- | The Wanted constraints we couldn't solve.
|
| 5680 | 5684 | --
|
| 5681 | 5685 | -- N.B.: the 'ErrorItem' at the head of the list has been tidied,
|
| 5682 | 5686 | -- perhaps not the others.
|
| 5683 | - , cnd_wanted :: NE.NonEmpty ErrorItem
|
|
| 5687 | + , cnd_wanted :: NE.NonEmpty ErrorItem
|
|
| 5684 | 5688 | |
| 5685 | - -- | Some additional info consumed by 'mk_supplementary_ea_msg'.
|
|
| 5686 | - , cnd_extra :: Maybe CND_Extra
|
|
| 5689 | + -- | Additional "expected/actual" information
|
|
| 5690 | + -- consumed by 'mk_supplementary_ea_msg'.
|
|
| 5691 | + , cnd_ea :: Maybe CND_ExpectedActual
|
|
| 5692 | + |
|
| 5693 | + -- | Additional message relating to unsolved constraints for
|
|
| 5694 | + -- typeclasses which have built-in instances.
|
|
| 5695 | + , cnd_noBuiltin_msg :: Maybe NoBuiltinInstanceMsg
|
|
| 5687 | 5696 | }
|
| 5688 | 5697 | deriving Generic
|
| 5689 | 5698 | |
| ... | ... | @@ -5753,7 +5762,7 @@ mkPlainMismatchMsg msg |
| 5753 | 5762 | |
| 5754 | 5763 | -- | Additional information to be given in a 'CouldNotDeduce' message,
|
| 5755 | 5764 | -- which is then passed on to 'mk_supplementary_ea_msg'.
|
| 5756 | -data CND_Extra = CND_Extra TypeOrKind Type Type
|
|
| 5765 | +data CND_ExpectedActual = CND_ExpectedActual TypeOrKind Type Type
|
|
| 5757 | 5766 | |
| 5758 | 5767 | -- | A cue to print out information about type variables,
|
| 5759 | 5768 | -- e.g. where they were bound, when there is a mismatch @tv1 ~ ty2@.
|
| ... | ... | @@ -5967,6 +5976,48 @@ data CoercibleMsg |
| 5967 | 5976 | -- Test cases: TcCoercibleFail.
|
| 5968 | 5977 | | OutOfScopeNewtypeConstructor TyCon DataCon
|
| 5969 | 5978 | |
| 5979 | +-- | Explains why GHC wasn't able to provide a built-in instance for
|
|
| 5980 | +-- a particular class.
|
|
| 5981 | +data NoBuiltinInstanceMsg
|
|
| 5982 | + = NoBuiltinHasFieldMsg HasFieldMsg
|
|
| 5983 | + |
|
| 5984 | + -- Other useful constructors might be:
|
|
| 5985 | + -- NoBuiltinTypeableMsg -- explains polykinded Typeable restrictions
|
|
| 5986 | + -- NoBuiltinDataToTagMsg -- see conditions in Note [DataToTag overview]
|
|
| 5987 | + -- NoBuiltinWithDictMsg -- see Note [withDict]
|
|
| 5988 | + |
|
| 5989 | +-- | Explains why GHC wasn't able to provide a built-in 'HasField' instance
|
|
| 5990 | +-- for the given types.
|
|
| 5991 | +data HasFieldMsg
|
|
| 5992 | + -- | The field is not a literal field name, e.g. @HasField x u v@ where @x@
|
|
| 5993 | + -- is a type variable.
|
|
| 5994 | + = NotALiteralFieldName Type
|
|
| 5995 | + -- | The type we are selecting from is not a record type,
|
|
| 5996 | + -- e.g. @HasField "fld" Int fld@.
|
|
| 5997 | + | NotARecordType Type
|
|
| 5998 | + -- | The field is out of scope.
|
|
| 5999 | + | OutOfScopeField TyCon FieldLabel [ImportSuggestion]
|
|
| 6000 | + -- | The field has a type which means that GHC cannot solve
|
|
| 6001 | + -- a 'HasField' constraint for it.
|
|
| 6002 | + | FieldTooFancy TyCon FieldLabelString TooFancyField
|
|
| 6003 | + -- | No such field, but the field is perhaps mis-spelled;
|
|
| 6004 | + -- here are some suggestions.
|
|
| 6005 | + | SuggestSimilarFields
|
|
| 6006 | + (Maybe (TyCon, TyCon)) -- ^ (optional) desired parent (tc and rep_tc)
|
|
| 6007 | + FieldLabelString -- ^ field name
|
|
| 6008 | + [(TyCon, SimilarName)] -- ^ suggestions (for this 'TyCon' or other 'TyCon's)
|
|
| 6009 | + [(PatSyn, SimilarName)] -- ^ pattern synonyms with similarly named fields
|
|
| 6010 | + [ImportSuggestion] -- ^ import suggestions
|
|
| 6011 | + |
|
| 6012 | + -- | Using -XRebindableSyntax and a different 'HasField'.
|
|
| 6013 | + | CustomHasField TyCon -- ^ the custom HasField TyCon
|
|
| 6014 | + |
|
| 6015 | +-- | Why is a record field "too fancy" for GHC to be able to properly
|
|
| 6016 | +-- solve a 'HasField' constraint?
|
|
| 6017 | +data TooFancyField
|
|
| 6018 | + = FieldHasExistential
|
|
| 6019 | + | FieldHasForAlls
|
|
| 6020 | + |
|
| 5970 | 6021 | -- | Explain a problem with an import.
|
| 5971 | 6022 | data ImportError
|
| 5972 | 6023 | -- | Couldn't find a module with the requested name.
|
| ... | ... | @@ -1247,6 +1247,11 @@ matchHasField dflags short_cut clas tys mb_ct_loc |
| 1247 | 1247 | -- The selector must not be "naughty" (i.e. the field
|
| 1248 | 1248 | -- cannot have an existentially quantified type),
|
| 1249 | 1249 | -- and it must not be higher-rank.
|
| 1250 | + --
|
|
| 1251 | + -- See also 'GHC.Tc.Errors.hasFieldInfo_maybe', which is
|
|
| 1252 | + -- responsible for the error messages in cases of unsolved
|
|
| 1253 | + -- HasField constraints when the field type runs afoul
|
|
| 1254 | + -- of these conditions.
|
|
| 1250 | 1255 | ; if (isNaughtyRecordSelector sel_id) || not (isTauTy sel_ty)
|
| 1251 | 1256 | then try_user_instances
|
| 1252 | 1257 | else
|
| ... | ... | @@ -1306,6 +1311,11 @@ lookupHasFieldLabel |
| 1306 | 1311 | -- A complication is that `T` might be a data family, so we need to
|
| 1307 | 1312 | -- look it up in the `fam_envs` to find its representation tycon.
|
| 1308 | 1313 | lookupHasFieldLabel fam_inst_envs rdr_env arg_tys
|
| 1314 | + |
|
| 1315 | + -- NB: if you edit this function, you might also want to update
|
|
| 1316 | + -- GHC.Tc.Errors.hasfieldInfo_maybe which is responsible for error messages
|
|
| 1317 | + -- when GHC /does not/ solve a 'HasField' constraint.
|
|
| 1318 | + |
|
| 1309 | 1319 | | -- We are matching HasField {k} {r_rep} {a_rep} x r a...
|
| 1310 | 1320 | (_k : _rec_rep : _fld_rep : x_ty : rec_ty : fld_ty : _) <- arg_tys
|
| 1311 | 1321 | -- x should be a literal string
|
| ... | ... | @@ -136,7 +136,7 @@ tcInferPatSynDecl (PSB { psb_id = lname@(L _ name), psb_args = details |
| 136 | 136 | ; let (arg_names, is_infix) = collectPatSynArgInfo details
|
| 137 | 137 | ; (tclvl, wanted, ((lpat', args), pat_ty))
|
| 138 | 138 | <- pushLevelAndCaptureConstraints $
|
| 139 | - tcInferPat FRRPatSynArg PatSyn lpat $
|
|
| 139 | + tcInferPat FRRPatSynArg PatSynCtx lpat $
|
|
| 140 | 140 | mapM tcLookupId arg_names
|
| 141 | 141 | |
| 142 | 142 | ; let (ex_tvs, prov_dicts) = tcCollectEx lpat'
|
| ... | ... | @@ -421,7 +421,7 @@ tcCheckPatSynDecl psb@PSB{ psb_id = lname@(L _ name), psb_args = details |
| 421 | 421 | assertPpr (equalLength arg_names arg_tys) (ppr name $$ ppr arg_names $$ ppr arg_tys) $
|
| 422 | 422 | pushLevelAndCaptureConstraints $
|
| 423 | 423 | tcExtendNameTyVarEnv univ_tv_prs $
|
| 424 | - tcCheckPat PatSyn lpat (unrestricted skol_pat_ty) $
|
|
| 424 | + tcCheckPat PatSynCtx lpat (unrestricted skol_pat_ty) $
|
|
| 425 | 425 | do { let in_scope = mkInScopeSetList skol_univ_tvs
|
| 426 | 426 | empty_subst = mkEmptySubst in_scope
|
| 427 | 427 | ; (inst_subst, ex_tvs') <- mapAccumLM newMetaTyVarX empty_subst skol_ex_tvs
|
| ... | ... | @@ -843,7 +843,7 @@ tcPatSynMatcher (L loc ps_name) lpat prag_fn |
| 843 | 843 | gen = Generated OtherExpansion SkipPmc
|
| 844 | 844 | body = mkLHsWrap (mkWpLet req_ev_binds) $
|
| 845 | 845 | L (getLoc lpat) $
|
| 846 | - HsCase PatSyn (nlHsVar scrutinee) $
|
|
| 846 | + HsCase PatSynCtx (nlHsVar scrutinee) $
|
|
| 847 | 847 | MG{ mg_alts = L (l2l $ getLoc lpat) cases
|
| 848 | 848 | , mg_ext = MatchGroupTc [unrestricted pat_ty] res_ty gen
|
| 849 | 849 | }
|
| ... | ... | @@ -21,7 +21,7 @@ module GHC.Tc.TyCl.Utils( |
| 21 | 21 | addTyConsToGblEnv, mkDefaultMethodType,
|
| 22 | 22 | |
| 23 | 23 | -- * Record selectors
|
| 24 | - tcRecSelBinds, mkRecSelBinds, mkOneRecordSelector
|
|
| 24 | + tcRecSelBinds, mkRecSelBinds, mkOneRecordSelector,
|
|
| 25 | 25 | ) where
|
| 26 | 26 | |
| 27 | 27 | import GHC.Prelude
|
| ... | ... | @@ -899,7 +899,7 @@ mkOneRecordSelector all_cons idDetails fl has_sel |
| 899 | 899 | |
| 900 | 900 | |
| 901 | 901 | -- Selector type; Note [Polymorphic selectors]
|
| 902 | - (univ_tvs, _, _, _, req_theta, _, data_ty) = conLikeFullSig con1
|
|
| 902 | + (_, _, _, _, req_theta, _, data_ty) = conLikeFullSig con1
|
|
| 903 | 903 | |
| 904 | 904 | field_ty = conLikeFieldType con1 lbl
|
| 905 | 905 | field_ty_tvs = tyCoVarsOfType field_ty
|
| ... | ... | @@ -909,17 +909,13 @@ mkOneRecordSelector all_cons idDetails fl has_sel |
| 909 | 909 | conLikeUserTyVarBinders con1
|
| 910 | 910 | |
| 911 | 911 | -- is_naughty: see Note [Naughty record selectors]
|
| 912 | - is_naughty = not ok_scoping || no_selectors
|
|
| 913 | - ok_scoping = case con1 of
|
|
| 914 | - RealDataCon {} -> field_ty_tvs `subVarSet` data_ty_tvs
|
|
| 915 | - PatSynCon {} -> field_ty_tvs `subVarSet` mkVarSet univ_tvs
|
|
| 916 | - -- In the PatSynCon case, the selector type is (data_ty -> field_ty), but
|
|
| 917 | - -- fvs(data_ty) are all universals (see Note [Pattern synonym result type] in
|
|
| 918 | - -- GHC.Core.PatSyn, so no need to check them.
|
|
| 919 | - |
|
| 920 | - no_selectors = has_sel == NoFieldSelectors -- No field selectors => all are naughty
|
|
| 921 | - -- thus suppressing making a binding
|
|
| 922 | - -- A slight hack!
|
|
| 912 | + is_naughty = isExistentialRecordField field_ty con1 || no_selectors
|
|
| 913 | + |
|
| 914 | + no_selectors = has_sel == NoFieldSelectors
|
|
| 915 | + -- For PatternSynonyms with -XNoFieldSelectors, pretend the fields
|
|
| 916 | + -- are naughty record selectors to suppress making a binding.
|
|
| 917 | + --
|
|
| 918 | + -- See Note [NoFieldSelectors and naughty record selectors]
|
|
| 923 | 919 | |
| 924 | 920 | sel_ty | is_naughty = unitTy -- See Note [Naughty record selectors]
|
| 925 | 921 | | otherwise = mkForAllTys sel_tvbs $
|
| ... | ... | @@ -524,7 +524,7 @@ data CtOrigin |
| 524 | 524 | ----------- Below here, all are Origins for Wanted constraints ------------
|
| 525 | 525 | |
| 526 | 526 | | OccurrenceOf Name -- ^ Occurrence of an overloaded identifier
|
| 527 | - | OccurrenceOfRecSel RdrName -- ^ Occurrence of a record selector
|
|
| 527 | + | OccurrenceOfRecSel (LocatedN RdrName) -- ^ Occurrence of a record selector
|
|
| 528 | 528 | | AppOrigin -- ^ An application of some kind
|
| 529 | 529 | |
| 530 | 530 | | SpecPragOrigin UserTypeCtxt -- ^ Specialisation pragma for
|
| ... | ... | @@ -558,7 +558,10 @@ data CtOrigin |
| 558 | 558 | -- IMPORTANT: These constraints will never cause errors;
|
| 559 | 559 | -- See Note [Constraints to ignore] in GHC.Tc.Errors
|
| 560 | 560 | | SectionOrigin
|
| 561 | - | GetFieldOrigin FastString
|
|
| 561 | + | GetFieldOrigin (LocatedN FastString)
|
|
| 562 | + |
|
| 563 | + -- | A overloaded record field projection like @.fld@ or @.fld1.fld2.fld@.
|
|
| 564 | + | RecordFieldProjectionOrigin (FieldLabelStrings GhcRn)
|
|
| 562 | 565 | | TupleOrigin -- (..,..)
|
| 563 | 566 | | ExprSigOrigin -- e :: ty
|
| 564 | 567 | | PatSigOrigin -- p :: ty
|
| ... | ... | @@ -566,7 +569,7 @@ data CtOrigin |
| 566 | 569 | | ProvCtxtOrigin -- The "provided" context of a pattern synonym signature
|
| 567 | 570 | (PatSynBind GhcRn GhcRn) -- Information about the pattern synonym, in
|
| 568 | 571 | -- particular the name and the right-hand side
|
| 569 | - | RecordUpdOrigin
|
|
| 572 | + | RecordUpdOrigin (LHsRecUpdFields GhcRn)
|
|
| 570 | 573 | | ViewPatOrigin
|
| 571 | 574 | |
| 572 | 575 | -- | 'ScOrigin' is used only for the Wanted constraints for the
|
| ... | ... | @@ -737,7 +740,7 @@ lexprCtOrigin (L _ e) = exprCtOrigin e |
| 737 | 740 | |
| 738 | 741 | exprCtOrigin :: HsExpr GhcRn -> CtOrigin
|
| 739 | 742 | exprCtOrigin (HsVar _ (L _ (WithUserRdr _ name))) = OccurrenceOf name
|
| 740 | -exprCtOrigin (HsGetField _ _ (L _ f)) = GetFieldOrigin (field_label $ unLoc $ dfoLabel f)
|
|
| 743 | +exprCtOrigin (HsGetField _ _ (L _ f)) = GetFieldOrigin (fmap field_label $ dfoLabel f)
|
|
| 741 | 744 | exprCtOrigin (HsOverLabel _ l) = OverLabelOrigin l
|
| 742 | 745 | exprCtOrigin (ExplicitList {}) = ListOrigin
|
| 743 | 746 | exprCtOrigin (HsIPVar _ ip) = IPOccOrigin ip
|
| ... | ... | @@ -749,9 +752,9 @@ exprCtOrigin (HsAppType _ e1 _) = lexprCtOrigin e1 |
| 749 | 752 | exprCtOrigin (OpApp _ _ op _) = lexprCtOrigin op
|
| 750 | 753 | exprCtOrigin (NegApp _ e _) = lexprCtOrigin e
|
| 751 | 754 | exprCtOrigin (HsPar _ e) = lexprCtOrigin e
|
| 752 | -exprCtOrigin (HsProjection _ _) = SectionOrigin
|
|
| 753 | -exprCtOrigin (SectionL _ _ _) = SectionOrigin
|
|
| 754 | -exprCtOrigin (SectionR _ _ _) = SectionOrigin
|
|
| 755 | +exprCtOrigin (HsProjection _ p) = RecordFieldProjectionOrigin (FieldLabelStrings $ fmap noLocA p)
|
|
| 756 | +exprCtOrigin (SectionL {}) = SectionOrigin
|
|
| 757 | +exprCtOrigin (SectionR {}) = SectionOrigin
|
|
| 755 | 758 | exprCtOrigin (ExplicitTuple {}) = Shouldn'tHappenOrigin "explicit tuple"
|
| 756 | 759 | exprCtOrigin ExplicitSum{} = Shouldn'tHappenOrigin "explicit sum"
|
| 757 | 760 | exprCtOrigin (HsCase _ _ matches) = matchesCtOrigin matches
|
| ... | ... | @@ -760,7 +763,7 @@ exprCtOrigin (HsMultiIf _ rhs) = lGRHSCtOrigin rhs |
| 760 | 763 | exprCtOrigin (HsLet _ _ e) = lexprCtOrigin e
|
| 761 | 764 | exprCtOrigin (HsDo {}) = DoOrigin
|
| 762 | 765 | exprCtOrigin (RecordCon {}) = Shouldn'tHappenOrigin "record construction"
|
| 763 | -exprCtOrigin (RecordUpd {}) = RecordUpdOrigin
|
|
| 766 | +exprCtOrigin (RecordUpd _ _ flds)= RecordUpdOrigin flds
|
|
| 764 | 767 | exprCtOrigin (ExprWithTySig {}) = ExprSigOrigin
|
| 765 | 768 | exprCtOrigin (ArithSeq {}) = Shouldn'tHappenOrigin "arithmetic sequence"
|
| 766 | 769 | exprCtOrigin (HsPragE _ _ e) = lexprCtOrigin e
|
| ... | ... | @@ -779,7 +782,7 @@ exprCtOrigin (XExpr (ExpandedThingRn thing _)) | OrigExpr a <- thing = exprCtOri |
| 779 | 782 | | OrigStmt _ <- thing = DoOrigin
|
| 780 | 783 | | OrigPat p <- thing = DoPatOrigin p
|
| 781 | 784 | exprCtOrigin (XExpr (PopErrCtxt {})) = Shouldn'tHappenOrigin "PopErrCtxt"
|
| 782 | -exprCtOrigin (XExpr (HsRecSelRn f)) = OccurrenceOfRecSel (foExt f)
|
|
| 785 | +exprCtOrigin (XExpr (HsRecSelRn f)) = OccurrenceOfRecSel $ L (getLoc $ foLabel f) (foExt f)
|
|
| 783 | 786 | |
| 784 | 787 | -- | Extract a suitable CtOrigin from a MatchGroup
|
| 785 | 788 | matchesCtOrigin :: MatchGroup GhcRn (LHsExpr GhcRn) -> CtOrigin
|
| ... | ... | @@ -937,7 +940,7 @@ ppr_br AppOrigin = text "an application" |
| 937 | 940 | ppr_br (IPOccOrigin name) = hsep [text "a use of implicit parameter", quotes (ppr name)]
|
| 938 | 941 | ppr_br (OverLabelOrigin l) = hsep [text "the overloaded label"
|
| 939 | 942 | ,quotes (char '#' <> ppr l)]
|
| 940 | -ppr_br RecordUpdOrigin = text "a record update"
|
|
| 943 | +ppr_br (RecordUpdOrigin {}) = text "a record update"
|
|
| 941 | 944 | ppr_br ExprSigOrigin = text "an expression type signature"
|
| 942 | 945 | ppr_br PatSigOrigin = text "a pattern type signature"
|
| 943 | 946 | ppr_br PatOrigin = text "a pattern"
|
| ... | ... | @@ -945,6 +948,7 @@ ppr_br ViewPatOrigin = text "a view pattern" |
| 945 | 948 | ppr_br (LiteralOrigin lit) = hsep [text "the literal", quotes (ppr lit)]
|
| 946 | 949 | ppr_br (ArithSeqOrigin seq) = hsep [text "the arithmetic sequence", quotes (ppr seq)]
|
| 947 | 950 | ppr_br SectionOrigin = text "an operator section"
|
| 951 | +ppr_br (RecordFieldProjectionOrigin p) = text "the record selector" <+> quotes (ppr p)
|
|
| 948 | 952 | ppr_br (GetFieldOrigin f) = hsep [text "selecting the field", quotes (ppr f)]
|
| 949 | 953 | ppr_br AssocFamPatOrigin = text "the LHS of a family instance"
|
| 950 | 954 | ppr_br TupleOrigin = text "a tuple"
|
| ... | ... | @@ -42,12 +42,14 @@ import GHC.Core.TyCon (TyCon) |
| 42 | 42 | import GHC.Core.Type (Type)
|
| 43 | 43 | import GHC.Types.Fixity (LexicalFixity(..))
|
| 44 | 44 | import GHC.Types.Name (Name, NameSpace, OccName (occNameFS), isSymOcc, nameOccName)
|
| 45 | -import GHC.Types.Name.Reader (RdrName (Unqual), ImpDeclSpec)
|
|
| 45 | +import GHC.Types.Name.Reader (RdrName (Unqual), ImpDeclSpec, GlobalRdrElt)
|
|
| 46 | 46 | import GHC.Types.SrcLoc (SrcSpan)
|
| 47 | 47 | import GHC.Types.Basic (Activation, RuleName)
|
| 48 | 48 | import GHC.Parser.Errors.Basic
|
| 49 | 49 | import GHC.Utils.Outputable
|
| 50 | -import GHC.Data.FastString (fsLit, FastString)
|
|
| 50 | +import GHC.Data.FastString (fsLit)
|
|
| 51 | + |
|
| 52 | +import Language.Haskell.Syntax.Basic (FieldLabelString)
|
|
| 51 | 53 | |
| 52 | 54 | import Data.Typeable ( Typeable )
|
| 53 | 55 | import Data.Map.Strict (Map)
|
| ... | ... | @@ -394,6 +396,12 @@ data GhcHint |
| 394 | 396 | -}
|
| 395 | 397 | | SuggestSimilarNames RdrName (NE.NonEmpty SimilarName)
|
| 396 | 398 | |
| 399 | + {-| Suggest a similar record selector that the user might have meant.
|
|
| 400 | + |
|
| 401 | + Test case: T26480b.
|
|
| 402 | + -}
|
|
| 403 | + | SuggestSimilarSelectors TyCon TyCon FieldLabelString (NE.NonEmpty (TyCon, SimilarName))
|
|
| 404 | + |
|
| 397 | 405 | {-| Remind the user that the field selector has been suppressed
|
| 398 | 406 | because of -XNoFieldSelectors.
|
| 399 | 407 | |
| ... | ... | @@ -464,9 +472,6 @@ data GhcHint |
| 464 | 472 | {-| Suggest eta-reducing a type synonym used in the implementation
|
| 465 | 473 | of abstract data. -}
|
| 466 | 474 | | SuggestEtaReduceAbsDataTySyn TyCon
|
| 467 | - {-| Remind the user that there is no field of a type and name in the record,
|
|
| 468 | - constructors are in the usual order $x$, $r$, $a$ -}
|
|
| 469 | - | RemindRecordMissingField FastString Type Type
|
|
| 470 | 475 | {-| Suggest binding the type variable on the LHS of the type declaration
|
| 471 | 476 | -}
|
| 472 | 477 | | SuggestBindTyVarOnLhs RdrName
|
| ... | ... | @@ -579,7 +584,7 @@ data HowInScope |
| 579 | 584 | |
| 580 | 585 | data SimilarName
|
| 581 | 586 | = SimilarName Name
|
| 582 | - | SimilarRdrName RdrName (Maybe HowInScope)
|
|
| 587 | + | SimilarRdrName RdrName (Maybe GlobalRdrElt) (Maybe HowInScope)
|
|
| 583 | 588 | |
| 584 | 589 | -- | Some kind of signature, such as a fixity signature, standalone
|
| 585 | 590 | -- kind signature, COMPLETE pragma, role annotation, etc.
|
| ... | ... | @@ -15,7 +15,7 @@ import GHC.Types.Hint |
| 15 | 15 | |
| 16 | 16 | import GHC.Core.FamInstEnv (FamFlavor(..))
|
| 17 | 17 | import GHC.Core.TyCon
|
| 18 | -import GHC.Core.TyCo.Rep ( mkVisFunTyMany )
|
|
| 18 | +import GHC.Hs.Binds (hsSigDoc)
|
|
| 19 | 19 | import GHC.Hs.Expr () -- instance Outputable
|
| 20 | 20 | import GHC.Types.Id
|
| 21 | 21 | import GHC.Types.Name
|
| ... | ... | @@ -25,14 +25,16 @@ import GHC.Unit.Module.Imported (ImportedModsVal(..)) |
| 25 | 25 | import GHC.Unit.Types
|
| 26 | 26 | import GHC.Utils.Outputable
|
| 27 | 27 | |
| 28 | +import qualified GHC.LanguageExtensions as LangExt
|
|
| 29 | + |
|
| 28 | 30 | import GHC.Driver.Flags
|
| 29 | 31 | |
| 32 | +import Language.Haskell.Syntax.Basic (FieldLabelString)
|
|
| 33 | + |
|
| 34 | +import Data.List (partition)
|
|
| 30 | 35 | import qualified Data.List.NonEmpty as NE
|
| 31 | 36 | import qualified Data.Map.Strict as Map
|
| 32 | 37 | |
| 33 | -import qualified GHC.LanguageExtensions as LangExt
|
|
| 34 | -import GHC.Hs.Binds (hsSigDoc)
|
|
| 35 | - |
|
| 36 | 38 | instance Outputable GhcHint where
|
| 37 | 39 | ppr = \case
|
| 38 | 40 | UnknownHint m
|
| ... | ... | @@ -198,7 +200,9 @@ instance Outputable GhcHint where |
| 198 | 200 | , nest 2 (pprWithCommas pp_item $ NE.toList similar_names) ]
|
| 199 | 201 | where
|
| 200 | 202 | tried_ns = occNameSpace $ rdrNameOcc tried_rdr_name
|
| 201 | - pp_item = pprSimilarName tried_ns
|
|
| 203 | + pp_item = pprSimilarName (Just tried_ns)
|
|
| 204 | + SuggestSimilarSelectors tc rep_tc fld suggs ->
|
|
| 205 | + pprSimilarFields tc rep_tc fld (NE.toList suggs)
|
|
| 202 | 206 | RemindFieldSelectorSuppressed rdr_name parents
|
| 203 | 207 | -> text "Notice that" <+> quotes (ppr rdr_name)
|
| 204 | 208 | <+> text "is a field selector" <+> whose
|
| ... | ... | @@ -255,12 +259,6 @@ instance Outputable GhcHint where |
| 255 | 259 | SuggestEtaReduceAbsDataTySyn tc
|
| 256 | 260 | -> text "If possible, eta-reduce the type synonym" <+> ppr_tc <+> text "so that it is nullary."
|
| 257 | 261 | where ppr_tc = quotes (ppr $ tyConName tc)
|
| 258 | - RemindRecordMissingField x r a ->
|
|
| 259 | - text "NB: There is no field selector" <+> ppr_sel
|
|
| 260 | - <+> text "in scope for record type" <+> ppr_r
|
|
| 261 | - where ppr_sel = quotes (ftext x <+> dcolon <+> ppr_arr_r_a)
|
|
| 262 | - ppr_arr_r_a = ppr $ mkVisFunTyMany r a
|
|
| 263 | - ppr_r = quotes $ ppr r
|
|
| 264 | 262 | SuggestBindTyVarOnLhs tv
|
| 265 | 263 | -> text "Bind" <+> quotes (ppr tv) <+> text "on the LHS of the type declaration"
|
| 266 | 264 | SuggestAnonymousWildcard
|
| ... | ... | @@ -405,10 +403,10 @@ pprImportSuggestion dc_occ (ImportDataCon { ies_suggest_import_from = Just mod |
| 405 | 403 | parens_sp d = parens (space <> d <> space)
|
| 406 | 404 | |
| 407 | 405 | -- | Pretty-print a 'SimilarName'.
|
| 408 | -pprSimilarName :: NameSpace -> SimilarName -> SDoc
|
|
| 406 | +pprSimilarName :: Maybe NameSpace -> SimilarName -> SDoc
|
|
| 409 | 407 | pprSimilarName _ (SimilarName name)
|
| 410 | 408 | = quotes (ppr name) <+> parens (pprDefinedAt name)
|
| 411 | -pprSimilarName tried_ns (SimilarRdrName rdr_name how_in_scope)
|
|
| 409 | +pprSimilarName mb_tried_ns (SimilarRdrName rdr_name _gre_info how_in_scope)
|
|
| 412 | 410 | = pp_ns rdr_name <+> quotes (ppr rdr_name) <+> loc
|
| 413 | 411 | where
|
| 414 | 412 | loc = case how_in_scope of
|
| ... | ... | @@ -421,8 +419,12 @@ pprSimilarName tried_ns (SimilarRdrName rdr_name how_in_scope) |
| 421 | 419 | ImportedBy is ->
|
| 422 | 420 | parens (text "imported from" <+> ppr (moduleName $ is_mod is))
|
| 423 | 421 | pp_ns :: RdrName -> SDoc
|
| 424 | - pp_ns rdr | ns /= tried_ns = pprNameSpace ns
|
|
| 425 | - | otherwise = empty
|
|
| 422 | + pp_ns rdr
|
|
| 423 | + | Just tried_ns <- mb_tried_ns
|
|
| 424 | + , ns /= tried_ns
|
|
| 425 | + = pprNameSpace ns
|
|
| 426 | + | otherwise
|
|
| 427 | + = empty
|
|
| 426 | 428 | where ns = rdrNameSpace rdr
|
| 427 | 429 | |
| 428 | 430 | pprImpliedExtensions :: LangExt.Extension -> SDoc
|
| ... | ... | @@ -437,6 +439,34 @@ pprPrefixUnqual :: Name -> SDoc |
| 437 | 439 | pprPrefixUnqual name =
|
| 438 | 440 | pprPrefixOcc (getOccName name)
|
| 439 | 441 | |
| 442 | +pprSimilarFields :: TyCon -> TyCon -> FieldLabelString -> [(TyCon, SimilarName)] -> SDoc
|
|
| 443 | +pprSimilarFields _tc rep_tc _fld suggs
|
|
| 444 | + | null suggs
|
|
| 445 | + = empty
|
|
| 446 | + -- There are similarly named fields for the right TyCon: report those first.
|
|
| 447 | + | same_tc_sugg1 : same_tc_rest <- same_tc
|
|
| 448 | + = case same_tc_rest of
|
|
| 449 | + [] ->
|
|
| 450 | + text "Perhaps use" <+> ppr_same_tc same_tc_sugg1 <> dot
|
|
| 451 | + _ ->
|
|
| 452 | + vcat [ text "Perhaps use one of"
|
|
| 453 | + , nest 2 $ pprWithCommas ppr_same_tc same_tc
|
|
| 454 | + ]
|
|
| 455 | + -- Otherwise, report the similarly named fields for other TyCons.
|
|
| 456 | + | otherwise
|
|
| 457 | + = vcat [ text "Perhaps use" <+> similar_field <+> text "of another type" <> colon
|
|
| 458 | + , nest 2 $ pprWithCommas ppr_other_tc others
|
|
| 459 | + ]
|
|
| 460 | + where
|
|
| 461 | + (same_tc, others) = partition ((== rep_tc) . fst) suggs
|
|
| 462 | + similar_field =
|
|
| 463 | + case others of
|
|
| 464 | + _:_:_ -> "one of the similarly named fields"
|
|
| 465 | + _ -> "the similarly named field"
|
|
| 466 | + ppr_same_tc (_, nm) = pprSimilarName Nothing nm
|
|
| 467 | + ppr_other_tc (other_tc, nm) =
|
|
| 468 | + quotes (ppr other_tc) <> colon <+> pprSimilarName Nothing nm
|
|
| 469 | + |
|
| 440 | 470 | pprSigLike :: SigLike -> SDoc
|
| 441 | 471 | pprSigLike = \case
|
| 442 | 472 | SigLikeSig sig ->
|
| ... | ... | @@ -1403,7 +1403,7 @@ data HsMatchContext fn |
| 1403 | 1403 | |
| 1404 | 1404 | | ThPatSplice -- ^A Template Haskell pattern splice
|
| 1405 | 1405 | | ThPatQuote -- ^A Template Haskell pattern quotation [p| (a,b) |]
|
| 1406 | - | PatSyn -- ^A pattern synonym declaration
|
|
| 1406 | + | PatSynCtx -- ^A pattern synonym declaration
|
|
| 1407 | 1407 | | LazyPatCtx -- ^An irrefutable pattern
|
| 1408 | 1408 | |
| 1409 | 1409 | {- Note [mc_fun field of FunRhs]
|
| ... | ... | @@ -1467,8 +1467,8 @@ qualifiedDoModuleName_maybe ctxt = case ctxt of |
| 1467 | 1467 | isPatSynCtxt :: HsMatchContext fn -> Bool
|
| 1468 | 1468 | isPatSynCtxt ctxt =
|
| 1469 | 1469 | case ctxt of
|
| 1470 | - PatSyn -> True
|
|
| 1471 | - _ -> False
|
|
| 1470 | + PatSynCtx -> True
|
|
| 1471 | + _ -> False
|
|
| 1472 | 1472 | |
| 1473 | 1473 | isComprehensionContext :: HsStmtContext fn -> Bool
|
| 1474 | 1474 | -- Uses comprehension syntax [ e | quals ]
|
| 1 | +{-# LANGUAGE DataKinds #-}
|
|
| 2 | +{-# LANGUAGE PatternSynonyms #-}
|
|
| 3 | + |
|
| 4 | +module T26480 where
|
|
| 5 | + |
|
| 6 | +import Data.Proxy
|
|
| 7 | +import GHC.TypeLits
|
|
| 8 | +import GHC.Records
|
|
| 9 | + |
|
| 10 | +import T26480_aux1 (R1)
|
|
| 11 | +import qualified T26480_aux2 as XXX (R2)
|
|
| 12 | + |
|
| 13 | +data S = MkS { fld_s :: Int }
|
|
| 14 | + |
|
| 15 | +data E where
|
|
| 16 | + MkE :: { fld_e :: e } -> E
|
|
| 17 | + |
|
| 18 | +data Q = MkQ { fld_q :: forall a. a -> a }
|
|
| 19 | + |
|
| 20 | +data T = MkT { specificFieldName :: Int }
|
|
| 21 | + |
|
| 22 | +data G = MkG { xyzzywyzzydyzzy :: Int }
|
|
| 23 | + |
|
| 24 | +pattern P :: Int -> S
|
|
| 25 | +pattern P { patSynField } = MkS patSynField
|
|
| 26 | + |
|
| 27 | +-- Not a literal string
|
|
| 28 | +test1 :: forall (fld_s :: Symbol). Proxy fld_s -> S -> Int
|
|
| 29 | +test1 _ = getField @fld_s
|
|
| 30 | + |
|
| 31 | +-- Not a record type
|
|
| 32 | +test2 :: Int -> Int
|
|
| 33 | +test2 = getField @"int_fld"
|
|
| 34 | + |
|
| 35 | +-- Field out of scope: unqualified import
|
|
| 36 | +test3a :: R1 -> Int
|
|
| 37 | +test3a = getField @"f1"
|
|
| 38 | + |
|
| 39 | +-- Field out of scope: qualified import
|
|
| 40 | +test3b :: XXX.R2 -> Int
|
|
| 41 | +test3b = getField @"f2"
|
|
| 42 | + |
|
| 43 | +-- Existential record field
|
|
| 44 | +test4 :: E -> Int
|
|
| 45 | +test4 = getField @"fld_e"
|
|
| 46 | + |
|
| 47 | +-- Record field contains forall
|
|
| 48 | +test5 :: Q -> Bool -> Bool
|
|
| 49 | +test5 = getField @"fld_q"
|
|
| 50 | + |
|
| 51 | +-- Record field is misspelled
|
|
| 52 | +test6 :: T -> Int
|
|
| 53 | +test6 = getField @"specificFieldTame"
|
|
| 54 | + |
|
| 55 | +-- Record field is for a different type
|
|
| 56 | +test7 :: T -> Int
|
|
| 57 | +test7 = getField @"xyzzywyzzydyzzy"
|
|
| 58 | + |
|
| 59 | +-- Record field is misspelled and is for a different type
|
|
| 60 | +test8 :: T -> Int
|
|
| 61 | +test8 = getField @"xyzzywyzzyzyzzy"
|
|
| 62 | + |
|
| 63 | +-- Pattern synonym field
|
|
| 64 | +test9 :: S -> Int
|
|
| 65 | +test9 = getField @"patSynField" |
| 1 | +T26480.hs:29:11: error: [GHC-39999]
|
|
| 2 | + • No instance for ‘HasField fld_s S Int’
|
|
| 3 | + arising from a use of ‘getField’
|
|
| 4 | + NB: ‘fld_s’ is a type variable, not a string literal.
|
|
| 5 | + • In the expression: getField @fld_s
|
|
| 6 | + In an equation for ‘test1’: test1 _ = getField @fld_s
|
|
| 7 | + |
|
| 8 | +T26480.hs:33:9: error: [GHC-39999]
|
|
| 9 | + • No instance for ‘HasField "int_fld" Int Int’
|
|
| 10 | + arising from a use of ‘getField’
|
|
| 11 | + NB: ‘Int’ is not a record type.
|
|
| 12 | + • In the expression: getField @"int_fld"
|
|
| 13 | + In an equation for ‘test2’: test2 = getField @"int_fld"
|
|
| 14 | + |
|
| 15 | +T26480.hs:37:10: error: [GHC-39999]
|
|
| 16 | + • No instance for ‘HasField "f1" R1 Int’
|
|
| 17 | + arising from a use of ‘getField’
|
|
| 18 | + NB: the record field ‘f1’ of ‘R1’ is out of scope.
|
|
| 19 | + • In the expression: getField @"f1"
|
|
| 20 | + In an equation for ‘test3a’: test3a = getField @"f1"
|
|
| 21 | + Suggested fix:
|
|
| 22 | + Add ‘f1’ to the import list in the import of ‘T26480_aux1’
|
|
| 23 | + (at T26480.hs:10:1-23).
|
|
| 24 | + |
|
| 25 | +T26480.hs:41:10: error: [GHC-39999]
|
|
| 26 | + • No instance for ‘HasField "f2" XXX.R2 Int’
|
|
| 27 | + arising from a use of ‘getField’
|
|
| 28 | + NB: the record field ‘f2’ of ‘XXX.R2’ is out of scope.
|
|
| 29 | + • In the expression: getField @"f2"
|
|
| 30 | + In an equation for ‘test3b’: test3b = getField @"f2"
|
|
| 31 | + Suggested fix:
|
|
| 32 | + Add ‘f2’ to the import list in the import of ‘T26480_aux2’
|
|
| 33 | + (at T26480.hs:11:1-40).
|
|
| 34 | + |
|
| 35 | +T26480.hs:45:9: error: [GHC-39999]
|
|
| 36 | + • No instance for ‘HasField "fld_e" E Int’
|
|
| 37 | + arising from a use of ‘getField’
|
|
| 38 | + NB: the record field ‘fld_e’ of ‘E’ contains existential variables.
|
|
| 39 | + • In the expression: getField @"fld_e"
|
|
| 40 | + In an equation for ‘test4’: test4 = getField @"fld_e"
|
|
| 41 | + |
|
| 42 | +T26480.hs:49:9: error: [GHC-39999]
|
|
| 43 | + • No instance for ‘HasField "fld_q" Q (Bool -> Bool)’
|
|
| 44 | + arising from a use of ‘getField’
|
|
| 45 | + NB: the field type of the record field ‘fld_q’ of ‘Q’ is not a mono-type.
|
|
| 46 | + • In the expression: getField @"fld_q"
|
|
| 47 | + In an equation for ‘test5’: test5 = getField @"fld_q"
|
|
| 48 | + |
|
| 49 | +T26480.hs:53:9: error: [GHC-39999]
|
|
| 50 | + • No instance for ‘HasField "specificFieldTame" T Int’
|
|
| 51 | + arising from a use of ‘getField’
|
|
| 52 | + NB: ‘T’ does not have a record field named ‘specificFieldTame’.
|
|
| 53 | + • In the expression: getField @"specificFieldTame"
|
|
| 54 | + In an equation for ‘test6’: test6 = getField @"specificFieldTame"
|
|
| 55 | + Suggested fix: Perhaps use ‘specificFieldName’ (line 20).
|
|
| 56 | + |
|
| 57 | +T26480.hs:57:9: error: [GHC-39999]
|
|
| 58 | + • No instance for ‘HasField "xyzzywyzzydyzzy" T Int’
|
|
| 59 | + arising from a use of ‘getField’
|
|
| 60 | + NB: ‘T’ does not have a record field named ‘xyzzywyzzydyzzy’.
|
|
| 61 | + Another type has a field of this name: ‘G’.
|
|
| 62 | + • In the expression: getField @"xyzzywyzzydyzzy"
|
|
| 63 | + In an equation for ‘test7’: test7 = getField @"xyzzywyzzydyzzy"
|
|
| 64 | + |
|
| 65 | +T26480.hs:61:9: error: [GHC-39999]
|
|
| 66 | + • No instance for ‘HasField "xyzzywyzzyzyzzy" T Int’
|
|
| 67 | + arising from a use of ‘getField’
|
|
| 68 | + NB: ‘T’ does not have a record field named ‘xyzzywyzzyzyzzy’.
|
|
| 69 | + • In the expression: getField @"xyzzywyzzyzyzzy"
|
|
| 70 | + In an equation for ‘test8’: test8 = getField @"xyzzywyzzyzyzzy"
|
|
| 71 | + Suggested fix:
|
|
| 72 | + Perhaps use the similarly named field of another type:
|
|
| 73 | + ‘G’: ‘xyzzywyzzydyzzy’ (line 22)
|
|
| 74 | + |
|
| 75 | +T26480.hs:65:9: error: [GHC-39999]
|
|
| 76 | + • No instance for ‘HasField "patSynField" S Int’
|
|
| 77 | + arising from a use of ‘getField’
|
|
| 78 | + NB: ‘S’ does not have a record field named ‘patSynField’.
|
|
| 79 | + Pattern synonym record fields do not contribute ‘HasField’ instances.
|
|
| 80 | + • In the expression: getField @"patSynField"
|
|
| 81 | + In an equation for ‘test9’: test9 = getField @"patSynField"
|
|
| 82 | + |
| 1 | +module T26480_aux1 where
|
|
| 2 | + |
|
| 3 | +data R1 = MkR1 { f1 :: Int }
|
|
| 4 | +data R2 = MkR2 { f2 :: Int } |
| 1 | +module T26480_aux2 where
|
|
| 2 | + |
|
| 3 | +data R2 = MkR2 { f2 :: Int } |
| 1 | +{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
| 2 | +{-# LANGUAGE DataKinds #-}
|
|
| 3 | +{-# LANGUAGE RebindableSyntax #-}
|
|
| 4 | +{-# LANGUAGE OverloadedRecordDot #-}
|
|
| 5 | +{-# LANGUAGE OverloadedRecordUpdate #-}
|
|
| 6 | + |
|
| 7 | +module T26480b where
|
|
| 8 | + |
|
| 9 | +import Prelude
|
|
| 10 | +import Data.Proxy
|
|
| 11 | +import GHC.TypeLits
|
|
| 12 | +import GHC.Records
|
|
| 13 | + |
|
| 14 | + |
|
| 15 | +setField
|
|
| 16 | + :: forall (fld :: Symbol) rec ty
|
|
| 17 | + . HasField fld rec ty => ty -> rec -> rec
|
|
| 18 | +setField _ r = r
|
|
| 19 | + |
|
| 20 | +data N = N { no :: H }
|
|
| 21 | + |
|
| 22 | +data D = MkD{ field1 :: G }
|
|
| 23 | + |
|
| 24 | +data G = MkG { xyzzywyzzydyzzy :: H }
|
|
| 25 | + |
|
| 26 | +data H = MkH { field2 :: Int }
|
|
| 27 | + |
|
| 28 | +-- Direct usage of 'getField'
|
|
| 29 | +test1 :: G -> H
|
|
| 30 | +test1 = getField @"xyzzywyzzydyzza"
|
|
| 31 | + |
|
| 32 | +test1' :: N -> H
|
|
| 33 | +test1' = getField @"xyzzywyzzydyzzy"
|
|
| 34 | + |
|
| 35 | +test1'' :: N -> H
|
|
| 36 | +test1'' = getField @"ayzzywyzzydyzzy"
|
|
| 37 | + |
|
| 38 | +-- Record dot, applied
|
|
| 39 | +test2a :: G -> H
|
|
| 40 | +test2a g = g.xyzzywyzzydyzzb
|
|
| 41 | + |
|
| 42 | +test2b :: D -> H
|
|
| 43 | +test2b g = g.field1.xyzzywyzzydyzzc
|
|
| 44 | + |
|
| 45 | +-- Record dot, bare selector
|
|
| 46 | +test3a :: G -> H
|
|
| 47 | +test3a = (.xyzzywyzzydyzzd)
|
|
| 48 | + |
|
| 49 | +test3b :: D ->H
|
|
| 50 | +test3b = (.field1.xyzzywyzzydyzze)
|
|
| 51 | + |
|
| 52 | +-- Overloaded record update
|
|
| 53 | +test4a :: G -> G
|
|
| 54 | +test4a d = d { xyzzywyzzydyzzf = MkG ( MkH 3 ) }
|
|
| 55 | + |
|
| 56 | +test4b :: D -> D
|
|
| 57 | +test4b d = d { field1.xyzzywyzzydyzzg = MkH 3 } |
| 1 | +T26480b.hs:30:9: error: [GHC-39999]
|
|
| 2 | + • No instance for ‘HasField "xyzzywyzzydyzza" G H’
|
|
| 3 | + arising from a use of ‘getField’
|
|
| 4 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzza’.
|
|
| 5 | + • In the expression: getField @"xyzzywyzzydyzza"
|
|
| 6 | + In an equation for ‘test1’: test1 = getField @"xyzzywyzzydyzza"
|
|
| 7 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 8 | + |
|
| 9 | +T26480b.hs:33:10: error: [GHC-39999]
|
|
| 10 | + • No instance for ‘HasField "xyzzywyzzydyzzy" N H’
|
|
| 11 | + arising from a use of ‘getField’
|
|
| 12 | + NB: ‘N’ does not have a record field named ‘xyzzywyzzydyzzy’.
|
|
| 13 | + Another type has a field of this name: ‘G’.
|
|
| 14 | + • In the expression: getField @"xyzzywyzzydyzzy"
|
|
| 15 | + In an equation for ‘test1'’: test1' = getField @"xyzzywyzzydyzzy"
|
|
| 16 | + |
|
| 17 | +T26480b.hs:36:11: error: [GHC-39999]
|
|
| 18 | + • No instance for ‘HasField "ayzzywyzzydyzzy" N H’
|
|
| 19 | + arising from a use of ‘getField’
|
|
| 20 | + NB: ‘N’ does not have a record field named ‘ayzzywyzzydyzzy’.
|
|
| 21 | + • In the expression: getField @"ayzzywyzzydyzzy"
|
|
| 22 | + In an equation for ‘test1''’: test1'' = getField @"ayzzywyzzydyzzy"
|
|
| 23 | + Suggested fix:
|
|
| 24 | + Perhaps use the similarly named field of another type:
|
|
| 25 | + ‘G’: ‘xyzzywyzzydyzzy’ (line 24)
|
|
| 26 | + |
|
| 27 | +T26480b.hs:40:12: error: [GHC-39999]
|
|
| 28 | + • No instance for ‘HasField "xyzzywyzzydyzzb" G H’
|
|
| 29 | + arising from selecting the field ‘xyzzywyzzydyzzb’
|
|
| 30 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzzb’.
|
|
| 31 | + • In the expression: g.xyzzywyzzydyzzb
|
|
| 32 | + In an equation for ‘test2a’: test2a g = g.xyzzywyzzydyzzb
|
|
| 33 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 34 | + |
|
| 35 | +T26480b.hs:43:12: error: [GHC-39999]
|
|
| 36 | + • No instance for ‘HasField "xyzzywyzzydyzzc" G H’
|
|
| 37 | + arising from selecting the field ‘xyzzywyzzydyzzc’
|
|
| 38 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzzc’.
|
|
| 39 | + • In the expression: g.field1.xyzzywyzzydyzzc
|
|
| 40 | + In an equation for ‘test2b’: test2b g = g.field1.xyzzywyzzydyzzc
|
|
| 41 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 42 | + |
|
| 43 | +T26480b.hs:47:10: error: [GHC-39999]
|
|
| 44 | + • No instance for ‘HasField "xyzzywyzzydyzzd" G H’
|
|
| 45 | + arising from the record selector ‘xyzzywyzzydyzzd’
|
|
| 46 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzzd’.
|
|
| 47 | + • In the expression: (.xyzzywyzzydyzzd)
|
|
| 48 | + In an equation for ‘test3a’: test3a = (.xyzzywyzzydyzzd)
|
|
| 49 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 50 | + |
|
| 51 | +T26480b.hs:50:10: error: [GHC-39999]
|
|
| 52 | + • No instance for ‘HasField "xyzzywyzzydyzze" G H’
|
|
| 53 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzze’.
|
|
| 54 | + • In the expression: (.field1.xyzzywyzzydyzze)
|
|
| 55 | + In an equation for ‘test3b’: test3b = (.field1.xyzzywyzzydyzze)
|
|
| 56 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 57 | + |
|
| 58 | +T26480b.hs:54:12: error: [GHC-39999]
|
|
| 59 | + • No instance for ‘HasField "xyzzywyzzydyzzf" G G’
|
|
| 60 | + arising from a record update
|
|
| 61 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzzf’.
|
|
| 62 | + • In the expression: d {xyzzywyzzydyzzf = MkG (MkH 3)}
|
|
| 63 | + In an equation for ‘test4a’:
|
|
| 64 | + test4a d = d {xyzzywyzzydyzzf = MkG (MkH 3)}
|
|
| 65 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 66 | + |
|
| 67 | +T26480b.hs:57:12: error: [GHC-39999]
|
|
| 68 | + • No instance for ‘HasField "xyzzywyzzydyzzg" G H’
|
|
| 69 | + NB: ‘G’ does not have a record field named ‘xyzzywyzzydyzzg’.
|
|
| 70 | + • In the expression: d {field1.xyzzywyzzydyzzg = MkH 3}
|
|
| 71 | + In an equation for ‘test4b’:
|
|
| 72 | + test4b d = d {field1.xyzzywyzzydyzzg = MkH 3}
|
|
| 73 | + Suggested fix: Perhaps use ‘xyzzywyzzydyzzy’ (line 24).
|
|
| 74 | + |
| ... | ... | @@ -33,6 +33,8 @@ test('hasfieldfail03', normal, compile_fail, ['']) |
| 33 | 33 | test('hasfieldfail04', normal, compile_fail, [''])
|
| 34 | 34 | test('T14953', [extra_files(['T14953_A.hs', 'T14953_B.hs'])],
|
| 35 | 35 | multimod_compile_fail, ['T14953', ''])
|
| 36 | +test('T26480', extra_files(['T26480_aux1.hs', 'T26480_aux2.hs']), multimod_compile_fail, ['T26480', '-v0'])
|
|
| 37 | +test('T26480b', normal, compile_fail, [''])
|
|
| 36 | 38 | test('DuplicateExports', normal, compile_fail, [''])
|
| 37 | 39 | test('T17420', [extra_files(['T17420A.hs'])], multimod_compile_fail,
|
| 38 | 40 | ['T17420', ''])
|
| 1 | 1 | [1 of 3] Compiling HasFieldFail01_A ( HasFieldFail01_A.hs, HasFieldFail01_A.o )
|
| 2 | 2 | [2 of 3] Compiling Main ( hasfieldfail01.hs, hasfieldfail01.o )
|
| 3 | - |
|
| 4 | 3 | hasfieldfail01.hs:9:15: error: [GHC-39999]
|
| 5 | 4 | • No instance for ‘HasField "foo" T Int’
|
| 6 | 5 | arising from a use of ‘getField’
|
| 6 | + NB: the record field ‘foo’ of ‘T’ is out of scope.
|
|
| 7 | 7 | • In the first argument of ‘print’, namely
|
| 8 | 8 | ‘(getField @"foo" (MkT 42) :: Int)’
|
| 9 | 9 | In the expression: print (getField @"foo" (MkT 42) :: Int)
|
| 10 | 10 | In an equation for ‘main’:
|
| 11 | 11 | main = print (getField @"foo" (MkT 42) :: Int)
|
| 12 | + Suggested fix:
|
|
| 13 | + Add ‘foo’ to the import list in the import of ‘HasFieldFail01_A’
|
|
| 14 | + (at hasfieldfail01.hs:3:1-32).
|
|
| 15 | + |
| 1 | - |
|
| 2 | 1 | hasfieldfail02.hs:11:5: error: [GHC-39999]
|
| 3 | 2 | • No instance for ‘HasField "foo" T a1’
|
| 4 | 3 | arising from a use of ‘getField’
|
| 4 | + NB: the field type of the record field ‘foo’ of ‘T’ is not a mono-type.
|
|
| 5 | 5 | • In the expression: getField @"foo" (MkT id)
|
| 6 | 6 | In an equation for ‘x’: x = getField @"foo" (MkT id)
|
| 7 | 7 | |
| 8 | 8 | hasfieldfail02.hs:17:5: error: [GHC-39999]
|
| 9 | 9 | • No instance for ‘HasField "bar" U a0’
|
| 10 | 10 | arising from a use of ‘getField’
|
| 11 | + NB: the record field ‘bar’ of ‘U’ contains existential variables.
|
|
| 11 | 12 | • In the expression: getField @"bar" (MkU True)
|
| 12 | 13 | In an equation for ‘y’: y = getField @"bar" (MkU True)
|
| 14 | + |
| ... | ... | @@ -16,6 +16,7 @@ RecordDotSyntaxFail11.hs:8:3: error: [GHC-39999] |
| 16 | 16 | |
| 17 | 17 | RecordDotSyntaxFail11.hs:8:11: error: [GHC-39999]
|
| 18 | 18 | • No instance for ‘GHC.Internal.Records.HasField "baz" Int a0’
|
| 19 | + NB: ‘Int’ is not a record type.
|
|
| 19 | 20 | • In the second argument of ‘($)’, namely ‘(.foo.bar.baz) a’
|
| 20 | 21 | In a stmt of a 'do' block: print $ (.foo.bar.baz) a
|
| 21 | 22 | In the expression:
|
| ... | ... | @@ -28,10 +28,26 @@ data Baz = Baz { baz :: Quux } deriving (Show, Eq) |
| 28 | 28 | instance HasField "baz" Baz Quux where
|
| 29 | 29 | hasField r = (\x -> case r of Baz { .. } -> Baz { baz = x, .. }, baz r)
|
| 30 | 30 | |
| 31 | --- 'Quux' has a 'quux' field of type 'Int'
|
|
| 32 | -data Quux = Quux { quux :: Int } deriving (Show, Eq)
|
|
| 31 | +-- 'Quux' has 'quux' fields of type 'Wob'
|
|
| 32 | +data Quux = Quux { quux1, quux2, quux3 :: Wob } deriving (Show, Eq)
|
|
| 33 | 33 | -- Forget to write this type's 'HasField' instance
|
| 34 | 34 | |
| 35 | +-- 'Wob' has a field of type 'Bool'
|
|
| 36 | +data Wob = Wob { wob :: Bool } deriving (Show, Eq)
|
|
| 37 | +instance HasField "wob" Wob Bool where
|
|
| 38 | + hasField r = (\x -> case r of Wob { .. } -> Wob { wob = x, .. }, wob r)
|
|
| 39 | + |
|
| 40 | +myQuux :: Quux
|
|
| 41 | +myQuux = Quux w w w
|
|
| 42 | + where w = Wob { wob = True }
|
|
| 43 | + |
|
| 35 | 44 | main = do
|
| 36 | - let a = Foo { foo = Bar{ bar = Baz { baz = Quux { quux = 42 } } } }
|
|
| 37 | - print $ a.foo.bar.baz.quux |
|
| 45 | + let
|
|
| 46 | + a = Foo { foo = Bar{ bar = Baz { baz = myQuux } } }
|
|
| 47 | + print @Quux $ a.foo.bar.baz.quux1
|
|
| 48 | + |
|
| 49 | + let b = myQuux
|
|
| 50 | + print @Quux $ b.quux2
|
|
| 51 | + |
|
| 52 | + let c = Foo { foo = Bar{ bar = Baz { baz = myQuux } } }
|
|
| 53 | + print @Bool $ a.foo.bar.baz.quux3.wob |
| 1 | -RecordDotSyntaxFail8.hs:37:3: error: [GHC-39999]
|
|
| 2 | - • Ambiguous type variable ‘a0’ arising from a use of ‘print’
|
|
| 3 | - prevents the constraint ‘(Show a0)’ from being solved.
|
|
| 4 | - Probable fix: use a type annotation to specify what ‘a0’ should be.
|
|
| 5 | - Potentially matching instances:
|
|
| 6 | - instance Show Ordering -- Defined in ‘GHC.Internal.Show’
|
|
| 7 | - instance Show Bar -- Defined at RecordDotSyntaxFail8.hs:22:41
|
|
| 8 | - ...plus 29 others
|
|
| 9 | - ...plus 13 instances involving out-of-scope types
|
|
| 10 | - (use -fprint-potential-instances to see them all)
|
|
| 11 | - • In the first argument of ‘($)’, namely ‘print’
|
|
| 12 | - In a stmt of a 'do' block: print $ ....baz.quux
|
|
| 1 | +RecordDotSyntaxFail8.hs:47:17: error: [GHC-39999]
|
|
| 2 | + • No instance for ‘HasField "quux1" Quux Quux’
|
|
| 3 | + arising from selecting the field ‘quux1’
|
|
| 4 | + NB: ‘HasField’ is not the built-in ‘GHC.Internal.Records.HasField’ class.
|
|
| 5 | + • In the second argument of ‘($)’, namely ‘....bar.baz.quux1’
|
|
| 6 | + In a stmt of a 'do' block: print @Quux $ ....baz.quux1
|
|
| 13 | 7 | In the expression:
|
| 14 | 8 | do let a = Foo {foo = ...}
|
| 15 | - print $ ....quux
|
|
| 9 | + print @Quux $ ....quux1
|
|
| 10 | + let b = myQuux
|
|
| 11 | + print @Quux $ b.quux2
|
|
| 12 | + let c = Foo {foo = ...}
|
|
| 13 | + ...
|
|
| 16 | 14 | |
| 17 | -RecordDotSyntaxFail8.hs:37:11: error: [GHC-39999]
|
|
| 18 | - • No instance for ‘HasField "quux" Quux a0’
|
|
| 19 | - arising from selecting the field ‘quux’
|
|
| 20 | - • In the second argument of ‘($)’, namely ‘....bar.baz.quux’
|
|
| 21 | - In a stmt of a 'do' block: print $ ....baz.quux
|
|
| 15 | +RecordDotSyntaxFail8.hs:50:17: error: [GHC-39999]
|
|
| 16 | + • No instance for ‘HasField "quux2" Quux Quux’
|
|
| 17 | + arising from selecting the field ‘quux2’
|
|
| 18 | + NB: ‘HasField’ is not the built-in ‘GHC.Internal.Records.HasField’ class.
|
|
| 19 | + • In the second argument of ‘($)’, namely ‘b.quux2’
|
|
| 20 | + In a stmt of a 'do' block: print @Quux $ b.quux2
|
|
| 22 | 21 | In the expression:
|
| 23 | 22 | do let a = Foo {foo = ...}
|
| 24 | - print $ ....quux
|
|
| 25 | - Suggested fix:
|
|
| 26 | - NB: There is no field selector ‘quux :: Quux
|
|
| 27 | - -> a0’ in scope for record type ‘Quux’
|
|
| 23 | + print @Quux $ ....quux1
|
|
| 24 | + let b = myQuux
|
|
| 25 | + print @Quux $ b.quux2
|
|
| 26 | + let c = Foo {foo = ...}
|
|
| 27 | + ...
|
|
| 28 | + |
|
| 29 | +RecordDotSyntaxFail8.hs:53:17: error: [GHC-39999]
|
|
| 30 | + • No instance for ‘HasField "quux3" Quux r0’
|
|
| 31 | + arising from selecting the field ‘quux3’
|
|
| 32 | + NB: ‘HasField’ is not the built-in ‘GHC.Internal.Records.HasField’ class.
|
|
| 33 | + • In the expression: ....bar.baz.quux3
|
|
| 34 | + In the second argument of ‘($)’, namely ‘....baz.quux3.wob’
|
|
| 35 | + In a stmt of a 'do' block: print @Bool $ ....quux3.wob
|
|
| 28 | 36 |
| ... | ... | @@ -29,7 +29,7 @@ T19843h.hs:24:8: error: [GHC-39999] |
| 29 | 29 | • In the expression: undefined.getAll
|
| 30 | 30 | In an equation for ‘quur’: quur = undefined.getAll
|
| 31 | 31 | Suggested fixes:
|
| 32 | - • Perhaps use record field of Alt ‘getAlt’ (imported from Data.Monoid)
|
|
| 33 | 32 | • Add ‘getAll’ to the import list in the import of ‘Data.Monoid’
|
| 34 | - (at T19843h.hs:9:1-28).
|
|
| 33 | + (at T19843h.hs:8:1-46).
|
|
| 34 | + • Perhaps use record field of Alt ‘getAlt’ (imported from Data.Monoid)
|
|
| 35 | 35 |