-
Notifications
You must be signed in to change notification settings - Fork 21
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
Type inference does not dealias type constructors enough to infer type arguments #8709
Comments
Imported From: https://issues.scala-lang.org/browse/SI-8709?orig=1 |
@Blaisorblade said: $ scalac -Ytyper-debug Bug.scala
|-- <empty> EXPRmode-POLYmode-QUALmode (site: package <root>)
| \-> <empty>.type
|-- object Bug BYVALmode-EXPRmode (site: package <empty>)
| |-- Nothing TYPEmode (site: value ??? in Bug)
| | \-> Nothing
| |-- Nothing TYPEmode (site: value ??? in Bug)
| | \-> Nothing
| |-- super EXPRmode-POLYmode-QUALmode (silent: <init> in Bug)
| | |-- this EXPRmode (silent: <init> in Bug)
| | | \-> Bug.type
| | \-> Bug.type
| |-- $eq$qmark$greater$colon[A, B]PartialFunction[A, B] BYVALmode-EXPRmode (site: object Bug)
| | |-- PartialFunction[A, B] TYPEmode (site: type =?>: in Bug)
| | | |-- A TYPEmode (site: type =?>: in Bug)
| | | | \-> A
| | | |-- B TYPEmode (site: type =?>: in Bug)
| | | | \-> B
| | | \-> PartialFunction[A,B]
| | |-- PartialFunction[A, B] TYPEmode (site: type =?>: in Bug)
| | | \-> PartialFunction[A,B]
| | \-> [type $eq$qmark$greater$colon] Bug.=?>:[A,B]
| |-- Nothing BYVALmode-EXPRmode (site: object Bug)
| | |-- Nothing TYPEmode (site: value ??? in Bug)
| | | \-> Nothing
| | |-- throw new Exception() : pt=Nothing BYVALmode-EXPRmode (site: value ??? in Bug)
| | | |-- new Exception() : pt=Throwable BYVALmode-EXPRmode (site: value ??? in Bug)
| | | | |-- new Exception BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value ??? in Bug)
| | | | | |-- new Exception EXPRmode-POLYmode-QUALmode (silent: value ??? in Bug)
| | | | | | |-- Exception FUNmode-TYPEmode (silent: value ??? in Bug)
| | | | | | | |-- scala.`package` EXPRmode-POLYmode-QUALmode (silent: value ??? in Bug)
| | | | | | | | \-> scala.type
| | | | | | | \-> Exception
| | | | | | \-> Exception
| | | | | \-> (x$1: Throwable)Exception <and> (x$1: String, x$2: Throwable)Exception <and> (x$1: String)Exception <and> ()Exception
| | | | \-> Exception
| | | \-> Nothing
| | \-> [val $qmark$qmark$qmark ] Nothing
| |-- def $qmark$qmark$qmark BYVALmode-EXPRmode (site: object Bug)
| | |-- Nothing : pt=Nothing EXPRmode (site: value ??? in Bug)
| | | |-- Bug.type EXPRmode-POLYmode-QUALmode (site: value ??? in Bug)
| | | | \-> Bug.type
| | | \-> Bug.???.type (with underlying type Nothing)
| | \-> [def $qmark$qmark$qmark] => Nothing
| |-- def or[T, U] BYVALmode-EXPRmode (site: object Bug)
| | |-- _root_.scala.Function1[T, U] TYPEmode (site: method or in Bug)
| | | |-- T TYPEmode (site: method or in Bug)
| | | | \-> T
| | | |-- U TYPEmode (site: method or in Bug)
| | | | \-> U
| | | \-> T => U
| | |-- $eq$qmark$greater$colon[T, U] TYPEmode (site: value f in Bug)
| | | |-- T TYPEmode (site: value f in Bug)
| | | | \-> T
| | | |-- U TYPEmode (site: value f in Bug)
| | | | \-> U
| | | \-> Bug.=?>:[T,U]
| | |-- _root_.scala.Function1[T, U] TYPEmode (site: value g in Bug)
| | | |-- T TYPEmode (site: value g in Bug)
| | | | \-> T
| | | |-- U TYPEmode (site: value g in Bug)
| | | | \-> U
| | | \-> T => U
| | |-- $eq$qmark$greater$colon[T, U] TYPEmode (site: value f in Bug)
| | | \-> Bug.=?>:[T,U]
| | |-- _root_.scala.Function1[T, U] TYPEmode (site: value g in Bug)
| | | \-> T => U
| | |-- _root_.scala.Function1[T, U] TYPEmode (site: method or in Bug)
| | | \-> T => U
| | |-- $qmark$qmark$qmark : pt=T => U EXPRmode (site: method or in Bug)
| | | \-> Nothing
| | \-> [def or] [T, U](f: Bug.=?>:[T,U])(g: T => U)T => U
| |-- def bar BYVALmode-EXPRmode (site: object Bug)
| | |-- $eq$qmark$greater$colon[String, String] TYPEmode (site: method bar in Bug)
| | | |-- String TYPEmode (site: method bar in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | |-- String TYPEmode (site: method bar in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | \-> Bug.=?>:[String,String]
| | |-- $eq$qmark$greater$colon[String, String] TYPEmode (site: method bar in Bug)
| | | |-- String TYPEmode (site: method bar in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | |-- String TYPEmode (site: method bar in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | \-> Bug.=?>:[String,String]
| | |-- $qmark$qmark$qmark : pt=Bug.=?>:[String,String] EXPRmode (site: method bar in Bug)
| | | \-> Nothing
| | \-> [def bar] => Bug.=?>:[String,String]
| |-- def foo BYVALmode-EXPRmode (site: object Bug)
| | |-- _root_.scala.Function1[String, String] TYPEmode (site: method foo in Bug)
| | | |-- String TYPEmode (site: method foo in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | |-- String TYPEmode (site: method foo in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | \-> String => String
| | |-- _root_.scala.Function1[String, String] TYPEmode (site: method foo in Bug)
| | | |-- String TYPEmode (site: method foo in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | |-- String TYPEmode (site: method foo in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | \-> String => String
| | |-- $qmark$qmark$qmark : pt=String => String EXPRmode (site: method foo in Bug)
| | | \-> Nothing
| | \-> [def foo] => String => String
| |-- def bippy BYVALmode-EXPRmode (site: object Bug)
| | |-- _root_.scala.Function1[String, String] TYPEmode (site: method bippy in Bug)
| | | |-- String TYPEmode (site: method bippy in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | |-- String TYPEmode (site: method bippy in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | \-> String => String
| | |-- _root_.scala.Function1[String, String] TYPEmode (site: method bippy in Bug)
| | | |-- String TYPEmode (site: method bippy in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | |-- String TYPEmode (site: method bippy in Bug)
| | | | [adapt] String is now a TypeTree(String)
| | | | \-> String
| | | \-> String => String
| | |-- or(bar.orElse(bar))(foo) : pt=String => String EXPRmode (site: method bippy in Bug)
| | | |-- or(bar.orElse(bar)) BYVALmode-EXPRmode-FUNmode-POLYmode (silent: method bippy in Bug)
| | | | |-- or BYVALmode-EXPRmode-FUNmode-POLYmode (silent: method bippy in Bug)
| | | | | [adapt] [T, U](f: Bug.=?>:[T,U])(g: T => U)T => U adapted to [T, U](f: Bug.=?>:[T,U])(g: T => U)T => U
| | | | | \-> (f: Bug.=?>:[T,U])(g: T => U)T => U
| | | | |-- bar.orElse(bar) : pt=Bug.=?>:[?,?] BYVALmode-EXPRmode-POLYmode (silent: method bippy in Bug)
| | | | | |-- bar.orElse BYVALmode-EXPRmode-FUNmode-POLYmode (silent: method bippy in Bug)
| | | | | | |-- bar EXPRmode-POLYmode-QUALmode (silent: method bippy in Bug)
| | | | | | | \-> Bug.=?>:[String,String]
| | | | | | [adapt] [A1 <: A, B1 >: B](that: PartialFunction[A1,B1])PartialFu... adapted to [A1 <: A, B1 >: B](that: PartialFunction[A1,B1])PartialFu...
| | | | | | \-> (that: PartialFunction[A1,B1])PartialFunction[A1,B1]
| | | | | |-- bar : pt=PartialFunction[?,?] BYVALmode-EXPRmode-POLYmode (silent: method bippy in Bug)
| | | | | | \-> Bug.=?>:[String,String]
| | | | | solving for (A1: ?A1, B1: ?B1)
| | | | | \-> PartialFunction[String,String]
| | | | solving for (T: ?T, U: ?U)
| | | | \-> (g: T => String)T => String
Bug.scala:15: error: type mismatch;
found : PartialFunction[String,String]
required: Bug.=?>:[T,String]
(which expands to) PartialFunction[T,String]
or(bar orElse bar)(foo)
^
| | | |-- foo : pt=<error> EXPRmode (site solving: type T: method bippy in Bug)
| | | | solving for (T: ?T)
| | | | \-> String => String
| | | \-> <error>
| | \-> [def bippy] => String => String
| \-> [object Bug] Bug.type
one error found |
@retronym said: type =?>:[-A, +B] = PartialFunction[A, B] With this in mind, can you dig a bit further to show that there is a bug here? |
@Blaisorblade said: In fairness, I forgot to mention that or[String, String](bar orElse bar)(foo) typechecks correctly, as does Also, I just checked that dotty (38b00c5e7a2d3ea43391b5210925aaca13c79b36) does accept the example. Moreover, given that the alias can be statically resolved, I don't see how the two possible declarations of Given that type inference is not really specified, whether this is a Scalac bug is of course up to you. And how hard it is to change this (without breaking other things) is a different question. However, if you want to close this, you should convince SBT and dotty to fix their behavior :-) object Bug {
type =?>:[A, B] = PartialFunction[A, B]
val ??? : Nothing = throw new Exception
//Does not work.
def or[T, U](f: T =?>: U)(g: T => U): T => U =
//Works.
//def or[T, U](f: PartialFunction[T, U])(g: T => U): T => U =
//x => f applyOrElse (x, g)
???
def bar: String =?>: String = ???
def foo: String => String = ???
def bippy: String => String =
or(bar orElse bar)(foo) //Fails
def bippyWorking =
or(bar)(foo)
def theArg = bar orElse bar //Inferred type: PartialFunction[String,String]
def bippy2 = or(theArg)(foo) //Also fails
def theArg2: String =?>: String = bar orElse bar
def bippy3 = or(theArg2)(foo) //Succeeds.
} |
Triaged, unclear it's a bug, unlikely to progress in Scala 2. |
I disagree ... reopening :-) |
Scalac refuses to infer the type arguments of
or
below, in the definition ofbippy
. If however I inline the =?>: alias, it manages. I thought it was a regression, but it's there on every Scala I happen to have around (in 2.9.2, 2.10.3, 2.11.0 and 2.11.1).In 2.11.0:
In 2.9.2:
Random/fun facts:
What's more fun is that when
or
and its clients are in different files: introducing the breakage in the interface won't change the SBT interface "hash", so the client will not be recompiled right away, only when you're least expecting it (say, you clean).Original instance here:
inc-lc/ilc-scala@bea1580#diff-c23523827d5e9b210d097946ecae4a46L6
Error witnessed also on Travis below
https://travis-ci.org/inc-lc/ilc-scala/jobs/29252425
I thought it was a duplicate, but the only similar issue (at least superficially) seems #3777.
The text was updated successfully, but these errors were encountered: