Skip to content

Specificity in contravariant implicit resolution #2974

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

Closed
smarter opened this issue Aug 14, 2017 · 4 comments
Closed

Specificity in contravariant implicit resolution #2974

smarter opened this issue Aug 14, 2017 · 4 comments

Comments

@smarter
Copy link
Member

smarter commented Aug 14, 2017

The Dotty resolution algorithm was recently ported to scalac by @milessabin in scala/scala#6037 (comment) where this came up:

trait Foo[-T]

trait Bar[-T] extends Foo[T]

object Test {
  implicit val fa: Foo[Any] = ???
  implicit val ba: Bar[Int] = ???

  def test: Unit = {
    implicitly[Foo[Int]]
  }
}

This fails because Bar[Int] is not considered more specific than Foo[Any], because the variance-flipping we do in isAsSpecificValueType is not thorough enough:

[log frontend] ==> isSubType Bar[Int] <:< Foo[Any]?
[log frontend]   ==> isSubType Bar[Int] <:< Foo?
[log frontend]     ==> isSubType Foo <:< Foo?
[log frontend]     <== isSubType Foo <:< Foo = true
[log frontend]   <== isSubType Bar[Int] <:< Foo = true
[log frontend]   ==> hasMatchingMember(Bar[Int] . Foo$$T :?  =+ Any), mbr:  =- Int?
[log frontend]     ==> isSubType  =- Int <:<  =+ Any?
[log frontend]       ==> isSubType Any <:< Int?
[log frontend]       <== isSubType Any <:< Int = false
[log frontend]     <== isSubType  =- Int <:<  =+ Any = false
[log frontend]   <== hasMatchingMember(Bar[Int] . Foo$$T :?  =+ Any), mbr:  =- Int = false
[log frontend] <== isSubType Bar[Int] <:< Foo[Any] = false

hasMatchingMember returns the original member T in Bar where the variance is not flipped (=- Int). We could add a special case in hasMatchingMember but then we might miss some other cases.
Personally, I've never really been convinced by the rationale for flipping only at the top-level, so I think the simplest solution would be to flip at all levels, then we could use a global mode.

@milessabin
Copy link
Contributor

@odersky I'd appreciate some clarification on this ... it's unlikely that the Scala PR will be merged if the intended semantics in Dotty are unclear.

@smarter
Copy link
Member Author

smarter commented Aug 22, 2017

We've agreed in our internal meeting that the current Dotty behavior is wrong and should be changed so that Bar[Int] is more specific; we've also agreed to keep the current "flip variance only at the top-level" semantics. Of course all of this might still change in the future based on user feedback, etc, which hopefully Miles' implementation will help us get!

@milessabin
Copy link
Contributor

Fixed in scalac ;-)

@smarter
Copy link
Member Author

smarter commented Sep 27, 2017

@smarter smarter closed this as completed Sep 27, 2017
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