Skip to content

Wrong type inferred with Function1 and type parameter in result type #5413

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
panacekcz opened this issue Nov 8, 2018 · 2 comments · Fixed by #9142
Closed

Wrong type inferred with Function1 and type parameter in result type #5413

panacekcz opened this issue Nov 8, 2018 · 2 comments · Fixed by #9142

Comments

@panacekcz
Copy link
Contributor

This test (loosely based on tests/pos/t2023.scala) normally compiles, but does not pass -Ycheck:all:

trait Or[A]
trait C

object ImplicitChainTest {
  def ipl[A](implicit from: A => Or[A]): C = null
  ipl
}

Output of dotc -Ycheck:all Test.scala:

checking Test.scala after phase frontend
exception while typing ImplicitChainTest.ipl[Or[_]]($conforms[Or[_]]) of class class dotty.tools.dotc.ast.Trees$Apply # 255
exception while typing final module class ImplicitChainTest() extends Object() { 
  this: ImplicitChainTest.type =>
 
  def ipl[A >: Nothing <: Any](implicit from: Function1[A, Or[A]]): C = null
  ImplicitChainTest.ipl[Or[_]]($conforms[Or[_]])
} of class class dotty.tools.dotc.ast.Trees$TypeDef # 257
exception while typing package <empty> {
  <trait> interface trait Or[A >: Nothing <: Any]() extends Object { 
     A
  }
  <trait> interface trait C() extends Object {}
  final lazy module val ImplicitChainTest: ImplicitChainTest = 
    new ImplicitChainTest()
  final module class ImplicitChainTest() extends Object() { 
    this: ImplicitChainTest.type =>
   
    def ipl[A >: Nothing <: Any](implicit from: Function1[A, Or[A]]): C = null
    ImplicitChainTest.ipl[Or[_]]($conforms[Or[_]])
  }
} of class class dotty.tools.dotc.ast.Trees$PackageDef # 258
*** error while checking Test.scala after phase frontend ***
exception occurred while compiling Test.scala
java.lang.AssertionError: assertion failed: found:    Or[_] <:< Or[_]
required: Or[_] => Or[Or[_]]


tree = $conforms[Or[_]] while compiling Test.scala
Exception in thread "main" java.lang.AssertionError: assertion failed: found:    Or[_] <:< Or[_]
required: Or[_] => Or[Or[_]]


tree = $conforms[Or[_]]
	at scala.Predef$.assert(Predef.scala:219)
	at dotty.tools.dotc.transform.TreeChecker$Checker.adapt(TreeChecker.scala:465)
	at dotty.tools.dotc.typer.ProtoTypes$FunProto.typedArg(ProtoTypes.scala:302)
	at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:711)
	at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:709)
	at dotty.tools.dotc.typer.Applications$Application.addTyped$1(Applications.scala:478)
	at dotty.tools.dotc.typer.Applications$Application.matchArgs(Applications.scala:520)
	at dotty.tools.dotc.typer.Applications$Application.init(Applications.scala:299)
	at dotty.tools.dotc.typer.Applications$TypedApply.<init>(Applications.scala:612)
	at dotty.tools.dotc.typer.Applications$ApplyToUntyped.<init>(Applications.scala:710)
	at dotty.tools.dotc.typer.Applications.simpleApply$1(Applications.scala:770)
	at dotty.tools.dotc.typer.Applications.$anonfun$typedApply$7(Applications.scala:795)
	at dotty.tools.dotc.typer.Typer.tryEither(Typer.scala:2053)
	at dotty.tools.dotc.typer.Applications.$anonfun$typedApply$1(Applications.scala:796)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:37)
	at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:740)
	at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:841)
	at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:738)
	at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:79)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1885)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1939)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:110)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:269)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1970)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1966)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1982)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:257)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2021)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2034)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedStats(TreeChecker.scala:432)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedClassDef$1(Typer.scala:1597)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:37)
	at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:1519)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedClassDef(TreeChecker.scala:385)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1875)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1938)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:110)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:269)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1970)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1966)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1982)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:257)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2001)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2034)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedStats(TreeChecker.scala:432)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedPackageDef$1(Typer.scala:1711)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:37)
	at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:1704)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1917)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1939)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:110)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:269)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1970)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1966)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1982)
	at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:257)
	at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:2045)
	at dotty.tools.dotc.transform.TreeChecker.check(TreeChecker.scala:122)
	at dotty.tools.dotc.transform.TreeChecker.run(TreeChecker.scala:94)
	at dotty.tools.dotc.core.Phases$Phase.$anonfun$runOn$1(Phases.scala:297)
	at scala.collection.immutable.List.map(List.scala:282)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:295)
	at dotty.tools.dotc.core.Phases$Phase.runOn$(Phases.scala:294)
	at dotty.tools.dotc.transform.TreeChecker.runOn(TreeChecker.scala:38)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$3(Run.scala:172)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
	at dotty.tools.dotc.util.Stats$.trackTime(Stats.scala:49)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$2(Run.scala:169)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$2$adapted(Run.scala:167)
	at scala.collection.IndexedSeqOptimized.foreach(IndexedSeqOptimized.scala:32)
	at scala.collection.IndexedSeqOptimized.foreach$(IndexedSeqOptimized.scala:29)
	at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:194)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:167)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$1(Run.scala:192)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:90)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:147)
	at dotty.tools.dotc.Run.compileSources(Run.scala:134)
	at dotty.tools.dotc.Run.compile(Run.scala:118)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:30)
	at dotty.tools.dotc.Driver.process(Driver.scala:136)
	at dotty.tools.dotc.Driver.process(Driver.scala:105)
	at dotty.tools.dotc.Driver.process(Driver.scala:117)
	at dotty.tools.dotc.Driver.main(Driver.scala:144)
	at dotty.tools.dotc.Main.main(Main.scala)
@nicolasstucki
Copy link
Contributor

This can be reproduced without implicits with

object Foo {
  type Or[A]
  def foo[A](from: A => Or[A]): Any = null
  def id[A]: A => A = identity
  foo(id)
}

where typer produces

package <empty> {
  final lazy module val Foo: Foo$ = new Foo$()
  final module class Foo$() extends Object(), _root_.scala.Serializable { 
    this: Foo.type =>
   
    type Or[A >: Nothing <: Any] >: Nothing <: Any
    def foo[A >: Nothing <: Any](from: Function1[A, Foo.Or[A]]): Any = null
    def id[A >: Nothing <: Any]: Function1[A, A] = 
      {
        def $anonfun(x: A): A = identity[A](x)
        closure($anonfun)
      }
    Foo.foo[Foo.Or[_]](Foo.id[Foo.Or[_]])
  }
}

this issue is that the inferred type Foo.Or[_] is not valid.

Though writing the inferred type explicitly does result in the correct typing error

6 |  foo(id[Or[_]])
  |      ^^^^^^^^^
  |      Found:    Foo.Or[_] => Foo.Or[_]
  |      Required: Nothing => Foo.Or[A]
  |      
  |      where:    A is a type variable

or

-- [E007] Type Mismatch Error: Foo.scala:6:13 ----------------------------------
6 |  foo[Or[_]](id)
  |             ^^
  |             Found:    Nothing => Nothing
  |             Required: Foo.Or[_] => Foo.Or[Foo.Or[_]]

This could be due to a missing constraint while inferring the type of A.

@nicolasstucki nicolasstucki changed the title Ycheck failure on implicit Function1 with inferred type parameter in result type Ycheck failure on Function1 with inferred type parameter in result type May 2, 2019
@nicolasstucki nicolasstucki changed the title Ycheck failure on Function1 with inferred type parameter in result type Wrong type inferred with Function1 and type parameter in result type May 2, 2019
@odersky
Copy link
Contributor

odersky commented Mar 6, 2020

It infers a weird type, which looks nevertheless type correct.

package <empty> {
  final lazy module val Foo: Foo$ = new Foo$()
  final module class Foo$() extends Object(), _root_.scala.Serializable { 
    this: Foo.type =>
    type Or[A >: Nothing <: Any] >: Nothing <: Any
    def foo[A >: Nothing <: Any](from: Function1[A, Foo.Or[A]]): Any = null
    def id[A >: Nothing <: Any]: Function1[A, A] = 
      {
        def $anonfun(x: A): A = identity[A](x)
        closure($anonfun)
      }
    Foo.foo[Foo.Or[?]](Foo.id[Foo.Or[Foo.Or[?]]])
  }
}

This looks more like a problem with -Ycheck to me that it cannot typecheck this corner-case.

nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jun 9, 2020
@nicolasstucki nicolasstucki linked a pull request Jun 9, 2020 that will close this issue
anatoliykmetyuk added a commit that referenced this issue Jun 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants