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

crashy interplay between value class, existentials, inference #7818

Closed
scabug opened this issue Sep 6, 2013 · 7 comments
Closed

crashy interplay between value class, existentials, inference #7818

scabug opened this issue Sep 6, 2013 · 7 comments

Comments

@scabug
Copy link

scabug commented Sep 6, 2013

class Observable1[+T](val asJava: JObservable[_ <: T]) extends AnyVal {
  private def foo[X](a: JObservable[X]): JObservable[X] = ???
  def synchronize: Observable1[T] = new Observable1(foo(asJava))
}

class JObservable[T]
scalac-hash v2.11.0-M4 sandbox/value-class-existential.scala
[info] v2.11.0-M4 => /Users/jason/usr/scala-v2.11.0-M4-0-g8b41240
error: scala.reflect.internal.Types$TypeError: type mismatch;
 found   : Observable1[_$1] where type _$1 <: T
 required: Observable1[T]
	at scala.tools.nsc.typechecker.Contexts$Context.issue(Contexts.scala:549)
	at scala.tools.nsc.typechecker.ContextErrors$ErrorUtils$.issueTypeError(ContextErrors.scala:97)
	at scala.tools.nsc.typechecker.ContextErrors$ErrorUtils$.issueNormalTypeError(ContextErrors.scala:86)
	at scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen$.AdaptTypeError(ContextErrors.scala:184)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptMismatchedSkolems$1(Typers.scala:1126)
	at scala.tools.nsc.typechecker.Typers$Typer.fallbackAfterVanillaAdapt$1(Typers.scala:1195)
	at scala.tools.nsc.typechecker.Typers$Typer.vanillaAdapt$1(Typers.scala:1232)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1275)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5370)
	at scala.tools.nsc.typechecker.Typers$Typer.transformedOrTyped(Typers.scala:5554)
	at scala.tools.nsc.typechecker.Typers$Typer.typedDefDef(Typers.scala:2307)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5281)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5352)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5411)
	at scala.tools.nsc.typechecker.Typers$Typer.typedPos(Typers.scala:5418)
	at scala.tools.nsc.transform.ExtensionMethods$Extender$$anonfun$transformStats$1$$anonfun$10$$anonfun$apply$9.apply(ExtensionMethods.scala:260)
	at scala.tools.nsc.transform.ExtensionMethods$Extender$$a
@scabug
Copy link
Author

scabug commented Sep 6, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7818?orig=1
Reporter: @retronym
Affected Versions: 2.10.0

@scabug
Copy link
Author

scabug commented Sep 6, 2013

@retronym said:
Workaround is the explicitly add type argument:

def synchronize: Observable1[T] = new Observable1[T](foo(asJava))

@scabug
Copy link
Author

scabug commented Sep 6, 2013

@retronym said:
This problem adds to the list of lamentations that comment on adaptMismatchedSkolems.

In this case our expected type contains a new type parameter (of the extension method), whereas the type of the tree contains an existential skolem still pinned to the corresponding class type parameter.

tree.tpe         = Observable1#7037[_$1#12344]
<_$1#12344>.info =  <: T#7040

pt               = Observable1#7037[T#15644]

@scabug
Copy link
Author

scabug commented Sep 6, 2013

@retronym said:
scala/scala#2916

@scabug scabug closed this as completed Sep 10, 2013
@scabug
Copy link
Author

scabug commented Sep 11, 2013

Samuel Grütter (samuelgruetter) said:
I've run into a second problem related to this:

object Test {
  class Observable[+T](val asJava: JObservable[_ <: T]) extends AnyVal {
    private def foo[X](a: JObservable[X]): JObservable[X] = ???
    def window(count: Int): Observable[Observable[T]] = {
      // this line makes the compiler crash (if it's the last line of this method):
      // convert(asJava.window())
      
      // this line gives an error:
      // "type mismatch; found : Test.JObservable[Test.JObservable[_$1]] required: Test.JObservable[Test.JObservable[T]]"
      // convert(asJava.window(): JObservable[JObservable[T]])
      
      // workaround:
      convert(asJava.window().asInstanceOf[JObservable[JObservable[T]]])
    }
  }
  
  class JObservable[T] {
    def window(): JObservable[JObservable[T]] = ???
  }
  
  def convert[T](jObs: JObservable[JObservable[T]]): Observable[Observable[T]] = ???
}

The only workaround I found was a typecast. Is there a safer workaround?

@scabug
Copy link
Author

scabug commented Sep 11, 2013

@retronym said:
Here's a workaround that uses a type ascription, rather than a cast:

cat  sandbox/test.scala
object Test {
  class Observable[+T](val asJava: JObservable[_ <: T]) extends AnyVal {
    private def foo[X](a: JObservable[X]): JObservable[X] = ???
    def window(count: Int): Observable[Observable[T]] = {
      convert(asJava.window()): Observable[Observable[T]]
    }
  }

  class JObservable[T] {
    def window(): JObservable[JObservable[T]] = ???
  }

  def convert[T](jObs: JObservable[JObservable[T]]): Observable[Observable[T]] = ???
}
topic/2894-rebase ~/code/scala scalac-hash v2.10.2 sandbox/test.scala
[info] v2.10.2 => /Users/jason/usr/scala-v2.10.2-0-g60d462e
topic/2894-rebase ~/code/scala

@scabug
Copy link
Author

scabug commented Sep 11, 2013

Samuel Grütter (samuelgruetter) said:
Great thanks! I did not even try this because I thought the return type of the method would have the same effect as this ascription...

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

No branches or pull requests

2 participants