-
Notifications
You must be signed in to change notification settings - Fork 21
Transition from pattern match based on extractor with a typed parameter in unapply() skips next case #2337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Imported From: https://issues.scala-lang.org/browse/SI-2337?orig=1
|
@cunei said: |
@cunei said: |
@paulp said: |
@retronym said: This code: def matchBroken(element: PsiElement) = element match {
case RealPsiClass(c) => "matched: RealPsiClass(c)"
case x: ScNamedElement => "matched: x: ScNamedElement"
// This is matched if element is a ScTypeParam, should have been the previous case.
case x if x.isInstanceOf[ScNamedElement] => "matched: x if x.isInstanceOf[ScNamedElement]"
case _ => "matched _"
} compiled against a r18583, then decompiled with JAD, gives: public String matchBroken(PsiElement element) {
PsiClass temp2;
if (element instanceof PsiClass) {
if (RealPsiClass$$.MODULE$$.unapply(temp2 = (PsiClass) element).isEmpty()) {
if (gd1$$1(temp2)) {
return "matched: x if x.isInstanceOf[ScNamedElement]";
} else {
return "matched _";
}
} else {
return "matched: RealPsiClass(c)";
}
}
else if (element instanceof ScNamedElement) {
return "matched: x: ScNamedElement";
} else if (gd1$$1(element)) {
return "matched: x if x.isInstanceOf[ScNamedElement]";
}
return "matched _";
} Removing the first case, which uses an extractor object, fixes the problem. When I tried to make this a stand-alone example, replacing all referenced types with scala traits, the problem disappears. Maybe having a java super-interface has some impact. Still digging :( |
@retronym said: Here is the tree generated by the pattern match: {
var temp1: this.T1 = ({
final class $$anon extends java.lang.Object with this.T2 with this.U1 {
def this($$outer: anonymous class $$anon): anonymous class $$anon = {
$$anon.super.this();
()
};
<synthetic> <paramaccessor> private[this] val $$outer: anonymous class $$anon = _;
<synthetic> <stable> def main$$$$anon$$$$anon$$$$$$outer(): anonymous class $$anon = $$anon.this.$$outer
};
new anonymous class $$anon($$anon.this)
}: this.T1);
if (temp1.isInstanceOf[this.T2]())
{
{
{
{
if ($$anon.this.Extractor().unapply(temp1.asInstanceOf[this.T2]()).isEmpty().unary_!())
{
{
{
"Extractor(_)"
}
}
}
else
{
"matched _"
}
}
}
}
}
else
if (temp1.isInstanceOf[this.T1 with this.U1]())
{
{
{
{
"matched: U1"
}
}
}
}
else
{
"matched _"
}
} |
Andrey (andrey) said: import junit.framework._
import Assert._
class BugTest extends TestCase {
def compare(first: Any, second: Any): Int = {
(first, second) match {
case (k: Int, o: Int) => k compare o
//why the next case matches (Float, Int) but does not match (Int, Float) ???
case (k: Number, o: Number) => k.doubleValue() compare o.doubleValue()
case _ => throw new Exception("Unsupported compare " + first + "; " + second)
}
}
def testCompare() {
assertEquals("Both Int", -1, compare(0, 1))
assertEquals("Both Float", 1, compare(1.0, 0.0))
assertEquals("Float then Int", 0, compare(10.0, 10))
assertEquals("Int then Float", 0, compare(10, 10.0))//this fails with an exception
}
} |
Alex Black (alexblack) said: object App { def matcher1: PartialFunction[List[String], String] = { def matcher2: PartialFunction[List[String], String] = { def main(args: Array[String]): Unit = { I expected the output to be: true But, the output is: (on Scala 2.8.0 final) true |
Commit Message Bot (anonymous) said: wraps the call to a bridged synthetic unapply(Seq) in a defensive if-test: if (x.isInstanceOf[expectedType]) real.unapply(x.asInstanceOf[expectedType]) else None NOTE: the test is WRONG, but it has to be due to #1697/#2337 -- once those are fixed, this one should generate the expected output |
@paulp said: |
Not sure if this is a known limitation, an existing bug, or a new bug in 2.8.
I have a value 'element' of runtime type:
It was fed into the pattern match. I expected it to match x: !ScNamedElement. Instead, it matched the default case. I added an explicit case for 'x: !ScTypeParam' as a workaround.
Taking a closer look with the debugger, it appears, at least from a Java perspective, that the class literal !ScNamedElement.class refers to the class containing the method definitions from trait !ScNamedElement, rather than its abstract interface.
Debugger:
My brief attempt to isolate this to a small testcase were unsuccessful. If this isn't enough to pinpoint the problem, and it really is a bug, I'll spend some more time at this.
Tested against r18650
thanks,
-jason
The text was updated successfully, but these errors were encountered: