From 212787e9f137b4a89cdb4362f8b8de873c67a96f Mon Sep 17 00:00:00 2001 From: Daniel Dietrich Date: Sun, 31 Mar 2019 23:06:54 +0200 Subject: [PATCH] Fixes issue #2401 (#2403) --- vavr/generator/Generator.scala | 31 +++++++++-- vavr/src-gen/main/java/io/vavr/API.java | 58 ++++++++++++--------- vavr/src-gen/test/java/io/vavr/APITest.java | 15 ++++++ 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/vavr/generator/Generator.scala b/vavr/generator/Generator.scala index 05e37a2bd7..c92a1461da 100644 --- a/vavr/generator/Generator.scala +++ b/vavr/generator/Generator.scala @@ -960,7 +960,13 @@ def generateMainClasses(): Unit = { @Override public boolean isDefinedAt(T obj) { - return $Objects.equals(obj, prototype); + if (obj == prototype) { + return true; + } else if (prototype != null && prototype.getClass().isInstance(obj)) { + return $Objects.equals(obj, prototype); + } else { + return false; + } } }; } @@ -1205,7 +1211,7 @@ def generateMainClasses(): Unit = { @Override public boolean isDefinedAt(T obj) { - return obj != null && type.isAssignableFrom(obj.getClass()); + return type.isInstance(obj); } }; } @@ -1241,12 +1247,12 @@ def generateMainClasses(): Unit = { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final $unapplyTupleType u = unapply.apply(obj); return ${(1 to i).gen(j => s"((Pattern) p$j).isDefinedAt(u._$j)")(" &&\n")}; + } else { + return false; } } }; @@ -2606,6 +2612,8 @@ def generateTestClasses(): Unit = { val API = im.getType("io.vavr.API") val AssertionsExtensions = im.getType("io.vavr.AssertionsExtensions") val ListType = im.getType("io.vavr.collection.List") + val StreamType = im.getType("io.vavr.collection.Stream") + val SeqType = im.getType("io.vavr.collection.Seq") val MapType = im.getType("io.vavr.collection.Map") val OptionType = im.getType("io.vavr.control.Option") val FutureType = im.getType("io.vavr.concurrent.Future") @@ -2971,6 +2979,19 @@ def generateTestClasses(): Unit = { assertThat(Case($$(ignored -> false), 1).isDefinedAt(null)).isFalse(); } + @$test + public void shouldPassIssue2401() { + final $SeqType empty = $StreamType.empty(); + try { + final String matched = Match(empty).of( + Case($$($ListType.empty()), ignored -> "list") + ); + fail("expected MatchError"); + } catch (MatchError err) { + // ok! + } + } + // -- Match patterns static class ClzMatch {} diff --git a/vavr/src-gen/main/java/io/vavr/API.java b/vavr/src-gen/main/java/io/vavr/API.java index 9d2b7ed811..28dbae6338 100644 --- a/vavr/src-gen/main/java/io/vavr/API.java +++ b/vavr/src-gen/main/java/io/vavr/API.java @@ -4988,7 +4988,13 @@ public T apply(T obj) { @Override public boolean isDefinedAt(T obj) { - return Objects.equals(obj, prototype); + if (obj == prototype) { + return true; + } else if (prototype != null && prototype.getClass().isInstance(obj)) { + return Objects.equals(obj, prototype); + } else { + return false; + } } }; } @@ -5379,7 +5385,7 @@ public T apply(T obj) { @Override public boolean isDefinedAt(T obj) { - return obj != null && type.isAssignableFrom(obj.getClass()); + return type.isInstance(obj); } }; } @@ -5403,12 +5409,12 @@ public T1 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple1 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1); + } else { + return false; } } }; @@ -5433,13 +5439,13 @@ public Tuple2 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple2 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2); + } else { + return false; } } }; @@ -5464,14 +5470,14 @@ public Tuple3 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple3 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3); + } else { + return false; } } }; @@ -5496,15 +5502,15 @@ public Tuple4 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple4 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && ((Pattern) p2).isDefinedAt(u._2) && ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4); + } else { + return false; } } }; @@ -5529,9 +5535,7 @@ public Tuple5 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple5 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && @@ -5539,6 +5543,8 @@ public boolean isDefinedAt(T obj) { ((Pattern) p3).isDefinedAt(u._3) && ((Pattern) p4).isDefinedAt(u._4) && ((Pattern) p5).isDefinedAt(u._5); + } else { + return false; } } }; @@ -5563,9 +5569,7 @@ public Tuple6 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple6 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && @@ -5574,6 +5578,8 @@ public boolean isDefinedAt(T obj) { ((Pattern) p4).isDefinedAt(u._4) && ((Pattern) p5).isDefinedAt(u._5) && ((Pattern) p6).isDefinedAt(u._6); + } else { + return false; } } }; @@ -5598,9 +5604,7 @@ public Tuple7 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple7 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && @@ -5610,6 +5614,8 @@ public boolean isDefinedAt(T obj) { ((Pattern) p5).isDefinedAt(u._5) && ((Pattern) p6).isDefinedAt(u._6) && ((Pattern) p7).isDefinedAt(u._7); + } else { + return false; } } }; @@ -5634,9 +5640,7 @@ public Tuple8 apply(T obj) { @SuppressWarnings("unchecked") @Override public boolean isDefinedAt(T obj) { - if (obj == null || !type.isAssignableFrom(obj.getClass())) { - return false; - } else { + if (type.isInstance(obj)) { final Tuple8 u = unapply.apply(obj); return ((Pattern) p1).isDefinedAt(u._1) && @@ -5647,6 +5651,8 @@ public boolean isDefinedAt(T obj) { ((Pattern) p6).isDefinedAt(u._6) && ((Pattern) p7).isDefinedAt(u._7) && ((Pattern) p8).isDefinedAt(u._8); + } else { + return false; } } }; diff --git a/vavr/src-gen/test/java/io/vavr/APITest.java b/vavr/src-gen/test/java/io/vavr/APITest.java index d786a1a333..9e1c51c8ff 100644 --- a/vavr/src-gen/test/java/io/vavr/APITest.java +++ b/vavr/src-gen/test/java/io/vavr/APITest.java @@ -31,6 +31,8 @@ import io.vavr.collection.List; import io.vavr.collection.Map; +import io.vavr.collection.Seq; +import io.vavr.collection.Stream; import io.vavr.concurrent.Future; import io.vavr.control.Option; import io.vavr.control.Try; @@ -1406,6 +1408,19 @@ public void shouldReturnNoneWhenApplyingCaseGivenPredicateAndValue() { assertThat(Case($(ignored -> false), 1).isDefinedAt(null)).isFalse(); } + @Test + public void shouldPassIssue2401() { + final Seq empty = Stream.empty(); + try { + final String matched = Match(empty).of( + Case($(List.empty()), ignored -> "list") + ); + fail("expected MatchError"); + } catch (MatchError err) { + // ok! + } + } + // -- Match patterns static class ClzMatch {}