Skip to content
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 error when instantiating an object with a default argument #9970

Open
scabug opened this issue Oct 19, 2016 · 7 comments
Open

Type error when instantiating an object with a default argument #9970

scabug opened this issue Oct 19, 2016 · 7 comments
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) named/default args typer
Milestone

Comments

@scabug
Copy link

scabug commented Oct 19, 2016

The compiler allows to define this

class A[T](foo: T => Map[Int, Int] = (_: T) => Map.empty)

which implies that it infered that Map.empty to be of type Map[Int, Int], if we instanciate new A[String]() the compilation fails with

cmd9.sc:1: polymorphic expression cannot be instantiated to expected type;
 found   : [T]T => scala.collection.immutable.Map[Nothing,Nothing]
 required: ? => Map[Int,Int]
@scabug
Copy link
Author

scabug commented Oct 19, 2016

Imported From: https://issues.scala-lang.org/browse/SI-9970?orig=1
Reporter: Diogo Sousa (orium)
Affected Versions: 2.11.8
See #8884

@scabug
Copy link
Author

scabug commented Oct 19, 2016

@som-snytt said:
If it implied that, then we could leave off the param type ascription:

scala> class A[T] { def f: T => Map[Int, Int] = _ => Map.empty } // print

class A[T] {^J  def f: _root_.scala.Function1[T, scala.Predef.Map[scala.Int, scala.Int]] = ((x$1: T) => scala.Predef.Map.empty[Int, Nothing])^J} // : <notype>

Unfortunately, // print completion doesn't work for the example.

@scabug
Copy link
Author

scabug commented Nov 7, 2016

@SethTisue said:
[~orium] what passage in the Scala Language Specification justifies considering this a bug?

@scabug
Copy link
Author

scabug commented Nov 7, 2016

Diogo Sousa (orium) said:
I'm didn't study the Scala language spec (but I would say that if it agrees with this behavior then the bug still exists but it is in the spec).

In fact, as @apm said, it didn't infer Map.empty to be of type Map[Int, Int] as I said, but it must, at least, infer Map.empty to be of type Map[Int, _], since Map is invariant in the key. However, the error on instatiation says that it got a Map[Nothing, Nothing]. How could it even typecheck at the type of the class definition?

To be more general: I don't think it is acceptable to get a type error when a default parameter is used. It was typechecked before, it must fail at definition of the class/method if the types don't checkout

(Another way this is weird is that class A(foo: String => Map[Int, Int] = (_: String) => Map.empty) ; new A works. Having the type parameterized somehow makes a difference here. This is like breaking "referential transparency" for types.)

@scabug
Copy link
Author

scabug commented Nov 7, 2016

@som-snytt said:

        class C[A] extends scala.AnyRef {
          <paramaccessor> private[this] val f: A => Map[Int,Int] = _;
          def <init>(f: A => Map[Int,Int] = ((x$1: A) => scala.Predef.Map.empty[Int, Nothing])): C[A] = {
            C.super.<init>();
            ()
          }
        };
        <synthetic> object C extends AnyRef {
          def <init>(): C.type = {
            C.super.<init>();
            ()
          };
          <synthetic> def <init>$default$1[A]: A => scala.collection.immutable.Map[Nothing,Nothing] = ((x$1: A) => scala.Predef.Map.empty[Nothing, Nothing])
        }
      }

I think there's an open ticket for default args, of course I can't find it. Maybe similar to #8884.

Spec behavior.

@scabug
Copy link
Author

scabug commented Nov 8, 2016

@lrytz said:
{quote}I don't think it is acceptable to get a type error when a default parameter is used. It was typechecked before, it must fail at definition of the class/method if the types don't checkout{quote}

There's a special case with default arguments for parametric types, to support the following:

scala> def f[T](x: T = 1) = x
f: [T](x: T)T

scala> f()
res0: Int = 1

scala> f[String]()
<console>:13: error: type mismatch;
 found   : Int
 required: String
Error occurred in an application involving default arguments.
       f[String]()
        ^

See http://www.scala-lang.org/files/archive/spec/2.12/04-basic-declarations-and-definitions.html#default-arguments

For the original example in your report, I think it's a valid bug.

@eugengarkusha
Copy link

could you pls confirm that the following behavior is related to this issue

  def x(i: Int, m: Map[String, Boolean]) = ???
  def x(i: String, m: Map[String, Boolean]) = ???
  
  x(1, Map.empty[String, Boolean]) // compiles well
  x(1, Map.empty) // caused error
[error] /Users/ievgen/scalaprojects/pantheon/app/controllers/X.scala:41:3: overloaded method value x with alternatives:
[error]   (i: String,m: Map[String,Boolean])Nothing <and>
[error]   (i: Int,m: Map[String,Boolean])Nothing
[error]  cannot be applied to (Int, scala.collection.immutable.Map[Nothing,Nothing])
[error]   x(1, Map.empty) // caused error

@som-snytt som-snytt added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label Nov 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) named/default args typer
Projects
None yet
Development

No branches or pull requests

3 participants