From 48fb3482f8cbc8a4b37161021e846105f980eed4 Mon Sep 17 00:00:00 2001 From: Simon Peyton Jones <simonpj@microsoft.com> Date: Wed, 5 Jun 2019 08:55:17 +0100 Subject: [PATCH] Fix typechecking of partial type signatures Partial type sigs had grown hair. tcHsParialSigType was doing lots of unnecessary work, and tcInstSig was cloning it unnecessarily -- and the result didn't even work: #16728. This patch cleans it all up, described by TcHsType Note [Checking parital type signatures] I basically just deleted code... but very carefully! Some refactoring along the way * Distinguish more explicintly between "anonymous" wildcards "_" and "named" wildcards "_a". I changed the names of a number of functions to make this distinction much more apparent. The patch also revealed that the code in `TcExpr` that implements the special typing rule for `($)` was wrong. It called `getRuntimeRep` in a situation where where was no particular reason to suppose that the thing had kind `TYPE r`. This caused a crash in typecheck/should_run/T10846. The fix was easy, and actually simplifies the code in `TcExpr` quite a bit. Hooray. --- compiler/rename/RnTypes.hs | 7 +- compiler/typecheck/TcBinds.hs | 2 +- compiler/typecheck/TcCanonical.hs | 2 + compiler/typecheck/TcExpr.hs | 31 ++-- compiler/typecheck/TcHsType.hs | 161 ++++++++++-------- compiler/typecheck/TcRnDriver.hs | 4 +- compiler/typecheck/TcRnMonad.hs | 17 +- compiler/typecheck/TcRnTypes.hs | 2 +- compiler/typecheck/TcSigs.hs | 21 +-- compiler/typecheck/TcType.hs | 13 +- .../partial-sigs/should_compile/T16728.hs | 9 + .../partial-sigs/should_compile/T16728.stderr | 9 + .../partial-sigs/should_compile/T16728a.hs | 8 + .../should_compile/T16728a.stderr | 20 +++ .../partial-sigs/should_compile/T16728b.hs | 9 + .../should_compile/T16728b.stderr | 13 ++ .../tests/partial-sigs/should_compile/all.T | 3 + .../partial-sigs/should_fail/T14040a.stderr | 8 +- 18 files changed, 215 insertions(+), 124 deletions(-) create mode 100644 testsuite/tests/partial-sigs/should_compile/T16728.hs create mode 100644 testsuite/tests/partial-sigs/should_compile/T16728.stderr create mode 100644 testsuite/tests/partial-sigs/should_compile/T16728a.hs create mode 100644 testsuite/tests/partial-sigs/should_compile/T16728a.stderr create mode 100644 testsuite/tests/partial-sigs/should_compile/T16728b.hs create mode 100644 testsuite/tests/partial-sigs/should_compile/T16728b.stderr diff --git a/compiler/rename/RnTypes.hs b/compiler/rename/RnTypes.hs index 755ed206f0f5..4b4d519324cd 100644 --- a/compiler/rename/RnTypes.hs +++ b/compiler/rename/RnTypes.hs @@ -693,8 +693,8 @@ checkAnonWildCard env | otherwise = case rtke_what env of RnTypeBody -> Nothing - RnConstraint -> Just constraint_msg RnTopConstraint -> Just constraint_msg + RnConstraint -> Just constraint_msg constraint_msg = hang (notAllowed pprAnonWildCard <+> text "in a constraint") @@ -714,7 +714,10 @@ checkNamedWildCard env name | otherwise = case rtke_what env of RnTypeBody -> Nothing -- Allowed - RnTopConstraint -> Nothing -- Allowed + RnTopConstraint -> Nothing -- Allowed; e.g. + -- f :: (Eq _a) => _a -> Int + -- g :: (_a, _b) => T _a _b -> Int + -- The named tyvars get filled in from elsewhere RnConstraint -> Just constraint_msg constraint_msg = notAllowed (ppr name) <+> text "in a constraint" diff --git a/compiler/typecheck/TcBinds.hs b/compiler/typecheck/TcBinds.hs index c8c1bc06bd00..72748ac76f77 100644 --- a/compiler/typecheck/TcBinds.hs +++ b/compiler/typecheck/TcBinds.hs @@ -1020,7 +1020,7 @@ chooseInferredQuantifiers inferred_theta tau_tvs qtvs ; case tcGetCastedTyVar_maybe wc_var_ty of -- We know that wc_co must have type kind(wc_var) ~ Constraint, as it - -- comes from the checkExpectedKind in TcHsType.tcWildCardOcc. So, to + -- comes from the checkExpectedKind in TcHsType.tcAnonWildCardOcc. So, to -- make the kinds work out, we reverse the cast here. Just (wc_var, wc_co) -> writeMetaTyVar wc_var (ctuple `mkCastTy` mkTcSymCo wc_co) Nothing -> pprPanic "chooseInferredQuantifiers 1" (ppr wc_var_ty) diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs index c296a9eee393..31c9ad9a8968 100644 --- a/compiler/typecheck/TcCanonical.hs +++ b/compiler/typecheck/TcCanonical.hs @@ -1009,6 +1009,8 @@ can_eq_nc_forall ev eq_rel s1 s2 (substTy subst (tyVarKind tv2)) ; let subst' = extendTvSubstAndInScope subst tv2 (mkCastTy (mkTyVarTy skol_tv) kind_co) + -- skol_tv is already in the in-scope set, but the + -- free vars of kind_co are not; hence "...AndInScope" ; (co, wanteds2) <- go skol_tvs subst' bndrs2 ; return ( mkTcForAllCo skol_tv kind_co co , wanteds1 `unionBags` wanteds2 ) } diff --git a/compiler/typecheck/TcExpr.hs b/compiler/typecheck/TcExpr.hs index adaea907670f..891f3ad8c3c5 100644 --- a/compiler/typecheck/TcExpr.hs +++ b/compiler/typecheck/TcExpr.hs @@ -378,42 +378,35 @@ tcExpr expr@(OpApp fix arg1 op arg2) res_ty -- So: arg1_ty = arg2_ty -> op_res_ty -- where arg2_sigma maybe polymorphic; that's the point - ; arg2' <- tcArg op arg2 arg2_sigma 2 + ; arg2' <- tcArg op arg2 arg2_sigma 2 -- Make sure that the argument type has kind '*' -- ($) :: forall (r:RuntimeRep) (a:*) (b:TYPE r). (a->b) -> a -> b -- Eg we do not want to allow (D# $ 4.0#) #5570 -- (which gives a seg fault) - -- - -- The *result* type can have any kind (#8739), - -- so we don't need to check anything for that ; _ <- unifyKind (Just (XHsType $ NHsCoreTy arg2_sigma)) (tcTypeKind arg2_sigma) liftedTypeKind - -- ignore the evidence. arg2_sigma must have type * or #, - -- because we know arg2_sigma -> or_res_ty is well-kinded + -- Ignore the evidence. arg2_sigma must have type * or #, + -- because we know (arg2_sigma -> op_res_ty) is well-kinded -- (because otherwise matchActualFunTys would fail) - -- There's no possibility here of, say, a kind family reducing to *. + -- So this 'unifyKind' will either succeed with Refl, or will + -- produce an insoluble constraint * ~ #, which we'll report later. - ; wrap_res <- tcSubTypeHR orig1 (Just expr) op_res_ty res_ty - -- op_res -> res + -- NB: unlike the argument type, the *result* type, op_res_ty can + -- have any kind (#8739), so we don't need to check anything for that ; op_id <- tcLookupId op_name - ; res_ty <- readExpType res_ty - ; let op' = L loc (mkHsWrap (mkWpTyApps [ getRuntimeRep res_ty + ; let op' = L loc (mkHsWrap (mkWpTyApps [ getRuntimeRep op_res_ty , arg2_sigma - , res_ty]) + , op_res_ty]) (HsVar noExt (L lv op_id))) -- arg1' :: arg1_ty -- wrap_arg1 :: arg1_ty "->" (arg2_sigma -> op_res_ty) - -- wrap_res :: op_res_ty "->" res_ty - -- op' :: (a2_ty -> res_ty) -> a2_ty -> res_ty + -- op' :: (a2_ty -> op_res_ty) -> a2_ty -> op_res_ty - -- wrap1 :: arg1_ty "->" (arg2_sigma -> res_ty) - wrap1 = mkWpFun idHsWrapper wrap_res arg2_sigma res_ty doc - <.> wrap_arg1 - doc = text "When looking at the argument to ($)" + expr' = OpApp fix (mkLHsWrap wrap_arg1 arg1') op' arg2' - ; return (OpApp fix (mkLHsWrap wrap1 arg1') op' arg2') } + ; tcWrapResult expr expr' op_res_ty res_ty } | (L loc (HsRecFld _ (Ambiguous _ lbl))) <- op , Just sig_ty <- obviousSig (unLoc arg1) diff --git a/compiler/typecheck/TcHsType.hs b/compiler/typecheck/TcHsType.hs index f2a795045018..adc25f5ff886 100644 --- a/compiler/typecheck/TcHsType.hs +++ b/compiler/typecheck/TcHsType.hs @@ -36,7 +36,7 @@ module TcHsType ( -- Kind-checking types -- No kind generalisation, no checkValidType kcLHsQTyVars, - tcWildCardBinders, + tcNamedWildCardBinders, tcHsLiftedType, tcHsOpenType, tcHsLiftedTypeNC, tcHsOpenTypeNC, tcLHsType, tcLHsTypeUnsaturated, tcCheckLHsType, @@ -387,7 +387,7 @@ tcHsTypeApp wc_ty kind unsetWOptM Opt_WarnPartialTypeSignatures $ setXOptM LangExt.PartialTypeSignatures $ -- See Note [Wildcards in visible type application] - tcWildCardBinders sig_wcs $ \ _ -> + tcNamedWildCardBinders sig_wcs $ \ _ -> tcCheckLHsType hs_ty kind -- We must promote here. Ex: -- f :: forall a. a @@ -402,18 +402,19 @@ tcHsTypeApp (XHsWildCardBndrs _) _ = panic "tcHsTypeApp" {- Note [Wildcards in visible type application] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A HsWildCardBndrs's hswc_ext now only includes named wildcards, so any unnamed -wildcards stay unchanged in hswc_body and when called in tcHsTypeApp, tcCheckLHsType -will call emitWildCardHoleConstraints on them. However, this would trigger -error/warning when an unnamed wildcard is passed in as a visible type argument, -which we do not want because users should be able to write @_ to skip a instantiating -a type variable variable without fuss. The solution is to switch the -PartialTypeSignatures flags here to let the typechecker know that it's checking -a '@_' and do not emit hole constraints on it. -See related Note [Wildcards in visible kind application] -and Note [The wildcard story for types] in HsTypes.hs - +A HsWildCardBndrs's hswc_ext now only includes /named/ wildcards, so +any unnamed wildcards stay unchanged in hswc_body. When called in +tcHsTypeApp, tcCheckLHsType will call emitAnonWildCardHoleConstraint +on these anonymous wildcards. However, this would trigger +error/warning when an anonymous wildcard is passed in as a visible type +argument, which we do not want because users should be able to write +@_ to skip a instantiating a type variable variable without fuss. The +solution is to switch the PartialTypeSignatures flags here to let the +typechecker know that it's checking a '@_' and do not emit hole +constraints on it. See related Note [Wildcards in visible kind +application] and Note [The wildcard story for types] in HsTypes.hs + +Ugh! -} {- @@ -829,7 +830,7 @@ tc_hs_type mode ty@(HsAppKindTy{}) ek = tc_infer_hs_type_ek mode ty ek tc_hs_type mode ty@(HsOpTy {}) ek = tc_infer_hs_type_ek mode ty ek tc_hs_type mode ty@(HsKindSig {}) ek = tc_infer_hs_type_ek mode ty ek tc_hs_type mode ty@(XHsType (NHsCoreTy{})) ek = tc_infer_hs_type_ek mode ty ek -tc_hs_type _ wc@(HsWildCardTy _) ek = tcWildCardOcc wc ek +tc_hs_type _ wc@(HsWildCardTy _) ek = tcAnonWildCardOcc wc ek ------------------------------------------ tc_fun_type :: TcTyMode -> LHsType GhcRn -> LHsType GhcRn -> TcKind @@ -849,18 +850,18 @@ tc_fun_type mode ty1 ty2 exp_kind = case mode_level mode of liftedTypeKind exp_kind } --------------------------- -tcWildCardOcc :: HsType GhcRn -> Kind -> TcM TcType -tcWildCardOcc wc exp_kind - = do { wc_tv <- newWildTyVar - -- The wildcard's kind should be an un-filled-in meta tyvar - ; loc <- getSrcSpanM - ; uniq <- newUnique - ; let name = mkInternalName uniq (mkTyVarOcc "_") loc +tcAnonWildCardOcc :: HsType GhcRn -> Kind -> TcM TcType +tcAnonWildCardOcc wc exp_kind + = do { wc_tv <- newWildTyVar -- The wildcard's kind will be an un-filled-in meta tyvar + ; part_tysig <- xoptM LangExt.PartialTypeSignatures ; warning <- woptM Opt_WarnPartialTypeSignatures - -- See Note [Wildcards in visible kind application] - ; unless (part_tysig && not warning) - (emitWildCardHoleConstraints [(name,wc_tv)]) + + ; unless (part_tysig && not warning) $ + emitAnonWildCardHoleConstraint wc_tv + -- Why the 'unless' guard? + -- See Note [Wildcards in visible kind application] + ; checkExpectedKind wc (mkTyVarTy wc_tv) (tyVarKind wc_tv) exp_kind } @@ -877,11 +878,11 @@ x = MkT So we should allow '@_' without emitting any hole constraints, and regardless of whether PartialTypeSignatures is enabled or not. But how would the typechecker know which '_' is being used in VKA and which is not when it -calls emitWildCardHoleConstraints in tcHsPartialSigType on all HsWildCardBndrs? +calls emitNamedWildCardHoleConstraints in tcHsPartialSigType on all HsWildCardBndrs? The solution then is to neither rename nor include unnamed wildcards in HsWildCardBndrs, -but instead give every unnamed wildcard a fresh wild tyvar in tcWildCardOcc. +but instead give every anonymous wildcard a fresh wild tyvar in tcAnonWildCardOcc. And whenever we see a '@', we automatically turn on PartialTypeSignatures and -turn off hole constraint warnings, and never call emitWildCardHoleConstraints +turn off hole constraint warnings, and do not call emitAnonWildCardHoleConstraint under these conditions. See related Note [Wildcards in visible type application] here and Note [The wildcard story for types] in HsTypes.hs @@ -1722,23 +1723,26 @@ To avoid the double-zonk, we do two things: gathers free variables. So this way effectively sidesteps step 3. -} -tcWildCardBinders :: [Name] - -> ([(Name, TcTyVar)] -> TcM a) - -> TcM a -tcWildCardBinders wc_names thing_inside +tcNamedWildCardBinders :: [Name] + -> ([(Name, TcTyVar)] -> TcM a) + -> TcM a +-- Bring into scope the /named/ wildcard binders. Remember that +-- plain wildcards _ are anonymous and dealt with by HsWildCardTy +-- Soe Note [The wildcard story for types] in HsTypes +tcNamedWildCardBinders wc_names thing_inside = do { wcs <- mapM (const newWildTyVar) wc_names ; let wc_prs = wc_names `zip` wcs ; tcExtendNameTyVarEnv wc_prs $ thing_inside wc_prs } newWildTyVar :: TcM TcTyVar --- ^ New unification variable for a wildcard +-- ^ New unification variable '_' for a wildcard newWildTyVar = do { kind <- newMetaKindVar ; uniq <- newUnique ; details <- newMetaDetails TauTv - ; let name = mkSysTvName uniq (fsLit "_") - tyvar = (mkTcTyVar name kind details) + ; let name = mkSysTvName uniq (fsLit "_") + tyvar = mkTcTyVar name kind details ; traceTc "newWildTyVar" (ppr tyvar) ; return tyvar } @@ -2490,11 +2494,11 @@ tcHsPartialSigType -> LHsSigWcType GhcRn -- The type signature -> TcM ( [(Name, TcTyVar)] -- Wildcards , Maybe TcType -- Extra-constraints wildcard - , [Name] -- Original tyvar names, in correspondence with ... - , [TcTyVar] -- ... Implicitly and explicitly bound type variables + , [(Name,TcTyVar)] -- Original tyvar names, in correspondence with + -- the implicitly and explicitly bound type variables , TcThetaType -- Theta part , TcType ) -- Tau part --- See Note [Recipe for checking a signature] +-- See Note [Checking partial type signatures] tcHsPartialSigType ctxt sig_ty | HsWC { hswc_ext = sig_wcs, hswc_body = ib_ty } <- sig_ty , HsIB { hsib_ext = implicit_hs_tvs @@ -2502,8 +2506,11 @@ tcHsPartialSigType ctxt sig_ty , (explicit_hs_tvs, L _ hs_ctxt, hs_tau) <- splitLHsSigmaTy hs_ty = addSigCtxt ctxt hs_ty $ do { (implicit_tvs, (explicit_tvs, (wcs, wcx, theta, tau))) - <- solveLocalEqualities "tcHsPatSigTypes" $ - tcWildCardBinders sig_wcs $ \ wcs -> + <- solveLocalEqualities "tcHsPartialSigType" $ + -- This solveLocalEqualiltes fails fast if there are + -- insoluble equalities. See TcSimplify + -- Note [Fail fast if there are insoluble kind equalities] + tcNamedWildCardBinders sig_wcs $ \ wcs -> bindImplicitTKBndrs_Tv implicit_hs_tvs $ bindExplicitTKBndrs_Tv explicit_hs_tvs $ do { -- Instantiate the type-class context; but if there @@ -2514,38 +2521,23 @@ tcHsPartialSigType ctxt sig_ty ; return (wcs, wcx, theta, tau) } - -- We must return these separately, because all the zonking below - -- might change the name of a TyVarTv. This, in turn, causes trouble - -- in partial type signatures that bind scoped type variables, as - -- we bring the wrong name into scope in the function body. - -- Test case: partial-sigs/should_compile/LocalDefinitionBug - ; let tv_names = implicit_hs_tvs ++ hsLTyVarNames explicit_hs_tvs - -- Spit out the wildcards (including the extra-constraints one) -- as "hole" constraints, so that they'll be reported if necessary -- See Note [Extra-constraint holes in partial type signatures] - ; emitWildCardHoleConstraints wcs + ; emitNamedWildCardHoleConstraints wcs - -- The TyVarTvs created above will sometimes have too high a TcLevel - -- (note that they are generated *after* bumping the level in - -- the tc{Im,Ex}plicitTKBndrsSig functions. Bumping the level - -- is still important here, because the kinds of these variables - -- do indeed need to have the higher level, so they can unify - -- with other local type variables. But, now that we've type-checked - -- everything (and solved equalities in the tcImplicit call) - -- we need to promote the TyVarTvs so we don't violate the TcLevel - -- invariant - ; implicit_tvs <- zonkAndScopedSort implicit_tvs - ; explicit_tvs <- mapM zonkAndSkolemise explicit_tvs - ; theta <- mapM zonkTcType theta - ; tau <- zonkTcType tau - - ; let all_tvs = implicit_tvs ++ explicit_tvs + -- We return a proper (Name,TyVar) environment, to be sure that + -- we bring the right name into scope in the function body. + -- Test case: partial-sigs/should_compile/LocalDefinitionBug + ; let tv_prs = (implicit_hs_tvs `zip` implicit_tvs) + ++ (hsLTyVarNames explicit_hs_tvs `zip` explicit_tvs) - ; checkValidType ctxt (mkSpecForAllTys all_tvs $ mkPhiTy theta tau) + -- NB: checkValidType on the final inferred type will be + -- done later by checkInferredPolyId. We can't do it + -- here because we don't have a complete tuype to check - ; traceTc "tcHsPartialSigType" (ppr all_tvs) - ; return (wcs, wcx, tv_names, all_tvs, theta, tau) } + ; traceTc "tcHsPartialSigType" (ppr tv_prs) + ; return (wcs, wcx, tv_prs, theta, tau) } tcHsPartialSigType _ (HsWC _ (XHsImplicitBndrs _)) = panic "tcHsPartialSigType" tcHsPartialSigType _ (XHsWildCardBndrs _) = panic "tcHsPartialSigType" @@ -2555,14 +2547,43 @@ tcPartialContext hs_theta | Just (hs_theta1, hs_ctxt_last) <- snocView hs_theta , L wc_loc wc@(HsWildCardTy _) <- ignoreParens hs_ctxt_last = do { wc_tv_ty <- setSrcSpan wc_loc $ - tcWildCardOcc wc constraintKind + tcAnonWildCardOcc wc constraintKind ; theta <- mapM tcLHsPredType hs_theta1 ; return (theta, Just wc_tv_ty) } | otherwise = do { theta <- mapM tcLHsPredType hs_theta ; return (theta, Nothing) } -{- Note [Extra-constraint holes in partial type signatures] +{- Note [Checking partial type signatures] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +See also Note [Recipe for checking a signature] + +When we have a parital signature like + f,g :: forall a. a -> _ +we do the following + +* In TcSigs.tcUserSigType we return a PartialSig, which (unlike + the companion CompleteSig) contains the original, as-yet-unchecked + source-code LHsSigWcType + +* Then, for f and g /separately/, we call tcInstSig, which in turn + call tchsPartialSig (defined near this Note). It kind-checks the + LHsSigWcType, creating fresh unification variables for each "_" + wildcard. It's important that the wildcards for f and g are distinct + becase they migh get instantiated completely differently. E.g. + f,g :: forall a. a -> _ + f x = a + g x = True + It's really as if we'd written two distinct signatures. + +* Note that we don't make quantified type (forall a. blah) and then + instantiate it -- it makes no sense to instantiate a type with + wildcards in it. Rather, tcHsPartialSigType just returns the + 'a' and the 'blah' separately. + + Nor, for the same reason, do we push a level in tcHsPartialSigType. + +Note [Extra-constraint holes in partial type signatures] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider f :: (_) => a -> a @@ -2631,12 +2652,12 @@ tcHsPatSigType ctxt sig_ty -- Always solve local equalities if possible, -- else casts get in the way of deep skolemisation -- (#16033) - tcWildCardBinders sig_wcs $ \ wcs -> + tcNamedWildCardBinders sig_wcs $ \ wcs -> tcExtendNameTyVarEnv sig_tkv_prs $ do { sig_ty <- tcHsOpenType hs_ty ; return (wcs, sig_ty) } - ; emitWildCardHoleConstraints wcs + ; emitNamedWildCardHoleConstraints wcs -- sig_ty might have tyvars that are at a higher TcLevel (if hs_ty -- contains a forall). Promote these. diff --git a/compiler/typecheck/TcRnDriver.hs b/compiler/typecheck/TcRnDriver.hs index d13abf4e0314..3ffc5df61e98 100644 --- a/compiler/typecheck/TcRnDriver.hs +++ b/compiler/typecheck/TcRnDriver.hs @@ -2438,8 +2438,8 @@ tcRnType hsc_env flexi normalise rdr_type -- must push level to satisfy level precondition of -- kindGeneralize, below solveEqualities $ - tcWildCardBinders wcs $ \ wcs' -> - do { emitWildCardHoleConstraints wcs' + tcNamedWildCardBinders wcs $ \ wcs' -> + do { emitNamedWildCardHoleConstraints wcs' ; tcLHsTypeUnsaturated rn_type } -- Do kind generalisation; see Note [Kind-generalise in tcRnType] diff --git a/compiler/typecheck/TcRnMonad.hs b/compiler/typecheck/TcRnMonad.hs index 25cf04f1532b..9a76e9ced8df 100644 --- a/compiler/typecheck/TcRnMonad.hs +++ b/compiler/typecheck/TcRnMonad.hs @@ -103,7 +103,8 @@ module TcRnMonad( pushTcLevelM_, pushTcLevelM, pushTcLevelsM, getTcLevel, setTcLevel, isTouchableTcM, getLclTypeEnv, setLclTypeEnv, - traceTcConstraints, emitWildCardHoleConstraints, + traceTcConstraints, + emitNamedWildCardHoleConstraints, emitAnonWildCardHoleConstraint, -- * Template Haskell context recordThUse, recordThSpliceUse, recordTopLevelSpliceLoc, @@ -1676,8 +1677,16 @@ traceTcConstraints msg hang (text (msg ++ ": LIE:")) 2 (ppr lie) } -emitWildCardHoleConstraints :: [(Name, TcTyVar)] -> TcM () -emitWildCardHoleConstraints wcs +emitAnonWildCardHoleConstraint :: TcTyVar -> TcM () +emitAnonWildCardHoleConstraint tv + = do { ct_loc <- getCtLocM HoleOrigin Nothing + ; emitInsolubles $ unitBag $ + CHoleCan { cc_ev = CtDerived { ctev_pred = mkTyVarTy tv + , ctev_loc = ct_loc } + , cc_hole = TypeHole (mkTyVarOcc "_") } } + +emitNamedWildCardHoleConstraints :: [(Name, TcTyVar)] -> TcM () +emitNamedWildCardHoleConstraints wcs = do { ct_loc <- getCtLocM HoleOrigin Nothing ; emitInsolubles $ listToBag $ map (do_one ct_loc) wcs } @@ -1690,7 +1699,7 @@ emitWildCardHoleConstraints wcs where real_span = case nameSrcSpan name of RealSrcSpan span -> span - UnhelpfulSpan str -> pprPanic "emitWildCardHoleConstraints" + UnhelpfulSpan str -> pprPanic "emitNamedWildCardHoleConstraints" (ppr name <+> quotes (ftext str)) -- Wildcards are defined locally, and so have RealSrcSpans ct_loc' = setCtLocSpan ct_loc real_span diff --git a/compiler/typecheck/TcRnTypes.hs b/compiler/typecheck/TcRnTypes.hs index 221d9cea8c5d..3c6b8ca68590 100644 --- a/compiler/typecheck/TcRnTypes.hs +++ b/compiler/typecheck/TcRnTypes.hs @@ -1561,7 +1561,7 @@ data TcIdSigInst -- Extra-constraints wildcard to fill in, if any -- If this exists, it is surely of the form (meta_tv |> co) -- (where the co might be reflexive). This is filled in - -- only from the return value of TcHsType.tcWildCardOcc + -- only from the return value of TcHsType.tcAnonWildCardOcc } {- Note [sig_inst_tau may be polymorphic] diff --git a/compiler/typecheck/TcSigs.hs b/compiler/typecheck/TcSigs.hs index 5bcb0eee9c2a..da18065b93b9 100644 --- a/compiler/typecheck/TcSigs.hs +++ b/compiler/typecheck/TcSigs.hs @@ -498,25 +498,14 @@ tcInstSig hs_sig@(PartialSig { psig_hs_ty = hs_ty , sig_loc = loc }) = setSrcSpan loc $ -- Set the binding site of the tyvars do { traceTc "Staring partial sig {" (ppr hs_sig) - ; (wcs, wcx, tv_names, tvs, theta, tau) <- tcHsPartialSigType ctxt hs_ty - - -- Clone the quantified tyvars - -- Reason: we might have f, g :: forall a. a -> _ -> a - -- and we want it to behave exactly as if there were - -- two separate signatures. Cloning here seems like - -- the easiest way to do so, and is very similar to - -- the tcInstType in the CompleteSig case - -- See #14643 - ; (subst, tvs') <- newMetaTyVarTyVars tvs - -- Why newMetaTyVarTyVars? See TcBinds - -- Note [Quantified variables in partial type signatures] - ; let tv_prs = tv_names `zip` tvs' - inst_sig = TISI { sig_inst_sig = hs_sig + ; (wcs, wcx, tv_prs, theta, tau) <- tcHsPartialSigType ctxt hs_ty + -- See Note [Checking partial type signatures] in TcHsType + ; let inst_sig = TISI { sig_inst_sig = hs_sig , sig_inst_skols = tv_prs , sig_inst_wcs = wcs , sig_inst_wcx = wcx - , sig_inst_theta = substTysUnchecked subst theta - , sig_inst_tau = substTyUnchecked subst tau } + , sig_inst_theta = theta + , sig_inst_tau = tau } ; traceTc "End partial sig }" (ppr inst_sig) ; return inst_sig } diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs index 55427d509ab3..55cb50113991 100644 --- a/compiler/typecheck/TcType.hs +++ b/compiler/typecheck/TcType.hs @@ -1795,11 +1795,14 @@ hasTyVarHead ty -- Haskell 98 allows predicates of form Nothing -> False evVarPred :: EvVar -> PredType -evVarPred var - = ASSERT2( isEvVarType var_ty, ppr var <+> dcolon <+> ppr var_ty ) - var_ty - where - var_ty = varType var +evVarPred var = varType var + -- Historical note: I used to have an ASSERT here, + -- checking (isEvVarType (varType var)). But with something like + -- f :: c => _ -> _ + -- we end up with (c :: kappa), and (kappa ~ Constraint). Until + -- we solve and zonk (which there is no particular reason to do for + -- partial signatures, (isEvVarType kappa) will return False. But + -- nothing is wrong. So I just removed the ASSERT. ------------------ -- | When inferring types, should we quantify over a given predicate? diff --git a/testsuite/tests/partial-sigs/should_compile/T16728.hs b/testsuite/tests/partial-sigs/should_compile/T16728.hs new file mode 100644 index 000000000000..f54f17ef560d --- /dev/null +++ b/testsuite/tests/partial-sigs/should_compile/T16728.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE PartialTypeSignatures #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE ScopedTypeVariables #-} +module Bug where + +import Data.Proxy + +f :: forall k (x :: k). Proxy (x :: _) +f = Proxy diff --git a/testsuite/tests/partial-sigs/should_compile/T16728.stderr b/testsuite/tests/partial-sigs/should_compile/T16728.stderr new file mode 100644 index 000000000000..6efdae343ee4 --- /dev/null +++ b/testsuite/tests/partial-sigs/should_compile/T16728.stderr @@ -0,0 +1,9 @@ + +T16728.hs:8:37: warning: [-Wpartial-type-signatures (in -Wdefault)] + • Found type wildcard ‘_’ standing for ‘k’ + Where: ‘k’ is a rigid type variable bound by + the inferred type of f :: Proxy x + at T16728.hs:9:1-9 + • In the kind ‘_’ + In the first argument of ‘Proxy’, namely ‘(x :: _)’ + In the type ‘Proxy (x :: _)’ diff --git a/testsuite/tests/partial-sigs/should_compile/T16728a.hs b/testsuite/tests/partial-sigs/should_compile/T16728a.hs new file mode 100644 index 000000000000..96d693a192cb --- /dev/null +++ b/testsuite/tests/partial-sigs/should_compile/T16728a.hs @@ -0,0 +1,8 @@ +{-# LANGUAGE ExplicitForAll, PartialTypeSignatures #-} +module Bug where + +g,h:: forall a. a -> _ +g x = h x + +h x = g x + diff --git a/testsuite/tests/partial-sigs/should_compile/T16728a.stderr b/testsuite/tests/partial-sigs/should_compile/T16728a.stderr new file mode 100644 index 000000000000..50785ebc1ce2 --- /dev/null +++ b/testsuite/tests/partial-sigs/should_compile/T16728a.stderr @@ -0,0 +1,20 @@ + +T16728a.hs:4:22: warning: [-Wpartial-type-signatures (in -Wdefault)] + • Found type wildcard ‘_’ standing for ‘_’ + Where: ‘_’ is a rigid type variable bound by + the inferred types of + g :: a -> _ + h :: a -> _ + at T16728a.hs:(5,1)-(7,9) + • In the type ‘a -> _’ + In the type signature: g :: forall a. a -> _ + +T16728a.hs:4:22: warning: [-Wpartial-type-signatures (in -Wdefault)] + • Found type wildcard ‘_’ standing for ‘_’ + Where: ‘_’ is a rigid type variable bound by + the inferred types of + g :: a -> _ + h :: a -> _ + at T16728a.hs:(5,1)-(7,9) + • In the type ‘a -> _’ + In the type signature: h :: forall a. a -> _ diff --git a/testsuite/tests/partial-sigs/should_compile/T16728b.hs b/testsuite/tests/partial-sigs/should_compile/T16728b.hs new file mode 100644 index 000000000000..db1e564a1416 --- /dev/null +++ b/testsuite/tests/partial-sigs/should_compile/T16728b.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE ExplicitForAll, PartialTypeSignatures #-} +module Bug where + +g,h:: forall a. a -> _ + +g x = x -- Instantiates the wildcard to 'a' + +h x = True -- Instantiates the wildcard to Bool + diff --git a/testsuite/tests/partial-sigs/should_compile/T16728b.stderr b/testsuite/tests/partial-sigs/should_compile/T16728b.stderr new file mode 100644 index 000000000000..712acfe0b931 --- /dev/null +++ b/testsuite/tests/partial-sigs/should_compile/T16728b.stderr @@ -0,0 +1,13 @@ + +T16728b.hs:4:22: warning: [-Wpartial-type-signatures (in -Wdefault)] + • Found type wildcard ‘_’ standing for ‘Bool’ + • In the type ‘a -> _’ + In the type signature: h :: forall a. a -> _ + +T16728b.hs:4:22: warning: [-Wpartial-type-signatures (in -Wdefault)] + • Found type wildcard ‘_’ standing for ‘a’ + Where: ‘a’ is a rigid type variable bound by + the inferred type of g :: a -> a + at T16728b.hs:6:1-7 + • In the type ‘a -> _’ + In the type signature: g :: forall a. a -> _ diff --git a/testsuite/tests/partial-sigs/should_compile/all.T b/testsuite/tests/partial-sigs/should_compile/all.T index 56d821eca001..4cb12ed14437 100644 --- a/testsuite/tests/partial-sigs/should_compile/all.T +++ b/testsuite/tests/partial-sigs/should_compile/all.T @@ -92,3 +92,6 @@ test('T15039c', normal, compile, ['-fprint-equality-relations']) test('T15039d', normal, compile, ['-fprint-explicit-kinds -fprint-equality-relations']) test('T16334', normal, compile, ['']) +test('T16728', normal, compile, ['']) +test('T16728a', normal, compile, ['']) +test('T16728b', normal, compile, ['']) diff --git a/testsuite/tests/partial-sigs/should_fail/T14040a.stderr b/testsuite/tests/partial-sigs/should_fail/T14040a.stderr index 0a07f0590d18..24782235ba78 100644 --- a/testsuite/tests/partial-sigs/should_fail/T14040a.stderr +++ b/testsuite/tests/partial-sigs/should_fail/T14040a.stderr @@ -1,10 +1,10 @@ T14040a.hs:34:8: error: - • Cannot apply expression of type ‘Sing wl0 - -> (forall y. p0 _0 'WeirdNil) + • Cannot apply expression of type ‘Sing wl + -> (forall y. p _2 'WeirdNil) -> (forall z1 (x :: z1) (xs :: WeirdList (WeirdList z1)). - Sing x -> Sing xs -> p0 _1 xs -> p0 _2 ('WeirdCons x xs)) - -> p0 _3 wl0’ + Sing x -> Sing xs -> p _0 xs -> p _1 ('WeirdCons x xs)) + -> p _2 wl’ to a visible type argument ‘(WeirdList z)’ • In the sixth argument of ‘pWeirdCons’, namely ‘(elimWeirdList @(WeirdList z) @xs @p xs pWeirdNil pWeirdCons)’ -- GitLab