Skip to content

Commit

Permalink
Adding support for Throwable error result types in Kotlin (#741)
Browse files Browse the repository at this point in the history
* Adding support for returning opaques as the error type of a result, as a custom Kotlin exception type

* adding same support for throwable structs

* clippy

* fixing multiple inheritance

* moooore clippy

* test fix

* new error log

* making custom `error` attribute

* clippy

---------

Co-authored-by: Ellen Arteca <[email protected]>
  • Loading branch information
emarteca and Ellen Arteca authored Dec 9, 2024
1 parent 8593fda commit baa148b
Show file tree
Hide file tree
Showing 26 changed files with 128 additions and 33 deletions.
32 changes: 30 additions & 2 deletions core/src/hir/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub struct Attrs {
/// This attribute does not participate in inheritance and must always
/// be specified on individual methods
pub special_method: Option<SpecialMethod>,
/// This user-defined type can be used as the error type in a Result.
pub custom_errors: bool,

/// From #[diplomat::demo()]. Created from [`crate::ast::attrs::Attrs::demo_attrs`].
/// List of attributes specific to automatic demo generation.
Expand Down Expand Up @@ -349,9 +351,16 @@ impl Attrs {
continue;
}
}
} else if path == "error" {
if !support.custom_errors {
maybe_error_unsupported(auto_found, "error", backend, errors);
continue;
}
auto_used = true;
this.custom_errors = true;
} else {
errors.push(LoweringError::Other(format!(
"Unknown diplomat attribute {path}: expected one of: `disable, rename, namespace, constructor, stringifier, comparison, named_constructor, getter, setter, indexer`"
"Unknown diplomat attribute {path}: expected one of: `disable, rename, namespace, constructor, stringifier, comparison, named_constructor, getter, setter, indexer, error`"
)));
}
if auto_found && !auto_used {
Expand All @@ -361,7 +370,7 @@ impl Attrs {
}
} else {
errors.push(LoweringError::Other(format!(
"Unknown diplomat attribute {path:?}: expected one of: `disable, rename, namespace, constructor, stringifier, comparison, named_constructor, getter, setter, indexer`"
"Unknown diplomat attribute {path:?}: expected one of: `disable, rename, namespace, constructor, stringifier, comparison, named_constructor, getter, setter, indexer, error`"
)));
}
}
Expand Down Expand Up @@ -458,6 +467,7 @@ impl Attrs {
rename,
abi_rename,
special_method,
custom_errors,
demo_attrs: _,
} = &self;

Expand Down Expand Up @@ -745,6 +755,17 @@ impl Attrs {
)));
}
}

if *custom_errors
&& !matches!(
context,
AttributeContext::Type(..) | AttributeContext::Trait(..)
)
{
errors.push(LoweringError::Other(
"`error` can only be used on types".to_string(),
));
}
}

pub(crate) fn for_inheritance(&self, context: AttrInheritContext) -> Attrs {
Expand Down Expand Up @@ -773,6 +794,8 @@ impl Attrs {
abi_rename: Default::default(),
// Never inherited
special_method: None,
// Not inherited
custom_errors: false,
demo_attrs: Default::default(),
}
}
Expand Down Expand Up @@ -849,6 +872,8 @@ pub struct BackendAttrSupport {
pub callbacks: bool,
/// Allowing traits
pub traits: bool,
/// Marking a user-defined type as being a valid error result type.
pub custom_errors: bool,
}

impl BackendAttrSupport {
Expand All @@ -875,6 +900,7 @@ impl BackendAttrSupport {
option: true,
callbacks: true,
traits: true,
custom_errors: true,
}
}
}
Expand Down Expand Up @@ -1007,6 +1033,7 @@ impl AttributeValidator for BasicAttributeValidator {
option,
callbacks,
traits,
custom_errors,
} = self.support;
match value {
"namespacing" => namespacing,
Expand All @@ -1029,6 +1056,7 @@ impl AttributeValidator for BasicAttributeValidator {
"option" => option,
"callbacks" => callbacks,
"traits" => traits,
"custom_errors" => custom_errors,
_ => {
return Err(LoweringError::Other(format!(
"Unknown supports = value found: {value}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: core/src/hir/elision.rs
assertion_line: 536
expression: method
---
Method {
Expand Down Expand Up @@ -44,6 +45,7 @@ Method {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -97,6 +99,7 @@ Method {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand All @@ -123,6 +126,7 @@ Method {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: core/src/hir/elision.rs
assertion_line: 473
expression: tcx
---
TypeContext {
Expand Down Expand Up @@ -47,6 +48,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -104,6 +106,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -149,6 +152,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand All @@ -172,6 +176,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -236,6 +241,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -295,6 +301,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -333,6 +340,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -372,6 +380,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand All @@ -395,6 +404,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down Expand Up @@ -441,6 +451,7 @@ TypeContext {
pattern: None,
},
special_method: None,
custom_errors: false,
demo_attrs: DemoInfo {
generate: false,
default_constructor: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class DataProvider internal constructor (
if (returnVal.isOk == 1.toByte()) {
return Unit.ok()
} else {
return Unit.err()
return Unit.primitive_err()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class FixedDecimal internal constructor (
val returnString = DW.writeToString(write)
return returnString.ok()
} else {
return Unit.err()
return Unit.primitive_err()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class FixedDecimalFormatter internal constructor (
CLEANER.register(returnOpaque, FixedDecimalFormatter.FixedDecimalFormatterCleaner(handle, FixedDecimalFormatter.lib));
return returnOpaque.ok()
} else {
return Unit.err()
return Unit.primitive_err()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,14 @@ internal fun <T> T.ok(): Result<T> {
return Result.success(this)
}

internal fun <T, E> E.err(): Result<T> {
internal fun <T, E> E.primitive_err(): Result<T> {
return Result.failure(RuntimeException("Received error $this"))
}

internal fun <T> Throwable.err(): Result<T> {
return Result.failure(this)
}

internal class ResultPointerUnitUnion: Union() {
@JvmField
internal var ok: Pointer = Pointer(0)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit baa148b

Please sign in to comment.