Skip to content

Commit

Permalink
Avoid unnecessary conversions (#7952)
Browse files Browse the repository at this point in the history
Fixes #7854 by checking all elements of a union type for direct match and only then, if direct match isn't available, applying conversions.
  • Loading branch information
JaroslavTulach authored Oct 4, 2023
1 parent 0228022 commit 421e3f2
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ static final class OneOfNode extends ReadArgumentCheckNode {
@Override
@ExplodeLoop
Object executeCheckOrConversion(VirtualFrame frame, Object value) {
for (var n : checks) {
if (n instanceof TypeCheckNode typeCheck) {
var result = typeCheck.findAmongTypes(value);
if (result != null) {
return result;
}
}
}
for (var n : checks) {
var result = n.executeCheckOrConversion(frame, value);
if (result != null) {
Expand Down Expand Up @@ -218,11 +226,11 @@ static abstract class TypeCheckNode extends ReadArgumentCheckNode {
}

@Specialization
Object doPanicSentinel(VirtualFrame frame, PanicSentinel panicSentinel) {
throw panicSentinel;
}
Object doPanicSentinel(VirtualFrame frame, PanicSentinel panicSentinel) {
throw panicSentinel;
}

@Specialization(rewriteOn = InvalidAssumptionException.class)
@Specialization(rewriteOn = InvalidAssumptionException.class)
Object doCheckNoConversionNeeded(VirtualFrame frame, Object v) throws InvalidAssumptionException {
var ret = findAmongTypes(v);
if (ret != null) {
Expand Down
30 changes: 30 additions & 0 deletions test/Tests/src/Semantic/Conversion_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ Integer.from (that:MultiNumber) = that.v * 19
Number.from (that:MultiNumber) = that.v * 0.3
Float.from (that:MultiNumber) = that.v * 0.7

type Back
Times n:Integer

exchange : (Back | Forth) -> (Back | Forth)
exchange value:(Back | Forth) = value

type Forth
Times n:Integer

exchange : (Forth | Back) -> (Forth | Back)
exchange value:(Forth | Back) = value

Back.from (that:Forth) = Back.Times that.n+1
Forth.from (that:Back) = Forth.Times that.n+1

foreign js make_str x = """
return "js string"

Expand Down Expand Up @@ -201,6 +216,21 @@ spec =
once . should_equal second
Meta.is_same_object once second . should_be_true

Test.specify "Avoid back and forth conversions" <|
one = Forth.Times 1

two = Back.exchange one
three = Forth.exchange two
four = Back.exchange three
five = Forth.exchange four
six = Forth.exchange five
seven = Back.exchange six
eight = Back.exchange seven
nine = Forth.exchange eight

# no conversions needed when calling `exchange` methods
nine . should_equal one

Test.specify "Requesting Text & Foo" <|
check a (n : Text & Foo) = case a of
0 -> n.foo
Expand Down

0 comments on commit 421e3f2

Please sign in to comment.