Skip to content
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

AnyRef specialization seems broken in master #5488

Closed
scabug opened this issue Feb 16, 2012 · 11 comments
Closed

AnyRef specialization seems broken in master #5488

scabug opened this issue Feb 16, 2012 · 11 comments
Assignees

Comments

@scabug
Copy link

@scabug scabug commented Feb 16, 2012

So, while working on #3575 I noticed that AnyRef specialization didn't seem to be working. I created a simple test of AnyRef specialization, noted the failure with master, then tried compiling an example with Scala 2.9.1 and it worked.

Here's the program:

class C[@specialized(Int, AnyRef) A](v:A)                                                                                   
                                                                                                                            
object Test {                                                                                                               
  def main(args:Array[String]) {                                                                                            
    println(new C(123).getClass.getName)                                                                                    
    println(new C("abc").getClass.getName)                                                                                  
  }                                                                                                                         
}

The output on 2.9.1 is:

C$mcI$sp
C$mcT$sp

Whereas on master it is:

C$mcI$sp
C

I know that there was a change recently from using the (totally arbitrary) T to the (Java standard) L for referring to Object/AnyRef, as well as other AnyRef bugfixes. I'm currently trying to do a bisect to figure out when this example stopped working, but haven't figured it out yet.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@non said (edited on Feb 16, 2012 4:00:40 AM UTC):
I can confirm that this code worked as of commit a2ce52f83, with the following output:

C$mcI$sp
C$mcT$sp

So this bug was introduced after that point.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@paulp said:
The oddsmakers will be taking a huge, huge beating if it wasn't bb23d766bce .

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@paulp said:
Wait, what's the point of specializing a single type parameter on AnyRef?

If I make it realistic, it crashes 2.9, but works a little bit in trunk.

class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B](v:A, w:B)                                                                                  
                                                                                                                            
object Test {                                                                                                               
  def main(args:Array[String]) {                                                                                            
    println(new C(123, 123).getClass.getName)                                                                                    
    println(new C("abc", 123).getClass.getName)                                                                                  
    println(new C(123, "abc").getClass.getName)                                                                                  
    println(new C("abc", "abc").getClass.getName)
  }                                                                                                                         
}

% scalac29 -d /tmp test/files/run/t5488.scala error: scala.tools.nsc.symtab.Types$TypeError: type mismatch;
 found   : java.lang.String("abc")
 required: A$sp
	at scala.tools.nsc.typechecker.Contexts$Context.error(Contexts.scala:298)
	at scala.tools.nsc.typechecker.Infer$Inferencer.error(Infer.scala:207)
	at scala.tools.nsc.typechecker.Infer$Inferencer.typeError(Infer.scala:217)


% scalac3 -d /tmp test/files/run/t5488.scala 
$ scala3 -cp /tmp Test
C$mcII$sp
C
C
C
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@paulp said:
Where of course "a little bit" means "at least doesn't crash us out of seeing mcII."

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@paulp said:
Every nontrivial thing I try crashes 2.9, no wonder I wasn't setting the bar too high.

Here's a nice realistic one.

class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int, AnyRef) C](f: (A, B) => C)

object Test {
  def main(args:Array[String]) {
    def show(x: Any) = println(x.getClass.getName)
    
    show(new C((x: Int, y: Int) => 1))
    show(new C((x: Int, y: Int) => "abc"))
    show(new C((x: Int, y: AnyRef) => 1))
    show(new C((x: Int, y: AnyRef) => "abc"))
    show(new C((x: AnyRef, y: Int) => 1))
    show(new C((x: AnyRef, y: Int) => "abc"))
    show(new C((x: AnyRef, y: AnyRef) => 1))
    show(new C((x: AnyRef, y: AnyRef) => "abc"))
  }
}

Only works for III.

C$mcIII$sp
C
C
C
C
C
C
C
@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@non said:
The reason why specializing a single parameter is nice is that in principle it will let us use @final/inline methods from C$mcL$sp instead of from C. I guess that's a little bit perverse since it's working around the weird subtyping/specialization stuff, but I think we're stuck with that design so we might as well make the best of it.

But I agree, your example is a more realistic case.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 16, 2012

@paulp said:
I found it. Thanks for catching it so quickly.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 17, 2012

@paulp said:
If I create LL/LLL/etc specializations, the compiler crashes during mixin finding duplicate members. I don't think it makes any sense to create L specializations but not LL, LLL, etc. so the upshot is that your test case still behaves the same even though this is fixed. Mine on the other hand prints

C0$mcIII$sp
C0$mcIIL$sp
C0$mcILI$sp
C0$mcILL$sp
C0$mcLII$sp
C0$mcLIL$sp
C0$mcLLI$sp
C0

If there is sufficient motivation we can look into whether it makes sense to generate those all-AnyRef specializations, but I have no more time for this right now.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 17, 2012

@non said:
OK, that's fair. I'll put that on my list of things to look at later.

@scabug

This comment has been minimized.

Copy link
Author

@scabug scabug commented Feb 17, 2012

@paulp said:
1e648c3862

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.