[Git][ghc/ghc][wip/derived-refactor] 2 commits: Don't produce Deriveds
Richard Eisenberg
gitlab at gitlab.haskell.org
Fri Jun 19 22:54:58 UTC 2020
Richard Eisenberg pushed to branch wip/derived-refactor at Glasgow Haskell Compiler / GHC
Commits:
3e5514ec by Richard Eisenberg at 2020-06-19T11:54:15+01:00
Don't produce Deriveds
- - - - -
f5433f0b by Richard Eisenberg at 2020-06-19T23:54:41+01:00
Checkpoint. Want more CI.
- - - - -
23 changed files:
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Canonical.hs
- compiler/GHC/Tc/Solver/Interact.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- testsuite/tests/indexed-types/should_fail/SimpleFail16.stderr
- testsuite/tests/indexed-types/should_fail/T13784.stderr
- testsuite/tests/partial-sigs/should_compile/T10403.stderr
- testsuite/tests/polykinds/T11142.stderr
- testsuite/tests/polykinds/T12444.stderr
- testsuite/tests/polykinds/T14172.stderr
- + testsuite/tests/typecheck/should_compile/FunDepOrigin1.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_compile/hole_constraints.stderr
- + testsuite/tests/typecheck/should_fail/FunDepOrigin1b.hs
- + testsuite/tests/typecheck/should_fail/FunDepOrigin1b.stderr
- testsuite/tests/typecheck/should_fail/T14325.stderr
- testsuite/tests/typecheck/should_fail/T15767.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_fail/tcfail204.stderr
Changes:
=====================================
compiler/GHC/Tc/Errors.hs
=====================================
@@ -22,7 +22,8 @@ import GHC.Tc.Utils.Monad
import GHC.Tc.Types.Constraint
import GHC.Core.Predicate
import GHC.Tc.Utils.TcMType
-import GHC.Tc.Utils.Unify( occCheckForErrors, MetaTyVarUpdateResult(..), swapOverTyVars )
+import GHC.Tc.Utils.Unify( occCheckForErrors, MetaTyVarUpdateResult(..), swapOverTyVars
+ , canSolveByUnification )
import GHC.Tc.Utils.Env( tcInitTidyEnv )
import GHC.Tc.Utils.TcType
import GHC.Tc.Types.Origin
@@ -45,11 +46,12 @@ import GHC.Tc.Types.EvTerm
import GHC.Hs.Binds ( PatSynBind(..) )
import GHC.Types.Name
import GHC.Types.Name.Reader ( lookupGRE_Name, GlobalRdrEnv, mkRdrUnqual )
-import GHC.Builtin.Names ( typeableClassName )
+import GHC.Builtin.Names
import GHC.Types.Id
import GHC.Types.Var
import GHC.Types.Var.Set
import GHC.Types.Var.Env
+import GHC.Types.Unique.Set
import GHC.Types.Name.Set
import GHC.Data.Bag
import GHC.Utils.Error ( ErrMsg, errDoc, pprLocErrMsg )
@@ -234,7 +236,8 @@ report_unsolved type_errors expr_holes
-- See #15539 and c.f. setting ic_status
-- in GHC.Tc.Solver.setImplicationStatus
, cec_warn_redundant = warn_redundant
- , cec_binds = binds_var }
+ , cec_binds = binds_var
+ , cec_already_reported = emptyUniqSet }
; tc_lvl <- getTcLevel
; reportWanteds err_ctxt tc_lvl wanted
@@ -342,6 +345,8 @@ data ReportErrCtxt
-- so create bindings if need be, but
-- don't issue any more errors/warnings
-- See Note [Suppressing error messages]
+ , cec_already_reported :: UniqSet Unique
+ -- See Note [Avoid reporting duplicates]
}
instance Outputable ReportErrCtxt where
@@ -535,6 +540,8 @@ data ErrorItem
, ei_evdest :: Maybe TcEvDest -- for Wanteds, where to put evidence
, ei_flavour :: CtFlavour
, ei_loc :: CtLoc
+ , ei_unique :: Unique
+ -- for deduplication; see Note [Avoid reporting duplicates]
}
instance Outputable ErrorItem where
@@ -553,17 +560,19 @@ mkErrorItem ct = EI { ei_pred = tyvar_first pred
, ei_type = ctPred ct
, ei_evdest = m_evdest
, ei_flavour = ctFlavour ct
- , ei_loc = loc }
+ , ei_loc = loc
+ , ei_unique = unique }
where
loc = ctLoc ct
- (m_evdest, pred)
+ (m_evdest, pred, unique)
| CtWanted { ctev_dest = dest
, ctev_report_as = report_as
, ctev_pred = ct_pred } <- ctEvidence ct
- = (Just dest, ctPredToReport ct_pred report_as)
+ , (u, p) <- ctPredToReport dest ct_pred report_as
+ = (Just dest, p, u)
| otherwise
- = (Nothing, ctPred ct)
+ = (Nothing, ctPred ct, ctUnique ct)
-- We reorient any tyvar equalities to put the tyvar first; this
-- allows fewer cases when choosing how to treat errors. Forgetting
@@ -636,13 +645,17 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics
; reportHoles tidy_items ctxt_for_insols other_holes
-- holes never suppress
- ; (ctxt1, items1) <- tryReporters ctxt_for_insols report1 tidy_items
+ -- See Note [Suppressing confusing errors]
+ ; dflags <- getDynFlags
+ ; let (suppressed_items, items0) = partition (suppress dflags) 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 items1
+ ; let ctxt2 = ctxt1 { cec_suppress = cec_suppress ctxt || cec_suppress ctxt1 }
+ ; (ctxt3, leftovers) <- tryReporters ctxt2 report2 items1
; MASSERT2( null leftovers, ppr leftovers )
-- All the Derived ones have been filtered out of simples
@@ -650,49 +663,79 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics
-- to report unsolved Derived goals as errors
-- See Note [Do not report derived but soluble errors]
- ; mapBagM_ (reportImplic ctxt2) implics }
+ ; let inner_ctxt = ctxt2 { cec_already_reported = cec_already_reported ctxt3 }
-- 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)
+
+ ; mapBagM_ (reportImplic inner_ctxt) implics
+
+ -- 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
+ ; MASSERT2( null more_leftovers, ppr more_leftovers ) } }
where
env = cec_tidy ctxt
tidy_items = bagToList (mapBag (mkErrorItem . tidyCt env) simples)
tidy_holes = bagToList (mapBag (tidyHole env) holes)
+ -- See Note [Suppressing confusing errors]
+ suppress :: DynFlags -> ErrorItem -> Bool
+ suppress dflags item@(EI { ei_pred = pred })
+ | badCoercionHole pred
+ = True
+
+ -- See Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Canonical;
+ -- point (4c)
+ | Just (_, ty1, ty2) <- getEqPredTys_maybe pred
+ , Just tv1 <- getTyVar_maybe ty1
+ , canSolveByUnification tc_lvl tv1 ty2
+ , MTVU_OK () <- occCheckForErrors dflags tv1 ty2
+ -- this last line checks for e.g. impredicative situations; we don't
+ -- want to suppress an error if the problem is impredicativity
+ = True
+
+ | is_ww_fundep_item item
+ = True
+
+ | 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.insolubleCt) 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_non_blocked_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)
, ("Irreds", is_irred, False, mkGroupReporter mkIrredErr)
, ("Dicts", is_dict, False, mkGroupReporter mkDictErr) ]
- -- also checks to make sure the constraint isn't BlockedCIS
- -- See GHC.Tc.Solver.Canonical Note [Equalities with incompatible kinds], (4)
- unblocked :: (ErrorItem -> Pred -> Bool) -> ErrorItem -> Pred -> Bool
- unblocked checker item pred
- | badCoercionHole (ei_pred item) = False
- | otherwise = checker item pred
+ -- report3: suppressed errors should be reported as categorized by either report1
+ -- or report2.
+ report3 = [ ("wanted/wanted fundeps", is_ww_fundep, True, mkGroupReporter mkEqErr)
+ , ("Blocked eqs", is_equality, True, mkGroupReporter mkBlockedEqErr) ]
-- rigid_nom_eq, rigid_nom_tv_eq,
is_dict, is_equality, is_ip, is_irred :: ErrorItem -> Pred -> Bool
@@ -723,15 +766,6 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics
is_homo_equality _ (EqPred _ ty1 ty2) = tcTypeKind ty1 `tcEqType` tcTypeKind ty2
is_homo_equality _ _ = False
- -- we've already checked homogeneous equalities, so this one must be hetero
- is_non_blocked_equality _ (EqPred _ ty1 _)
- | Just tv1 <- getTyVar_maybe ty1
- , isTouchableMetaTyVar tc_lvl tv1
- = False -- See Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Canonical,
- -- wrinkle (4c).
- is_non_blocked_equality _ (EqPred {}) = True
- is_non_blocked_equality _ _ = False
-
is_equality _ (EqPred {}) = True
is_equality _ _ = False
@@ -744,6 +778,10 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics
is_irred _ (IrredPred {}) = True
is_irred _ _ = False
+ -- See situation (2) of Note [Suppress 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)
= ("insoluble1a", is_given_eq, True, mkGivenErrorReporter)
@@ -785,6 +823,75 @@ 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:
+
+1) Errors which are blocked by a coercion hole. This is described
+ in point (4) of Note [Equalities with incompatible kinds] in Tc.Solver.Canonical.
+
+2) 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 [Avoid reporting duplicates]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+It would be embarrassing to report two identical errors to the user. We
+avoid doing so by logging a Unique associated with every error, in the
+cec_already_reported field of a ReportErrCtxt. These Uniques come from:
+
+ * For Givens: it's the Unique on the ctev_evar storing the Given evidence.
+
+ * For Wanteds with CtReportAsSame: it's the Unique associated with the
+ TcEvDest.
+
+ * For Wanteds with CtReportAsOther: it's the Unique in the CtReportAsOther,
+ which in turn comes from the TcEvDest of the originating Wanted, as placed
+ there in updateReportAs.
+
+We still must be sure to process all errors, including duplicates, because
+of the possibility of -fdefer-type-errors; each duplicate may carry its own
+evidence (in the case of several constraints sharing the same CtReportAsOther).
+But when an error appears already in the cec_already_reported, we suppress
+the user-visible error report.
+
+-}
+
+
+
--------------------------------------------
-- Reporters
--------------------------------------------
@@ -822,7 +929,7 @@ reportHoles tidy_items ctxt
mkUserTypeErrorReporter :: Reporter
mkUserTypeErrorReporter ctxt
= mapM_ $ \item -> do { err <- mkUserTypeError ctxt item
- ; maybeReportError ctxt err
+ ; maybeReportError ctxt [item] err
; addDeferredBinding ctxt err item }
mkUserTypeError :: ReportErrCtxt -> ErrorItem -> TcM ErrMsg
@@ -910,11 +1017,6 @@ mkGroupReporter :: (ReportErrCtxt -> [ErrorItem] -> TcM ErrMsg)
mkGroupReporter mk_err ctxt items
= mapM_ (reportGroup mk_err ctxt . toList) (equivClasses cmp_loc items)
--- Like mkGroupReporter, but doesn't actually print error messages
-mkSuppressReporter :: (ReportErrCtxt -> [ErrorItem] -> TcM ErrMsg) -> Reporter
-mkSuppressReporter mk_err ctxt items
- = mapM_ (suppressGroup mk_err ctxt . toList) (equivClasses cmp_loc items)
-
eq_lhs_type :: ErrorItem -> ErrorItem -> Bool
eq_lhs_type item1 item2
= case (classifyPredType (ei_pred item1), classifyPredType (ei_pred item2)) of
@@ -933,7 +1035,7 @@ reportGroup mk_err ctxt items =
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 err
+ ; maybeReportError ctxt items err
-- But see Note [Always warn with -fdefer-type-errors]
; traceTc "reportGroup" (ppr items)
; mapM_ (addDeferredBinding ctxt err) items }
@@ -942,14 +1044,6 @@ reportGroup mk_err ctxt items =
-- but that's hard to know for sure, and if we don't
-- abort, we need bindings for all (e.g. #12156)
--- like reportGroup, but does not actually report messages. It still adds
--- -fdefer-type-errors bindings, though.
-suppressGroup :: (ReportErrCtxt -> [ErrorItem] -> TcM ErrMsg) -> Reporter
-suppressGroup mk_err ctxt items
- = do { err <- mk_err ctxt items
- ; traceTc "Suppressing errors for" (ppr items)
- ; mapM_ (addDeferredBinding ctxt err) items }
-
maybeReportHoleError :: ReportErrCtxt -> Hole -> ErrMsg -> TcM ()
maybeReportHoleError ctxt hole err
| isOutOfScopeHole hole
@@ -989,12 +1083,19 @@ maybeReportHoleError ctxt hole@(Hole { hole_sort = ExprHole _ }) err
HoleWarn -> reportWarning (Reason Opt_WarnTypedHoles) err
HoleDefer -> return ()
-maybeReportError :: ReportErrCtxt -> ErrMsg -> TcM ()
+maybeReportError :: ReportErrCtxt -> [ErrorItem] -> ErrMsg -> TcM ()
-- Report the error and/or make a deferred binding for it
-maybeReportError ctxt err
+maybeReportError ctxt items err
| cec_suppress ctxt -- Some worse error has occurred;
= return () -- so suppress this error/warning
+ | any ((`elementOfUniqSet` cec_already_reported ctxt) . ei_unique) items
+ = return ()
+ -- suppress the group if any have been reported. Ideally, we'd like
+ -- to suppress exactly those that have been reported, but this is
+ -- awkward, and it's more embarrassing to report the same error
+ -- twice than to suppress too eagerly
+
| otherwise
= case cec_defer_type_errors ctxt of
TypeDefer -> return ()
@@ -1074,9 +1175,15 @@ tryReporter ctxt (str, keep_me, suppress_after, reporter) 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_these = cec_suppress ctxt
+ suppress_now = not no_errs && suppress_after
-- See Note [Suppressing error messages]
- ctxt' = ctxt { cec_suppress = suppress_now || cec_suppress ctxt }
+ already_reported = cec_already_reported ctxt
+ already_reported'
+ | suppress_these = already_reported
+ | otherwise = addListToUniqSet already_reported (map ei_unique yeses)
+ ctxt' = ctxt { cec_suppress = suppress_now || suppress_these
+ , cec_already_reported = already_reported' }
; traceTc "tryReporter end }" (text str <+> ppr (cec_suppress ctxt) <+> ppr suppress_after)
; return (ctxt', nos) }
where
@@ -1364,7 +1471,7 @@ validHoleFits :: ReportErrCtxt -- The context we're in, i.e. the
-- with a possibly updated
-- tidy environment, and
-- the message.
-validHoleFits ctxt@(CEC {cec_encl = implics
+validHoleFits ctxt@(CEC { cec_encl = implics
, cec_tidy = lcl_env}) simps hole
= do { (tidy_env, msg) <- findValidHoleFits lcl_env implics (map mk_wanted simps) hole
; return (ctxt {cec_tidy = tidy_env}, msg) }
@@ -1632,7 +1739,7 @@ reportEqErr ctxt report item oriented ty1 ty2
mkTyVarEqErr, mkTyVarEqErr'
:: DynFlags -> ReportErrCtxt -> Report -> ErrorItem
- -> Maybe SwapFlag -> TcTyVar -> TcType -> TcM ErrMsg
+ -> Maybe SwapFlag -> TcTyVar -> TcType -> TcM ErrMsg
-- tv1 and ty2 are already tidied
mkTyVarEqErr dflags ctxt report item oriented tv1 ty2
= do { traceTc "mkTyVarEqErr" (ppr item $$ ppr tv1 $$ ppr ty2)
=====================================
compiler/GHC/Tc/Solver.hs
=====================================
@@ -1513,7 +1513,9 @@ solveWanteds wc@(WC { wc_simple = simples, wc_impl = implics, wc_holes = holes }
; solved_wc <- simpl_loop 0 (solverIterations dflags) floated_eqs
(wc1 { wc_impl = implics2 })
- ; let final_wc = solved_wc { wc_holes = holes }
+ ; holes' <- simplifyHoles holes
+ ; let final_wc = solved_wc { wc_holes = holes' }
+
; ev_binds_var <- getTcEvBindsVar
; bb <- TcS.getTcEvBindsMap ev_binds_var
; traceTcS "solveWanteds }" $
@@ -1880,6 +1882,15 @@ neededEvVars implic@(Implic { ic_given = givens
| is_given = needs -- Add the rhs vars of the Wanted bindings only
| otherwise = evVarsOfTerm rhs `unionVarSet` needs
+-------------------------------------------------
+simplifyHoles :: Bag Hole -> TcS (Bag Hole)
+simplifyHoles = mapBagM simpl_hole
+ where
+ simpl_hole :: Hole -> TcS Hole
+ simpl_hole h@(Hole { hole_ty = ty, hole_loc = loc })
+ = do { ty' <- flattenType loc ty
+ ; return (h { hole_ty = ty' }) }
+
{- Note [Delete dead Given evidence bindings]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As a result of superclass expansion, we speculatively
=====================================
compiler/GHC/Tc/Solver/Canonical.hs
=====================================
@@ -1894,7 +1894,7 @@ canCFunEqCan ev fn tys fsk
flav = ctEvFlavour ev
- report_as = updateReportAs wrw (ctEvPred ev) (ctEvReportAs ev)
+ report_as = updateReportAs wrw (ctEvUnique ev) (ctEvPred ev) (ctEvReportAs ev)
; (ev', fsk')
<- if isTcReflexiveCo kind_co -- See Note [canCFunEqCan]
then do { traceTcS "canCFunEqCan: refl" (ppr new_lhs)
@@ -2380,7 +2380,7 @@ rewriteEvidence wrw ev@(CtWanted { ctev_pred = old_pred
Fresh new_ev -> continueWith new_ev
Cached _ -> stopWith ev "Cached wanted" }
where
- report_as' = updateReportAs wrw old_pred report_as
+ report_as' = updateReportAs wrw (tcEvDestUnique dest) old_pred report_as
rewriteEqEvidence :: WRWFlag -- YesWRW <=> a wanted rewrote a wanted
@@ -2425,7 +2425,7 @@ rewriteEqEvidence wrw old_ev swapped nlhs nrhs lhs_co rhs_co
, ctev_dest = dest
, ctev_nosh = si
, ctev_report_as = report_as } <- old_ev
- , let report_as' = updateReportAs wrw old_pred report_as
+ , let report_as' = updateReportAs wrw (tcEvDestUnique dest) old_pred report_as
= case dest of
HoleDest hole ->
do { (new_ev, hole_co) <- newWantedEq_SI (ch_blocker hole) si loc' report_as'
=====================================
compiler/GHC/Tc/Solver/Interact.hs
=====================================
@@ -1587,7 +1587,7 @@ inertsCanDischarge inerts tv rhs fr
keep_deriv ev_i
| Wanted WOnly <- ctEvFlavour ev_i -- inert is [W]
, (Wanted WDeriv, _) <- fr -- work item is [WD]
- = True -- Keep a derived version of the work item
+ = False -- "RAE" True -- Keep a derived version of the work item
| otherwise
= False -- Work item is fully discharged
=====================================
compiler/GHC/Tc/Solver/Monad.hs
=====================================
@@ -1416,17 +1416,17 @@ maybeEmitShadow :: InertCans -> Ct -> TcS Ct
-- See Note [The improvement story and derived shadows]
maybeEmitShadow ics ct
| let ev = ctEvidence ct
- , CtWanted { ctev_pred = pred, ctev_loc = loc
- , ctev_nosh = WDeriv } <- ev
+ , CtWanted { {- "RAE" ctev_pred = pred, ctev_loc = loc
+ , -} ctev_nosh = WDeriv } <- ev
, shouldSplitWD (inert_eqs ics) ct
- = do { traceTcS "Emit derived shadow" (ppr ct)
- ; let derived_ev = CtDerived { ctev_pred = pred
+ = do { traceTcS "RAE: NO: Emit derived shadow" (ppr ct)
+ {- ; let derived_ev = CtDerived { ctev_pred = pred
, ctev_loc = loc }
shadow_ct = ct { cc_ev = derived_ev }
-- Te shadow constraint keeps the canonical shape.
-- This just saves work, but is sometimes important;
-- see Note [Keep CDictCan shadows as CDictCan]
- ; emitWork [shadow_ct]
+ ; emitWork [shadow_ct] -}
; let ev' = ev { ctev_nosh = WOnly }
ct' = ct { cc_ev = ev' }
@@ -3594,9 +3594,9 @@ emitNewDerivedEq loc role ty1 ty2
-- See Note [Prioritise equalities] (Avoiding fundep iteration)
newDerivedNC :: CtLoc -> TcPredType -> TcS CtEvidence
-newDerivedNC loc pred
+newDerivedNC = newWantedNC {- "RAE"
= do { -- checkReductionDepth loc pred
- ; return (CtDerived { ctev_pred = pred, ctev_loc = loc }) }
+ ; return (CtDerived { ctev_pred = pred, ctev_loc = loc }) } -}
-- --------- Check done in GHC.Tc.Solver.Interact.selectNewWorkItem???? ---------
-- | Checks if the depth of the given location is too much. Fails if
=====================================
compiler/GHC/Tc/Types/Constraint.hs
=====================================
@@ -22,7 +22,7 @@ module GHC.Tc.Types.Constraint (
mkIrredCt,
ctEvPred, ctEvLoc, ctEvOrigin, ctEvEqRel,
ctEvExpr, ctEvTerm, ctEvCoercion, ctEvEvId,
- ctReportAs,
+ ctReportAs, ctUnique,
tyCoVarsOfCt, tyCoVarsOfCts,
tyCoVarsOfCtList, tyCoVarsOfCtsList,
@@ -51,7 +51,7 @@ module GHC.Tc.Types.Constraint (
isWanted, isGiven, isDerived, isGivenOrWDeriv,
ctEvRole, setCtEvLoc, arisesFromGivens,
tyCoVarsOfCtEvList, tyCoVarsOfCtEv, tyCoVarsOfCtEvsList,
- ctEvReportAs,
+ ctEvReportAs, ctEvUnique, tcEvDestUnique,
CtReportAs(..), ctPredToReport, substCtReportAs,
updateReportAs, WRWFlag(..), wantedRewriteWanted,
@@ -97,6 +97,7 @@ import GHC.Utils.FV
import GHC.Types.Var.Set
import GHC.Driver.Session
import GHC.Types.Basic
+import GHC.Types.Unique
import GHC.Utils.Outputable
import GHC.Types.SrcLoc
@@ -467,6 +468,10 @@ ctReportAs ct = case ctEvidence ct of
CtWanted { ctev_report_as = report_as } -> report_as
_ -> pprPanic "ctReportAs" (ppr ct)
+-- | Extract a Unique from a 'Ct'
+ctUnique :: Ct -> Unique
+ctUnique = ctEvUnique . ctEvidence
+
instance Outputable Ct where
ppr ct = ppr (ctEvidence ct) <+> parens pp_sort
where
@@ -1024,10 +1029,11 @@ insolubleCt :: Ct -> Bool
-- Definitely insoluble, in particular /excluding/ type-hole constraints
-- Namely: a) an equality constraint
-- b) that is insoluble
--- c) and does not arise from a Given
+-- c) and does not arise from a Given or a Wanted/Wanted fundep interaction
insolubleCt ct
| not (insolubleEqCt ct) = False
| arisesFromGivens (ctFlavour ct) (ctLoc ct) = False -- See Note [Given insolubles]
+ | isWantedWantedFunDepOrigin (ctOrigin ct) = False
| otherwise = True
insolubleEqCt :: Ct -> Bool
@@ -1410,8 +1416,9 @@ data TcEvDest
-- | What should we report to the user when reporting this Wanted?
-- See Note [Wanteds rewrite Wanteds]
data CtReportAs
- = CtReportAsSame -- just report the predicate in the Ct
- | CtReportAsOther TcPredType -- report this other type
+ = CtReportAsSame -- just report the predicate in the Ct
+ | CtReportAsOther Unique TcPredType -- report this other type
+ -- See GHC.Tc.Errors Note [Avoid reporting duplicates] about the Unique
-- | Did a wanted rewrite a wanted?
-- See Note [Wanteds rewrite Wanteds]
@@ -1488,12 +1495,21 @@ ctEvEvId (CtWanted { ctev_dest = HoleDest h }) = coHoleCoVar h
ctEvEvId (CtGiven { ctev_evar = ev }) = ev
ctEvEvId ctev@(CtDerived {}) = pprPanic "ctEvId:" (ppr ctev)
+ctEvUnique :: CtEvidence -> Unique
+ctEvUnique (CtGiven { ctev_evar = ev }) = varUnique ev
+ctEvUnique (CtWanted { ctev_dest = dest }) = tcEvDestUnique dest
+ctEvUnique (CtDerived {}) = mkUniqueGrimily 0 -- "RAE" this is evil.
+
+tcEvDestUnique :: TcEvDest -> Unique
+tcEvDestUnique (EvVarDest ev_var) = varUnique ev_var
+tcEvDestUnique (HoleDest co_hole) = varUnique (coHoleCoVar co_hole)
+
setCtEvLoc :: CtEvidence -> CtLoc -> CtEvidence
setCtEvLoc ctev loc = ctev { ctev_loc = loc }
arisesFromGivens :: CtFlavour -> CtLoc -> Bool
arisesFromGivens Given _ = True
-arisesFromGivens (Wanted {}) _ = False
+arisesFromGivens (Wanted {}) loc = isGivenLoc loc -- could be a Given FunDep
arisesFromGivens Derived loc = isGivenLoc loc
-- | Return a 'CtReportAs' from a 'CtEvidence'. Returns
@@ -1504,31 +1520,31 @@ ctEvReportAs _ = CtReportAsSame
-- | Given the pred in a CtWanted and its 'CtReportAs', get
-- the pred to report. See Note [Wanteds rewrite Wanteds]
-ctPredToReport :: TcPredType -> CtReportAs -> TcPredType
-ctPredToReport pred CtReportAsSame = pred
-ctPredToReport _ (CtReportAsOther pred) = pred
+ctPredToReport :: TcEvDest -> TcPredType -> CtReportAs -> (Unique, TcPredType)
+ctPredToReport dest pred CtReportAsSame = (tcEvDestUnique dest, pred)
+ctPredToReport _ _ (CtReportAsOther u pred) = (u, pred)
-- | Substitute in a 'CtReportAs'
substCtReportAs :: TCvSubst -> CtReportAs -> CtReportAs
-substCtReportAs _ CtReportAsSame = CtReportAsSame
-substCtReportAs subst (CtReportAsOther pred) = CtReportAsOther (substTy subst pred)
+substCtReportAs _ CtReportAsSame = CtReportAsSame
+substCtReportAs subst (CtReportAsOther u pred) = CtReportAsOther u (substTy subst pred)
-- | After rewriting a Wanted, update the 'CtReportAs' for the new Wanted.
-- If the old CtReportAs is CtReportAsSame and a wanted rewrote a wanted,
-- record the old pred as the new CtReportAs.
-- See Note [Wanteds rewrite Wanteds]
-updateReportAs :: WRWFlag -> TcPredType -- _old_ pred type
+updateReportAs :: WRWFlag -> Unique -> TcPredType -- _old_ pred type
-> CtReportAs -> CtReportAs
-updateReportAs YesWRW old_pred CtReportAsSame = CtReportAsOther old_pred
-updateReportAs _ _ report_as = report_as
+updateReportAs YesWRW unique old_pred CtReportAsSame = CtReportAsOther unique old_pred
+updateReportAs _ _ _ report_as = report_as
instance Outputable TcEvDest where
ppr (HoleDest h) = text "hole" <> ppr h
ppr (EvVarDest ev) = ppr ev
instance Outputable CtReportAs where
- ppr CtReportAsSame = text "CtReportAsSame"
- ppr (CtReportAsOther pred) = parens $ text "CtReportAsOther" <+> ppr pred
+ ppr CtReportAsSame = text "CtReportAsSame"
+ ppr (CtReportAsOther u pred) = parens $ text "CtReportAsOther" <+> ppr u <+> ppr pred
instance Outputable WRWFlag where
ppr NoWRW = text "NoWRW"
@@ -1676,6 +1692,9 @@ predicate with respect to any givens (only). That rewritten predicate
is reported to the user. Simple, and it costs time only when errors
are being reported.
+"RAE": Givens don't rewrite CtReportAs. But that's OK because givens
+get there first.
+
Note [Deriveds do rewrite Deriveds]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
However we DO allow Deriveds to rewrite Deriveds, because that's how
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -16,7 +16,7 @@ module GHC.Tc.Types.Origin (
-- CtOrigin
CtOrigin(..), exprCtOrigin, lexprCtOrigin, matchesCtOrigin, grhssCtOrigin,
isVisibleOrigin, toInvisibleOrigin,
- pprCtOrigin, isGivenOrigin
+ pprCtOrigin, isGivenOrigin, isWantedWantedFunDepOrigin
) where
@@ -462,6 +462,12 @@ isGivenOrigin (FunDepOrigin1 _ o1 _ _ o2 _) = isGivenOrigin o1 && isGivenOrigin
isGivenOrigin (FunDepOrigin2 _ o1 _ _) = isGivenOrigin o1
isGivenOrigin _ = False
+-- See Note [Suppressing confusing errors] in GHC.Tc.Errors
+isWantedWantedFunDepOrigin :: CtOrigin -> Bool
+isWantedWantedFunDepOrigin (FunDepOrigin1 _ orig1 _ _ orig2 _)
+ = not (isGivenOrigin orig1) && not (isGivenOrigin orig2)
+isWantedWantedFunDepOrigin _ = False
+
instance Outputable CtOrigin where
ppr = pprCtOrigin
=====================================
compiler/GHC/Tc/Utils/TcMType.hs
=====================================
@@ -242,13 +242,7 @@ emitDerivedEqs origin pairs
| null pairs
= return ()
| otherwise
- = do { loc <- getCtLocM origin Nothing
- ; emitSimples (listToBag (map (mk_one loc) pairs)) }
- where
- mk_one loc (ty1, ty2)
- = mkNonCanonical $
- CtDerived { ctev_pred = mkPrimEqPred ty1 ty2
- , ctev_loc = loc }
+ = mapM_ (uncurry (emitWantedEq origin TypeLevel Nominal)) pairs
-- | Emits a new equality constraint
emitWantedEq :: CtOrigin -> TypeOrKind -> Role -> TcType -> TcType -> TcM Coercion
@@ -2091,8 +2085,8 @@ zonkCtEvidence ctev@(CtWanted { ctev_pred = pred
-- necessary in simplifyInfer
HoleDest h -> HoleDest h
; report_as' <- case report_as of
- CtReportAsSame -> return CtReportAsSame
- CtReportAsOther report_pred -> CtReportAsOther <$> zonkTcType report_pred
+ CtReportAsSame -> return CtReportAsSame
+ CtReportAsOther u report_pred -> CtReportAsOther u <$> zonkTcType report_pred
; return (ctev { ctev_pred = pred', ctev_dest = dest'
, ctev_report_as = report_as' }) }
zonkCtEvidence ctev@(CtDerived { ctev_pred = pred })
@@ -2285,8 +2279,8 @@ tidyCtEvidence :: TidyEnv -> CtEvidence -> CtEvidence
tidyCtEvidence env ctev@(CtWanted { ctev_pred = pred, ctev_report_as = report_as })
= ctev { ctev_pred = tidyType env pred, ctev_report_as = tidy_report_as report_as }
where tidy_report_as CtReportAsSame = CtReportAsSame
- tidy_report_as (CtReportAsOther report_pred)
- = CtReportAsOther (tidyType env report_pred)
+ tidy_report_as (CtReportAsOther u report_pred)
+ = CtReportAsOther u (tidyType env report_pred)
tidyCtEvidence env ctev = ctev { ctev_pred = tidyType env ty }
where
ty = ctev_pred ctev
=====================================
testsuite/tests/indexed-types/should_fail/SimpleFail16.stderr
=====================================
@@ -1,9 +1,9 @@
SimpleFail16.hs:10:12: error:
- Couldn't match expected type ‘p0 a0’ with actual type ‘F ()’
- The type variables ‘p0’, ‘a0’ are ambiguous
- In the first argument of ‘foo’, namely ‘(undefined :: F ())’
- In the expression: foo (undefined :: F ())
- In an equation for ‘bar’: bar = foo (undefined :: F ())
- Relevant bindings include
- bar :: p0 a0 (bound at SimpleFail16.hs:10:1)
+ • Couldn't match expected type ‘F ()’ with actual type ‘p0 a0’
+ The type variables ‘p0’, ‘a0’ are ambiguous
+ • In the first argument of ‘foo’, namely ‘(undefined :: F ())’
+ In the expression: foo (undefined :: F ())
+ In an equation for ‘bar’: bar = foo (undefined :: F ())
+ • Relevant bindings include
+ bar :: p0 a0 (bound at SimpleFail16.hs:10:1)
=====================================
testsuite/tests/indexed-types/should_fail/T13784.stderr
=====================================
@@ -1,6 +1,19 @@
T13784.hs:29:28: error:
- • Couldn't match type ‘as’ with ‘a : Divide a as’
+ • Occurs check: cannot construct the infinite type:
+ t0 ~ Divide a (a : t0)
+ The type variable ‘t0’ is ambiguous
+ Expected type: Product (Divide a (a : as))
+ Actual type: Product as1
+ • In the expression: as
+ In the expression: (a, as)
+ In an equation for ‘divide’: divide (a :* as) = (a, as)
+ • Relevant bindings include
+ divide :: Product (a : as) -> (a, Product (Divide a (a : as)))
+ (bound at T13784.hs:29:5)
+
+T13784.hs:29:28: error:
+ • Couldn't match type ‘as’ with ‘a : a : a : t0’
‘as’ is a rigid type variable bound by
the instance declaration
at T13784.hs:25:10-30
=====================================
testsuite/tests/partial-sigs/should_compile/T10403.stderr
=====================================
@@ -39,16 +39,17 @@ T10403.hs:22:15: warning: [-Wdeferred-type-errors (in -Wdefault)]
In the expression: H . fmap (const ())
In the expression: (H . fmap (const ())) (fmap f b)
-T10403.hs:28:8: warning: [-Wdeferred-type-errors (in -Wdefault)]
+T10403.hs:28:20: warning: [-Wdeferred-type-errors (in -Wdefault)]
• Couldn't match type ‘f0’ with ‘B t’
because type variable ‘t’ would escape its scope
This (rigid, skolem) type variable is bound by
the type signature for:
app2 :: forall t. H (B t)
at T10403.hs:27:1-15
- Expected type: H (B t)
- Actual type: H f0
- • In the expression: h2 (H . I) (B ())
+ Expected type: f0 ()
+ Actual type: B t ()
+ • In the second argument of ‘h2’, namely ‘(B ())’
+ In the expression: h2 (H . I) (B ())
In an equation for ‘app2’: app2 = h2 (H . I) (B ())
• Relevant bindings include
app2 :: H (B t) (bound at T10403.hs:28:1)
=====================================
testsuite/tests/polykinds/T11142.stderr
=====================================
@@ -4,14 +4,3 @@ T11142.hs:9:49: error:
• In the second argument of ‘SameKind’, namely ‘b’
In the type signature:
foo :: forall b. (forall k (a :: k). SameKind a b) -> ()
-
-T11142.hs:10:7: error:
- • Cannot instantiate unification variable ‘a0’
- with a type involving polytypes:
- (forall k1 (a :: k1). SameKind a b) -> ()
- GHC doesn't yet support impredicative polymorphism
- • In the expression: undefined
- In an equation for ‘foo’: foo = undefined
- • Relevant bindings include
- foo :: (forall k1 (a :: k1). SameKind a b) -> ()
- (bound at T11142.hs:10:1)
=====================================
testsuite/tests/polykinds/T12444.stderr
=====================================
@@ -1,6 +1,6 @@
T12444.hs:19:11: error:
- • Couldn't match type ‘b’ with ‘'Succ (c :+: b)’
+ • Couldn't match type ‘b’ with ‘'Succ t0’
‘b’ is a rigid type variable bound by
the type signature for:
foo :: forall (c :: Nat) (b :: Nat).
=====================================
testsuite/tests/polykinds/T14172.stderr
=====================================
@@ -11,12 +11,12 @@ T14172.hs:6:46: error:
In the type ‘(a -> f b) -> g a -> f (h _)’
T14172.hs:7:19: error:
- • Occurs check: cannot construct the infinite type: a ~ g'0 a
- Expected type: (f'0 a -> f (f'0 b))
- -> Compose f'0 g'0 a -> f (h a')
- Actual type: (Unwrapped (Compose f'0 g'0 a)
- -> f (Unwrapped (h a')))
- -> Compose f'0 g'0 a -> f (h a')
+ • Couldn't match type ‘h’ with ‘Compose f'0 g'0’
+ arising from a use of ‘_Wrapping’
+ ‘h’ is a rigid type variable bound by
+ the inferred type of
+ traverseCompose :: (a -> f b) -> g a -> f (h a')
+ at T14172.hs:6:1-47
• In the first argument of ‘(.)’, namely ‘_Wrapping Compose’
In the expression: _Wrapping Compose . traverse
In an equation for ‘traverseCompose’:
@@ -24,3 +24,15 @@ T14172.hs:7:19: error:
• Relevant bindings include
traverseCompose :: (a -> f b) -> g a -> f (h a')
(bound at T14172.hs:7:1)
+
+T14172.hs:7:19: error:
+ • Couldn't match type ‘Compose f'0 g'1 a'0 -> f (h a')’
+ with ‘g a -> f (h a')’
+ Expected type: (a -> f b) -> g a -> f (h a')
+ Actual type: (a -> f b) -> Compose f'0 g'1 a'0 -> f (h a')
+ • In the expression: _Wrapping Compose . traverse
+ In an equation for ‘traverseCompose’:
+ traverseCompose = _Wrapping Compose . traverse
+ • Relevant bindings include
+ traverseCompose :: (a -> f b) -> g a -> f (h a')
+ (bound at T14172.hs:7:1)
=====================================
testsuite/tests/typecheck/should_compile/FunDepOrigin1.hs
=====================================
@@ -0,0 +1,12 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts #-}
+
+module FunDepOrigin1 where
+
+class C a b | a -> b where
+ op :: a -> b -> b
+
+foo _ = op True Nothing
+
+bar _ = op False []
+
+-- See Note [Suppressing confusing errors] in GHC.Tc.Errors
=====================================
testsuite/tests/typecheck/should_compile/all.T
=====================================
@@ -705,3 +705,4 @@ test('T18005', normal, compile, [''])
test('T18023', normal, compile, [''])
test('T18036', normal, compile, [''])
test('T18036a', normal, compile, [''])
+test('FunDepOrigin1', normal, compile, [''])
=====================================
testsuite/tests/typecheck/should_compile/hole_constraints.stderr
=====================================
@@ -47,8 +47,8 @@ hole_constraints.hs:16:35: warning: [-Wtyped-holes (in -Wdefault)]
mempty :: forall a. Monoid a => a
hole_constraints.hs:20:19: warning: [-Wtyped-holes (in -Wdefault)]
- • Found hole: _ :: a
- Where: ‘a’ is a rigid type variable bound by
+ • Found hole: _ :: b
+ Where: ‘b’ is a rigid type variable bound by
the type signature for:
castWith :: forall a b. (a :~: b) -> a -> b
at hole_constraints.hs:19:1-29
=====================================
testsuite/tests/typecheck/should_fail/FunDepOrigin1b.hs
=====================================
@@ -0,0 +1,10 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts #-}
+
+module FunDepOrigin1b where
+
+class C a b | a -> b where
+ op :: a -> b -> b
+
+foo _ = (op True Nothing, op False [])
+
+-- See Note [Suppressing confusing errors] in GHC.Tc.Errors
=====================================
testsuite/tests/typecheck/should_fail/FunDepOrigin1b.stderr
=====================================
@@ -0,0 +1,13 @@
+
+FunDepOrigin1b.hs:8:27: error:
+ • Couldn't match type ‘Maybe a’ with ‘[a1]’
+ arising from a functional dependency between constraints:
+ ‘C Bool [a1]’
+ arising from a use of ‘op’ at FunDepOrigin1b.hs:8:27-37
+ ‘C Bool (Maybe a)’
+ arising from a use of ‘op’ at FunDepOrigin1b.hs:8:10-24
+ • In the expression: op False []
+ In the expression: (op True Nothing, op False [])
+ In an equation for ‘foo’: foo _ = (op True Nothing, op False [])
+ • Relevant bindings include
+ foo :: p -> (Maybe a, [a1]) (bound at FunDepOrigin1b.hs:8:1)
=====================================
testsuite/tests/typecheck/should_fail/T14325.stderr
=====================================
@@ -1,9 +1,9 @@
T14325.hs:11:9: error:
- • Could not deduce (C b (f b)) arising from a use of ‘foo’
- from the context: C (f b) b
- bound by the type signature for:
- hm3 :: forall (f :: * -> *) b. C (f b) b => b -> f b
- at T14325.hs:10:1-28
+ • Occurs check: cannot construct the infinite type: b ~ f b
+ arising from a use of ‘foo’
• In the expression: foo x
In an equation for ‘hm3’: hm3 x = foo x
+ • Relevant bindings include
+ x :: b (bound at T14325.hs:11:5)
+ hm3 :: b -> f b (bound at T14325.hs:11:1)
=====================================
testsuite/tests/typecheck/should_fail/T15767.stderr
=====================================
@@ -1,6 +1,6 @@
T15767.hs:7:5: error:
- • No instance for (C () b) arising from a use of ‘x’
+ • No instance for (C () b0) arising from a use of ‘x’
• In the expression: x
In an equation for ‘y’:
y = x
=====================================
testsuite/tests/typecheck/should_fail/all.T
=====================================
@@ -563,3 +563,4 @@ test('T17021', normal, compile_fail, [''])
test('T17021b', normal, compile_fail, [''])
test('T17955', normal, compile_fail, [''])
test('T17173', normal, compile_fail, [''])
+test('FunDepOrigin1b', normal, compile_fail, [''])
=====================================
testsuite/tests/typecheck/should_fail/tcfail204.stderr
=====================================
@@ -5,5 +5,9 @@ tcfail204.hs:10:7: error: [-Wtype-defaults (in -Wall), -Werror=type-defaults]
arising from a use of ‘ceiling’ at tcfail204.hs:10:7-17
(Fractional a0)
arising from the literal ‘6.3’ at tcfail204.hs:10:15-17
+ (Num a0) arising from the literal ‘6.3’ at tcfail204.hs:10:15-17
+ (Real a0) arising from a use of ‘ceiling’ at tcfail204.hs:10:7-17
+ (Ord a0) arising from a use of ‘ceiling’ at tcfail204.hs:10:7-17
+ (Eq a0) arising from a use of ‘ceiling’ at tcfail204.hs:10:7-17
• In the expression: ceiling 6.3
In an equation for ‘foo’: foo = ceiling 6.3
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e091141d11228f719a56681736d5c2d75e760407...f5433f0bc06f65deb96a44b62d47875ec4bc5b38
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e091141d11228f719a56681736d5c2d75e760407...f5433f0bc06f65deb96a44b62d47875ec4bc5b38
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20200619/6954a17f/attachment-0001.html>
More information about the ghc-commits
mailing list