-
Notifications
You must be signed in to change notification settings - Fork 21
Type aliases with return type inference works bad #8740
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
Comments
Imported From: https://issues.scala-lang.org/browse/SI-8740?orig=1 |
@retronym said: But I pushed on to analyze why this fails. See the comments in the test case here: https://github.com/retronym/scala/compare/scala:2.11.x...ticket/8740?expand=1 That branch also sketches out a fix, in which I reorder the descent into a refinement's parent types on the LHS to avoid overconstraining type variables. |
@milessabin said: |
@retronym said: I was never all that happy with my solution, it seemed very arbitrary. Maybe this version would be a fraction less ugly. def check = parents exists (retry(_, tp2))
if (tp.isGround) check
else suspendingTypeVars(typeVarsInType(tp))(check) else check |
@benhutchison said: In the failing example,
That is, can't stack 2 aliases over a tagged type, but 1 seems OK. |
@cvogt said: |
B. Tommy Jensen (tommy-at-grindvoll.com) said: |
Tweak the example a bit and I suspect the outlined fix breaks down again: trait SomeTag
type @@[+A, T] = A with T
def withSomeTag[A, B](a: A): A @@ B = a.asInstanceOf[A @@ B]
// def need(a: String @@ SomeTag) = ??? // <- it works
// but this not:
type TypeAlias = String @@ SomeTag
def need(a: TypeAlias) = ???
need(withSomeTag("foo")) Now we have type variables in both parents of the refined type (not uncommon if we're defining an implicit typeclass instance for any tag) and |
This works though: trait Tagged[T]
trait SomeTag
type @@[+A, T] = Tagged[T] with A
def withSomeTag[A, B](a: A): A @@ B = a.asInstanceOf[A @@ B]
// def need(a: String @@ SomeTag) = ??? // <- it works
// but this not:
type TypeAlias = String @@ SomeTag
def need(a: TypeAlias) = ???
need(withSomeTag("foo")) |
^ Sorry, now it infers the correct types, but the erasure is wrong 😩 |
A workaround that works: object Main {
trait SomeTag
type @@[+A, T] <: A with T
def withSomeTag[A, B](a: A): A @@ B = a.asInstanceOf[A @@ B]
// def need(a: String @@ SomeTag) = ??? // <- it works
// but this not:
type TypeAlias = String @@ SomeTag
def need(a: TypeAlias) = ???
need(withSomeTag("foo"))
} The only downside is that primitives will be boxed. |
Example below shows the problem:
Causes:
Changing parameter's type to unaliased version works fine.
Because of this bug, using of scalaz.Tag / shapeless.tag.Tagged is difficult.
The text was updated successfully, but these errors were encountered: