diff --git a/hilti/toolchain/src/compiler/codegen/ctors.cc b/hilti/toolchain/src/compiler/codegen/ctors.cc index c9fc3a4c7..20a4d9b55 100644 --- a/hilti/toolchain/src/compiler/codegen/ctors.cc +++ b/hilti/toolchain/src/compiler/codegen/ctors.cc @@ -157,7 +157,9 @@ struct Visitor : hilti::visitor::PreOrder { void operator()(ctor::Result* n) final { auto t = cg->compile(n->type(), codegen::TypeUsage::Storage); - if ( auto e = n->value() ) + if ( n->value()->type()->type()->isA() ) + result = fmt("::hilti::rt::Nothing{}"); + else if ( auto e = n->value() ) result = fmt("%s(%s)", t, cg->compile(e)); else result = fmt("%s(%s)", t, cg->compile(n->error())); diff --git a/hilti/toolchain/src/compiler/codegen/types.cc b/hilti/toolchain/src/compiler/codegen/types.cc index 61b887167..86b4322c5 100644 --- a/hilti/toolchain/src/compiler/codegen/types.cc +++ b/hilti/toolchain/src/compiler/codegen/types.cc @@ -706,8 +706,12 @@ struct VisitorStorage : hilti::visitor::PreOrder { void operator()(type::Result* n) final { std::string t; - if ( const auto& ct = n->dereferencedType(); ! ct->isWildcard() ) - t = fmt("::hilti::rt::Result<%s>", cg->compile(ct, codegen::TypeUsage::Storage)); + if ( const auto& ct = n->dereferencedType(); ! ct->isWildcard() ) { + if ( ct->type()->isA() ) + t = "::hilti::rt::Result<::hilti::rt::Nothing>"; + else + t = fmt("::hilti::rt::Result<%s>", cg->compile(ct, codegen::TypeUsage::Storage)); + } else t = "*"; diff --git a/hilti/toolchain/src/compiler/coercer.cc b/hilti/toolchain/src/compiler/coercer.cc index 844c4de7d..97954ed2c 100644 --- a/hilti/toolchain/src/compiler/coercer.cc +++ b/hilti/toolchain/src/compiler/coercer.cc @@ -70,6 +70,11 @@ struct VisitorCtor : visitor::PreOrder { return; } + if ( auto t = dst->type()->tryAs(); t && t->dereferencedType()->type()->isA() ) { + result = builder->ctorResult(builder->expressionCtor(builder->ctorNull())); + return; + } + if ( auto t = dst->type()->tryAs() ) { result = builder->ctorStrongReference(t->dereferencedType()); return; @@ -462,6 +467,8 @@ struct VisitorType : visitor::PreOrder { void operator()(type::Null* n) final { if ( dst->type()->isA() ) result = dst; + else if ( auto t = dst->type()->tryAs(); t && t->dereferencedType()->type()->isA() ) + result = dst; else if ( dst->type()->isA() ) result = dst; else if ( dst->type()->isA() ) diff --git a/hilti/toolchain/src/compiler/validator.cc b/hilti/toolchain/src/compiler/validator.cc index 7c529dc28..21ba59951 100644 --- a/hilti/toolchain/src/compiler/validator.cc +++ b/hilti/toolchain/src/compiler/validator.cc @@ -643,7 +643,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { if ( n->isWildcard() ) return; - if ( const auto& t = n->dereferencedType(); ! t->type()->isAllocable() ) + if ( const auto& t = n->dereferencedType(); ! t->type()->isAllocable() && ! t->type()->isA() ) error(fmt("type %s cannot be used inside result", *t), n); } diff --git a/tests/hilti/types/result/void.hlt b/tests/hilti/types/result/void.hlt new file mode 100644 index 000000000..91e80cd79 --- /dev/null +++ b/tests/hilti/types/result/void.hlt @@ -0,0 +1,19 @@ +# @TEST-EXEC: hiltic -j %INPUT >output +# +# @TEST-DOC: Test the special-case of `result`. + +module Foo { + +import hilti; + +function result x(bool b) { + if ( b ) + return Null; + else + return error("trouble..."); +} + +assert x(True); +assert x(False).error() == error("trouble..."); + +}