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

TypeVars can't specialize Scope declarations #10506

Open
joroKr21 opened this issue Sep 9, 2017 · 3 comments
Open

TypeVars can't specialize Scope declarations #10506

joroKr21 opened this issue Sep 9, 2017 · 3 comments
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) typelevel
Milestone

Comments

@joroKr21
Copy link
Member

joroKr21 commented Sep 9, 2017

Below are a few examples involving type aliases and refinement types that show how among several equivalent types, some can be resolved implicitly while others cannot.

object Main {
  type With[A, B] = A with B

  class TC[A]
  object TC {
    def apply[A](implicit tc: TC[A]): TC[A] = tc
    implicit def tc[A, B]: TC[A With B] = new TC
  }

  trait Trait { def head: Int }
  TC[Trait With Serializable] // ok
  TC[Trait with Serializable] // ok

  type Struct = { def head: Int }
  TC[Struct With Serializable] // ok
  TC[Struct with Serializable] // missing (1)

  type TwSeq = Trait With Seq[Int]
  TC[TwSeq With Serializable] // ok
  TC[TwSeq with Serializable] // ok

  type SwSeq = Struct With Seq[Int]
  TC[SwSeq With Serializable] // ok
  TC[SwSeq with Serializable] // missing (2)

  TC[(Trait With Seq[Int]) with Serializable] // missing (3)
  TC[(Trait with Seq[Int]) with Serializable] // ok

  TC[(Struct With Seq[Int]) with Serializable] // missing (4)
  TC[(Struct with Seq[Int]) with Serializable] // missing (5)
}

I looked more closely into (1). -Xlog-implicits reports:

Information:(16, 5) Main.this.TC.tc is not a valid implicit value for Main.TC[Main.Struct with Serializable] because:
hasMatchingSymbol reported error: polymorphic expression cannot be instantiated to expected type;
 found   : [A, B]Main.TC[Main.With[A,B]]
    (which expands to)  [A, B]Main.TC[A with B]
 required: Main.TC[Main.Struct with Serializable]
    (which expands to)  Main.TC[AnyRef{def head: Int} with Serializable]
  TC[Struct with Serializable] // missing (1)

Further debugging reveals that at some point implicit resolution checks if the types below are compatible:

Main.TC[Main.With[?A,?B]] weak_<:< Main.TC[Main.Struct with Serializable] // false

Strangely enough though:

Main.TC[Main.With[?A,?B]] =:= Main.TC[Main.Struct with Serializable] // true

Intuitively I would expect A =:= B to imply A <:< B. But I'm not sure what role type variables play here.

Scala version: 2.12.3
Java version: Oracle 1.8.0_144

@milessabin
Copy link

Somewhat related to #9770.

@joroKr21
Copy link
Member Author

@milessabin I don't know about that. But here is how to reproduce inconsistencies in the subtype relation involving type variables:

import scala.reflect.runtime
val universe = runtime.universe.asInstanceOf[runtime.JavaUniverse]
import universe._

val tvar = TypeVar(symbolOf[Set[Any]].typeParams.head)
val struct = typeOf[{ def i: Int }]
val pat = refinedType(tvar :: typeOf[Serializable] :: Nil, NoSymbol)
val tpe = refinedType(struct :: typeOf[Serializable] :: Nil, NoSymbol)

println(tvar =:= struct) // true
println(tvar.constr) // _= AnyRef{def i: Int}

println(tpe =:= pat) // true
println(tpe <:< pat) // true
println(pat <:< tpe) // false
println(pat <:< struct) // false
println(tvar <:< struct) // true
println(tvar.member(TermName("i"))) // <none>
println(tvar.inst.member(TermName("i"))) // method i

@joroKr21 joroKr21 changed the title Weird inconsistencies involving implicit resolution, refinement types and type aliases TypeVars can't specialize Scope declarations Jan 13, 2018
@joroKr21
Copy link
Member Author

joroKr21 commented Jan 13, 2018

Further minimization:

object Test {
  type Parent
  type Scope = { val x: Int }  
  implicit def refined[A]: Parent with A = ???
  implicitly[Parent with Int] // ok
  implicitly[Parent with Scope] // missing
}

A leaky abstraction:
?A <:< Scope and Parent with ?A <:< Parent with Int,
but not Parent with ?A <:< Parent with Scope

@joroKr21 joroKr21 added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label Jan 6, 2021
@SethTisue SethTisue added this to the Backlog milestone Sep 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) typelevel
Projects
None yet
Development

No branches or pull requests

3 participants