diff options
Diffstat (limited to 'compiler/GHC/Tc/Errors.hs')
-rw-r--r-- | compiler/GHC/Tc/Errors.hs | 853 |
1 files changed, 478 insertions, 375 deletions
diff --git a/compiler/GHC/Tc/Errors.hs b/compiler/GHC/Tc/Errors.hs index a833e76661..b71a6b1dd4 100644 --- a/compiler/GHC/Tc/Errors.hs +++ b/compiler/GHC/Tc/Errors.hs @@ -3,6 +3,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} @@ -13,8 +14,6 @@ module GHC.Tc.Errors( reportUnsolved, reportAllUnsolved, warnAllUnsolved, warnDefaulting, - solverDepthErrorTcS, - -- * GHC API helper functions solverReportMsg_ExpectedActuals, solverReportInfo_ExpectedActuals @@ -92,7 +91,7 @@ import Data.List.NonEmpty ( NonEmpty(..), (<|) ) import qualified Data.List.NonEmpty as NE ( map, reverse ) import Data.List ( sortBy ) import Data.Ord ( comparing ) - +import qualified Data.Semigroup as S {- ************************************************************************ @@ -464,20 +463,73 @@ But without the context we won't find beta := Zero. This only matters in instance declarations.. -} +-- | Should we completely ignore this constraint in error reporting? +-- It *must* be the case that any constraint for which this returns True +-- somehow causes an error to be reported elsewhere. +-- See Note [Constraints to ignore]. +ignoreConstraint :: Ct -> Bool +ignoreConstraint ct + | AssocFamPatOrigin <- ctOrigin ct + = True + | otherwise + = False + +-- | Makes an error item from a constraint, calculating whether or not +-- the item should be suppressed. See Note [Wanteds rewrite Wanteds] +-- in GHC.Tc.Types.Constraint. Returns Nothing if we should just ignore +-- a constraint. See Note [Constraints to ignore]. +mkErrorItem :: Ct -> TcM (Maybe ErrorItem) +mkErrorItem ct + | ignoreConstraint ct + = do { traceTc "Ignoring constraint:" (ppr ct) + ; return Nothing } -- See Note [Constraints to ignore] + + | otherwise + = do { let loc = ctLoc ct + flav = ctFlavour ct + + ; (suppress, m_evdest) <- case ctEvidence ct of + CtGiven {} -> return (False, Nothing) + CtWanted { ctev_rewriters = rewriters, ctev_dest = dest } + -> do { supp <- anyUnfilledCoercionHoles rewriters + ; return (supp, Just dest) } + + ; let m_reason = case ct of CIrredCan { cc_reason = reason } -> Just reason + _ -> Nothing + + ; return $ Just $ EI { ei_pred = ctPred ct + , ei_evdest = m_evdest + , ei_flavour = flav + , ei_loc = loc + , ei_m_reason = m_reason + , ei_suppress = suppress }} + +---------------------------------------------------------------- reportWanteds :: SolverReportErrCtxt -> TcLevel -> WantedConstraints -> TcM () -reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics - , wc_holes = holes }) - = do { traceTc "reportWanteds" (vcat [ text "Simples =" <+> ppr simples - , text "Suppress =" <+> ppr (cec_suppress ctxt) - , text "tidy_cts =" <+> ppr tidy_cts - , text "tidy_holes = " <+> ppr tidy_holes ]) +reportWanteds ctxt tc_lvl wc@(WC { wc_simple = simples, wc_impl = implics + , wc_holes = holes }) + | isEmptyWC wc = traceTc "reportWanteds empty WC" empty + | otherwise + = do { tidy_items <- mapMaybeM mkErrorItem tidy_cts + ; traceTc "reportWanteds 1" (vcat [ text "Simples =" <+> ppr simples + , text "Suppress =" <+> ppr (cec_suppress ctxt) + , text "tidy_cts =" <+> ppr tidy_cts + , text "tidy_items =" <+> ppr tidy_items + , text "tidy_holes =" <+> ppr tidy_holes ]) + + -- This check makes sure that we aren't suppressing the only error that will + -- actually stop compilation + ; massert $ + null simples || -- no errors to report here + any ignoreConstraint simples || -- one error is ignorable (is reported elsewhere) + not (all ei_suppress tidy_items) -- not all error are suppressed -- First, deal with any out-of-scope errors: ; let (out_of_scope, other_holes) = partition isOutOfScopeHole tidy_holes -- don't suppress out-of-scope errors ctxt_for_scope_errs = ctxt { cec_suppress = False } ; (_, no_out_of_scope) <- askNoErrs $ - reportHoles tidy_cts ctxt_for_scope_errs out_of_scope + reportHoles tidy_items ctxt_for_scope_errs out_of_scope -- Next, deal with things that are utterly wrong -- Like Int ~ Bool (incl nullary TyCons) @@ -485,57 +537,71 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics -- These /ones/ are not suppressed by the incoming context -- (but will be by out-of-scope errors) ; let ctxt_for_insols = ctxt { cec_suppress = not no_out_of_scope } - ; reportHoles tidy_cts ctxt_for_insols other_holes + ; reportHoles tidy_items ctxt_for_insols other_holes -- holes never suppress - ; (ctxt1, cts1) <- tryReporters ctxt_for_insols report1 tidy_cts + -- See Note [Suppressing confusing errors] + ; let (suppressed_items, items0) = partition suppress tidy_items + ; traceTc "reportWanteds suppressed:" (ppr suppressed_items) + ; (ctxt1, items1) <- tryReporters ctxt_for_insols report1 items0 -- Now all the other constraints. We suppress errors here if -- any of the first batch failed, or if the enclosing context -- says to suppress - ; let ctxt2 = ctxt { cec_suppress = cec_suppress ctxt || cec_suppress ctxt1 } - ; (_, leftovers) <- tryReporters ctxt2 report2 cts1 + ; let ctxt2 = ctxt1 { cec_suppress = cec_suppress ctxt || cec_suppress ctxt1 } + ; (ctxt3, leftovers) <- tryReporters ctxt2 report2 items1 ; massertPpr (null leftovers) (text "The following unsolved Wanted constraints \ \have not been reported to the user:" $$ ppr leftovers) - -- All the Derived ones have been filtered out of simples - -- by the constraint solver. This is ok; we don't want - -- to report unsolved Derived goals as errors - -- See Note [Do not report derived but soluble errors] - - ; mapBagM_ (reportImplic ctxt2) implics } + ; mapBagM_ (reportImplic ctxt2) implics -- NB ctxt2: don't suppress inner insolubles if there's only a -- wanted insoluble here; but do suppress inner insolubles -- if there's a *given* insoluble here (= inaccessible code) + + -- Only now, if there are no errors, do we report suppressed ones + -- See Note [Suppressing confusing errors] + -- We don't need to update the context further because of the + -- whenNoErrs guard + ; whenNoErrs $ + do { (_, more_leftovers) <- tryReporters ctxt3 report3 suppressed_items + ; massertPpr (null more_leftovers) (ppr more_leftovers) } } where - env = cec_tidy ctxt + env = cec_tidy ctxt tidy_cts = bagToList (mapBag (tidyCt env) simples) tidy_holes = bagToList (mapBag (tidyHole env) holes) + -- See Note [Suppressing confusing errors] + suppress :: ErrorItem -> Bool + suppress item + | Wanted <- ei_flavour item + = is_ww_fundep_item item + | otherwise + = False + -- report1: ones that should *not* be suppressed by -- an insoluble somewhere else in the tree -- It's crucial that anything that is considered insoluble -- (see GHC.Tc.Utils.insolublWantedCt) is caught here, otherwise -- we might suppress its error message, and proceed on past -- type checking to get a Lint error later - report1 = [ ("custom_error", unblocked is_user_type_error, True, mkUserTypeErrorReporter) + report1 = [ ("custom_error", is_user_type_error, True, mkUserTypeErrorReporter) , given_eq_spec - , ("insoluble2", unblocked utterly_wrong, True, mkGroupReporter mkEqErr) - , ("skolem eq1", unblocked very_wrong, True, mkSkolReporter) - , ("skolem eq2", unblocked skolem_eq, True, mkSkolReporter) - , ("non-tv eq", unblocked non_tv_eq, True, mkSkolReporter) + , ("insoluble2", utterly_wrong, True, mkGroupReporter mkEqErr) + , ("skolem eq1", very_wrong, True, mkSkolReporter) + , ("skolem eq2", skolem_eq, True, mkSkolReporter) + , ("non-tv eq", non_tv_eq, True, mkSkolReporter) -- The only remaining equalities are alpha ~ ty, -- where alpha is untouchable; and representational equalities -- Prefer homogeneous equalities over hetero, because the -- former might be holding up the latter. -- See Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Canonical - , ("Homo eqs", unblocked is_homo_equality, True, mkGroupReporter mkEqErr) - , ("Other eqs", unblocked is_equality, True, mkGroupReporter mkEqErr) - , ("Blocked eqs", is_equality, False, mkSuppressReporter mkBlockedEqErr)] + , ("Homo eqs", is_homo_equality, True, mkGroupReporter mkEqErr) + , ("Other eqs", is_equality, True, mkGroupReporter mkEqErr) + ] -- report2: we suppress these if there are insolubles elsewhere in the tree report2 = [ ("Implicit params", is_ip, False, mkGroupReporter mkIPErr) @@ -543,17 +609,17 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics , ("FixedRuntimeRep", is_FRR, False, mkGroupReporter mkFRRErr) , ("Dicts", is_dict, False, mkGroupReporter mkDictErr) ] - -- also checks to make sure the constraint isn't HoleBlockerReason - -- See TcCanonical Note [Equalities with incompatible kinds], (4) - unblocked :: (Ct -> Pred -> Bool) -> Ct -> Pred -> Bool - unblocked _ (CIrredCan { cc_reason = HoleBlockerReason {}}) _ = False - unblocked checker ct pred = checker ct pred + -- report3: suppressed errors should be reported as categorized by either report1 + -- or report2. Keep this in sync with the suppress function above + report3 = [ ("wanted/wanted fundeps", is_ww_fundep, True, mkGroupReporter mkEqErr) + ] -- rigid_nom_eq, rigid_nom_tv_eq, - is_dict, is_equality, is_ip, is_FRR, is_irred :: Ct -> Pred -> Bool + is_dict, is_equality, is_ip, is_FRR, is_irred :: ErrorItem -> Pred -> Bool - is_given_eq ct pred - | EqPred {} <- pred = arisesFromGivens ct + is_given_eq item pred + | Given <- ei_flavour item + , EqPred {} <- pred = True | otherwise = False -- I think all given residuals are equalities @@ -573,7 +639,7 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics non_tv_eq _ (EqPred NomEq ty1 _) = not (isTyVarTy ty1) non_tv_eq _ _ = False - is_user_type_error ct _ = isUserTypeErrorCt ct + is_user_type_error item _ = isUserTypeError (errorItemPred item) is_homo_equality _ (EqPred _ ty1 ty2) = tcTypeKind ty1 `tcEqType` tcTypeKind ty2 is_homo_equality _ _ = False @@ -587,8 +653,8 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics is_ip _ (ClassPred cls _) = isIPClass cls is_ip _ _ = False - is_FRR ct (SpecialPred ConcretePrimPred _) - | FixedRuntimeRepOrigin {} <- ctOrigin ct + is_FRR item (SpecialPred ConcretePrimPred _) + | FixedRuntimeRepOrigin {} <- errorItemOrigin item = True is_FRR _ _ = False @@ -596,8 +662,12 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics is_irred _ (IrredPred {}) = True is_irred _ _ = False + -- See situation (1) of Note [Suppressing confusing errors] + is_ww_fundep item _ = is_ww_fundep_item item + is_ww_fundep_item = isWantedWantedFunDepOrigin . errorItemOrigin + given_eq_spec -- See Note [Given errors] - | has_gadt_match (cec_encl ctxt) + | has_gadt_match_here = ("insoluble1a", is_given_eq, True, mkGivenErrorReporter) | otherwise = ("insoluble1b", is_given_eq, False, ignoreErrorReporter) @@ -608,6 +678,7 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics -- #13446 is an example -- See Note [Given errors] + has_gadt_match_here = has_gadt_match (cec_encl ctxt) has_gadt_match [] = False has_gadt_match (implic : implics) | PatSkol {} <- ic_info implic @@ -637,36 +708,119 @@ isTyFun_maybe ty = case tcSplitTyConApp_maybe ty of Just (tc,_) | isTypeFamilyTyCon tc -> Just tc _ -> Nothing +{- Note [Suppressing confusing errors] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Certain errors we might encounter are potentially confusing to users. +If there are any other errors to report, at all, we want to suppress these. + +Which errors (only 1 case right now): + +1) Errors which arise from the interaction of two Wanted fun-dep constraints. + Example: + + class C a b | a -> b where + op :: a -> b -> b + + foo _ = op True Nothing + + bar _ = op False [] + + Here, we could infer + foo :: C Bool (Maybe a) => p -> Maybe a + bar :: C Bool [a] => p -> [a] + + (The unused arguments suppress the monomorphism restriction.) The problem + is that these types can't both be correct, as they violate the functional + dependency. Yet reporting an error here is awkward: we must + non-deterministically choose either foo or bar to reject. We thus want + to report this problem only when there is nothing else to report. + See typecheck/should_fail/T13506 for an example of when to suppress + the error. The case above is actually accepted, because foo and bar + are checked separately, and thus the two fundep constraints never + encounter each other. It is test case typecheck/should_compile/FunDepOrigin1. + + This case applies only when both fundeps are *Wanted* fundeps; when + both are givens, the error represents unreachable code. For + a Given/Wanted case, see #9612. + +Mechanism: + +We use the `suppress` function within reportWanteds to filter out these two +cases, then report all other errors. Lastly, we return to these suppressed +ones and report them only if there have been no errors so far. + +Note [Constraints to ignore] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Some constraints are meant only to aid the solver by unification; a failure +to solve them is not necessarily an error to report to the user. It is critical +that compilation is aborted elsewhere if there are any ignored constraints here; +they will remain unfilled, and might have been used to rewrite another constraint. + +Currently, the constraints to ignore are: + +1) Constraints generated in order to unify associated type instance parameters + with class parameters. Here are two illustrative examples: + + class C (a :: k) where + type F (b :: k) + + instance C True where + type F a = Int + + instance C Left where + type F (Left :: a -> Either a b) = Bool + + In the first instance, we want to infer that `a` has type Bool. So we emit + a constraint unifying kappa (the guessed type of `a`) with Bool. All is well. + + In the second instance, we process the associated type instance only + after fixing the quantified type variables of the class instance. We thus + have skolems a1 and b1 such that the class instance is for (Left :: a1 -> Either a1 b1). + Unifying a1 and b1 with a and b in the type instance will fail, but harmlessly so. + checkConsistentFamInst checks for this, and will fail if anything has gone + awry. Really the equality constraints emitted are just meant as an aid, not + a requirement. This is test case T13972. + + We detect this case by looking for an origin of AssocFamPatOrigin; constraints + with this origin are dropped entirely during error message reporting. + + If there is any trouble, checkValidFamInst bleats, aborting compilation. + +-} + + + -------------------------------------------- -- Reporters -------------------------------------------- type Reporter - = SolverReportErrCtxt -> [Ct] -> TcM () + = SolverReportErrCtxt -> [ErrorItem] -> TcM () type ReporterSpec - = ( String -- Name - , Ct -> Pred -> Bool -- Pick these ones - , Bool -- True <=> suppress subsequent reporters - , Reporter) -- The reporter itself + = ( String -- Name + , ErrorItem -> Pred -> Bool -- Pick these ones + , Bool -- True <=> suppress subsequent reporters + , Reporter) -- The reporter itself mkSkolReporter :: Reporter -- Suppress duplicates with either the same LHS, or same location -mkSkolReporter ctxt cts - = mapM_ (reportGroup mkEqErr ctxt) (group cts) +-- Pre-condition: all items are equalities +mkSkolReporter ctxt items + = mapM_ (reportGroup mkEqErr ctxt) (group items) where group [] = [] - group (ct:cts) = (ct : yeses) : group noes + group (item:items) = (item : yeses) : group noes where - (yeses, noes) = partition (group_with ct) cts + (yeses, noes) = partition (group_with item) items - group_with ct1 ct2 - | EQ <- cmp_loc ct1 ct2 = True - | eq_lhs_type ct1 ct2 = True - | otherwise = False + group_with item1 item2 + | EQ <- cmp_loc item1 item2 = True + | eq_lhs_type item1 item2 = True + | otherwise = False -reportHoles :: [Ct] -- other (tidied) constraints +reportHoles :: [ErrorItem] -- other (tidied) constraints -> SolverReportErrCtxt -> [Hole] -> TcM () -reportHoles tidy_cts ctxt holes +reportHoles tidy_items ctxt holes = do diag_opts <- initDiagOpts <$> getDynFlags let severity = diagReasonSeverity diag_opts (cec_type_holes ctxt) @@ -675,7 +829,7 @@ reportHoles tidy_cts ctxt holes -- because otherwise types will be zonked and tidied many times over. (tidy_env', lcl_name_cache) <- zonkTidyTcLclEnvs (cec_tidy ctxt) (map (ctl_env . hole_loc) holes') let ctxt' = ctxt { cec_tidy = tidy_env' } - forM_ holes' $ \hole -> do { msg <- mkHoleError lcl_name_cache tidy_cts ctxt' hole + forM_ holes' $ \hole -> do { msg <- mkHoleError lcl_name_cache tidy_items ctxt' hole ; reportDiagnostic msg } keepThisHole :: Severity -> Hole -> Bool @@ -734,42 +888,43 @@ machinery, in cases where it is definitely going to be a no-op. mkUserTypeErrorReporter :: Reporter mkUserTypeErrorReporter ctxt - = mapM_ $ \ct -> do { let err = important ctxt $ mkUserTypeError ct - ; maybeReportError ctxt ct err - ; addDeferredBinding ctxt err ct } + = mapM_ $ \item -> do { let err = important ctxt $ mkUserTypeError item + ; maybeReportError ctxt [item] err + ; addDeferredBinding ctxt err item } -mkUserTypeError :: Ct -> TcSolverReportMsg -mkUserTypeError ct = - case getUserTypeErrorMsg ct of +mkUserTypeError :: ErrorItem -> TcSolverReportMsg +mkUserTypeError item = + case getUserTypeErrorMsg (errorItemPred item) of Just msg -> UserTypeError msg - Nothing -> pprPanic "mkUserTypeError" (ppr ct) + Nothing -> pprPanic "mkUserTypeError" (ppr item) mkGivenErrorReporter :: Reporter -- See Note [Given errors] -mkGivenErrorReporter ctxt cts - = do { (ctxt, relevant_binds, ct) <- relevantBindings True ctxt ct +mkGivenErrorReporter ctxt items + = do { (ctxt, relevant_binds, item) <- relevantBindings True ctxt item ; let (implic:_) = cec_encl ctxt -- Always non-empty when mkGivenErrorReporter is called - ct' = setCtLoc ct (setCtLocEnv (ctLoc ct) (ic_env implic)) + loc' = setCtLocEnv (ei_loc item) (ic_env implic) + item' = item { ei_loc = loc' } -- For given constraints we overwrite the env (and hence src-loc) -- with one from the immediately-enclosing implication. -- See Note [Inaccessible code] - ; (eq_err_msgs, _hints) <- mkEqErr_help ctxt ct' ty1 ty2 + ; (eq_err_msgs, _hints) <- mkEqErr_help ctxt item' ty1 ty2 -- The hints wouldn't help in this situation, so we discard them. ; let supplementary = [ SupplementaryBindings relevant_binds ] msg = TcRnInaccessibleCode implic (NE.reverse . NE.map (SolverReportWithCtxt ctxt) $ eq_err_msgs) - ; msg <- mkErrorReport (ctLocEnv (ctLoc ct')) msg (Just ctxt) supplementary + ; msg <- mkErrorReport (ctLocEnv loc') msg (Just ctxt) supplementary ; reportDiagnostic msg } where - (ct : _ ) = cts -- Never empty - (ty1, ty2) = getEqPredTys (ctPred ct) + (item : _ ) = items -- Never empty + (ty1, ty2) = getEqPredTys (errorItemPred item) ignoreErrorReporter :: Reporter -- Discard Given errors that don't come from -- a pattern match; maybe we should warn instead? -ignoreErrorReporter ctxt cts - = do { traceTc "mkGivenErrorReporter no" (ppr cts $$ ppr (cec_encl ctxt)) +ignoreErrorReporter ctxt items + = do { traceTc "mkGivenErrorReporter no" (ppr items $$ ppr (cec_encl ctxt)) ; return () } @@ -807,59 +962,43 @@ pattern match which binds some equality constraints. If we find one, we report the insoluble Given. -} -mkGroupReporter :: (SolverReportErrCtxt -> [Ct] -> TcM SolverReport) +mkGroupReporter :: (SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport) -- Make error message for a group -> Reporter -- Deal with lots of constraints -- Group together errors from same location, -- and report only the first (to avoid a cascade) -mkGroupReporter mk_err ctxt cts - = mapM_ (reportGroup mk_err ctxt . toList) (equivClasses cmp_loc cts) - --- Like mkGroupReporter, but doesn't actually print error messages -mkSuppressReporter :: (SolverReportErrCtxt -> [Ct] -> TcM SolverReport) - -> Reporter -mkSuppressReporter mk_err ctxt cts - = mapM_ (suppressGroup mk_err ctxt . toList) (equivClasses cmp_loc cts) - -eq_lhs_type :: Ct -> Ct -> Bool -eq_lhs_type ct1 ct2 - = case (classifyPredType (ctPred ct1), classifyPredType (ctPred ct2)) of +mkGroupReporter mk_err ctxt items + = mapM_ (reportGroup mk_err ctxt . toList) (equivClasses cmp_loc items) + +eq_lhs_type :: ErrorItem -> ErrorItem -> Bool +eq_lhs_type item1 item2 + = case (classifyPredType (errorItemPred item1), classifyPredType (errorItemPred item2)) of (EqPred eq_rel1 ty1 _, EqPred eq_rel2 ty2 _) -> (eq_rel1 == eq_rel2) && (ty1 `eqType` ty2) - _ -> pprPanic "mkSkolReporter" (ppr ct1 $$ ppr ct2) + _ -> pprPanic "mkSkolReporter" (ppr item1 $$ ppr item2) -cmp_loc :: Ct -> Ct -> Ordering -cmp_loc ct1 ct2 = get ct1 `compare` get ct2 +cmp_loc :: ErrorItem -> ErrorItem -> Ordering +cmp_loc item1 item2 = get item1 `compare` get item2 where - get ct = realSrcSpanStart (ctLocSpan (ctLoc ct)) + get ei = realSrcSpanStart (ctLocSpan (errorItemCtLoc ei)) -- Reduce duplication by reporting only one error from each -- /starting/ location even if the end location differs -reportGroup :: (SolverReportErrCtxt -> [Ct] -> TcM SolverReport) -> Reporter -reportGroup mk_err ctxt cts - | ct1 : _ <- cts = - do { err <- mk_err ctxt cts - ; traceTc "About to maybeReportErr" $ - vcat [ text "Constraint:" <+> ppr cts - , text "cec_suppress =" <+> ppr (cec_suppress ctxt) - , text "cec_defer_type_errors =" <+> ppr (cec_defer_type_errors ctxt) ] - ; maybeReportError ctxt ct1 err - -- But see Note [Always warn with -fdefer-type-errors] - ; traceTc "reportGroup" (ppr cts) - ; mapM_ (addDeferredBinding ctxt err) cts } - -- Add deferred bindings for all - -- Redundant if we are going to abort compilation, - -- but that's hard to know for sure, and if we don't - -- abort, we need bindings for all (e.g. #12156) - | otherwise = panic "empty reportGroup" - --- like reportGroup, but does not actually report messages. It still adds --- -fdefer-type-errors bindings, though. -suppressGroup :: (SolverReportErrCtxt -> [Ct] -> TcM SolverReport) -> Reporter -suppressGroup mk_err ctxt cts - = do { err <- mk_err ctxt cts - ; traceTc "Suppressing errors for" (ppr cts) - ; mapM_ (addDeferredBinding ctxt err) cts } +reportGroup :: (SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport) -> Reporter +reportGroup mk_err ctxt items + = do { err <- mk_err ctxt items + ; traceTc "About to maybeReportErr" $ + vcat [ text "Constraint:" <+> ppr items + , text "cec_suppress =" <+> ppr (cec_suppress ctxt) + , text "cec_defer_type_errors =" <+> ppr (cec_defer_type_errors ctxt) ] + ; maybeReportError ctxt items err + -- But see Note [Always warn with -fdefer-type-errors] + ; traceTc "reportGroup" (ppr items) + ; mapM_ (addDeferredBinding ctxt err) items } + -- Add deferred bindings for all + -- Redundant if we are going to abort compilation, + -- but that's hard to know for sure, and if we don't + -- abort, we need bindings for all (e.g. #12156) -- See Note [No deferring for multiplicity errors] nonDeferrableOrigin :: CtOrigin -> Bool @@ -868,23 +1007,33 @@ nonDeferrableOrigin (UsageEnvironmentOf {}) = True nonDeferrableOrigin (FixedRuntimeRepOrigin {}) = True nonDeferrableOrigin _ = False -maybeReportError :: SolverReportErrCtxt -> Ct -> SolverReport -> TcM () -maybeReportError ctxt ct (SolverReport { sr_important_msgs = important, sr_supplementary = supp, sr_hints = hints }) - = unless (cec_suppress ctxt) $ -- Some worse error has occurred, so suppress this diagnostic - do let reason | nonDeferrableOrigin (ctOrigin ct) = ErrorWithoutFlag - | otherwise = cec_defer_type_errors ctxt +maybeReportError :: SolverReportErrCtxt + -> [ErrorItem] -- items covered by the Report + -> SolverReport -> TcM () +maybeReportError ctxt items@(item1:_) (SolverReport { sr_important_msgs = important + , sr_supplementary = supp + , sr_hints = hints }) + = unless (cec_suppress ctxt -- Some worse error has occurred, so suppress this diagnostic + || all ei_suppress items) $ + -- if they're all to be suppressed, report nothing + -- if at least one is not suppressed, do report: + -- the function that generates the error message + -- should look for an unsuppressed error item + do let reason | any (nonDeferrableOrigin . errorItemOrigin) items = ErrorWithoutFlag + | otherwise = cec_defer_type_errors ctxt -- See Note [No deferring for multiplicity errors] diag = TcRnSolverReport important reason hints - msg <- mkErrorReport (ctLocEnv (ctLoc ct)) diag (Just ctxt) supp + msg <- mkErrorReport (ctLocEnv (errorItemCtLoc item1)) diag (Just ctxt) supp reportDiagnostic msg +maybeReportError _ _ _ = panic "maybeReportError" -addDeferredBinding :: SolverReportErrCtxt -> SolverReport -> Ct -> TcM () +addDeferredBinding :: SolverReportErrCtxt -> SolverReport -> ErrorItem -> TcM () -- See Note [Deferring coercion errors to runtime] -addDeferredBinding ctxt err ct +addDeferredBinding ctxt err (EI { ei_evdest = Just dest, ei_pred = item_ty + , ei_loc = loc }) + -- if evdest is Just, then the constraint was from a wanted | deferringAnyBindings ctxt - , CtWanted { ctev_pred = pred, ctev_dest = dest } <- ctEvidence ct - -- Only add deferred bindings for Wanted constraints - = do { err_tm <- mkErrorTerm ctxt (ctLoc ct) pred err + = do { err_tm <- mkErrorTerm ctxt loc item_ty err ; let ev_binds_var = cec_binds ctxt ; case dest of @@ -895,9 +1044,7 @@ addDeferredBinding ctxt err ct let co_var = coHoleCoVar hole ; addTcEvBind ev_binds_var $ mkWantedEvBind co_var err_tm ; fillCoercionHole hole (mkTcCoVarCo co_var) }} - - | otherwise -- Do not set any evidence for Given/Derived - = return () +addDeferredBinding _ _ _ = return () -- Do not set any evidence for Given mkErrorTerm :: SolverReportErrCtxt -> CtLoc -> Type -- of the error term -> SolverReport -> TcM EvTerm @@ -913,42 +1060,44 @@ mkErrorTerm ctxt ct_loc ty (SolverReport { sr_important_msgs = important, sr_sup ; return $ evDelayedError ty err_str } -tryReporters :: SolverReportErrCtxt -> [ReporterSpec] -> [Ct] -> TcM (SolverReportErrCtxt, [Ct]) +tryReporters :: SolverReportErrCtxt -> [ReporterSpec] -> [ErrorItem] -> TcM (SolverReportErrCtxt, [ErrorItem]) -- Use the first reporter in the list whose predicate says True -tryReporters ctxt reporters cts - = do { let (vis_cts, invis_cts) = partition (isVisibleOrigin . ctOrigin) cts - ; traceTc "tryReporters {" (ppr vis_cts $$ ppr invis_cts) - ; (ctxt', cts') <- go ctxt reporters vis_cts invis_cts - ; traceTc "tryReporters }" (ppr cts') - ; return (ctxt', cts') } +tryReporters ctxt reporters items + = do { let (vis_items, invis_items) + = partition (isVisibleOrigin . errorItemOrigin) items + ; traceTc "tryReporters {" (ppr vis_items $$ ppr invis_items) + ; (ctxt', items') <- go ctxt reporters vis_items invis_items + ; traceTc "tryReporters }" (ppr items') + ; return (ctxt', items') } where - go ctxt [] vis_cts invis_cts - = return (ctxt, vis_cts ++ invis_cts) + go ctxt [] vis_items invis_items + = return (ctxt, vis_items ++ invis_items) - go ctxt (r : rs) vis_cts invis_cts + go ctxt (r : rs) vis_items invis_items -- always look at *visible* Origins before invisible ones -- this is the whole point of isVisibleOrigin - = do { (ctxt', vis_cts') <- tryReporter ctxt r vis_cts - ; (ctxt'', invis_cts') <- tryReporter ctxt' r invis_cts - ; go ctxt'' rs vis_cts' invis_cts' } + = do { (ctxt', vis_items') <- tryReporter ctxt r vis_items + ; (ctxt'', invis_items') <- tryReporter ctxt' r invis_items + ; go ctxt'' rs vis_items' invis_items' } -- Carry on with the rest, because we must make -- deferred bindings for them if we have -fdefer-type-errors -- But suppress their error messages -tryReporter :: SolverReportErrCtxt -> ReporterSpec -> [Ct] -> TcM (SolverReportErrCtxt, [Ct]) -tryReporter ctxt (str, keep_me, suppress_after, reporter) cts +tryReporter :: SolverReportErrCtxt -> ReporterSpec -> [ErrorItem] -> TcM (SolverReportErrCtxt, [ErrorItem]) +tryReporter ctxt (str, keep_me, suppress_after, reporter) items | null yeses - = return (ctxt, cts) + = return (ctxt, items) | otherwise = do { traceTc "tryReporter{ " (text str <+> ppr yeses) ; (_, no_errs) <- askNoErrs (reporter ctxt yeses) - ; let suppress_now = not no_errs && suppress_after + ; let suppress_now = not no_errs && suppress_after -- See Note [Suppressing error messages] ctxt' = ctxt { cec_suppress = suppress_now || cec_suppress ctxt } ; traceTc "tryReporter end }" (text str <+> ppr (cec_suppress ctxt) <+> ppr suppress_after) ; return (ctxt', nos) } where - (yeses, nos) = partition (\ct -> keep_me ct (classifyPredType (ctPred ct))) cts + (yeses, nos) = partition keep items + keep item = keep_me item (classifyPredType (errorItemPred item)) -- | Wrap an input 'TcRnMessage' with additional contextual information, -- such as relevant bindings or valid hole fits. @@ -1069,56 +1218,6 @@ from that EvVar, filling the hole with that coercion. Because coercions' types are unlifted, the error is guaranteed to be hit before we get to the coercion. -Note [Do not report derived but soluble errors] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The wc_simples include Derived constraints that have not been solved, -but are not insoluble (in that case they'd be reported by 'report1'). -We do not want to report these as errors: - -* Superclass constraints. If we have an unsolved [W] Ord a, we'll also have - an unsolved [D] Eq a, and we do not want to report that; it's just noise. - -* Functional dependencies. For givens, consider - class C a b | a -> b - data T a where - MkT :: C a d => [d] -> T a - f :: C a b => T a -> F Int - f (MkT xs) = length xs - Then we get a [D] b~d. But there *is* a legitimate call to - f, namely f (MkT [True]) :: T Bool, in which b=d. So we should - not reject the program. - - For wanteds, something similar - data T a where - MkT :: C Int b => a -> b -> T a - g :: C Int c => c -> () - f :: T a -> () - f (MkT x y) = g x - Here we get [G] C Int b, [W] C Int a, hence [D] a~b. - But again f (MkT True True) is a legitimate call. - -(We leave the Deriveds in wc_simple until reportErrors, so that we don't lose -derived superclasses between iterations of the solver.) - -For functional dependencies, here is a real example, -stripped off from libraries/utf8-string/Codec/Binary/UTF8/Generic.hs - - class C a b | a -> b - g :: C a b => a -> b -> () - f :: C a b => a -> b -> () - f xa xb = - let loop = g xa - in loop xb - -We will first try to infer a type for loop, and we will succeed: - C a b' => b' -> () -Subsequently, we will type check (loop xb) and all is good. But, -recall that we have to solve a final implication constraint: - C a b => (C a b' => .... cts from body of loop .... )) -And now we have a problem as we will generate an equality b ~ b' and fail to -solve it. - - ************************************************************************ * * Irreducible predicate errors @@ -1126,14 +1225,23 @@ solve it. ************************************************************************ -} -mkIrredErr :: SolverReportErrCtxt -> [Ct] -> TcM SolverReport -mkIrredErr ctxt cts - = do { (ctxt, binds_msg, ct1) <- relevantBindings True ctxt ct1 +mkIrredErr :: SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport +mkIrredErr ctxt items + = do { (ctxt, binds_msg, item1) <- relevantBindings True ctxt item1 ; let msg = important ctxt $ - CouldNotDeduce (getUserGivens ctxt) (ct1 :| others) Nothing + CouldNotDeduce (getUserGivens ctxt) (item1 :| others) Nothing ; return $ msg `mappend` mk_relevant_bindings binds_msg } where - ct1:others = cts + (item1:others) = final_items + + filtered_items = filter (not . ei_suppress) items + final_items | null filtered_items = items + -- they're all suppressed; must report *something* + -- NB: even though reportWanteds asserts that not + -- all items are suppressed, it's possible all the + -- irreducibles are suppressed, and so this function + -- might get all suppressed items + | otherwise = filtered_items {- Note [Constructing Hole Errors] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1171,7 +1279,7 @@ See also 'reportUnsolved'. ---------------- -- | Constructs a new hole error, unless this is deferred. See Note [Constructing Hole Errors]. -mkHoleError :: NameEnv Type -> [Ct] -> SolverReportErrCtxt -> Hole -> TcM (MsgEnvelope TcRnMessage) +mkHoleError :: NameEnv Type -> [ErrorItem] -> SolverReportErrCtxt -> Hole -> TcM (MsgEnvelope TcRnMessage) mkHoleError _ _tidy_simples ctxt hole@(Hole { hole_occ = occ, hole_loc = ct_loc }) | isOutOfScopeHole hole = do { dflags <- getDynFlags @@ -1277,19 +1385,27 @@ maybeAddDeferredBindings ctxt hole report = do -- We unwrap the SolverReportErrCtxt here, to avoid introducing a loop in module -- imports -validHoleFits :: SolverReportErrCtxt -- ^ The context we're in, i.e. the - -- implications and the tidy environment - -> [Ct] -- ^ Unsolved simple constraints - -> Hole -- ^ The hole - -> TcM (SolverReportErrCtxt, ValidHoleFits) - -- ^ We return the new context - -- with a possibly updated - -- tidy environment, and - -- the valid hole fits. -validHoleFits ctxt@(CEC {cec_encl = implics - , cec_tidy = lcl_env}) simps hole - = do { (tidy_env, fits) <- findValidHoleFits lcl_env implics simps hole +validHoleFits :: SolverReportErrCtxt -- ^ The context we're in, i.e. the + -- implications and the tidy environment + -> [ErrorItem] -- ^ Unsolved simple constraints + -> Hole -- ^ The hole + -> TcM (SolverReportErrCtxt, ValidHoleFits) + -- ^ We return the new context + -- with a possibly updated + -- tidy environment, and + -- the valid hole fits. +validHoleFits ctxt@(CEC { cec_encl = implics + , cec_tidy = lcl_env}) simps hole + = do { (tidy_env, fits) <- findValidHoleFits lcl_env implics (map mk_wanted simps) hole ; return (ctxt {cec_tidy = tidy_env}, fits) } + where + mk_wanted :: ErrorItem -> CtEvidence + mk_wanted (EI { ei_pred = pred, ei_evdest = Just dest, ei_loc = loc }) + = CtWanted { ctev_pred = pred + , ctev_dest = dest + , ctev_loc = loc + , ctev_rewriters = emptyRewriterSet } + mk_wanted item = pprPanic "validHoleFits no evdest" (ppr item) -- See Note [Constraints include ...] givenConstraints :: SolverReportErrCtxt -> [(Type, RealSrcSpan)] @@ -1300,13 +1416,16 @@ givenConstraints ctxt ---------------- -mkIPErr :: SolverReportErrCtxt -> [Ct] -> TcM SolverReport -mkIPErr ctxt cts - = do { (ctxt, binds_msg, ct1) <- relevantBindings True ctxt ct1 - ; let msg = important ctxt $ UnboundImplicitParams (ct1 :| others) +mkIPErr :: SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport +-- What would happen if an item is suppressed because of +-- Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint? Very unclear +-- what's best. Let's not worry about this. +mkIPErr ctxt items + = do { (ctxt, binds_msg, item1) <- relevantBindings True ctxt item1 + ; let msg = important ctxt $ UnboundImplicitParams (item1 :| others) ; return $ msg `mappend` mk_relevant_bindings binds_msg } where - ct1:others = cts + item1:others = items ---------------- @@ -1314,15 +1433,15 @@ mkIPErr ctxt cts -- Wanted constraints arising from representation-polymorphism checks. -- -- See Note [Reporting representation-polymorphism errors] in GHC.Tc.Types.Origin. -mkFRRErr :: SolverReportErrCtxt -> [Ct] -> TcM SolverReport -mkFRRErr ctxt cts +mkFRRErr :: SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport +mkFRRErr ctxt items = do { -- Zonking/tidying. ; origs <- -- Zonk/tidy the 'CtOrigin's. - zonkTidyOrigins (cec_tidy ctxt) (map ctOrigin cts) + zonkTidyOrigins (cec_tidy ctxt) (map errorItemOrigin items) <&> -- Then remove duplicates: only retain one 'CtOrigin' per representation-polymorphic type. - (nubOrdBy (nonDetCmpType `on` (snd . frr_orig_and_type)) . snd) + (nubOrdBy (nonDetCmpType `on` (snd . frr_orig_and_type)) . snd) -- Obtain all the errors we want to report (constraints with FixedRuntimeRep origin), -- with the corresponding types: -- ty1 :: TYPE rep1, ty2 :: TYPE rep2, ... @@ -1396,21 +1515,29 @@ any more. So we don't assert that it is. -- Don't have multiple equality errors from the same location -- E.g. (Int,Bool) ~ (Bool,Int) one error will do! -mkEqErr :: SolverReportErrCtxt -> [Ct] -> TcM SolverReport -mkEqErr ctxt (ct:_) = mkEqErr1 ctxt ct -mkEqErr _ [] = panic "mkEqErr" - -mkEqErr1 :: SolverReportErrCtxt -> Ct -> TcM SolverReport -mkEqErr1 ctxt ct -- Wanted or derived; - -- givens handled in mkGivenErrorReporter - = do { (ctxt, binds_msg, ct) <- relevantBindings True ctxt ct +mkEqErr :: SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport +mkEqErr ctxt items + | item:_ <- filter (not . ei_suppress) items + = mkEqErr1 ctxt item + + | item:_ <- items -- they're all suppressed. still need an error message + -- for -fdefer-type-errors though + = mkEqErr1 ctxt item + + | otherwise + = panic "mkEqErr" -- guaranteed to have at least one item + +mkEqErr1 :: SolverReportErrCtxt -> ErrorItem -> TcM SolverReport +mkEqErr1 ctxt item -- Wanted only + -- givens handled in mkGivenErrorReporter + = do { (ctxt, binds_msg, item) <- relevantBindings True ctxt item ; rdr_env <- getGlobalRdrEnv ; fam_envs <- tcGetFamInstEnvs - ; let mb_coercible_msg = case ctEqRel ct of + ; let mb_coercible_msg = case errorItemEqRel item of NomEq -> Nothing ReprEq -> ReportCoercibleMsg <$> mkCoercibleExplanation rdr_env fam_envs ty1 ty2 - ; traceTc "mkEqErr1" (ppr ct $$ pprCtOrigin (ctOrigin ct)) - ; (last_msg :| prev_msgs, hints) <- mkEqErr_help ctxt ct ty1 ty2 + ; traceTc "mkEqErr1" (ppr item $$ pprCtOrigin (errorItemOrigin item)) + ; (last_msg :| prev_msgs, hints) <- mkEqErr_help ctxt item ty1 ty2 ; let report = foldMap (important ctxt) (reverse prev_msgs) `mappend` (important ctxt $ mkTcReportWithInfo last_msg $ maybeToList mb_coercible_msg) @@ -1418,7 +1545,7 @@ mkEqErr1 ctxt ct -- Wanted or derived; `mappend` (mk_report_hints hints) ; return report } where - (ty1, ty2) = getEqPredTys (ctPred ct) + (ty1, ty2) = getEqPredTys (errorItemPred item) -- | This function tries to reconstruct why a "Coercible ty1 ty2" constraint -- is left over. @@ -1465,41 +1592,40 @@ mkCoercibleExplanation rdr_env fam_envs ty1 ty2 type AccReportMsgs = NonEmpty TcSolverReportMsg mkEqErr_help :: SolverReportErrCtxt - -> Ct + -> ErrorItem -> TcType -> TcType -> TcM (AccReportMsgs, [GhcHint]) -mkEqErr_help ctxt ct ty1 ty2 +mkEqErr_help ctxt item ty1 ty2 | Just (tv1, _) <- tcGetCastedTyVar_maybe ty1 - = mkTyVarEqErr ctxt ct tv1 ty2 + = mkTyVarEqErr ctxt item tv1 ty2 | Just (tv2, _) <- tcGetCastedTyVar_maybe ty2 - = mkTyVarEqErr ctxt ct tv2 ty1 + = mkTyVarEqErr ctxt item tv2 ty1 | otherwise - = return (reportEqErr ctxt ct ty1 ty2 :| [], []) + = return (reportEqErr ctxt item ty1 ty2 :| [], []) reportEqErr :: SolverReportErrCtxt - -> Ct + -> ErrorItem -> TcType -> TcType -> TcSolverReportMsg -reportEqErr ctxt ct ty1 ty2 +reportEqErr ctxt item ty1 ty2 = mkTcReportWithInfo mismatch eqInfos where - mismatch = misMatchOrCND False ctxt ct ty1 ty2 - eqInfos = eqInfoMsgs ct ty1 ty2 + mismatch = misMatchOrCND False ctxt item ty1 ty2 + eqInfos = eqInfoMsgs ty1 ty2 -mkTyVarEqErr :: SolverReportErrCtxt -> Ct +mkTyVarEqErr :: SolverReportErrCtxt -> ErrorItem -> TcTyVar -> TcType -> TcM (AccReportMsgs, [GhcHint]) -- tv1 and ty2 are already tidied -mkTyVarEqErr ctxt ct tv1 ty2 - = do { traceTc "mkTyVarEqErr" (ppr ct $$ ppr tv1 $$ ppr ty2) - ; dflags <- getDynFlags - ; mkTyVarEqErr' dflags ctxt ct tv1 ty2 } +mkTyVarEqErr ctxt item tv1 ty2 + = do { traceTc "mkTyVarEqErr" (ppr item $$ ppr tv1 $$ ppr ty2) + ; mkTyVarEqErr' ctxt item tv1 ty2 } -mkTyVarEqErr' :: DynFlags -> SolverReportErrCtxt -> Ct +mkTyVarEqErr' :: SolverReportErrCtxt -> ErrorItem -> TcTyVar -> TcType -> TcM (AccReportMsgs, [GhcHint]) -mkTyVarEqErr' dflags ctxt ct tv1 ty2 +mkTyVarEqErr' ctxt item tv1 ty2 -- impredicativity is a simple error to understand; try it first | check_eq_result `cterHasProblem` cteImpredicative = do tyvar_eq_info <- extraTyVarEqInfo tv1 ty2 let - poly_msg = CannotUnifyWithPolytype ct tv1 ty2 + poly_msg = CannotUnifyWithPolytype item tv1 ty2 poly_msg_with_info | isSkolemTyVar tv1 = mkTcReportWithInfo poly_msg tyvar_eq_info @@ -1513,7 +1639,7 @@ mkTyVarEqErr' dflags ctxt ct tv1 ty2 | isSkolemTyVar tv1 -- ty2 won't be a meta-tyvar; we would have -- swapped in Solver.Canonical.canEqTyVarHomo || isTyVarTyVar tv1 && not (isTyVarTy ty2) - || ctEqRel ct == ReprEq + || errorItemEqRel item == ReprEq -- The cases below don't really apply to ReprEq (except occurs check) = do tv_extra <- extraTyVarEqInfo tv1 ty2 @@ -1523,7 +1649,7 @@ mkTyVarEqErr' dflags ctxt ct tv1 ty2 -- We report an "occurs check" even for a ~ F t a, where F is a type -- function; it's not insoluble (because in principle F could reduce) -- but we have certainly been unable to solve it - = let extras2 = eqInfoMsgs ct ty1 ty2 + = let extras2 = eqInfoMsgs ty1 ty2 interesting_tyvars = filter (not . noFreeVarsOfType . tyVarKind) $ filter isTyVar $ @@ -1536,6 +1662,11 @@ mkTyVarEqErr' dflags ctxt ct tv1 ty2 in return (mkTcReportWithInfo headline_msg (extras2 ++ extras3) :| [], []) + -- This is wrinkle (4) in Note [Equalities with incompatible kinds] in + -- GHC.Tc.Solver.Canonical + | hasCoercionHoleTy ty2 + = return (mkBlockedEqErr item :| [], []) + -- If the immediately-enclosing implication has 'tv' a skolem, and -- we know by now its an InferSkol kind of skolem, then presumably -- it started life as a TyVarTv, else it'd have been unified, given @@ -1552,7 +1683,7 @@ mkTyVarEqErr' dflags ctxt ct tv1 ty2 , Implic { ic_skols = skols } <- implic , let esc_skols = filter (`elemVarSet` (tyCoVarsOfType ty2)) skols , not (null esc_skols) - = return (SkolemEscape ct implic esc_skols :| [mismatch_msg], []) + = return (SkolemEscape item implic esc_skols :| [mismatch_msg], []) -- Nastiest case: attempt to unify an untouchable variable -- So tv is a meta tyvar (or started that way before we @@ -1568,43 +1699,48 @@ mkTyVarEqErr' dflags ctxt ct tv1 ty2 return (mkTcReportWithInfo tclvl_extra tv_extra :| [mismatch_msg], add_sig) | otherwise - = return (reportEqErr ctxt ct (mkTyVarTy tv1) ty2 :| [], []) + = return (reportEqErr ctxt item (mkTyVarTy tv1) ty2 :| [], []) -- This *can* happen (#6123) -- Consider an ambiguous top-level constraint (a ~ F a) -- Not an occurs check, because F is a type function. where - headline_msg = misMatchOrCND insoluble_occurs_check ctxt ct ty1 ty2 - mismatch_msg = mkMismatchMsg ct ty1 ty2 + headline_msg = misMatchOrCND insoluble_occurs_check ctxt item ty1 ty2 + mismatch_msg = mkMismatchMsg item ty1 ty2 add_sig = maybeToList $ suggestAddSig ctxt ty1 ty2 ty1 = mkTyVarTy tv1 - check_eq_result = case ct of - CIrredCan { cc_reason = NonCanonicalReason result } -> result - CIrredCan { cc_reason = HoleBlockerReason {} } -> cteProblem cteHoleBlocker - _ -> checkTyVarEq dflags tv1 ty2 + check_eq_result = case ei_m_reason item of + Just (NonCanonicalReason result) -> result + _ -> checkTyVarEq tv1 ty2 -- in T2627b, we report an error for F (F a0) ~ a0. Note that the type -- variable is on the right, so we don't get useful info for the CIrredCan, -- and have to compute the result of checkTyVarEq here. insoluble_occurs_check = check_eq_result `cterHasProblem` cteInsolubleOccurs -eqInfoMsgs :: Ct -> TcType -> TcType -> [TcSolverReportInfo] +eqInfoMsgs :: TcType -> TcType -> [TcSolverReportInfo] -- Report (a) ambiguity if either side is a type function application -- e.g. F a0 ~ Int -- (b) warning about injectivity if both sides are the same -- type function application F a ~ F b -- See Note [Non-injective type functions] -eqInfoMsgs ct ty1 ty2 +eqInfoMsgs ty1 ty2 = catMaybes [tyfun_msg, ambig_msg] where mb_fun1 = isTyFun_maybe ty1 mb_fun2 = isTyFun_maybe ty2 - (ambig_kvs, ambig_tvs) = getAmbigTkvs ct + + -- if a type isn't headed by a type function, then any ambiguous + -- variables need not be reported as such. e.g.: F a ~ t0 -> t0, where a is a skolem + ambig_tkvs1 = maybe mempty (\_ -> ambigTkvsOfTy ty1) mb_fun1 + ambig_tkvs2 = maybe mempty (\_ -> ambigTkvsOfTy ty2) mb_fun2 + + ambig_tkvs@(ambig_kvs, ambig_tvs) = ambig_tkvs1 S.<> ambig_tkvs2 ambig_msg | isJust mb_fun1 || isJust mb_fun2 , not (null ambig_kvs && null ambig_tvs) - = Just $ Ambiguity False (ambig_kvs, ambig_tvs) + = Just $ Ambiguity False ambig_tkvs | otherwise = Nothing @@ -1616,24 +1752,23 @@ eqInfoMsgs ct ty1 ty2 | otherwise = Nothing -misMatchOrCND :: Bool -> SolverReportErrCtxt -> Ct +misMatchOrCND :: Bool -> SolverReportErrCtxt -> ErrorItem -> TcType -> TcType -> TcSolverReportMsg -- If oriented then ty1 is actual, ty2 is expected -misMatchOrCND insoluble_occurs_check ctxt ct ty1 ty2 +misMatchOrCND insoluble_occurs_check ctxt item ty1 ty2 | insoluble_occurs_check -- See Note [Insoluble occurs check] || (isRigidTy ty1 && isRigidTy ty2) - || isGivenCt ct + || (ei_flavour item == Given) || null givens = -- If the equality is unconditionally insoluble -- or there is no context, don't report the context - mkMismatchMsg ct ty1 ty2 + mkMismatchMsg item ty1 ty2 | otherwise - = CouldNotDeduce givens (ct :| []) (Just $ CND_Extra level ty1 ty2) + = CouldNotDeduce givens (item :| []) (Just $ CND_Extra level ty1 ty2) where - ev = ctEvidence ct - level = ctLocTypeOrKind_maybe (ctEvLoc ev) `orElse` TypeLevel + level = ctLocTypeOrKind_maybe (errorItemCtLoc item) `orElse` TypeLevel givens = [ given | given <- getUserGivens ctxt, ic_given_eqs given /= NoGivenEqs ] -- Keep only UserGivens that have some equalities. -- See Note [Suppress redundant givens during error reporting] @@ -1643,9 +1778,8 @@ misMatchOrCND insoluble_occurs_check ctxt ct ty1 ty2 -- always be another unsolved wanted around, which will ordinarily suppress -- this message. But this can still be printed out with -fdefer-type-errors -- (sigh), so we must produce a message. -mkBlockedEqErr :: SolverReportErrCtxt -> [Ct] -> TcM SolverReport -mkBlockedEqErr ctxt (ct:_) = return $ important ctxt (BlockedEquality ct) -mkBlockedEqErr _ [] = panic "mkBlockedEqErr no constraints" +mkBlockedEqErr :: ErrorItem -> TcSolverReportMsg +mkBlockedEqErr item = BlockedEquality item {- Note [Suppress redundant givens during error reporting] @@ -1732,53 +1866,49 @@ suggestAddSig ctxt ty1 _ty2 = find implics (seen_eqs || ic_given_eqs implic /= NoGivenEqs) tv -------------------- - -mkMismatchMsg :: Ct -> Type -> Type -> TcSolverReportMsg -mkMismatchMsg ct ty1 ty2 = - case ctOrigin ct of +mkMismatchMsg :: ErrorItem -> Type -> Type -> TcSolverReportMsg +mkMismatchMsg item ty1 ty2 = + case orig of TypeEqOrigin { uo_actual, uo_expected, uo_thing = mb_thing } -> mkTcReportWithInfo (TypeEqMismatch { teq_mismatch_ppr_explicit_kinds = ppr_explicit_kinds - , teq_mismatch_ct = ct - , teq_mismatch_ty1 = ty1 - , teq_mismatch_ty2 = ty2 + , teq_mismatch_item = item + , teq_mismatch_ty1 = ty1 + , teq_mismatch_ty2 = ty2 , teq_mismatch_actual = uo_actual , teq_mismatch_expected = uo_expected , teq_mismatch_what = mb_thing}) extras KindEqOrigin cty1 cty2 sub_o mb_sub_t_or_k -> - mkTcReportWithInfo (Mismatch False ct ty1 ty2) + mkTcReportWithInfo (Mismatch False item ty1 ty2) (WhenMatching cty1 cty2 sub_o mb_sub_t_or_k : extras) _ -> mkTcReportWithInfo - (Mismatch False ct ty1 ty2) + (Mismatch False item ty1 ty2) extras where - orig = ctOrigin ct + orig = errorItemOrigin item extras = sameOccExtras ty2 ty1 ppr_explicit_kinds = shouldPprWithExplicitKinds ty1 ty2 orig --- | Whether to prints explicit kinds (with @-fprint-explicit-kinds@) +-- | Whether to print explicit kinds (with @-fprint-explicit-kinds@) -- in an 'SDoc' when a type mismatch occurs to due invisible kind arguments. -- -- This function first checks to see if the 'CtOrigin' argument is a --- 'TypeEqOrigin', and if so, uses the expected/actual types from that to --- check for a kind mismatch (as these types typically have more surrounding --- types and are likelier to be able to glean information about whether a --- mismatch occurred in an invisible argument position or not). If the --- 'CtOrigin' is not a 'TypeEqOrigin', fall back on the actual mismatched types --- themselves. +-- 'TypeEqOrigin'. If so, it first checks whether the equality is a visible +-- equality; if it's not, definitely print the kinds. Even if the equality is +-- a visible equality, check the expected/actual types to see if the types +-- have equal visible components. If the 'CtOrigin' is +-- not a 'TypeEqOrigin', fall back on the actual mismatched types themselves. shouldPprWithExplicitKinds :: Type -> Type -> CtOrigin -> Bool -shouldPprWithExplicitKinds ty1 ty2 ct - = tcEqTypeVis act_ty exp_ty - -- True when the visible bit of the types look the same, - -- so we want to show the kinds in the displayed type. - where - (act_ty, exp_ty) = case ct of - TypeEqOrigin { uo_actual = act - , uo_expected = exp } -> (act, exp) - _ -> (ty1, ty2) +shouldPprWithExplicitKinds _ty1 _ty2 (TypeEqOrigin { uo_actual = act + , uo_expected = exp + , uo_visible = vis }) + | not vis = True -- See tests T15870, T16204c + | otherwise = tcEqTypeVis act exp -- See tests T9171, T9144. +shouldPprWithExplicitKinds ty1 ty2 _ct + = tcEqTypeVis ty1 ty2 {- Note [Insoluble occurs check] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1880,39 +2010,44 @@ Warn of loopy local equalities that were dropped. ************************************************************************ -} -mkDictErr :: HasDebugCallStack => SolverReportErrCtxt -> [Ct] -> TcM SolverReport -mkDictErr ctxt cts - = assert (not (null cts)) $ +mkDictErr :: HasDebugCallStack => SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport +mkDictErr ctxt orig_items + = assert (not (null items)) $ do { inst_envs <- tcGetInstEnvs - ; let min_cts = elim_superclasses cts - lookups = map (lookup_cls_inst inst_envs) min_cts - (no_inst_cts, overlap_cts) = partition is_no_inst lookups + ; let min_items = elim_superclasses items + lookups = map (lookup_cls_inst inst_envs) min_items + (no_inst_items, overlap_items) = partition is_no_inst lookups -- Report definite no-instance errors, -- or (iff there are none) overlap errors -- But we report only one of them (hence 'head') because they all -- have the same source-location origin, to try avoid a cascade -- of error from one location - ; err <- mk_dict_err ctxt (head (no_inst_cts ++ overlap_cts)) + ; err <- mk_dict_err ctxt (head (no_inst_items ++ overlap_items)) ; return $ important ctxt err } where + filtered_items = filter (not . ei_suppress) orig_items + items | null filtered_items = orig_items -- all suppressed, but must report + -- something for -fdefer-type-errors + | otherwise = filtered_items -- common case + no_givens = null (getUserGivens ctxt) - is_no_inst (ct, (matches, unifiers, _)) + is_no_inst (item, (matches, unifiers, _)) = no_givens && null matches - && (nullUnifiers unifiers || all (not . isAmbiguousTyVar) (tyCoVarsOfCtList ct)) + && (nullUnifiers unifiers || all (not . isAmbiguousTyVar) (tyCoVarsOfTypeList (errorItemPred item))) - lookup_cls_inst inst_envs ct - = (ct, lookupInstEnv True inst_envs clas tys) + lookup_cls_inst inst_envs item + = (item, lookupInstEnv True inst_envs clas tys) where - (clas, tys) = getClassPredTys (ctPred ct) + (clas, tys) = getClassPredTys (errorItemPred item) -- When simplifying [W] Ord (Set a), we need -- [W] Eq a, [W] Ord a -- but we really only want to report the latter - elim_superclasses cts = mkMinimalBySCs ctPred cts + elim_superclasses items = mkMinimalBySCs errorItemPred items -- Note [mk_dict_err] -- ~~~~~~~~~~~~~~~~~~~ @@ -1925,16 +2060,16 @@ mkDictErr ctxt cts -- - One match, one or more unifiers: report "Overlapping instances for", show the -- matching and unifying instances, and say "The choice depends on the instantion of ..., -- and the result of evaluating ...". -mk_dict_err :: HasCallStack => SolverReportErrCtxt -> (Ct, ClsInstLookupResult) +mk_dict_err :: HasCallStack => SolverReportErrCtxt -> (ErrorItem, ClsInstLookupResult) -> TcM TcSolverReportMsg -- Report an overlap error if this class constraint results -- from an overlap (returning Left clas), otherwise return (Right pred) -mk_dict_err ctxt (ct, (matches, unifiers, unsafe_overlapped)) +mk_dict_err ctxt (item, (matches, unifiers, unsafe_overlapped)) | null matches -- No matches but perhaps several unifiers - = do { (_, rel_binds, ct) <- relevantBindings True ctxt ct + = do { (_, rel_binds, item) <- relevantBindings True ctxt item ; candidate_insts <- get_candidate_instances ; (imp_errs, field_suggestions) <- record_field_suggestions - ; return (cannot_resolve_msg ct candidate_insts rel_binds imp_errs field_suggestions) } + ; return (cannot_resolve_msg item candidate_insts rel_binds imp_errs field_suggestions) } | null unsafe_overlapped -- Some matches => overlap errors = return $ overlap_msg @@ -1942,8 +2077,8 @@ mk_dict_err ctxt (ct, (matches, unifiers, unsafe_overlapped)) | otherwise = return $ safe_haskell_msg where - orig = ctOrigin ct - pred = ctPred ct + orig = errorItemOrigin item + pred = errorItemPred item (clas, tys) = getClassPredTys pred ispecs = [ispec | (ispec, _) <- matches] unsafe_ispecs = [ispec | (ispec, _) <- unsafe_overlapped] @@ -1990,21 +2125,22 @@ mk_dict_err ctxt (ct, (matches, unifiers, unsafe_overlapped)) HasFieldOrigin name -> Just (mkVarOccFS name) _ -> Nothing - cannot_resolve_msg :: Ct -> [ClsInst] -> RelevantBindings -> [ImportError] -> [GhcHint] -> TcSolverReportMsg - cannot_resolve_msg ct candidate_insts binds imp_errs field_suggestions - = CannotResolveInstance ct (getPotentialUnifiers unifiers) candidate_insts imp_errs field_suggestions binds + cannot_resolve_msg :: ErrorItem -> [ClsInst] -> RelevantBindings + -> [ImportError] -> [GhcHint] -> TcSolverReportMsg + cannot_resolve_msg item candidate_insts binds imp_errs field_suggestions + = CannotResolveInstance item (getPotentialUnifiers unifiers) candidate_insts imp_errs field_suggestions binds -- Overlap errors. overlap_msg, safe_haskell_msg :: TcSolverReportMsg -- Normal overlap error overlap_msg - = assert (not (null matches)) $ OverlappingInstances ct ispecs (getPotentialUnifiers unifiers) + = assert (not (null matches)) $ OverlappingInstances item ispecs (getPotentialUnifiers unifiers) -- Overlap error because of Safe Haskell (first -- match should be the most specific match) safe_haskell_msg = assert (matches `lengthIs` 1 && not (null unsafe_ispecs)) $ - UnsafeOverlap ct ispecs unsafe_ispecs + UnsafeOverlap item ispecs unsafe_ispecs {- Note [Report candidate instances] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2086,14 +2222,6 @@ the above error message would instead be displayed as: Which makes it clearer that the culprit is the mismatch between `k2` and `k20`. -} -getAmbigTkvs :: Ct -> ([Var],[Var]) -getAmbigTkvs ct - = partition (`elemVarSet` dep_tkv_set) ambig_tkvs - where - tkvs = tyCoVarsOfCtList ct - ambig_tkvs = filter isAmbiguousTyVar tkvs - dep_tkv_set = tyCoVarsOfTypes (map tyVarKind tkvs) - ----------------------- -- relevantBindings looks at the value environment and finds values whose -- types mention any of the offending type variables. It has to be @@ -2105,11 +2233,11 @@ getAmbigTkvs ct relevantBindings :: Bool -- True <=> filter by tyvar; False <=> no filtering -- See #8191 - -> SolverReportErrCtxt -> Ct - -> TcM (SolverReportErrCtxt, RelevantBindings, Ct) + -> SolverReportErrCtxt -> ErrorItem + -> TcM (SolverReportErrCtxt, RelevantBindings, ErrorItem) -- Also returns the zonked and tidied CtOrigin of the constraint -relevantBindings want_filtering ctxt ct - = do { traceTc "relevantBindings" (ppr ct) +relevantBindings want_filtering ctxt item + = do { traceTc "relevantBindings" (ppr item) ; (env1, tidy_orig) <- zonkTidyOrigin (cec_tidy ctxt) (ctLocOrigin loc) -- For *kind* errors, report the relevant bindings of the @@ -2117,19 +2245,19 @@ relevantBindings want_filtering ctxt ct ; let extra_tvs = case tidy_orig of KindEqOrigin t1 t2 _ _ -> tyCoVarsOfTypes [t1,t2] _ -> emptyVarSet - ct_fvs = tyCoVarsOfCt ct `unionVarSet` extra_tvs + ct_fvs = tyCoVarsOfType (errorItemPred item) `unionVarSet` extra_tvs - -- Put a zonked, tidied CtOrigin into the Ct + -- Put a zonked, tidied CtOrigin into the ErrorItem loc' = setCtLocOrigin loc tidy_orig - ct' = setCtLoc ct loc' + item' = item { ei_loc = loc' } ; (env2, lcl_name_cache) <- zonkTidyTcLclEnvs env1 [lcl_env] ; relev_bds <- relevant_bindings want_filtering lcl_env lcl_name_cache ct_fvs ; let ctxt' = ctxt { cec_tidy = env2 } - ; return (ctxt', relev_bds, ct') } + ; return (ctxt', relev_bds, item') } where - loc = ctLoc ct + loc = errorItemCtLoc item lcl_env = ctLocEnv loc -- slightly more general version, to work also with holes @@ -2222,9 +2350,12 @@ warnDefaulting _ [] _ warnDefaulting the_tv wanteds@(ct:_) default_ty = do { warn_default <- woptM Opt_WarnTypeDefaults ; env0 <- tcInitTidyEnv - ; let tidy_env = tidyFreeTyCoVars env0 $ - tyCoVarsOfCtsList (listToBag wanteds) - tidy_wanteds = map (tidyCt tidy_env) wanteds + -- don't want to report all the superclass constraints, which + -- add unhelpful clutter + ; let filtered = filter (not . isWantedSuperclassOrigin . ctOrigin) wanteds + tidy_env = tidyFreeTyCoVars env0 $ + tyCoVarsOfCtsList (listToBag filtered) + tidy_wanteds = map (tidyCt tidy_env) filtered tidy_tv = lookupVarEnv (snd tidy_env) the_tv diag = TcRnWarnDefaulting tidy_wanteds tidy_tv default_ty loc = ctLoc ct @@ -2236,36 +2367,8 @@ Note [Runtime skolems] We want to give a reasonably helpful error message for ambiguity arising from *runtime* skolems in the debugger. These are created by in GHC.Runtime.Heap.Inspect.zonkRTTIType. - -************************************************************************ -* * - Error from the canonicaliser - These ones are called *during* constraint simplification -* * -************************************************************************ -} -solverDepthErrorTcS :: CtLoc -> TcType -> TcM a -solverDepthErrorTcS loc ty - = setCtLocM loc $ - do { ty <- zonkTcType ty - ; env0 <- tcInitTidyEnv - ; let tidy_env = tidyFreeTyCoVars env0 (tyCoVarsOfTypeList ty) - tidy_ty = tidyType tidy_env ty - msg = TcRnUnknownMessage $ mkPlainError noHints $ - vcat [ text "Reduction stack overflow; size =" <+> ppr depth - , hang (text "When simplifying the following type:") - 2 (ppr tidy_ty) - , note ] - ; failWithTcM (tidy_env, msg) } - where - depth = ctLocDepth loc - note = vcat - [ text "Use -freduction-depth=0 to disable this check" - , text "(any upper bound you could choose might fail unpredictably with" - , text " minor updates to GHC, so disabling the check is recommended if" - , text " you're sure that type checking should terminate)" ] - {-********************************************************************** * * GHC API helper functions |