Skip to content

Issue with Type inference? #1036

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
allanrenucci opened this issue Jan 18, 2016 · 5 comments
Closed

Issue with Type inference? #1036

allanrenucci opened this issue Jan 18, 2016 · 5 comments

Comments

@allanrenucci
Copy link
Contributor

The following code snippet does not compile with Dotty but does with Scalac.

object Test {
  def second[A, B <: A](foo: A, bar: B): B = bar
  def expectString(s: String) = s

  def test = {
    second(Set.empty[String], Set.empty) map expectString
  }
}

It fails with the following error:

./tests/allan/Experiment.scala:7: error: type mismatch:
 found   : Any(s)
 required: String
    second(Set.empty[String], Set.empty) map expectString
                                             ^

It also fails to compile if second is defined as follow:

def second[A, B >: A](foo: A, bar: B): B = bar

with the following error:

./tests/allan/Experiment.scala:7: error: type mismatch:
 found   : (scala.collection.immutable.Set[String] | scala.collection.immutable.Set[Any]) @UnsafeNonvariant#A(s)
 required: String
    second(Set.empty[String], Set.empty) map expectString
                                             ^

Note that it does compile with second applied on List instead of Set:

second(List.empty[String], List.empty) map expectString

Not sure if it is a duplicate of #998

@odersky
Copy link
Contributor

odersky commented Jan 18, 2016

It might well be a duplicate of #998. Thanks for the analysis!

@odersky
Copy link
Contributor

odersky commented Jan 19, 2016

I verified that it is not a duplicate of #998, after all.

@allanrenucci
Copy link
Contributor Author

#1040 did not completely fix the bug. If I rewrite slightly the test case, it doesn't compile anymore.

second(Set.empty[String], Set.empty) map (s => expectString(s))
third(Set.empty[String], Set.empty) map (s => expectString(s))

// Instead of
second(Set.empty[String], Set.empty) map expectString
third(Set.empty[String], Set.empty) map expectString

@smarter smarter reopened this Jan 24, 2016
@odersky
Copy link
Contributor

odersky commented Jan 24, 2016

That looks like a bug / problem in scalac. scalac expands f to x => f(x) very early, before the checking
the rules of eta expansion. It then has to "assume" that x => f(x) was f in the user program. Dotty does eta expansion as part of adaptation, so it knows which is which.

In the scenario given, we need to infer the parameter type for s from the expected type. The expected type is not fully defined, so it gets approximated. And that leads to the error. If we write f instead of x => f x we can apply an additional rule, which says that if the expected type of an eta expansion is not fully defined we take the parameter type of f instead. But doing this for general expressions looks like a lot of trouble, and I'd like us to stay out of it.

@odersky odersky closed this as completed Jan 24, 2016
@smarter
Copy link
Member

smarter commented Jan 24, 2016

But doing this for general expressions looks like a lot of trouble, and I'd like us to stay out of it.

Do you have a specific example in mind where this could be problematic? It doesn't seem like such a bad idea to me.

DarkDimius pushed a commit to dotty-linker/dotty that referenced this issue May 9, 2016
Achieved by tweaking from where we get the parameter types of an eta-expansion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants