diff --git a/ghc/compiler/simplCore/SimplCase.lhs b/ghc/compiler/simplCore/SimplCase.lhs
index f571658ec54ba2b32e79307da961c1b2d52d4fdc..9b9a5ad5931d41b902ba635148156bea21e9505c 100644
--- a/ghc/compiler/simplCore/SimplCase.lhs
+++ b/ghc/compiler/simplCore/SimplCase.lhs
@@ -1,4 +1,4 @@
-%
+`%
 % (c) The AQUA Project, Glasgow University, 1994-1996
 %
 \section[SimplCase]{Simplification of `case' expression}
@@ -18,10 +18,11 @@ import CmdLineOpts	( SimplifierSwitch(..) )
 import CoreSyn
 import CoreUnfold	( Unfolding, SimpleUnfolding )
 import CoreUtils	( coreAltsType, nonErrorRHSs, maybeErrorApp,
-			  unTagBindersAlts
+			  unTagBindersAlts, unTagBinders, coreExprType
 			)
 import Id		( idType, isDataCon, getIdDemandInfo,
-			  SYN_IE(DataCon), GenId{-instance Eq-}
+			  SYN_IE(DataCon), GenId{-instance Eq-},
+			  SYN_IE(Id)
 			)
 import IdInfo		( willBeDemanded, DemandInfo )
 import Literal		( isNoRepLit, Literal{-instance Eq-} )
@@ -34,7 +35,8 @@ import Type		( isPrimType, getAppDataTyConExpandingDicts, mkFunTy, mkFunTys, eqT
 import TysPrim		( voidTy )
 import Unique		( Unique{-instance Eq-} )
 import Usage		( GenUsage{-instance Eq-} )
-import Util		( isIn, isSingleton, zipEqual, panic, assertPanic )
+import Util		( SYN_IE(Eager), runEager, appEager,
+			  isIn, isSingleton, zipEqual, panic, assertPanic )
 \end{code}
 
 Float let out of case.
@@ -44,7 +46,7 @@ simplCase :: SimplEnv
 	  -> InExpr	-- Scrutinee
 	  -> InAlts	-- Alternatives
 	  -> (SimplEnv -> InExpr -> SmplM OutExpr)	-- Rhs handler
-	  -> OutType				-- Type of result expression
+	  -> OutType					-- Type of result expression
 	  -> SmplM OutExpr
 
 simplCase env (Let bind body) alts rhs_c result_ty
@@ -109,7 +111,7 @@ simplCase env (Case inner_scrut inner_alts) outer_alts rhs_c result_ty
     else
 	bindLargeAlts env outer_alts rhs_c result_ty	`thenSmpl` \ (extra_bindings, outer_alts') ->
 	let
-	   rhs_c' = \env rhs -> simplExpr env rhs []
+	   rhs_c' = \env rhs -> simplExpr env rhs [] result_ty
 	in
 	simplCase env inner_scrut inner_alts
 		  (\env rhs -> simplCase env rhs outer_alts' rhs_c' result_ty)
@@ -129,10 +131,9 @@ simplCase env scrut alts rhs_c result_ty
   | maybeToBool maybe_error_app
   = 	-- Look for an application of an error id
     tick CaseOfError 	`thenSmpl_`
-    rhs_c env retyped_error_app
+    returnSmpl retyped_error_app
   where
-    alts_ty 	    	   = coreAltsType (unTagBindersAlts alts)
-    maybe_error_app 	   = maybeErrorApp scrut (Just alts_ty)
+    maybe_error_app 	   = maybeErrorApp scrut (Just result_ty)
     Just retyped_error_app = maybe_error_app
 \end{code}
 
@@ -140,9 +141,18 @@ Finally the default case
 
 \begin{code}
 simplCase env other_scrut alts rhs_c result_ty
-  = 	-- Float the let outside the case scrutinee
-    simplExpr env other_scrut []	`thenSmpl` \ scrut' ->
+  = simplTy env scrut_ty			`appEager` \ scrut_ty' ->
+    simplExpr env' other_scrut [] scrut_ty	`thenSmpl` \ scrut' ->
     completeCase env scrut' alts rhs_c
+  where
+	-- When simplifying the scrutinee of a complete case that
+	-- has no default alternative
+    env' = case alts of
+		AlgAlts _ NoDefault  -> setCaseScrutinee env
+		PrimAlts _ NoDefault -> setCaseScrutinee env
+		other		     -> env
+
+    scrut_ty = coreExprType (unTagBinders other_scrut)
 \end{code}
 
 
@@ -355,7 +365,7 @@ completeCase env scrut alts rhs_c
 	-- the scrutinee.  Remember that the rhs is as yet unsimplified.
     rhs1_is_scrutinee = case (scrut, rhs1) of
 			  (Var scrut_var, Var rhs_var)
-				-> case lookupId env rhs_var of
+				-> case (runEager $ lookupId env rhs_var) of
 				    VarArg rhs_var' -> rhs_var' == scrut_var
 				    other	    -> False
 			  other -> False
@@ -440,14 +450,16 @@ bindLargeRhs env args rhs_ty rhs_c
 		App (Var prim_rhs_fun_id) (VarArg voidId))
 
   | otherwise
-  = 	-- Make the new binding Id.  NB: it's an OutId
-    newId rhs_fun_ty 		`thenSmpl` \ rhs_fun_id ->
-
-	-- Generate its rhs
+  =	-- Generate the rhs
     cloneIds env used_args	`thenSmpl` \ used_args' ->
     let
 	new_env = extendIdEnvWithClones env used_args used_args'
+	rhs_fun_ty :: OutType
+	rhs_fun_ty = mkFunTys (map idType used_args') rhs_ty
     in
+
+	-- Make the new binding Id.  NB: it's an OutId
+    newId rhs_fun_ty 		`thenSmpl` \ rhs_fun_id ->
     rhs_c new_env		`thenSmpl` \ rhs' ->
     let
 	final_rhs = mkValLam used_args' rhs'
@@ -459,8 +471,6 @@ bindLargeRhs env args rhs_ty rhs_c
 	-- it's processed the OutId won't be found in the environment, so it
 	-- will be left unmodified.
   where
-    rhs_fun_ty :: OutType
-    rhs_fun_ty = mkFunTys [simplTy env (idType id) | (id,_) <- used_args] rhs_ty
 
     used_args      = [arg | arg@(_,usage) <- args, not (dead usage)]
     used_arg_atoms = [VarArg arg_id | (arg_id,_) <- used_args]
@@ -505,8 +515,7 @@ simplAlts env scrut (AlgAlts alts deflt) rhs_c
 	    new_env = case scrut of
 		       Var v -> extendEnvGivenNewRhs env1 v (Con con args)
 			     where
-				(_, ty_args, _) = --trace "SimplCase.getAppData..." $
-						  getAppDataTyConExpandingDicts (idType v)
+				(_, ty_args, _) = getAppDataTyConExpandingDicts (idType v)
 				args = map TyArg ty_args ++ map VarArg con_args'
 
 		       other -> env1
diff --git a/ghc/compiler/simplCore/SimplCore.lhs b/ghc/compiler/simplCore/SimplCore.lhs
index 787d1688e2582b10a0c8dc9845c07a051249dbcb..df9572751b96eb57c53c20739aeb2658e4f928b3 100644
--- a/ghc/compiler/simplCore/SimplCore.lhs
+++ b/ghc/compiler/simplCore/SimplCore.lhs
@@ -27,7 +27,7 @@ import CmdLineOpts	( CoreToDo(..), SimplifierSwitch(..), switchIsOn,
 import CoreLint		( lintCoreBindings )
 import CoreSyn
 import CoreUtils	( coreExprType )
-import SimplUtils	( etaCoreExpr )
+import SimplUtils	( etaCoreExpr, typeOkForCase )
 import CoreUnfold
 import Literal		( Literal(..), literalType, mkMachInt )
 import ErrUtils		( ghcExit )
@@ -35,19 +35,20 @@ import FiniteMap	( FiniteMap )
 import FloatIn		( floatInwards )
 import FloatOut		( floatOutwards )
 import FoldrBuildWW	( mkFoldrBuildWW )
-import Id		( mkSysLocal, setIdVisibility,
+import Id		( mkSysLocal, setIdVisibility, mkIdWithNewName, getIdDemandInfo, idType,
 			  nullIdEnv, addOneToIdEnv, delOneFromIdEnv,
- 			  lookupIdEnv, SYN_IE(IdEnv),
-			  GenId{-instance Outputable-}
+ 			  lookupIdEnv, SYN_IE(IdEnv), omitIfaceSigForId,
+			  GenId{-instance Outputable-}, SYN_IE(Id)
 			)
-import Name		( isExported, isLocallyDefined )
+import IdInfo		( willBeDemanded, DemandInfo )
+import Name		( isExported, isLocallyDefined, SYN_IE(Module), NamedThing(..) )
 import TyCon		( TyCon )
 import PrimOp		( PrimOp(..) )
 import PrelVals		( unpackCStringId, unpackCString2Id,
 			  integerZeroId, integerPlusOneId,
 			  integerPlusTwoId, integerMinusOneId
 			)
-import Type		( maybeAppDataTyCon, getAppDataTyConExpandingDicts, maybeAppSpecDataTyConExpandingDicts )
+import Type		( maybeAppDataTyCon, isPrimType, SYN_IE(Type) )
 import TysWiredIn	( stringTy )
 import LiberateCase	( liberateCase )
 import MagicUFs		( MagicUnfoldingFun )
@@ -55,7 +56,7 @@ import Outputable	( Outputable(..){-instance * (,) -} )
 import PprCore
 import PprStyle		( PprStyle(..) )
 import PprType		( GenType{-instance Outputable-}, GenTyVar{-ditto-} )
-import Pretty		( ppShow, ppAboves, ppAbove, ppCat )
+import Pretty		( Doc, vcat, ($$), hsep )
 import SAT		( doStaticArgs )
 import SimplMonad	( zeroSimplCount, showSimplCount, SimplCount )
 import SimplPgm		( simplifyPgm )
@@ -64,7 +65,8 @@ import SpecUtils	( pprSpecErrs )
 import StrictAnal	( saWwTopBinds )
 import TyVar		( nullTyVarEnv, GenTyVar{-instance Eq-} )
 import Unique		( integerTyConKey, ratioTyConKey, Unique{-instance Eq-} )
-import UniqSupply	( splitUniqSupply, getUnique )
+import UniqFM           ( Uniquable(..) )
+import UniqSupply	( splitUniqSupply, getUnique, UniqSupply )
 import Util		( mapAccumL, assertPanic, panic{-ToDo:rm-}, pprTrace, pprPanic )
 import SrcLoc		( noSrcLoc )
 import Constants	( tARGET_MIN_INT, tARGET_MAX_INT )
@@ -207,7 +209,7 @@ core2core core_todos module_name ppr_style us local_tycons tycon_specs binds
 		   -- if we got errors, we die straight away
 		   (if not spec_noerrs ||
 		       (opt_ShowImportSpecs && not (isEmptyBag spec_warn)) then
-			hPutStr stderr (ppShow 1000 {-pprCols-}
+			hPutStr stderr (show
 			    (pprSpecErrs module_name spec_errs spec_warn spec_tyerrs))
 			>> hPutStr stderr "\n"
 		    else
@@ -250,8 +252,8 @@ core2core core_todos module_name ppr_style us local_tycons tycon_specs binds
 	 then
 	    hPutStr stderr ("\n*** "++what++":\n")
 		>>
-	    hPutStr stderr (ppShow 1000
-		(ppAboves (map (pprCoreBinding ppr_style) binds2)))
+	    hPutStr stderr (show
+		(vcat (map (pprCoreBinding ppr_style) binds2)))
 		>>
 	    hPutStr stderr "\n"
 	 else
@@ -324,6 +326,9 @@ Several tasks are done by @tidyCorePgm@
 	nuke them if possible.   (In general the simplifier does eta expansion not
 	eta reduction, up to this point.)
 
+8.	Do let-to-case.  See notes in Simplify.lhs for why we defer let-to-case
+	for multi-constructor types.
+
 
 Eliminate indirections
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -383,15 +388,48 @@ tidyCorePgm mod us binds_in
     (indirection_env, reduced_binds) = mapAccumL try_bind nullIdEnv binds_in
 
     try_bind :: IdEnv Id -> CoreBinding -> (IdEnv Id, Maybe CoreBinding)
-    try_bind env_so_far
-	     (NonRec exported_binder (Var local_id))
+    try_bind env_so_far (NonRec exported_binder rhs)
 	| isExported exported_binder &&		-- Only if this is exported
-	  isLocallyDefined local_id &&		-- Only if this one is defined in this
-	  not (isExported local_id) &&		-- 	module, so that we *can* change its
+	  maybeToBool maybe_rhs_id &&		-- 	and the RHS is a simple Id
+
+	  isLocallyDefined rhs_id &&		-- Only if this one is defined in this
+	  					-- 	module, so that we *can* change its
 					  	-- 	binding to be the exported thing!
-	  not (maybeToBool (lookupIdEnv env_so_far local_id))
+
+	  not (isExported rhs_id) &&		-- Only if this one is not itself exported,
+						--	since the transformation will nuke it
+
+	  not (omitIfaceSigForId rhs_id) &&	-- Don't do the transformation if rhs_id is
+						-- 	something like a constructor, whose 
+						--	definition is implicitly exported and 
+						-- 	which must not vanish.
+		-- To illustrate the preceding check consider
+		--	data T = MkT Int
+		--	mkT = MkT
+		--	f x = MkT (x+1)
+		-- Here, we'll make a local, non-exported, defn for MkT, and without the
+		-- above condition we'll transform it to:
+		--	mkT = \x. MkT [x]
+		--	f = \y. mkT (y+1)
+		-- This is bad because mkT will get the IdDetails of MkT, and won't
+		-- be exported.  Also the code generator won't make a definition for
+		-- the MkT constructor.
+		-- Slightly gruesome, this.
+
+	  not (maybeToBool (lookupIdEnv env_so_far rhs_id))
 						-- Only if not already substituted for
-	= (addOneToIdEnv env_so_far local_id exported_binder, Nothing)
+
+	= (addOneToIdEnv env_so_far rhs_id new_rhs_id, Nothing)
+	where
+	   maybe_rhs_id = case etaCoreExpr rhs of
+				Var rhs_id -> Just rhs_id
+				other	   -> Nothing
+	   Just rhs_id  = maybe_rhs_id
+	   new_rhs_id   = mkIdWithNewName rhs_id (getName exported_binder)
+				-- NB: we keep the Pragmas and IdInfo for the old rhs_id!
+				-- This is important; it might be marked "no-inline" by
+				-- the occurrence analyser (because it's recursive), and
+				-- we must not lose that information.
 
     try_bind env_so_far bind
 	= (env_so_far, Just bind)
@@ -469,6 +507,14 @@ tidyCoreExpr (Lam bndr body)
   = tidyCoreExpr body		`thenTM` \ body' ->
     returnTM (Lam bndr body')
 
+	-- Try for let-to-case (see notes in Simplify.lhs for why
+	-- some let-to-case stuff is deferred to now).
+tidyCoreExpr (Let (NonRec bndr rhs) body)
+  | willBeDemanded (getIdDemandInfo bndr) && 
+    typeOkForCase (idType bndr)
+  = ASSERT( not (isPrimType (idType bndr)) )
+    tidyCoreExpr (Case rhs (AlgAlts [] (BindDefault bndr body)))
+
 tidyCoreExpr (Let bind body)
   = tidyCoreBinding bind	`thenTM` \ bind' ->
     tidyCoreExprEta body	`thenTM` \ body' ->
@@ -491,7 +537,7 @@ tidyCoreExpr (Case scrut@(Prim op args) (PrimAlts _ (BindDefault binder rhs)))
 
 -- Eliminate polymorphic case, for which we can't generate code just yet
 tidyCoreExpr (Case scrut (AlgAlts [] (BindDefault deflt_bndr rhs)))
-  | not (maybeToBool (maybeAppSpecDataTyConExpandingDicts (coreExprType scrut)))
+  | not (typeOkForCase (idType deflt_bndr))
   = pprTrace "Warning: discarding polymorphic case:" (ppr PprDebug scrut) $
     case scrut of
 	Var v -> extendEnvTM deflt_bndr v (tidyCoreExpr rhs)