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

Compiler error when using tagged types and case classes #5183

Closed
scabug opened this Issue Nov 13, 2011 · 12 comments

Comments

Projects
None yet
1 participant
@scabug
Copy link

scabug commented Nov 13, 2011

Using AnyVal tagged types and case classes leads to hard to understand error messages.

  1. First example
trait Day
case class Test1(d: Int with Day)

The message is:

[error] ambiguous reference to overloaded definition,
[error] both method == in class Object of type (x$1: AnyRef)Boolean
[error] and  method == in class Int of type (x: Int)Boolean
[error] match argument types (Int with core.package.Day) and expected result type Boolean
[error]   case class Test1(d: Int with Day)
[error]              ^
  1. Second example
trait Day
case class Test2(d1: Int with Day, d2: Int with Day)

The message is:

[error] C:\projects\calypso\healthcheck\src\main\scala\core\package.scala:21: type mismatch;
[error]  found   : Double
[error]  required: AnyRef
[error] Note: an implicit exists from scala.Double => java.lang.Double, but
[error] methods inherited from Object are rendered ambiguous.  This is to avoid
[error] a blanket implicit which would convert any scala.Double to any AnyRef.
[error] You may wish to use a type ascription: `x: java.lang.Double`.
[error]   case class Test2(d1: Int with Day, d2: Int with Day)
[error]              ^
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Nov 13, 2011

Imported From: https://issues.scala-lang.org/browse/SI-5183?orig=1
Reporter: @etorreborre
Affected Versions: 2.9.1

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jun 16, 2012

@dlwh said:
Just to add a follow up, this trick doesn't work with Arrays either:

https://gist.github.com/cace1fcb319fbb776f6e

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jul 3, 2012

@adriaanm said:
let the user know the error arose from synthetic code

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Oct 25, 2012

Taylor Leese (tleese22) said:
Does this affect versions > 2.9.1 as well or just 2.9.1?

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Oct 25, 2012

@adriaanm said:
I think it works like this right up to 2.10.0-RC1:

Welcome to Scala version 2.10.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).
Type in expressions to have them evaluated.
Type :help for more information.

scala> trait Day
defined trait Day

scala> case class Test1(d: Int with Day)
error: type mismatch;
 found   : Double
 required: AnyRef
Note: an implicit exists from scala.Double => java.lang.Double, but
methods inherited from Object are rendered ambiguous.  This is to avoid
a blanket implicit which would convert any scala.Double to any AnyRef.
You may wish to use a type ascription: `x: java.lang.Double`.
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jan 12, 2013

@retronym said:
The varargs issue mentioned by David appears to be gone in 2.10.0

scala210
Welcome to Scala version 2.10.0-20121024-085118-2c554249fd (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_27).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class User
defined class User

scala> class Checkin
defined class Checkin

scala>   
     | type Tagged[U] = { type Tag = U }
defined type alias Tagged

scala> type @@[T, U] = T with Tagged[U] // Thanks to @retronym for suggesting this type alias
defined type alias $at$at

scala>   
     | class Tagger[U] {
     |   def apply[T](t : T) : T @@ U = t.asInstanceOf[T @@ U]
     | }
defined class Tagger

scala> def tag[U] = new Tagger[U]
tag: [U]=> Tagger[U]

scala>  
     | // Manual specialization needed here ... specializing apply above doesn't help

scala> def tag[U](i : Int) : Int @@ U = i.asInstanceOf[Int @@ U]
tag: [U](i: Int)@@[Int,U]

scala> def tag[U](l : Long) : Long @@ U = l.asInstanceOf[Long @@ U]
tag: [U](l: Long)@@[Long,U]

scala> def tag[U](d : Double) : Double @@ U = d.asInstanceOf[Double @@ U]
tag: [U](d: Double)@@[Double,U]

scala>  
     | def fetch[A](id: Int @@ A): A = null.asInstanceOf[A]
fetch: [A](id: @@[Int,A])A

scala>  
     | def tag[U](arr: Array[Int]):Array[Int @@ U] = arr.asInstanceOf[Array[Int @@ U]]
tag: [U](arr: Array[Int])Array[@@[Int,U]]

scala>  
     | tag[User](Array(3, 4, 5)).map(_.toString) 
res6: Array[String] = Array(3, 4, 5)
@scabug

This comment has been minimized.

Copy link
Author

scabug commented Feb 5, 2013

@retronym said:
Distilled:

scala> 

scala> trait Day; def foo(t: Int with Day) = t == t
<console>:7: error: ambiguous reference to overloaded definition,
both method == in class Object of type (x$1: AnyRef)Boolean
and  method == in class Int of type (x: Double)Boolean
match argument types (Int with Day)
       trait Day; def foo(t: Int with Day) = t == t
                                               ^
error: type mismatch;
 found   : Double
 required: AnyRef
Note: an implicit exists from scala.Double => java.lang.Double, but
methods inherited from Object are rendered ambiguous.  This is to avoid
a blanket implicit which would convert any scala.Double to any AnyRef.
You may wish to use a type ascription: `x: java.lang.Double`.
@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 20, 2013

@JamesIry said:
2.10.2 is about to be cut. Kicking down the road and un-assigning to foster work stealing.

@scabug

This comment has been minimized.

Copy link
Author

scabug commented Jul 26, 2013

Ben Hutchison (ben_hutchison) said:
This also shows up combining Tag Types with Value Classes:

scala> trait Day
defined trait Day

scala> class DayOps(val i: Int with Day) extends AnyVal
<console>:8: error: ambiguous reference to overloaded definition,
both method == in class Object of type (x$1: AnyRef)Boolean
and  method == in class Int of type (x: Double)Boolean
match argument types (Int with Day) and expected result type Boolean
       class DayOps(val i: Int with Day) extends AnyVal
             ^
error: type mismatch;
 found   : Double
 required: AnyRef
Note: an implicit exists from scala.Double => java.lang.Double, but
methods inherited from Object are rendered ambiguous.  This is to avoid
a blanket implicit which would convert any scala.Double to any AnyRef.
You may wish to use a type ascription: `x: java.lang.Double`.
@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 1, 2016

@benhutchison said:
Just noticed.. this appears mysteriously fixed in 2.11.7? :)

`~:$> scala
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_51).

scala> trait Day
defined trait Day

scala> case class Test1(d: Int with Day)
defined class Test1

scala> trait Day
defined trait Day

scala> case class Test2(d1: Int with Day, d2: Int with Day)
defined class Test2

scala> def foo(t: Int with Day) = t == t
foo: (t: Int with Day)Boolean

scala> class DayOps(val i: Int with Day) extends AnyVal
defined class DayOps`

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 1, 2016

@retronym said:
Looks like it progressed in scala/scala#3497.

Would you care to contribute a pull request with test cases for this so we can close this bug?

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 19, 2016

@lrytz said:
test case in scala/scala#5144

@scabug scabug closed this May 19, 2016

@scabug scabug added this to the 2.12.0-M5 milestone Apr 7, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.