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

Wildcards should infer bounds #11491

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

Comments

Projects
None yet
6 participants
@WellingR
Copy link

commented Apr 17, 2019

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Author

commented Apr 23, 2019

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

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

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

Duplicate of #1786

@WellingR

This comment has been minimized.

Copy link
Author

commented Apr 24, 2019

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

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

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

@eed3si9n

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

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

This comment has been minimized.

Copy link
Member

commented Apr 24, 2019

hmm, also seems related to #11480

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.