Uploaded image for project: 'Scala Programming Language'
  1. Scala Programming Language
  2. SI-5259

Bogus type mismatch reported against default implicit argument

    Details

      Description

      With trunk as of 2.10.0.r26093-b20111130020250 compiling the following,

      class A[T]
      class B {
        def m(a: A[this.type] = new A[this.type]) { }
      }
       
      object DefaultArgBogusTypeMismatch {
        def newB = new B
       
        newB.m()
       
        // this compiles
        // val stableB = new B
        // stableB.m()
      }
      

      Results in the error report below,

      t5259.scala:9: error: type mismatch;
       found   : A[_2.type] where val _2: B
       required: A[_1.type] where val _1: B
        newB.m()
             ^
      

      Adriaan's comment is that it shouldn't be necessary to existentially abstract over the "this" reference, which is what's causing the problem here.

        Attachments

          Activity

          Hide
          rytz Lukas Rytz added a comment -

          same behavior since at least 2.8.1

          Show
          rytz Lukas Rytz added a comment - same behavior since at least 2.8.1
          Hide
          rytz Lukas Rytz added a comment -

          This is not so easy to fix. The invocation

          newB.m()
          

          is first transformed by named/default args to

          { val qual$1 = newB
            qual$1.m(qual$1.m$default$1)
          }
          

          In the method call qual$1.m, the qualifier tree Ident(qual$1) is created in blockWithQualifier using gen.mkAttributedRef which doesn't assign a SingleType.

          That's why the qualifier has type B instead of SingleType(qual$1). Selecting the m method therefore has an existential type

          qual$1.m: (a: A[_1.type])Unit

          Note that I applied a small change which runs the type-checker on the Select node, instead of assigning the type directly:

          -          val f = Select(gen.mkAttributedRef(sym), selected)
          -                   .setType(baseFun1.tpe).setSymbol(baseFun1.symbol)
          +          val sel = Select(gen.mkAttributedRef(sym), selected)
          +          val f = blockTyper.typedOperator(sel)
          

          Then there's the question why qual$1.m$default$1 also has an existential types, but I guess it's something along the same lines.

          Anyway, I'll stop working on this for now, it seems a very cornery case, and there's no deep underlying bad bug, it's due to the singleton this.type.

          Show
          rytz Lukas Rytz added a comment - This is not so easy to fix. The invocation newB.m() is first transformed by named/default args to { val qual$1 = newB qual$1.m(qual$1.m$default$1) } In the method call qual$1.m , the qualifier tree Ident(qual$1) is created in blockWithQualifier using gen.mkAttributedRef which doesn't assign a SingleType . That's why the qualifier has type B instead of SingleType(qual$1) . Selecting the m method therefore has an existential type qual$1.m: (a: A[_1.type])Unit Note that I applied a small change which runs the type-checker on the Select node, instead of assigning the type directly: - val f = Select(gen.mkAttributedRef(sym), selected) - .setType(baseFun1.tpe).setSymbol(baseFun1.symbol) + val sel = Select(gen.mkAttributedRef(sym), selected) + val f = blockTyper.typedOperator(sel) Then there's the question why qual$1.m$default$1 also has an existential types, but I guess it's something along the same lines. Anyway, I'll stop working on this for now, it seems a very cornery case, and there's no deep underlying bad bug, it's due to the singleton this.type .
          Hide
          rytz Lukas Rytz added a comment -

          Oh, I just realized that we can create an Ident tree and type-check it instead of using gen.mkAttributedRef, that should be fine in this case (it's always an Ident to a the local value). So now the question is only about qual$1.m$default$1

          Show
          rytz Lukas Rytz added a comment - Oh, I just realized that we can create an Ident tree and type-check it instead of using gen.mkAttributedRef , that should be fine in this case (it's always an Ident to a the local value). So now the question is only about qual$1.m$default$1
          Show
          rytz Lukas Rytz added a comment - fixed in https://github.com/scala/scala/commit/7d79c4460814c9f8997de0fa1d756a734fb8a3d3

            People

            • Assignee:
              rytz Lukas Rytz
              Reporter:
              milessabin Miles Sabin
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: