Skip to content

Wildcards should infer bounds #11491

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

Open
WellingR opened this issue Apr 17, 2019 · 17 comments
Open

Wildcards should infer bounds #11491

WellingR opened this issue Apr 17, 2019 · 17 comments
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) regression typer
Milestone

Comments

@WellingR
Copy link

The following code compiles on scala 2.12.8, but it does not compile on scala 2.13.0-RC1

object Example {
  sealed trait DBIOAction[+R, +S <: NoStream, -E <: Effect] {
    def flatMap[R2, S2 <: NoStream, E2 <: Effect](f: R => DBIOAction[R2, S2, E2]): DBIOAction[R2, S2, E with E2] = ???
    def map[R2](f: R => R2): DBIOAction[R2, NoStream, E] = ???
  }

  sealed trait NoStream
  sealed trait Streaming[+T] extends NoStream

  trait Effect
  object Effect {
    trait Write extends Effect
    trait Schema extends Effect
  }

  def createSchema(): DBIOAction[Unit, NoStream, Effect.Schema] = ???
  def writeAction(): DBIOAction[Option[Int], NoStream, Effect.Write] = ???

  def test: DBIOAction[Unit, _, _] = for {
    _ <- createSchema()
    _ <- writeAction()
  } yield ()
}

This fails with the following errors

Error:(22, 22) inferred type arguments [Unit,Any,Nothing] do not conform to method flatMap's type parameter bounds [R2,S2 <: example.Example.NoStream,E2 <: example.Example.Effect]
_ <- createSchema()

Error:(22, 7) type mismatch;
found : Unit => example.Example.DBIOAction[Unit,Any,Nothing]
required: Unit => example.Example.DBIOAction[R2,S2,E2]
_ <- createSchema()

Error:(22, 7) type mismatch;
found : example.Example.DBIOAction[R2,S2,example.Example.Effect.Schema with E2]
required: example.Example.DBIOAction[Unit, _, _]
_ <- createSchema()

Oddly enough the code does compile when changing the body of def test to

  for {
    a <- createSchema()
    b <- writeAction()
  } yield ()

It appears that this somehow changes the inferred types which makes it typecheck again...

@WellingR WellingR changed the title Type inferencing regression in scala 2.13.--RC1 Type inferencing regression in scala 2.13.0-RC1 Apr 17, 2019
@SethTisue SethTisue added this to the 2.13.0-RC2 milestone Apr 17, 2019
@szeiger
Copy link

szeiger commented Apr 23, 2019

I ran into this while upgrading Slick, too. The code is not correct in the first place. The bounds in the return type of test are wrong. The definition of DBIOAction is sealed trait DBIOAction[+R, +S <: NoStream, -E <: Effect] so these bounds need to be repeated. Alternatively, since the type parameters are ignored anyway (by using existentials), this can be written simply as DBIO[Unit].

Previously the compiler ignored the bad bounds and everything worked fine but now they leak into type inference and get reported as errors. The underlying bug in my opinion is that the return type of test itself is not reported as an error.

@smarter
Copy link
Member

smarter commented Apr 23, 2019

The underlying bug in my opinion is that the return type of test itself is not reported as an error.

I disagree. If Foo has one type parameter then I should always be able to write Foo[_] and the compiler should figure out the bounds. This is how it works in Dotty (and the example from this issue compiles fine there).

@WellingR
Copy link
Author

Given trait DBIOAction[+R, +S <: NoStream, -E <: Effect] then the compiler could also infer that def test: DBIOAction[Unit, _, _] means def test: DBIOAction[Unit, _ <: NoStream, _ <: Effect]
I thought this was what happened in scala 2.11 and 2.12, but I might be wrong.

@smarter
Copy link
Member

smarter commented Apr 23, 2019

In fact, being able to write _ without writing down the bounds is necessary to be able to work with some F-bounded types without having to use existentials:
https://contributors.scala-lang.org/t/proposal-to-remove-existential-types-from-the-language/2785/7?u=smarter

@adriaanm adriaanm modified the milestones: 2.13.0-RC2, 2.13.1 Apr 24, 2019
@adriaanm adriaanm added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label Apr 24, 2019
@adriaanm
Copy link
Contributor

There have been previous attempts in this area. This looks like a good thread to pull: scala/scala#3471. For Scala 3 cross-building, it would be good to implement the same logic as dotty, but this is not exactly trivial, nor a blocker for 2.13.0.

@adriaanm adriaanm changed the title Type inferencing regression in scala 2.13.0-RC1 Wildcards should infer bounds Apr 24, 2019
@adriaanm
Copy link
Contributor

adriaanm commented Apr 24, 2019

Duplicate of #1786

@WellingR
Copy link
Author

I agree that #1786 is indeed very similar to this issue. But keep in mind that the code example from this issue DOES compile in scala 2.11 and 2.12. I think that it is very likely that other will encounter this issue when upgrading from scala 2.12 to 2.13.

Also this issue had the milestone 2.13.1, shouldn't #1786 receive the same milestone as it is considered a duplicate?

@adriaanm
Copy link
Contributor

We’ll investigate if a fix is feasible for 2.13.1, so I’ll reopen this for the more limited scope of the problem. This regressed due to a fix for another more insidious problem due to the way this was originally implemented (type var inheriting constraints from its origin type param)

@adriaanm adriaanm reopened this Apr 24, 2019
@eed3si9n
Copy link
Member

eed3si9n commented Apr 24, 2019

I'd be curious to see if the behavior changed before and after scala/scala#7900, which axed object AdjustedTypeArgs that's been around since 2010. Likely unrelated.

@adriaanm
Copy link
Contributor

adriaanm commented Apr 24, 2019

I assume (actually not sure anymore) this is why it regressed: scala/scala#6789

@eed3si9n
Copy link
Member

So we have a puzzle of making sure #10819 and this both do not regress:

scala> def id[T <: AnyVal](x: T): T = x
id: [T <: AnyVal](x: T)T

scala> id(1 + 1) - 1
res0: Int = 1

@adriaanm
Copy link
Contributor

hmm, also seems related to #11480

@szeiger szeiger modified the milestones: 2.13.1, 2.13.2 Sep 9, 2019
@SethTisue SethTisue modified the milestones: 2.13.2, Backlog Feb 6, 2020
@SethTisue SethTisue added the typer label Feb 6, 2020
@SethTisue
Copy link
Member

moved to Backlog, as the linked PRs seem to have stalled

@SethTisue
Copy link
Member

SethTisue commented May 13, 2020

on Gitter @er1c reports that the following compiles on 2.11, 2.12, and Dotty, but not on 2.13:

def foo[T]: Set[Class[_ <: T]] = bar(??? : Class[T])
def bar[T](clazz: Class[T]): Set[Class[_ <: T]] = ???

I'm not certain it's actually the “same” problem, but it's at least in that same territory where type inference, bounds, and existentials overlap

the workaround is to give inference a little extra help: bar[T](...)

@martijnhoekstra
Copy link

might scala/scala3#8955 be related?

@SethTisue
Copy link
Member

well, overloads aren't in play in this ticket

@martijnhoekstra
Copy link

I don't know what I was thinking. I swear it made sense when I posted it!

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/) regression typer
Projects
None yet
Development

No branches or pull requests

7 participants