Throw exceptions directly. (#8320)

* Update protobuf to throw exceptions directly.

Part of #8020. This PR changes the exception protobuf and AST (Haskell
side) to make exceptions be thrown directly via a primitive expression
(EThrow), instead of wrapping them up via AnyException.

changelog_begin
changelog_end

* Rename MakeAnyException to ToAnyException

* update EToAnyException field names

* Missing stuff

* missing scala case

* Make AnyException unserializable

* reindex protobuf builtins

* meaningless change

* refrobulate

* change pretty
This commit is contained in:
Sofia Faro 2020-12-17 14:14:46 +00:00 committed by GitHub
parent 604787eb07
commit 33df124d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 108 additions and 60 deletions

View File

@ -196,13 +196,20 @@ alphaExpr' env = \case
ETypeRep t1 -> \case
ETypeRep t2 -> alphaType' env t1 t2
_ -> False
EMakeAnyException t1 e1a e1b -> \case
EMakeAnyException t2 e2a e2b -> alphaType' env t1 t2
&& alphaExpr' env e1a e2a
&& alphaExpr' env e1b e2b
EToAnyException t1 e1 -> \case
EToAnyException t2 e2
-> alphaType' env t1 t2
&& alphaExpr' env e1 e2
_ -> False
EFromAnyException t1 e1 -> \case
EFromAnyException t2 e2 -> alphaType' env t1 t2
EFromAnyException t2 e2
-> alphaType' env t1 t2
&& alphaExpr' env e1 e2
_ -> False
EThrow t1a t1b e1 -> \case
EThrow t2a t2b e2
-> alphaType' env t1a t2a
&& alphaType' env t1b t2b
&& alphaExpr' env e1 e2
_ -> False
EUpdate u1 -> \case

View File

@ -236,7 +236,6 @@ data BuiltinExpr
-- Exceptions
| BEError -- :: ∀a. Text -> a
| BEThrow -- :: ∀a. AnyException -> a
| BEAnyExceptionMessage -- :: AnyException -> Text
| BEGeneralErrorMessage -- :: GeneralError -> Text
| BEArithmeticErrorMessage -- :: ArithmeticError -> Text
@ -516,16 +515,21 @@ data Expr
}
| ETypeRep !Type
-- | Construct an 'AnyException' value from a value of an exception type.
| EMakeAnyException
{ makeAnyExceptionType :: !Type
, makeAnyExceptionMessage :: !Expr
, makeAnyExceptionValue :: !Expr
| EToAnyException
{ toAnyExceptionType :: !Type
, toAnyExceptionValue :: !Expr
}
-- | Convert 'AnyException' back to its underlying value, if possible.
| EFromAnyException
{ fromAnyExceptionType :: !Type
, fromAnyExceptionValue :: !Expr
}
-- | Throw an exception.
| EThrow
{ throwReturnType :: !Type
, throwExceptionType :: !Type
, throwExceptionValue :: !Expr
}
-- | Update expression.
| EUpdate !Update
-- | Scenario expression.
@ -831,6 +835,7 @@ data Template = Template
data DefException = DefException
{ exnLocation :: !(Maybe SourceLoc)
, exnName :: !TypeConName
, exnMessage :: !Expr
}
deriving (Eq, Data, Generic, NFData, Show)

View File

@ -101,8 +101,9 @@ freeVarsStep = \case
EToAnyF t e -> freeVarsInType t <> e
EFromAnyF t e -> freeVarsInType t <> e
ETypeRepF t -> freeVarsInType t
EMakeAnyExceptionF t e1 e2 -> freeVarsInType t <> e1 <> e2
EToAnyExceptionF t e -> freeVarsInType t <> e
EFromAnyExceptionF t e -> freeVarsInType t <> e
EThrowF t1 t2 e -> freeVarsInType t1 <> freeVarsInType t2 <> e
where

View File

@ -211,7 +211,6 @@ instance Pretty BuiltinExpr where
BEUnit -> keyword_ "unit"
BEBool b -> keyword_ $ case b of { False -> "false"; True -> "true" }
BEError -> "ERROR"
BEThrow -> "THROW"
BEAnyExceptionMessage -> "ANY_EXCEPTION_MESSAGE"
BEGeneralErrorMessage -> "GENERAL_ERROR_MESSAGE"
BEArithmeticErrorMessage -> "ARITHMETIC_ERROR_MESSAGE"
@ -509,10 +508,12 @@ instance Pretty Expr where
EToAny ty body -> pPrintAppKeyword lvl prec "to_any" [TyArg ty, TmArg body]
EFromAny ty body -> pPrintAppKeyword lvl prec "from_any" [TyArg ty, TmArg body]
ETypeRep ty -> pPrintAppKeyword lvl prec "type_rep" [TyArg ty]
EMakeAnyException ty msg val -> pPrintAppKeyword lvl prec "make_any_exception"
[TyArg ty, TmArg msg, TmArg val]
EToAnyException ty val -> pPrintAppKeyword lvl prec "to_any_exception"
[TyArg ty, TmArg val]
EFromAnyException ty val -> pPrintAppKeyword lvl prec "from_any_exception"
[TyArg ty, TmArg val]
EThrow ty1 ty2 val -> pPrintAppKeyword lvl prec "throw"
[TyArg ty1, TyArg ty2, TmArg val]
instance Pretty DefTypeSyn where
pPrintPrec lvl _prec (DefTypeSyn mbLoc syn params typ) =
@ -521,8 +522,10 @@ instance Pretty DefTypeSyn where
lhsDoc = pPrint syn <-> hsep (map (pPrintAndKind lvl precParam) params) <-> "="
instance Pretty DefException where
pPrintPrec lvl _prec (DefException mbLoc tycon) =
withSourceLoc lvl mbLoc (keyword_ "exception" <-> pPrint tycon)
pPrintPrec lvl _prec (DefException mbLoc tycon msg) =
withSourceLoc lvl mbLoc
$ (keyword_ "exception" <-> pPrint tycon <-> "where")
$$ nest 2 ("message" <-> pPrintPrec lvl 0 msg)
instance Pretty DefDataType where
pPrintPrec lvl _prec (DefDataType mbLoc tcon (IsSerializable serializable) params dataCons) =

View File

@ -46,8 +46,9 @@ data ExprF expr
| EToAnyF !Type !expr
| EFromAnyF !Type !expr
| ETypeRepF !Type
| EMakeAnyExceptionF !Type !expr !expr
| EToAnyExceptionF !Type !expr
| EFromAnyExceptionF !Type !expr
| EThrowF !Type !Type !expr
deriving (Foldable, Functor, Traversable)
data BindingF expr = BindingF !(ExprVarName, Type) !expr
@ -186,8 +187,9 @@ instance Recursive Expr where
EToAny a b -> EToAnyF a b
EFromAny a b -> EFromAnyF a b
ETypeRep a -> ETypeRepF a
EMakeAnyException a b c -> EMakeAnyExceptionF a b c
EToAnyException a b -> EToAnyExceptionF a b
EFromAnyException a b -> EFromAnyExceptionF a b
EThrow a b c -> EThrowF a b c
instance Corecursive Expr where
embed = \case
@ -218,5 +220,6 @@ instance Corecursive Expr where
EToAnyF a b -> EToAny a b
EFromAnyF a b -> EFromAny a b
ETypeRepF a -> ETypeRep a
EMakeAnyExceptionF a b c -> EMakeAnyException a b c
EToAnyExceptionF a b -> EToAnyException a b
EFromAnyExceptionF a b -> EFromAnyException a b
EThrowF a b c -> EThrow a b c

View File

@ -182,13 +182,16 @@ applySubstInExpr subst@Subst{..} = \case
(applySubstInExpr subst e)
ETypeRep t -> ETypeRep
(applySubstInType subst t)
EMakeAnyException t e1 e2 -> EMakeAnyException
EToAnyException t e -> EToAnyException
(applySubstInType subst t)
(applySubstInExpr subst e1)
(applySubstInExpr subst e2)
(applySubstInExpr subst e)
EFromAnyException t e -> EFromAnyException
(applySubstInType subst t)
(applySubstInExpr subst e)
EThrow t1 t2 e -> EThrow
(applySubstInType subst t1)
(applySubstInType subst t2)
(applySubstInExpr subst e)
EUpdate u -> EUpdate
(applySubstInUpdate subst u)
EScenario s -> EScenario

View File

@ -249,6 +249,7 @@ decodeDefException LF1.DefException{..} =
DefException
<$> traverse decodeLocation defExceptionLocation
<*> decodeDottedNameId TypeConName defExceptionNameInternedDname
<*> mayDecode "exceptionMessage" defExceptionMessage decodeExpr
decodeDefDataType :: LF1.DefDataType -> Decode DefDataType
decodeDefDataType LF1.DefDataType{..} =
@ -441,7 +442,6 @@ decodeBuiltinFunction = pure . \case
LF1.BuiltinFunctionAPPEND_TEXT -> BEAppendText
LF1.BuiltinFunctionERROR -> BEError
LF1.BuiltinFunctionTHROW -> BEThrow
LF1.BuiltinFunctionANY_EXCEPTION_MESSAGE -> BEAnyExceptionMessage
LF1.BuiltinFunctionGENERAL_ERROR_MESSAGE -> BEGeneralErrorMessage
LF1.BuiltinFunctionARITHMETIC_ERROR_MESSAGE -> BEArithmeticErrorMessage
@ -604,13 +604,16 @@ decodeExprSum exprSum = mayDecode "exprSum" exprSum $ \case
return (EFromAny type' expr)
LF1.ExprSumTypeRep typ ->
ETypeRep <$> decodeType typ
LF1.ExprSumMakeAnyException LF1.Expr_MakeAnyException {..} -> EMakeAnyException
<$> mayDecode "expr_MakeAnyExceptionType" expr_MakeAnyExceptionType decodeType
<*> mayDecode "expr_MakeAnyExceptionMessage" expr_MakeAnyExceptionMessage decodeExpr
<*> mayDecode "expr_MakeAnyExceptionExpr" expr_MakeAnyExceptionExpr decodeExpr
LF1.ExprSumToAnyException LF1.Expr_ToAnyException {..} -> EToAnyException
<$> mayDecode "expr_ToAnyExceptionType" expr_ToAnyExceptionType decodeType
<*> mayDecode "expr_ToAnyExceptionExpr" expr_ToAnyExceptionExpr decodeExpr
LF1.ExprSumFromAnyException LF1.Expr_FromAnyException {..} -> EFromAnyException
<$> mayDecode "expr_FromAnyExceptionType" expr_FromAnyExceptionType decodeType
<*> mayDecode "expr_FromAnyExceptionExpr" expr_FromAnyExceptionExpr decodeExpr
LF1.ExprSumThrow LF1.Expr_Throw {..} -> EThrow
<$> mayDecode "expr_ThrowReturnType" expr_ThrowReturnType decodeType
<*> mayDecode "expr_ThrowExceptionType" expr_ThrowExceptionType decodeType
<*> mayDecode "expr_ThrowExceptionExpr" expr_ThrowExceptionExpr decodeExpr
decodeUpdate :: LF1.Update -> Decode Expr
decodeUpdate LF1.Update{..} = mayDecode "updateSum" updateSum $ \case

View File

@ -517,7 +517,6 @@ encodeBuiltinExpr = \case
BESha256Text -> builtin P.BuiltinFunctionSHA256_TEXT
BEError -> builtin P.BuiltinFunctionERROR
BEThrow -> builtin P.BuiltinFunctionTHROW
BEAnyExceptionMessage -> builtin P.BuiltinFunctionANY_EXCEPTION_MESSAGE
BEGeneralErrorMessage -> builtin P.BuiltinFunctionGENERAL_ERROR_MESSAGE
BEArithmeticErrorMessage -> builtin P.BuiltinFunctionARITHMETIC_ERROR_MESSAGE
@ -673,15 +672,19 @@ encodeExpr' = \case
pureExpr $ P.ExprSumFromAny P.Expr_FromAny{..}
ETypeRep ty -> do
expr . P.ExprSumTypeRep <$> encodeType' ty
EMakeAnyException ty msg val -> do
expr_MakeAnyExceptionType <- encodeType ty
expr_MakeAnyExceptionMessage <- encodeExpr msg
expr_MakeAnyExceptionExpr <- encodeExpr val
pureExpr $ P.ExprSumMakeAnyException P.Expr_MakeAnyException{..}
EToAnyException ty val -> do
expr_ToAnyExceptionType <- encodeType ty
expr_ToAnyExceptionExpr <- encodeExpr val
pureExpr $ P.ExprSumToAnyException P.Expr_ToAnyException{..}
EFromAnyException ty val -> do
expr_FromAnyExceptionType <- encodeType ty
expr_FromAnyExceptionExpr <- encodeExpr val
pureExpr $ P.ExprSumFromAnyException P.Expr_FromAnyException{..}
EThrow ty1 ty2 val -> do
expr_ThrowReturnType <- encodeType ty1
expr_ThrowExceptionType <- encodeType ty2
expr_ThrowExceptionExpr <- encodeExpr val
pureExpr $ P.ExprSumThrow P.Expr_Throw{..}
where
expr = P.Expr Nothing . Just
pureExpr = pure . expr
@ -856,6 +859,7 @@ encodeDefException :: DefException -> Encode P.DefException
encodeDefException DefException{..} = do
defExceptionNameInternedDname <- encodeDottedNameId unTypeConName exnName
defExceptionLocation <- traverse encodeSourceLoc exnLocation
defExceptionMessage <- encodeExpr exnMessage
pure P.DefException{..}
encodeTemplate :: Template -> Encode P.DefTemplate

View File

@ -83,7 +83,6 @@ safetyStep = \case
BEUnit -> Safe 0
BEBool _ -> Safe 0
BEError -> Safe 0
BEThrow -> Safe 0
BEAnyExceptionMessage -> Safe 1
BEGeneralErrorMessage -> Safe 1
BEArithmeticErrorMessage -> Safe 1
@ -216,12 +215,13 @@ safetyStep = \case
| Safe _ <- s -> Safe 0
| otherwise -> Unsafe
ETypeRepF _ -> Safe 0
EMakeAnyExceptionF _ s1 s2
| Safe _ <- min s1 s2 -> Safe 0
EToAnyExceptionF _ s
| Safe _ <- s -> Safe 0
| otherwise -> Unsafe
EFromAnyExceptionF _ s
| Safe _ <- s -> Safe 0
| otherwise -> Unsafe
EThrowF _ _ _ -> Unsafe
isTypeClassDictionary :: DefValue -> Bool
isTypeClassDictionary DefValue{..}

View File

@ -214,7 +214,6 @@ typeOfBuiltin = \case
BEUnit -> pure TUnit
BEBool _ -> pure TBool
BEError -> pure $ TForall (alpha, KStar) (TText :-> tAlpha)
BEThrow -> pure $ TForall (alpha, KStar) (TAnyException :-> tAlpha)
BEAnyExceptionMessage -> pure $ TAnyException :-> TText
BEGeneralErrorMessage -> pure $ TGeneralError :-> TText
BEArithmeticErrorMessage -> pure $ TArithmeticError :-> TText
@ -699,15 +698,19 @@ typeOf' = \case
ETypeRep ty -> do
checkGroundType ty
pure $ TBuiltin BTTypeRep
EMakeAnyException ty msg val -> do
EToAnyException ty val -> do
checkExceptionType ty
checkExpr msg TText
checkExpr val ty
pure TAnyException
EFromAnyException ty val -> do
checkExceptionType ty
checkExpr val TAnyException
pure (TOptional ty)
EThrow ty1 ty2 val -> do
checkType ty1 KStar
checkExceptionType ty2
checkExpr val ty2
pure ty1
EUpdate upd -> typeOfUpdate upd
EScenario scen -> typeOfScenario scen
ELocation _ expr -> typeOf' expr
@ -837,6 +840,7 @@ checkDefException m DefException{..} = do
tcon = Qualified PRSelf modName exnName
DefDataType _loc _name _serializable tyParams dataCons <- inWorld (lookupDataType tcon)
unless (null tyParams) $ throwWithContext (EExpectedExceptionTypeHasNoParams modName exnName)
checkExpr exnMessage (TCon tcon :-> TText)
_ <- match _DataRecord (EExpectedExceptionTypeIsRecord modName exnName) dataCons
case NM.lookup exnName (moduleTemplates m) of
Nothing -> pure ()

View File

@ -69,6 +69,7 @@ data UnserializabilityReason
| URNumericOutOfRange !Natural
| URTypeLevelNat
| URAny -- ^ It contains a value of type Any.
| URAnyException -- ^ It contains a value of type AnyException.
| URTypeRep -- ^ It contains a value of type TypeRep.
| URTypeSyn -- ^ It contains a type synonym.
@ -195,6 +196,7 @@ instance Pretty UnserializabilityReason where
URNumericOutOfRange n -> "Numeric scale " <> integer (fromIntegral n) <> " is out of range (needs to be between 0 and 38)"
URTypeLevelNat -> "type-level nat"
URAny -> "Any"
URAnyException -> "AnyException"
URTypeRep -> "TypeRep"
URTypeSyn -> "type synonym"

View File

@ -101,8 +101,8 @@ serializabilityConditionsType world0 _version mbModNameTpls vars = go
BTArrow -> Left URFunction
BTNumeric -> Left URNumeric -- 'Numeric' is used as a higher-kinded type constructor.
BTAny -> Left URAny
BTAnyException -> Left URAnyException
BTTypeRep -> Left URTypeRep
BTAnyException -> noConditions
BTGeneralError -> noConditions
BTArithmeticError -> noConditions
BTContractError -> noConditions

View File

@ -653,7 +653,6 @@ prettyNode Node{..}
meta p = text "" <-> p
archivedSC = annotateSC PredicateSC -- Magenta
prettyPartialTransaction :: PartialTransaction -> M (Doc SyntaxClass)
prettyPartialTransaction PartialTransaction{..} = do
world <- askWorld

View File

@ -485,14 +485,13 @@ enum BuiltinFunction {
APPEND_TEXT = 24;
ERROR = 25;
THROW = 137; // *Available in versions >= 1.dev*
ANY_EXCEPTION_MESSAGE = 138; // *Available in versions >= 1.dev*
MAKE_GENERAL_ERROR = 139; // *Available in versions >= 1.dev*
GENERAL_ERROR_MESSAGE = 140; // *Available in versions >= 1.dev*
MAKE_ARITHMETIC_ERROR = 141; // *Available in versions >= 1.dev*
ARITHMETIC_ERROR_MESSAGE = 142; // *Available in versions >= 1.dev*
MAKE_CONTRACT_ERROR = 143; // *Available in versions >= 1.dev*
CONTRACT_ERROR_MESSAGE = 144; // *Available in versions >= 1.dev*
ANY_EXCEPTION_MESSAGE = 137; // *Available in versions >= 1.dev*
MAKE_GENERAL_ERROR = 138; // *Available in versions >= 1.dev*
GENERAL_ERROR_MESSAGE = 139; // *Available in versions >= 1.dev*
MAKE_ARITHMETIC_ERROR = 140; // *Available in versions >= 1.dev*
ARITHMETIC_ERROR_MESSAGE = 141; // *Available in versions >= 1.dev*
MAKE_CONTRACT_ERROR = 142; // *Available in versions >= 1.dev*
CONTRACT_ERROR_MESSAGE = 143; // *Available in versions >= 1.dev*
LEQ_INT64 = 33; // *Available in versions < 1.dev*
LEQ_DECIMAL = 34; // *Available in versions < 1.7*
@ -580,7 +579,7 @@ enum BuiltinFunction {
TEXT_FROM_CODE_POINTS = 105; // *Available in versions >= 1.6*
TEXT_TO_CODE_POINTS = 106; // *Available in versions >= 1.6*
// Next id is 145. 144 is CONTRACT_ERROR_MESSAGE.
// Next id is 144. 143 is CONTRACT_ERROR_MESSAGE.
// EXPERIMENTAL TEXT PRIMITIVES -- these do not yet have stable numbers.
TEXT_TO_UPPER = 9901; // *Available in versions >= 1.dev*
@ -880,17 +879,15 @@ message Expr {
// Wrap an exception value in AnyException
// *Available in versions >= 1.dev*
message MakeAnyException {
message ToAnyException {
// type of argument. Must be an exception type.
Type type = 1;
// argument
Expr expr = 2;
// error message
Expr message = 3;
}
// Extract the given exception type from AnyException or return None on type-mismatch
// *Available in versions >= 1.7*
// *Available in versions >= 1.dev*
message FromAnyException {
// type that should be extracted. Must be an exception type.
Type type = 1;
@ -898,6 +895,16 @@ message Expr {
Expr expr = 2;
}
// Throw an exception.
// *Available in versions >= 1.dev*
message Throw {
// Overall type of the "throw" expression.
Type return_type = 1;
// Type of exception to throw. Must be an exception type.
Type exception_type = 2;
// Value of type "exception_type".
Expr exception_expr = 3;
}
// Location of the expression in the DAML code source.
// Optional
@ -997,13 +1004,17 @@ message Expr {
// *Available in versions >= 1.7*
Type type_rep = 32;
// Wrap an arbitrary exception into an AnyException ('ExpMakeAnyException').
// Wrap an arbitrary exception into an AnyException ('ExpToAnyException').
// *Available in versions >= 1.dev*
MakeAnyException make_any_exception = 33;
ToAnyException to_any_exception = 33;
// Extract an arbitrary exception from an AnyException ('ExpFromAnyException').
// *Available in versions >= 1.dev*
FromAnyException from_any_exception = 34;
// Throw an exception ('ExpThrow').
// *Available in versions >= 1.dev*
Throw throw = 35;
}
reserved 19; // This was equals. Removed in favour of BuiltinFunction.EQUAL_*
@ -1418,6 +1429,7 @@ message DefException {
// *Must be a valid interned dotted name*
int32 name_interned_dname = 1;
Location location = 2;
Expr message = 3;
}
// Data type definition

View File

@ -987,11 +987,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
assertSince(LV.Features.typeRep, "Expr.type_rep")
ETypeRep(decodeType(lfExpr.getTypeRep))
case PLF.Expr.SumCase.MAKE_ANY_EXCEPTION =>
throw ParseError("Expr.MAKE_ANY_EXCEPTION") // TODO #8020
case PLF.Expr.SumCase.TO_ANY_EXCEPTION =>
throw ParseError("Expr.TO_ANY_EXCEPTION") // TODO https://github.com/digital-asset/daml/issues/8020
case PLF.Expr.SumCase.FROM_ANY_EXCEPTION =>
throw ParseError("Expr.FROM_ANY_EXCEPTION") // TODO #8020
throw ParseError("Expr.FROM_ANY_EXCEPTION") // TODO https://github.com/digital-asset/daml/issues/8020
case PLF.Expr.SumCase.THROW =>
throw ParseError("Expr.THROW") // TODO https://github.com/digital-asset/daml/issues/8020
case PLF.Expr.SumCase.SUM_NOT_SET =>
throw ParseError("Expr.SUM_NOT_SET")
@ -1698,7 +1701,6 @@ private[lf] object DecodeV1 {
BuiltinFunctionInfo(EQUAL_CONTRACT_ID, BEqualContractId, maxVersion = Some(genMap)),
BuiltinFunctionInfo(TRACE, BTrace),
BuiltinFunctionInfo(COERCE_CONTRACT_ID, BCoerceContractId),
BuiltinFunctionInfo(THROW, BTextToUpper, minVersion = exceptions), // TODO #8020
BuiltinFunctionInfo(MAKE_GENERAL_ERROR, BTextToUpper, minVersion = exceptions), // TODO #8020
BuiltinFunctionInfo(MAKE_ARITHMETIC_ERROR, BTextToUpper, minVersion = exceptions), // TODO #8020
BuiltinFunctionInfo(MAKE_CONTRACT_ERROR, BTextToUpper, minVersion = exceptions), // TODO #8020