diff --git a/ghc/compiler/basicTypes/BasicTypes.lhs b/ghc/compiler/basicTypes/BasicTypes.lhs
index cec3fa8e28c2b5144f2251f176efcb7d612eff18..5625103a86e9c7a9349e51cf60c25f6a74c95d01 100644
--- a/ghc/compiler/basicTypes/BasicTypes.lhs
+++ b/ghc/compiler/basicTypes/BasicTypes.lhs
@@ -22,6 +22,8 @@ module BasicTypes(
 
 #include "HsVersions.h"
 
+import {-# SOURCE #-} DataCon ( DataCon )
+import {-# SOURCE #-} Type    ( Type )
 import Outputable
 \end{code}
 
@@ -101,9 +103,6 @@ data NewOrData
   deriving( Eq )	-- Needed because Demand derives Eq
 \end{code}
 
-The @RecFlag@ tells whether the thing is part of a recursive group or not.
-
-
 %************************************************************************
 %*									*
 \subsection[Top-level/local]{Top-level/not-top level flag}
@@ -116,10 +115,9 @@ data TopLevelFlag
   | NotTopLevel
 \end{code}
 
-
 %************************************************************************
 %*									*
-\subsection[Top-level/local]{Top-level/not-top level flag}
+\subsection[Recursive/Non-Recursive]{Recursive/Non-Recursive flag}
 %*									*
 %************************************************************************
 
@@ -136,5 +134,6 @@ data RecFlag = Recursive
 
 \begin{code}
 data StrictnessMark = MarkedStrict
+		    | MarkedUnboxed DataCon [Type]
 		    | NotMarkedStrict
 \end{code}
diff --git a/ghc/compiler/basicTypes/DataCon.lhs b/ghc/compiler/basicTypes/DataCon.lhs
index 3ecd9689e692c81837478f3820b49cbd1ca1bd23..ffa98ea621269f3a73e48c5ab27970fcc247649e 100644
--- a/ghc/compiler/basicTypes/DataCon.lhs
+++ b/ghc/compiler/basicTypes/DataCon.lhs
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1998
 %
-\section[Literal]{@Literal@: Machine literals (unboxed, of course)}
+\section[DataCon]{@DataCon@: Data Constructors}
 
 \begin{code}
 module DataCon (
@@ -9,7 +9,7 @@ module DataCon (
 	ConTag, fIRST_TAG,
 	mkDataCon,
 	dataConType, dataConSig, dataConName, dataConTag,
-	dataConArgTys, dataConRawArgTys, dataConTyCon,
+	dataConOrigArgTys, dataConArgTys, dataConRawArgTys, dataConTyCon,
 	dataConFieldLabels, dataConStrictMarks, dataConSourceArity,
 	dataConNumFields, dataConNumInstArgs, dataConId,
 	isNullaryDataCon, isTupleCon, isUnboxedTupleCon,
@@ -22,18 +22,23 @@ import CmdLineOpts	( opt_DictsStrict )
 import TysPrim
 import Type		( Type, ThetaType, TauType,
 			  mkSigmaTy, mkFunTys, mkTyConApp, 
-			  mkTyVarTys, mkDictTy, substTy
+			  mkTyVarTys, mkDictTy, substTy,
+			  splitAlgTyConApp_maybe
 			)
+import PprType
 import TyCon		( TyCon, tyConDataCons, isDataTyCon,
 			  isTupleTyCon, isUnboxedTupleTyCon )
 import Class		( classTyCon )
-import Name		( Name, NamedThing(..), nameUnique )
+import Name		( Name, NamedThing(..), nameUnique, isLocallyDefinedName )
 import Var		( TyVar, Id )
 import VarEnv
 import FieldLabel	( FieldLabel )
 import BasicTypes	( StrictnessMark(..), Arity )
 import Outputable
 import Unique		( Unique, Uniquable(..) )
+import CmdLineOpts	( opt_UnboxStrictFields )
+import UniqSet
+import Maybe
 import Util		( assoc )
 \end{code}
 
@@ -68,7 +73,7 @@ data DataCon
 	-- 	dcTheta    = [Eq a]
 	--	dcExTyVars = [b]
 	--	dcExTheta  = [Ord b]
-	--	dcArgTys   = [a,List b]
+	--	dcOrigArgTys   = [a,List b]
 	--	dcTyCon    = T
 
 	dcTyVars :: [TyVar], 		-- Type vars and context for the data type decl
@@ -77,16 +82,28 @@ data DataCon
 	dcExTyVars :: [TyVar], 		-- Ditto for the context of the constructor, 
 	dcExTheta  :: ThetaType,	-- the existentially quantified stuff
 					
-	dcArgTys :: [Type],		-- Argument types
+	dcOrigArgTys :: [Type],		-- Original argument types
+					-- (before unboxing and flattening of
+					--  strict fields)
+	dcRepArgTys :: [Type],		-- Constructor Argument types
 	dcTyCon  :: TyCon,		-- Result tycon 
 
 	-- Now the strictness annotations and field labels of the constructor
-	dcStricts :: [StrictnessMark],	-- Strict args, in the same order as the argument types;
-					-- length = dataConNumFields dataCon
-
-	dcFields  :: [FieldLabel],	-- Field labels for this constructor, in the
-					-- same order as the argument types; 
-					-- length = 0 (if not a record) or dataConSourceArity.
+	dcUserStricts :: [StrictnessMark], 
+		-- Strictness annotations, as placed on the data type defn,
+		-- in the same order as the argument types;
+		-- length = dataConNumFields dataCon
+
+	dcRealStricts :: [StrictnessMark],
+		-- Strictness annotations as deduced by the compiler.  May
+		-- include some MarkedUnboxed fields that are MarkedStrict
+		-- in dcUserStricts.
+		-- length = dataConNumFields dataCon
+
+	dcFields  :: [FieldLabel],
+		-- Field labels for this constructor, in the
+		-- same order as the argument types; 
+		-- length = 0 (if not a record) or dataConSourceArity.
 
 	-- Finally, the curried function that corresponds to the constructor
 	-- 	mkT :: forall a b. (Eq a, Ord b) => a -> [b] -> T a
@@ -154,32 +171,103 @@ mkDataCon :: Name
 	  -> DataCon
   -- Can get the tag from the TyCon
 
-mkDataCon name arg_stricts fields tyvars theta ex_tyvars ex_theta arg_tys tycon id
-  = ASSERT(length arg_stricts == length arg_tys)
+mkDataCon name arg_stricts fields tyvars theta ex_tyvars ex_theta orig_arg_tys tycon id
+  = ASSERT(length arg_stricts == length orig_arg_tys)
 	-- The 'stricts' passed to mkDataCon are simply those for the
 	-- source-language arguments.  We add extra ones for the
 	-- dictionary arguments right here.
     con
   where
     con = MkData {dcName = name, dcUnique = nameUnique name,
-	  	  dcTyVars = tyvars, dcTheta = theta, dcArgTys = arg_tys,
+	  	  dcTyVars = tyvars, dcTheta = theta, 
+		  dcOrigArgTys = orig_arg_tys, 
+		  dcRepArgTys = rep_arg_tys,
 	     	  dcExTyVars = ex_tyvars, dcExTheta = ex_theta,
-		  dcStricts = all_stricts, dcFields = fields,
-	     	  dcTag = tag, dcTyCon = tycon, dcType = ty,
+		  dcRealStricts = all_stricts, dcUserStricts = user_stricts,
+		  dcFields = fields, dcTag = tag, dcTyCon = tycon, dcType = ty,
 		  dcId = id}
 
-    all_stricts = (map mk_dict_strict_mark ex_theta) ++ arg_stricts
+    (real_arg_stricts, strict_arg_tyss) 
+	= unzip (zipWith (unbox_strict_arg_ty tycon) arg_stricts orig_arg_tys)
+    rep_arg_tys = concat strict_arg_tyss
+
+    all_stricts = (map mk_dict_strict_mark ex_theta) ++ real_arg_stricts
+    user_stricts = (map mk_dict_strict_mark ex_theta) ++ arg_stricts
 	-- Add a strictness flag for the existential dictionary arguments
 
     tag = assoc "mkDataCon" (tyConDataCons tycon `zip` [fIRST_TAG..]) con
     ty  = mkSigmaTy (tyvars ++ ex_tyvars) 
 	            ex_theta
-	            (mkFunTys arg_tys (mkTyConApp tycon (mkTyVarTys tyvars)))
+	            (mkFunTys rep_arg_tys 
+			(mkTyConApp tycon (mkTyVarTys tyvars)))
 
 mk_dict_strict_mark (clas,tys)
   | opt_DictsStrict &&
-    isDataTyCon (classTyCon clas) = MarkedStrict	-- Don't mark newtype things as strict!
+	-- Don't mark newtype things as strict!
+    isDataTyCon (classTyCon clas) = MarkedStrict
   | otherwise		          = NotMarkedStrict
+
+-- We attempt to unbox/unpack a strict field when either:
+--   (i)  The tycon is imported, and the field is marked '! !', or
+--   (ii) The tycon is defined in this module, the field is marked '!', 
+--	  and the -funbox-strict-fields flag is on.
+--
+-- This ensures that if we compile some modules with -funbox-strict-fields and
+-- some without, the compiler doesn't get confused about the constructor
+-- representations.
+
+unbox_strict_arg_ty :: TyCon -> StrictnessMark -> Type -> (StrictnessMark, [Type])
+unbox_strict_arg_ty tycon NotMarkedStrict ty 
+  = (NotMarkedStrict, [ty])
+unbox_strict_arg_ty tycon MarkedStrict ty 
+  | not opt_UnboxStrictFields
+  || not (isLocallyDefinedName (getName tycon)) = (MarkedStrict, [ty])
+unbox_strict_arg_ty tycon marked_unboxed ty
+  -- MarkedUnboxed || (MarkedStrict && opt_UnboxStrictFields && not imported)
+  = case splitAlgTyConApp_maybe ty of
+	Just (tycon,_,[])
+	   -> panic (showSDoc (hcat [
+			text "unbox_strict_arg_ty: constructors for ",
+			ppr tycon,
+			text " not available."
+		     ]))
+	Just (tycon,ty_args,[con]) 
+	   -> case maybe_unpack_fields emptyUniqSet 
+		     (zip (dataConOrigArgTys con ty_args) 
+			  (dcUserStricts con))
+	      of 
+		 Nothing  -> (MarkedStrict, [ty])
+	         Just tys -> (MarkedUnboxed con tys, tys)
+	_ -> (MarkedStrict, [ty])
+
+-- bail out if we encounter the same tycon twice.  This avoids problems like
+--
+--   data A = !B
+--   data B = !A
+--
+-- where no useful unpacking can be done.
+
+maybe_unpack_field :: UniqSet TyCon -> Type -> StrictnessMark -> Maybe [Type]
+maybe_unpack_field set ty NotMarkedStrict
+  = Just [ty]
+maybe_unpack_field set ty MarkedStrict | not opt_UnboxStrictFields
+  = Just [ty]
+maybe_unpack_field set ty strict
+  = case splitAlgTyConApp_maybe ty of
+	Just (tycon,ty_args,[con])
+	   | tycon `elementOfUniqSet` set -> Nothing
+	   | otherwise ->
+		let set' = addOneToUniqSet set tycon in
+		maybe_unpack_fields set' 
+		    (zip (dataConOrigArgTys con ty_args)
+			 (dcUserStricts con))
+	_ -> Just [ty]
+
+maybe_unpack_fields :: UniqSet TyCon -> [(Type,StrictnessMark)] -> Maybe [Type]
+maybe_unpack_fields set tys
+  | any isNothing unpacked_fields = Nothing
+  | otherwise = Just (concat (catMaybes unpacked_fields))
+  where unpacked_fields = map (\(ty,str) -> maybe_unpack_field set ty str) tys
 \end{code}
 
 
@@ -204,14 +292,14 @@ dataConFieldLabels :: DataCon -> [FieldLabel]
 dataConFieldLabels = dcFields
 
 dataConStrictMarks :: DataCon -> [StrictnessMark]
-dataConStrictMarks = dcStricts
+dataConStrictMarks = dcRealStricts
 
 dataConRawArgTys :: DataCon -> [TauType] -- a function of convenience
-dataConRawArgTys = dcArgTys
+dataConRawArgTys = dcRepArgTys
 
 dataConSourceArity :: DataCon -> Arity
 	-- Source-level arity of the data constructor
-dataConSourceArity dc = length (dcArgTys dc)
+dataConSourceArity dc = length (dcOrigArgTys dc)
 
 dataConSig :: DataCon -> ([TyVar], ThetaType, 
 			  [TyVar], ThetaType, 
@@ -219,17 +307,22 @@ dataConSig :: DataCon -> ([TyVar], ThetaType,
 
 dataConSig (MkData {dcTyVars = tyvars, dcTheta = theta,
 		     dcExTyVars = ex_tyvars, dcExTheta = ex_theta,
-		     dcArgTys = arg_tys, dcTyCon = tycon})
+		     dcOrigArgTys = arg_tys, dcTyCon = tycon})
   = (tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon)
 
-dataConArgTys :: DataCon 
+dataConArgTys, dataConOrigArgTys :: DataCon 
 	      -> [Type] 	-- Instantiated at these types
 				-- NB: these INCLUDE the existentially quantified arg types
 	      -> [Type]		-- Needs arguments of these types
 				-- NB: these INCLUDE the existentially quantified dict args
 				--     but EXCLUDE the data-decl context which is discarded
 
-dataConArgTys (MkData {dcArgTys = arg_tys, dcTyVars = tyvars, 
+dataConArgTys (MkData {dcRepArgTys = arg_tys, dcTyVars = tyvars, 
+		       dcExTyVars = ex_tyvars, dcExTheta = ex_theta}) inst_tys
+ = map (substTy (zipVarEnv (tyvars ++ ex_tyvars) inst_tys)) 
+       ([mkDictTy cls tys | (cls,tys) <- ex_theta] ++ arg_tys)
+
+dataConOrigArgTys (MkData {dcOrigArgTys = arg_tys, dcTyVars = tyvars, 
 		       dcExTyVars = ex_tyvars, dcExTheta = ex_theta}) inst_tys
  = map (substTy (zipVarEnv (tyvars ++ ex_tyvars) inst_tys)) 
        ([mkDictTy cls tys | (cls,tys) <- ex_theta] ++ arg_tys)
@@ -246,7 +339,7 @@ dictionaries
 -- stored in the DataCon, and are matched in a case expression
 dataConNumInstArgs (MkData {dcTyVars = tyvars}) = length tyvars
 
-dataConNumFields (MkData {dcExTheta = theta, dcArgTys = arg_tys})
+dataConNumFields (MkData {dcExTheta = theta, dcRepArgTys = arg_tys})
   = length theta + length arg_tys
 
 isNullaryDataCon con
diff --git a/ghc/compiler/basicTypes/Id.lhs b/ghc/compiler/basicTypes/Id.lhs
index 4ac8170d677623ed4f87ecf964463df2c56fbe64..f5bff89ff0baf67f0636be3debedfcae3207c2ad 100644
--- a/ghc/compiler/basicTypes/Id.lhs
+++ b/ghc/compiler/basicTypes/Id.lhs
@@ -9,7 +9,7 @@ module Id (
 
 	-- Simple construction
 	mkVanillaId, mkImportedId, mkSysLocal, mkUserLocal,
-	mkTemplateLocals, mkWildId, mkUserId,
+	mkTemplateLocals, mkTemplateLocal, mkWildId, mkUserId,
 
 	-- Taking an Id apart
 	idName, idType, idUnique, idInfo, idDetails,
@@ -131,6 +131,9 @@ mkTemplateLocals :: [Type] -> [Id]
 mkTemplateLocals tys = zipWith (mkSysLocal SLIT("tpl"))
 			       (getBuiltinUniques (length tys))
 			       tys
+
+mkTemplateLocal :: Int -> Type -> Id
+mkTemplateLocal i ty = mkSysLocal SLIT("tpl") (mkBuiltinUnique i) ty
 \end{code}
 
 
diff --git a/ghc/compiler/basicTypes/MkId.lhs b/ghc/compiler/basicTypes/MkId.lhs
index 1c6b5d0dbd1830e562b1e66769f6a3a5c090b14b..cb53da0c120867084fef98c48cfa648ce5e8f965 100644
--- a/ghc/compiler/basicTypes/MkId.lhs
+++ b/ghc/compiler/basicTypes/MkId.lhs
@@ -46,11 +46,11 @@ import Name		( mkDerivedName, mkWiredInIdName,
 			)
 import PrimOp		( PrimOp, primOpType, primOpOcc, primOpUniq )
 import DataCon		( DataCon, dataConStrictMarks, dataConFieldLabels, 
-			  dataConArgTys, dataConSig
+			  dataConArgTys, dataConSig, dataConRawArgTys
 			)
 import Id		( idType,
 			  mkUserLocal, mkVanillaId, mkTemplateLocals,
-			  setInlinePragma
+			  mkTemplateLocal, setInlinePragma
 			)
 import IdInfo		( noIdInfo,
 			  exactArity, setUnfoldingInfo, 
@@ -139,44 +139,68 @@ Notice that
 dataConInfo :: DataCon -> IdInfo
 
 dataConInfo data_con
-  = setInlinePragInfo IMustBeINLINEd $
-	    	-- Always inline constructors; we won't create a binding for them
-    setArityInfo (exactArity (length locals)) $
+  = setInlinePragInfo IMustBeINLINEd $ -- Always inline constructors
+    setArityInfo (exactArity (n_dicts + n_ex_dicts + n_id_args)) $
     setUnfoldingInfo unfolding $
     noIdInfo
   where
         unfolding = mkUnfolding con_rhs
 
-	(tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon) = dataConSig data_con
+	(tyvars, theta, ex_tyvars, ex_theta, orig_arg_tys, tycon) 
+	   = dataConSig data_con
+	rep_arg_tys = dataConRawArgTys data_con
 	all_tyvars   = tyvars ++ ex_tyvars
 
 	dict_tys     = [mkDictTy clas tys | (clas,tys) <- theta]
 	ex_dict_tys  = [mkDictTy clas tys | (clas,tys) <- ex_theta]
+
 	n_dicts	     = length dict_tys
+	n_ex_dicts   = length ex_dict_tys
+	n_id_args    = length orig_arg_tys
+ 	n_rep_args   = length rep_arg_tys
+
 	result_ty    = mkTyConApp tycon (mkTyVarTys tyvars)
 
-	locals        = mkTemplateLocals (dict_tys ++ ex_dict_tys ++ arg_tys)
-	data_args     = drop n_dicts locals
-	(data_arg1:_) = data_args		-- Used for newtype only
+	mkLocals i n tys   = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
+	(dict_args, i1)    = mkLocals 1  n_dicts    dict_tys
+	(ex_dict_args,i2)  = mkLocals i1 n_ex_dicts ex_dict_tys
+	(id_args,i3)       = mkLocals i2 n_id_args  orig_arg_tys
+
+	(id_arg1:_) = id_args		-- Used for newtype only
 	strict_marks  = dataConStrictMarks data_con
-	strict_args   = [arg | (arg,MarkedStrict) <- data_args `zip` strict_marks]
-		-- NB: we can't call mkTemplateLocals twice, because it
-		-- always starts from the same unique.
 
-	con_app | isNewTyCon tycon 
-		= ASSERT( length arg_tys == 1)
-		  Note (Coerce result_ty (head arg_tys)) (Var data_arg1)
+	con_app i rep_ids
+                | isNewTyCon tycon 
+		= ASSERT( length orig_arg_tys == 1 )
+		  Note (Coerce result_ty (head orig_arg_tys)) (Var id_arg1)
  		| otherwise
-		= mkConApp data_con (map Type (mkTyVarTys all_tyvars) ++ map Var data_args)
-
-	con_rhs = mkLams all_tyvars $ mkLams locals $
-		  foldr mk_case con_app strict_args
-
-	mk_case arg body | isUnLiftedType (idType arg)
-			 = body			-- "!" on unboxed arg does nothing
-			 | otherwise
-			 = Case (Var arg) arg [(DEFAULT,[],body)]
-				-- This case shadows "arg" but that's fine
+		= mkConApp data_con 
+			(map Type (mkTyVarTys all_tyvars) ++ 
+			 map Var (reverse rep_ids))
+
+	con_rhs = mkLams all_tyvars $ mkLams dict_args $ 
+		  mkLams ex_dict_args $ mkLams id_args $
+		  foldr mk_case con_app (zip id_args strict_marks) i3 []
+
+	mk_case 
+	   :: (Id, StrictnessMark)	-- arg, strictness
+	   -> (Int -> [Id] -> CoreExpr) -- body
+	   -> Int			-- next rep arg id
+	   -> [Id]			-- rep args so far
+	   -> CoreExpr
+	mk_case (arg,strict) body i rep_args
+  	  = case strict of
+		NotMarkedStrict -> body i (arg:rep_args)
+		MarkedStrict 
+		   | isUnLiftedType (idType arg) -> body i (arg:rep_args)
+		   | otherwise ->
+			Case (Var arg) arg [(DEFAULT,[], body i (arg:rep_args))]
+
+		MarkedUnboxed con tys ->
+		   Case (Var arg) arg [(DataCon con, con_args,
+					body i' (reverse con_args++rep_args))]
+		   where n_tys = length tys
+			 (con_args,i') = mkLocals i (length tys) tys
 \end{code}
 
 
diff --git a/ghc/compiler/deSugar/DsUtils.lhs b/ghc/compiler/deSugar/DsUtils.lhs
index a26082fb8348e49487232846f6a54e1f0168fc77..9da5d956f92b05ce9f61e0f88d11c778fb059c35 100644
--- a/ghc/compiler/deSugar/DsUtils.lhs
+++ b/ghc/compiler/deSugar/DsUtils.lhs
@@ -39,7 +39,8 @@ import PrelVals		( iRREFUT_PAT_ERROR_ID )
 import Id		( idType, Id, mkWildId )
 import Const		( Literal(..), Con(..) )
 import TyCon		( isNewTyCon, tyConDataCons )
-import DataCon		( DataCon )
+import DataCon		( DataCon, dataConStrictMarks, dataConArgTys )
+import BasicTypes	( StrictnessMark(..) )
 import Type		( mkFunTy, isUnLiftedType, splitAlgTyConApp,
 			  Type
 			)
@@ -216,7 +217,9 @@ mkCoAlgCaseMatchResult var match_alts
 
     mk_alt fail (con, args, MatchResult _ body_fn)
 	= body_fn fail		`thenDs` \ body ->
-	  returnDs (DataCon con, args, body)
+	  rebuildConArgs con args (dataConStrictMarks con) body 
+				`thenDs` \ (body', real_args) ->
+	  returnDs (DataCon con, real_args, body')
 
     mk_default fail | exhaustive_case = []
 		    | otherwise       = [(DEFAULT, [], fail)]
@@ -225,7 +228,32 @@ mkCoAlgCaseMatchResult var match_alts
         = mkUniqSet data_cons `minusUniqSet` mkUniqSet [ con | (con, _, _) <- match_alts]
     exhaustive_case = isEmptyUniqSet un_mentioned_constructors
 
-
+-- for each constructor we match on, we might need to re-pack some
+-- of the strict fields if they are unpacked in the constructor.
+
+rebuildConArgs
+  :: DataCon				-- the con we're matching on
+  -> [Id]				-- the source-level args
+  -> [StrictnessMark]			-- the strictness annotations (per-arg)
+  -> CoreExpr				-- the body
+  -> DsM (CoreExpr, [Id])
+
+rebuildConArgs con [] stricts body = returnDs (body, [])
+rebuildConArgs con (arg:args) (str:stricts) body
+  = rebuildConArgs con args stricts body `thenDs` \ (body', real_args) ->
+    case str of
+	MarkedUnboxed pack_con tys -> 
+	    let id_tys  = dataConArgTys pack_con ty_args in
+	    newSysLocalsDs id_tys `thenDs` \ unpacked_args ->
+	    returnDs (
+		 Let (NonRec arg (Con (DataCon pack_con) 
+				      (map Type ty_args ++
+				       map Var  unpacked_args))) body', 
+		 unpacked_args ++ real_args
+	    )
+	_ -> returnDs (body', arg:real_args)
+
+  where ty_args = case splitAlgTyConApp (idType arg) of { (_,args,_) -> args }
 \end{code}
 
 %************************************************************************
diff --git a/ghc/compiler/hsSyn/HsDecls.lhs b/ghc/compiler/hsSyn/HsDecls.lhs
index d5f0b1b504d569ed21a9d46a9baeca2f0b5189aa..fe026da2cca4ced32555ccc385aecbbb9590aa9e 100644
--- a/ghc/compiler/hsSyn/HsDecls.lhs
+++ b/ghc/compiler/hsSyn/HsDecls.lhs
@@ -282,6 +282,7 @@ data ConDetails name
 data BangType name
   = Banged   (HsType name)	-- HsType: to allow Haskell extensions
   | Unbanged (HsType name)	-- (MonoType only needed for straight Haskell)
+  | Unpacked (HsType name)	-- Field is strict and to be unpacked if poss.
 \end{code}
 
 \begin{code}
@@ -312,6 +313,7 @@ ppr_con_details con (RecCon fields)
 
 ppr_bang (Banged   ty) = ptext SLIT("!") <> pprParendHsType ty
 ppr_bang (Unbanged ty) = pprParendHsType ty
+ppr_bang (Unpacked ty) = ptext SLIT("! !") <> pprParendHsType ty
 \end{code}
 
 
diff --git a/ghc/compiler/main/CmdLineOpts.lhs b/ghc/compiler/main/CmdLineOpts.lhs
index 08aa38feba7a14e83428245306c72288ada4bec5..87b89395d31d716755f07e9afd467abfb19ee66e 100644
--- a/ghc/compiler/main/CmdLineOpts.lhs
+++ b/ghc/compiler/main/CmdLineOpts.lhs
@@ -55,6 +55,7 @@ module CmdLineOpts (
 	opt_EmitCExternDecls,
 	opt_EnsureSplittableC,
 	opt_FoldrBuildOn,
+	opt_UnboxStrictFields,
 	opt_GlasgowExts,
 	opt_GranMacros,
 	opt_HiMap,
@@ -324,6 +325,7 @@ opt_DoTickyProfiling		= lookUp  SLIT("-fticky-ticky")
 opt_EmitCExternDecls	        = lookUp  SLIT("-femit-extern-decls")
 opt_EnsureSplittableC		= lookUp  SLIT("-fglobalise-toplev-names")
 opt_FoldrBuildOn		= lookUp  SLIT("-ffoldr-build-on")
+opt_UnboxStrictFields		= lookUp  SLIT("-funbox-strict-fields")
 opt_GranMacros			= lookUp  SLIT("-fgransim")
 opt_GlasgowExts			= lookUp  SLIT("-fglasgow-exts")
 opt_HiMap 			= lookup_str "-himap="       -- file saying where to look for .hi files
diff --git a/ghc/compiler/main/MkIface.lhs b/ghc/compiler/main/MkIface.lhs
index 4a41a101feebe1861abd36460a4db1971b9cdd0f..088de6a2fa9f790a136aa1577da7be8e27a9de9e 100644
--- a/ghc/compiler/main/MkIface.lhs
+++ b/ghc/compiler/main/MkIface.lhs
@@ -498,11 +498,9 @@ ifaceTyCon tycon
 
     ppr_arg_ty (strict_mark, ty) = ppr_strict_mark strict_mark <> pprParendType ty
 
-    ppr_strict_mark NotMarkedStrict = empty
-    ppr_strict_mark MarkedStrict    = ptext SLIT("! ")
-				-- The extra space helps the lexical analyser that lexes
-				-- interface files; it doesn't make the rigid operator/identifier
-				-- distinction, so "!a" is a valid identifier so far as it is concerned
+    ppr_strict_mark NotMarkedStrict        = empty
+    ppr_strict_mark (MarkedUnboxed _ _)    = ptext SLIT("! ! ")
+    ppr_strict_mark MarkedStrict           = ptext SLIT("! ")
 
     ppr_field (strict_mark, field_label)
 	= hsep [ ppr (fieldLabelName field_label),
diff --git a/ghc/compiler/rename/ParseIface.y b/ghc/compiler/rename/ParseIface.y
index bcf592d070a6dde2d631a5c4f6b62c137d87af41..aac197f6d44680364b70c56b18df3343a48848d0 100644
--- a/ghc/compiler/rename/ParseIface.y
+++ b/ghc/compiler/rename/ParseIface.y
@@ -348,6 +348,7 @@ batypes		:  					{ [] }
 batype		:: { RdrNameBangType }
 batype		:  atype				{ Unbanged $1 }
 		|  '!' atype				{ Banged   $2 }
+		|  '!' '!' atype			{ Unpacked $3 }
 
 fields1		:: { [([RdrName], RdrNameBangType)] }
 fields1		: field					{ [$1] }
@@ -356,6 +357,7 @@ fields1		: field					{ [$1] }
 field		:: { ([RdrName], RdrNameBangType) }
 field		:  var_names1 '::' type		{ ($1, Unbanged $3) }
 		|  var_names1 '::' '!' type    	{ ($1, Banged   $4) }
+		|  var_names1 '::' '!' '!' type	{ ($1, Unpacked $5) }
 --------------------------------------------------------------------------
 
 type		:: { RdrNameHsType }
diff --git a/ghc/compiler/rename/RnSource.lhs b/ghc/compiler/rename/RnSource.lhs
index b43f6cbe405517cb5681b2a210f1a8ead0fd0d13..498d309fceab17635862baecc2dfb10a7787b523 100644
--- a/ghc/compiler/rename/RnSource.lhs
+++ b/ghc/compiler/rename/RnSource.lhs
@@ -428,9 +428,13 @@ rnBangTy doc (Banged ty)
     returnRn (Banged new_ty, fvs)
 
 rnBangTy doc (Unbanged ty)
-  = rnHsType doc ty `thenRn` \ (new_ty, fvs) ->
+  = rnHsType doc ty 		`thenRn` \ (new_ty, fvs) ->
     returnRn (Unbanged new_ty, fvs)
 
+rnBangTy doc (Unpacked ty)
+  = rnHsType doc ty 		`thenRn` \ (new_ty, fvs) ->
+    returnRn (Unpacked new_ty, fvs)
+
 -- This data decl will parse OK
 --	data T = a Int
 -- treating "a" as the constructor.
diff --git a/ghc/compiler/simplCore/Simplify.lhs b/ghc/compiler/simplCore/Simplify.lhs
index a4c5e70b997d911d0789f0428d830167ecb569ba..bb2df3ed7745a03dbda261f6081fd03204228dab 100644
--- a/ghc/compiler/simplCore/Simplify.lhs
+++ b/ghc/compiler/simplCore/Simplify.lhs
@@ -1480,20 +1480,26 @@ simplAlts zap_occ_info scrut_cons case_bndr'' alts cont'
 	--	case x of { T a b -> T (a+1) b }
 	--
 	-- We really must record that b is already evaluated so that we don't
-	-- go and re-evaluated it when constructing the result.
+	-- go and re-evaluate it when constructing the result.
 
-    add_evals (DataCon dc) vs = stretchZipEqual add_eval vs (dataConStrictMarks dc)
+    add_evals (DataCon dc) vs = cat_evals vs (dataConStrictMarks dc)
     add_evals other_con    vs = vs
 
-    add_eval v m | isTyVar v = Nothing
-		 | otherwise = case m of
-				  MarkedStrict    -> Just (zap_occ_info v `setIdUnfolding` OtherCon [])
-				  NotMarkedStrict -> Just (zap_occ_info v)
+    cat_evals [] [] = []
+    cat_evals (v:vs) (str:strs) 
+	| isTyVar v = cat_evals vs (str:strs)
+	| otherwise = 
+	   case str of
+		MarkedStrict    -> 
+		  (zap_occ_info v `setIdUnfolding` OtherCon [])	
+			: cat_evals vs strs
+		MarkedUnboxed con _ -> 
+		  cat_evals (v:vs) (dataConStrictMarks con ++ strs)
+		NotMarkedStrict -> zap_occ_info v : cat_evals vs strs
 \end{code}
 
 
 
-
 %************************************************************************
 %*									*
 \subsection{Duplicating continuations}
diff --git a/ghc/compiler/typecheck/TcTyClsDecls.lhs b/ghc/compiler/typecheck/TcTyClsDecls.lhs
index 00104dbe2e901b30d279033e4df9654d26ecdd5e..995d0a1c5a98b9cf28b3c2a0c32d340025cfe295 100644
--- a/ghc/compiler/typecheck/TcTyClsDecls.lhs
+++ b/ghc/compiler/typecheck/TcTyClsDecls.lhs
@@ -302,6 +302,7 @@ get_con_details (RecCon nbtys)       = unionManyUniqSets (map (get_bty.snd) nbty
 ----------------------------------------------------
 get_bty (Banged ty)   = get_ty ty
 get_bty (Unbanged ty) = get_ty ty
+get_bty (Unpacked ty) = get_ty ty
 
 ----------------------------------------------------
 get_ty (MonoTyVar name)
diff --git a/ghc/compiler/typecheck/TcTyDecls.lhs b/ghc/compiler/typecheck/TcTyDecls.lhs
index 5d549435163559652b6bcea505c87dcc97797e0e..d33163cf519e5dcd9552710dcb094ceaa4ae6a7c 100644
--- a/ghc/compiler/typecheck/TcTyDecls.lhs
+++ b/ghc/compiler/typecheck/TcTyDecls.lhs
@@ -91,6 +91,7 @@ kcConDecl (ConDecl _ ex_tvs ex_ctxt details loc)
 
     kc_bty (Banged ty)   = tcHsType ty
     kc_bty (Unbanged ty) = tcHsType ty
+    kc_bty (Unpacked ty) = tcHsType ty
 
     kc_field (_, bty)    = kc_bty bty
 \end{code}
@@ -237,9 +238,12 @@ thinContext arg_tys ctxt
   
 get_strictness (Banged   _) = MarkedStrict
 get_strictness (Unbanged _) = NotMarkedStrict
+get_strictness (Unpacked _) = MarkedUnboxed bot bot
+	where bot = error "get_strictness"
 
 get_pty (Banged ty)   = ty
 get_pty (Unbanged ty) = ty
+get_pty (Unpacked ty) = ty
 \end{code}