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

lub weirdness #5317

Closed
scabug opened this issue Dec 15, 2011 · 5 comments
Closed

lub weirdness #5317

scabug opened this issue Dec 15, 2011 · 5 comments
Assignees
Labels

Comments

@scabug
Copy link

scabug commented Dec 15, 2011

It seems there is a serious regression of lub between 2.9 and 2.10, which leads to illogical types.
Here is one scenario which works:

scala> trait S { type T }
defined trait S

scala> trait A extends S { type T <: A }
defined trait A

scala> trait B extends S { type T <: B }
defined trait B

scala> val a = new A{}
a: Object with A = $anon$1@edfd5b8

scala> val b = new B{}
b: Object with B = $anon$1@68d88d5

scala> val x = if (true) a else b
x: S{type T <: S} = $anon$1@edfd5b8

This one looks good. Now, add a field x to types S, A, B:

scala> trait S { type T; val x: AnyRef }
defined trait S

scala> trait A extends S { type T <: A; val x: A = null }
defined trait A

scala> trait B extends S { type T <: B; val x: B = null }
defined trait B

scala> val a = new A{}
a: Object with A = $anon$1@370410a7

scala> val b = new B{}
b: Object with B = $anon$1@2a3fa87a

scala> val x = if (true) a else b
x: ScalaObject with S = $anon$1@370410a7

I would have expected to see S { type T <: S; val x: S as the type but instead I get ScalaObject with S.
Note this is a regression from 2.9.1, where I get ScalaObject with S{val x: ScalaObject with S; type T <: ScalaObject with S}.

Since this affects fundamental type operations I classify a solution as critical for 2.10.

@scabug
Copy link
Author

scabug commented Dec 15, 2011

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

@scabug
Copy link
Author

scabug commented Dec 15, 2011

@paulp said:
Eugene recently opened this as #5302. See my comment there; this will be easy to fix one way or another, I only need to understand why/how this situation arises:

type C = lub(A, B)
!(A <:< C)

Doesn't the definition of "lub" require that to be true? Both that ticket and this one lead to situations where it isn't.

@scabug
Copy link
Author

scabug commented Dec 16, 2011

@paulp said:
I have pinpointed this; it's definitely NullaryMethodType not being handled in the isSubType2 typecase. I have a blunt instrument fix, but I'm investigating something more appealing.

@scabug
Copy link
Author

scabug commented Dec 16, 2011

@paulp said:
That's slipperier than I'd thought. Since there's a good chance that even if I come up with something it will not be quite what you want, I will table this for an opinion.

The long and the short of it is that a subtype test is done with a nullary method type on the left and a refinement on the right. The nullary result type is a subtype of the refined type, but the nullary method itself is not. Poking around I tried letting those through; then the lub is correctly calculated and everything looks good for a while, until cleanup when it crashes here:

          val t: Tree = ad.symbol.tpe match {
            case MethodType(mparams, resType) =>
              assert(params.length == mparams.length)
              typedPos {
                val sym = currentOwner.newValue(ad.pos, mkTerm("qual")) setInfo qual0.tpe
                qual = safeREF(sym)

                BLOCK(
                  VAL(sym) === qual0,
                  callAsReflective(mparams map (_.tpe), resType)
                )
              }
          }

With a match error because a TypeRef turns up. In case that's interesting.

@scabug
Copy link
Author

scabug commented Dec 26, 2011

@paulp said:
This is fixed in f737e35ddf . The commit message explains what happened.

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

No branches or pull requests

2 participants