diff options
Diffstat (limited to 'compiler/GHC/Runtime')
-rw-r--r-- | compiler/GHC/Runtime/Eval.hs | 42 | ||||
-rw-r--r-- | compiler/GHC/Runtime/Heap/Inspect.hs | 50 |
2 files changed, 49 insertions, 43 deletions
diff --git a/compiler/GHC/Runtime/Eval.hs b/compiler/GHC/Runtime/Eval.hs index 0891da5808..aad557579b 100644 --- a/compiler/GHC/Runtime/Eval.hs +++ b/compiler/GHC/Runtime/Eval.hs @@ -81,7 +81,6 @@ import GHC.ByteCode.Types import GHC.Runtime.Linker as Linker import GHC.Driver.Session import GHC.Driver.Ppr -import GHC.LanguageExtensions import GHC.Types.Unique import GHC.Types.Unique.Supply import GHC.Utils.Monad @@ -1283,10 +1282,7 @@ obtainTermFromVal hsc_env _bound _force _ty _x = withInterp hsc_env $ \case obtainTermFromId :: HscEnv -> Int -> Bool -> Id -> IO Term obtainTermFromId hsc_env bound force id = do hv <- Linker.getHValue hsc_env (varName id) - cvObtainTerm (updEnv hsc_env) bound force (idType id) hv - where updEnv env = env {hsc_dflags = -- #14828 - xopt_set (hsc_dflags env) ImpredicativeTypes} - -- See Note [Setting ImpredicativeTypes for :print command] + cvObtainTerm hsc_env bound force (idType id) hv -- Uses RTTI to reconstruct the type of an Id, making it less polymorphic reconstructType :: HscEnv -> Int -> Id -> IO (Maybe Type) @@ -1296,39 +1292,3 @@ reconstructType hsc_env bound id = do mkRuntimeUnkTyVar :: Name -> Kind -> TyVar mkRuntimeUnkTyVar name kind = mkTcTyVar name kind RuntimeUnk - - -{- -Note [Setting ImpredicativeTypes for :print command] - -If ImpredicativeTypes is not enabled, then `:print <term>` will fail if the -type of <term> has nested `forall`s or `=>`s. -This is because the GHCi debugger's internals will attempt to unify a -metavariable with the type of <term> and then display the result, but if the -type has nested `forall`s or `=>`s, then unification will fail. -As a result, `:print` will bail out and the unhelpful result will be -`<term> = (_t1::t1)` (where `t1` is a metavariable). - -Beware: <term> can have nested `forall`s even if its definition doesn't use -RankNTypes! Here is an example from #14828: - - class Functor f where - fmap :: (a -> b) -> f a -> f b - -Somewhat surprisingly, `:print fmap` considers the type of fmap to have -nested foralls. This is because the GHCi debugger sees the type -`fmap :: forall f. Functor f => forall a b. (a -> b) -> f a -> f b`. -We could envision deeply instantiating this type to get the type -`forall f a b. Functor f => (a -> b) -> f a -> f b`, -but this trick wouldn't work for higher-rank types. - -Instead, we adopt a simpler fix: enable `ImpredicativeTypes` when using -`:print` and friends in the GHCi debugger. This allows metavariables -to unify with types that have nested (or higher-rank) `forall`s/`=>`s, -which makes `:print fmap` display as -`fmap = (_t1::forall a b. Functor f => (a -> b) -> f a -> f b)`, as expected. - -Although ImpredicativeTypes is a somewhat unpredictable from a type inference -perspective, there is no danger in using it in the GHCi debugger, since all -of the terms that the GHCi debugger deals with have already been typechecked. --} diff --git a/compiler/GHC/Runtime/Heap/Inspect.hs b/compiler/GHC/Runtime/Heap/Inspect.hs index ea682702c6..7bcb1a364c 100644 --- a/compiler/GHC/Runtime/Heap/Inspect.hs +++ b/compiler/GHC/Runtime/Heap/Inspect.hs @@ -559,11 +559,52 @@ trIO = liftTcM . liftIO liftTcM :: TcM a -> TR a liftTcM = id +-- When we make new unification variables in the GHCi debugger, +-- we use RuntimeUnkTvs. See Note [RuntimeUnkTv]. newVar :: Kind -> TR TcType -newVar = liftTcM . newFlexiTyVarTy +newVar kind = liftTcM (do { tv <- newAnonMetaTyVar RuntimeUnkTv kind + ; return (mkTyVarTy tv) }) newOpenVar :: TR TcType -newOpenVar = liftTcM newOpenFlexiTyVarTy +newOpenVar = liftTcM (do { kind <- newOpenTypeKind + ; newVar kind }) + +{- Note [RuntimeUnkTv] +~~~~~~~~~~~~~~~~~~~~~~ +In the GHCi debugger we use unification variables whose MetaInfo is +RuntimeUnkTv. The special property of a RuntimeUnkTv is that it can +unify with a polytype (see GHC.Tc.Utils.Unify.metaTyVarUpdateOK). +If we don't do this `:print <term>` will fail if the type of <term> +has nested `forall`s or `=>`s. + +This is because the GHCi debugger's internals will attempt to unify a +metavariable with the type of <term> and then display the result, but +if the type has nested `forall`s or `=>`s, then unification will fail +unless we do something special. As a result, `:print` will bail out +and the unhelpful result will be `<term> = (_t1::t1)` (where `t1` is a +metavariable). + +Beware: <term> can have nested `forall`s even if its definition doesn't use +RankNTypes! Here is an example from #14828: + + class Functor f where + fmap :: (a -> b) -> f a -> f b + +Somewhat surprisingly, `:print fmap` considers the type of fmap to have +nested foralls. This is because the GHCi debugger sees the type +`fmap :: forall f. Functor f => forall a b. (a -> b) -> f a -> f b`. +We could envision deeply instantiating this type to get the type +`forall f a b. Functor f => (a -> b) -> f a -> f b`, +but this trick wouldn't work for higher-rank types. + +Instead, we adopt a simpler fix: allow RuntimeUnkTv to unify with a +polytype (specifically, see ghci_tv in GHC.Tc.Utils.Unify.preCheck). +This allows metavariables to unify with types that have +nested (or higher-rank) `forall`s/`=>`s, which makes `:print fmap` +display as +`fmap = (_t1::forall a b. Functor f => (a -> b) -> f a -> f b)`, as expected. +-} + instTyVars :: [TyVar] -> TR (TCvSubst, [TcTyVar]) -- Instantiate fresh mutable type variables from some TyVars @@ -578,6 +619,10 @@ type RttiInstantiation = [(TcTyVar, TyVar)] -- If the TcTyVar has not been refined by the runtime type -- elaboration, then we want to turn it back into the -- original RuntimeUnk + -- + -- July 20: I'm not convinced that the little dance from + -- RuntimeUnkTv unification variables to RuntimeUnk skolems + -- is buying us anything. ToDo: get rid of it. -- | Returns the instantiated type scheme ty', and the -- mapping from new (instantiated) -to- old (skolem) type variables @@ -585,6 +630,7 @@ instScheme :: QuantifiedType -> TR (TcType, RttiInstantiation) instScheme (tvs, ty) = do { (subst, tvs') <- instTyVars tvs ; let rtti_inst = [(tv',tv) | (tv',tv) <- tvs' `zip` tvs] + ; traceTR (text "instScheme" <+> (ppr tvs $$ ppr ty $$ ppr tvs')) ; return (substTy subst ty, rtti_inst) } applyRevSubst :: RttiInstantiation -> TR () |