Scala Programming Language
  1. Scala Programming Language
  2. SI-7782

type inference regression after analyzer plugins patch

    Details

      Description

      package pack
      
      object Test1 {
        import TestIteratee1._
      
        def foo(empty: Any): Any = ???
      
        foo(empty = ???)
      }
      
      object TestIteratee1
        extends TestEnumeratorTFunctions
           with TestEnumeratorPFunctions
      
      trait TestEnumeratorT {
        def map[BB](f: Int => BB)
      }
      
      abstract class TestEnumeratorP[E, F[_]] {
      
        def test[B](f: Int => B): Any = {
          (null: TestEnumeratorT).map(f)
          ???
        }
      }
      
      trait TestEnumeratorPFunctions {
        def empty[E, F[_]]: TestEnumeratorP[E, F] = ???
      }
      
      trait TestEnumeratorTFunctions {
        def empty[E, F[_]](implicit a: Any): Any = ???
      }
      
       /code/scala scalac-hash e67a039 /Users/jason/code/scratch3/src/main/scala/pack/TestEnumeratorP.scala
      [info] e67a039 => /Users/jason/usr/scala-v2.11.0-M1-393-ge67a039
      warning: there were 3 feature warnings; re-run with -feature for details
      one warning found
        /code/scala scalac-hash f3cdf14 /Users/jason/code/scratch3/src/main/scala/pack/TestEnumeratorP.scala[info] f3cdf14 => /Users/jason/usr/scala-v2.10.0-463-gf3cdf14
      warning: there were 3 feature warnings; re-run with -feature for details
      one warning found
        /code/scala scalac-hash df8de9063 /Users/jason/code/scratch3/src/main/scala/pack/TestEnumeratorP.scala
      [info] df8de9063 => /Users/jason/usr/scala-v2.11.0-M1-401-gdf8de90
      /Users/jason/code/scratch3/src/main/scala/pack/TestEnumeratorP.scala:22: error: no type parameters for method map: (f: Int => BB)Unit exist so that it can be applied to arguments (Int => B)
       --- because ---
      argument expression's type is not compatible with formal parameter type;
       found   : Int => B
       required: Int => ?BB
          (null: TestEnumeratorT).map(f)
                                  ^
      /Users/jason/code/scratch3/src/main/scala/pack/TestEnumeratorP.scala:22: error: type mismatch;
       found   : Int => B
       required: Int => BB
          (null: TestEnumeratorT).map(f)
                                      ^
      two errors found
        /code/scala git show df8de9063
      commit df8de9063ce2008d2e23b46b6464abee03f75e5a
      Merge: e67a039 f3cdf14
      Author: Lukas Rytz <lukas.rytz@epfl.ch>
      Date:   Mon Feb 4 11:32:14 2013 +0100
      
          Merge commit 'f3cdf146709e0dd98533ee77e8ca2566380cb932'
      
          Conflicts:
              src/compiler/scala/tools/nsc/typechecker/Contexts.scala
              src/compiler/scala/tools/nsc/typechecker/Namers.scala
              src/compiler/scala/tools/nsc/typechecker/Typers.scala
              src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
              src/reflect/scala/reflect/internal/AnnotationCheckers.scala
              src/reflect/scala/reflect/internal/Symbols.scala
      

        Activity

        Hide
        Jason Zaugg added a comment -

        Further reduced:

        package pack
        
        object Named {
          import O.empty
          def foo(empty: Any): Any = ???
          // is `empty` a named arg or an assignment? Checking for that has nasty side effects!
          foo(empty = ???)
        }
        
        object O {
          // order matters (!!!)
          def empty(implicit a: Any): Any = ???
          def empty[E]: C[E] = ???
        }
        
        abstract class C[E] {
          def foo[BB](f: BB)
          def test[B](f: B): Any = foo(f)
        }
        
        
        Show
        Jason Zaugg added a comment - Further reduced: package pack object Named { import O.empty def foo(empty: Any): Any = ??? // is `empty` a named arg or an assignment? Checking for that has nasty side effects! foo(empty = ???) } object O { // order matters (!!!) def empty(implicit a: Any): Any = ??? def empty[E]: C[E] = ??? } abstract class C[E] { def foo[BB](f: BB) def test[B](f: B): Any = foo(f) }
        Hide
        Jason Zaugg added a comment - - edited

        Okay, this is skolem related.

        package pack
        
        object Test {
          import O.empty
          empty // this will trigger PolyTypeCompleter of `test`
                // which picks up `skolemizationLevel = 1` from the in-flight `isAsSpecific` check
                // that happens to be computing `Any <:< pack.this.C[E] forSome { E }`
        }
        
        object O {
          // order matters (!!!)
          def empty(implicit a: Any): Any = ???
          def empty[E]: C[E] = ???
        }
        
        abstract class C[E] {
          def foo[BB](f: BB)
          def test[B](f: B): Any = foo(f)
          // error: no type parameters for method foo: (<param> f: BB)scala.this.Unit exist so that it can be applied to arguments (B&1)
          // --- because ---
          // argument expression's type is not compatible with formal parameter type;
          // found   : B&1
          // required: ?BB
        }
        
        Show
        Jason Zaugg added a comment - - edited Okay, this is skolem related. package pack object Test { import O.empty empty // this will trigger PolyTypeCompleter of `test` // which picks up `skolemizationLevel = 1` from the in-flight `isAsSpecific` check // that happens to be computing `Any <:< pack.this.C[E] forSome { E }` } object O { // order matters (!!!) def empty(implicit a: Any): Any = ??? def empty[E]: C[E] = ??? } abstract class C[E] { def foo[BB](f: BB) def test[B](f: B): Any = foo(f) // error: no type parameters for method foo: (<param> f: BB)scala.this.Unit exist so that it can be applied to arguments (B&1) // --- because --- // argument expression's type is not compatible with formal parameter type; // found : B&1 // required: ?BB }
        Hide
        Jason Zaugg added a comment -

        2.10.2 is also susceptible to the problem:

        package pack
        
        object Test {
          import O.empty
          empty // this will trigger completion of `test`
                // with skolemizationLevel = 1
        }
        
        object O {
          // order matters (!!!)
          // def empty(implicit a: Any): Any = ???
          def empty[E]: C[E] = ???
           def empty(implicit a: Any): Any = ???
        }
        
        abstract class C[E] {
          def foo[BB](f: BB)
          def test[B](f: B): Any = foo(f)
          // error: no type parameters for method foo: (<param> f: BB)scala.this.Unit exist so that it can be applied to arguments (B&1)
          // --- because ---
          // argument expression's type is not compatible with formal parameter type;
          // found   : B&1
          // required: ?BB
        }
        

        I had to switch the order of the `empty` methods around as a `inferExprAlternative` seems to try these in a a different order in master, and if the completers trigger earlier outside of:

              case ExistentialType(_, _) =>
                try {
                  skolemizationLevel += 1
                  isSubType(tp1.skolemizeExistential, tp2, depth)
                } finally {
                  skolemizationLevel -= 1
                }
        
        

        This test case regresses at: b74c33eb860622e363 "SI-1803, plus documentation and cleanups in Namers, mainly in typeSig".

        I think the fix is to force the level of skolems derived in `PolyTypeCompleter` to 0.

        Show
        Jason Zaugg added a comment - 2.10.2 is also susceptible to the problem: package pack object Test { import O.empty empty // this will trigger completion of `test` // with skolemizationLevel = 1 } object O { // order matters (!!!) // def empty(implicit a: Any): Any = ??? def empty[E]: C[E] = ??? def empty(implicit a: Any): Any = ??? } abstract class C[E] { def foo[BB](f: BB) def test[B](f: B): Any = foo(f) // error: no type parameters for method foo: (<param> f: BB)scala.this.Unit exist so that it can be applied to arguments (B&1) // --- because --- // argument expression's type is not compatible with formal parameter type; // found : B&1 // required: ?BB } I had to switch the order of the `empty` methods around as a `inferExprAlternative` seems to try these in a a different order in master, and if the completers trigger earlier outside of: case ExistentialType(_, _) => try { skolemizationLevel += 1 isSubType(tp1.skolemizeExistential, tp2, depth) } finally { skolemizationLevel -= 1 } This test case regresses at: b74c33eb860622e363 " SI-1803 , plus documentation and cleanups in Namers, mainly in typeSig". I think the fix is to force the level of skolems derived in `PolyTypeCompleter` to 0.
        Hide
        Jason Zaugg added a comment -
        Show
        Jason Zaugg added a comment - PR: https://github.com/scala/scala/pull/2876

          People

          • Assignee:
            Jason Zaugg
            Reporter:
            Jason Zaugg
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development