Skip to content

Imprecise type inference on pattern #4816

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
Medowhill opened this issue Jul 20, 2018 · 3 comments
Closed

Imprecise type inference on pattern #4816

Medowhill opened this issue Jul 20, 2018 · 3 comments

Comments

@Medowhill
Copy link
Contributor

import annotation.unchecked.uncheckedVariance

abstract class Type {
  def dealias: Type
}

object Trees {
  abstract class Tree[-T >: Null] {
    def tpe: T @uncheckedVariance = ???
  }

  case class AppliedTypeTree[-T >: Null]() extends Tree[T]
}

abstract class Instance[T >: Null <: Type] {
  type Tree = Trees.Tree[T]
  type AppliedTypeTree = Trees.AppliedTypeTree[T]
}

object untpd extends Instance[Null] {
  case class TypedSplice(tree: tpd.Tree) extends Tree

  def New(tpt: Tree): Type = tpt match {
    case TypedSplice(tpt1: AppliedTypeTree) => tpt1.tpe.dealias
    case _ => ???
  }
}

object tpd extends Instance[Type]

When I compiled the above code by scalac, it succeeded. However, when I used dotc, it failed with the following error message:

-- [E008] Member Not Found Error: Test.scala:24:56 -----------------------------
24 |    case TypedSplice(tpt1: AppliedTypeTree) => tpt1.tpe.dealias
   |                                               ^^^^^^^^^^^^^^^^
   |              value `dealias` is not a member of Null @uncheckedVariance
one error found

When I changed tpt1: AppliedTypeTree into tpt1: tpd.AppliedTypeTree in line 24, it was compiled successfully on both scalac and dotc.
Changing tpt1: AppliedTypeTree into tpt1 @ Trees.AppliedTypeTree() also worked.

I found this issue while working on issue #4557. Related PR can be found at #4798.

@Blaisorblade
Copy link
Contributor

My initial analysis is that tpt1 should be typed as tpd.Tree & AppliedTypeTree, that this simplifies to Trees. AppliedTypeTree[Type], and that then tpt1.tpe should have type Type and not Null, so Scalac is right. Haven't verified what happens in Dotty.

@Medowhill
Copy link
Contributor Author

A more simplified version:

trait A
trait B

object X {
  def unapply(x: Any): Option[A] = ???
}

trait T {
  0 match {
    case X(a: B) => a: A
    case _ =>
  }
}

Compiled in scalac, but failed in dotc with the following:

-- [E007] Type Mismatch Error: ../C1.scala:10:20 -------------------------------
10 |    case X(a: B) => a: A
   |                    ^
   |                    found:    B(a)
   |                    required: A

It looks like dotc infers a as B rather than A & B.

@smarter
Copy link
Member

smarter commented Jul 27, 2018

This is a known issue: #3208

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

3 participants