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

Regression in rescala-lang/rescala #18160

Closed
WojciechMazur opened this issue Jul 6, 2023 · 5 comments · Fixed by #18204
Closed

Regression in rescala-lang/rescala #18160

WojciechMazur opened this issue Jul 6, 2023 · 5 comments · Fixed by #18204
Assignees
Labels
area:typer itype:bug regression This worked in a previous version but doesn't anymore
Milestone

Comments

@WojciechMazur
Copy link
Contributor

WojciechMazur commented Jul 6, 2023

Regression found in Open Community Build for rescala-lang/rescala and vigoo/prox

Compiler version

Since 3.3.1-RC1-bin-20230216 Nightly
Bisect points to 8d65f19
Project-wise bisect logs: https://github.com/VirtusLab/community-build3/actions/runs/5475858690/jobs/9973280267

Similar issue with the same bisection result where found in other projects:

Minimized code

Not yet minimized, bisected on whole project, multiple compilation errors including typer and implicit resoultion errors
Link to failing project: https://github.com/rescala-lang/REScala

Output (click arrow to expand)

Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/jvm/src/test/scala/tests/rescala/testtools/SynchronizedReevaluation.scala:50:29 
Error:  50 |    (sync, evt.map(sync.reev))
Error:     |                             ^
Error:     |Could not find capability to create reactives. Maybe a missing import?.
Error:     |I found:
Error:     |
Error:     |    rescala.core.CreationTicket.fromScope[EventCompatBundle.this.State](
Error:     |      rescala.core.ScopeSearch.fromTicketImplicit[EventCompatBundle.this.State](
Error:     |        /* missing */summon[rescala.core.StaticTicket[EventCompatBundle.this.State]]
Error:     |        ),
Error:     |    rescala.core.ReInfo)
Error:     |
Error:     |But no implicit values were found that match type rescala.core.StaticTicket[EventCompatBundle.this.State].
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/dynamic/FlattenTest.scala:117:48 
Error:  117 |      val level1Event   = e1.map(_ => "level 1")
Error:      |                                                ^
Error:      |Could not find capability to create reactives. Maybe a missing import?.
Error:      |I found:
Error:      |
Error:      |    rescala.core.CreationTicket.fromScope[EventCompatBundle.this.State](
Error:      |      rescala.core.ScopeSearch.fromTicketImplicit[EventCompatBundle.this.State](
Error:      |        /* missing */summon[rescala.core.StaticTicket[EventCompatBundle.this.State]]
Error:      |        ),
Error:      |    rescala.core.ReInfo)
Error:      |
Error:      |But no implicit values were found that match type rescala.core.StaticTicket[EventCompatBundle.this.State].
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/dynamic/FlattenTest.scala:121:43 
Error:  121 |      val unwrapped = dynamicSignal.flatten
Error:      |                                           ^
Error:      |Ambiguous given instances: both method flattenImplicitForsignal in trait FlattenApi and method flattenImplicitForevent in trait FlattenApi match type engine.Flatten[engine.Signal[Nothing], R] of parameter flatten of method flatten in trait Signal
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/dynamic/FlattenTest.scala:135:44 
Error:  135 |      val level1EventA    = e1.map(_ => "A")
Error:      |                                            ^
Error:      |Could not find capability to create reactives. Maybe a missing import?.
Error:      |I found:
Error:      |
Error:      |    rescala.core.CreationTicket.fromScope[EventCompatBundle.this.State](
Error:      |      rescala.core.ScopeSearch.fromTicketImplicit[EventCompatBundle.this.State](
Error:      |        /* missing */summon[rescala.core.StaticTicket[EventCompatBundle.this.State]]
Error:      |        ),
Error:      |    rescala.core.ReInfo)
Error:      |
Error:      |But no implicit values were found that match type rescala.core.StaticTicket[EventCompatBundle.this.State].
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/dynamic/FlattenTest.scala:136:44 
Error:  136 |      val level1EventB    = e1.map(_ => "B")
Error:      |                                            ^
Error:      |Could not find capability to create reactives. Maybe a missing import?.
Error:      |I found:
Error:      |
Error:      |    rescala.core.CreationTicket.fromScope[EventCompatBundle.this.State](
Error:      |      rescala.core.ScopeSearch.fromTicketImplicit[EventCompatBundle.this.State](
Error:      |        /* missing */summon[rescala.core.StaticTicket[EventCompatBundle.this.State]]
Error:      |        ),
Error:      |    rescala.core.ReInfo)
Error:      |
Error:      |But no implicit values were found that match type rescala.core.StaticTicket[EventCompatBundle.this.State].
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/dynamic/FlattenTest.scala:139:43 
Error:  40 |      val r = s map { event => event map { _ + 1 } }
Error:     |                                           ^^^
Error:     |value + is not a member of T, but could be made available as an extension method.
Error:     |
Error:     |The following import might fix the problem:
Error:     |
Error:     |  import org.scalactic.Prettifier.default
Error:     |
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/static/signals/SignalMacro.scala:40:50 
Error:  40 |      val r = s map { event => event map { _ + 1 } }
Error:     |                                                  ^
Error:     |Could not find capability to create reactives. Maybe a missing import?.
Error:     |I found:
Error:     |
Error:     |    rescala.core.CreationTicket.fromScope[EventCompatBundle.this.State](
Error:     |      rescala.core.ScopeSearch.fromTicketImplicit[EventCompatBundle.this.State](
Error:     |        /* missing */summon[rescala.core.StaticTicket[EventCompatBundle.this.State]]
Error:     |        ),
Error:     |    rescala.core.ReInfo)
Error:     |
Error:     |But no implicit values were found that match type rescala.core.StaticTicket[EventCompatBundle.this.State].
Error:  -- [E007] Type Mismatch Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/static/signals/SignalMacro.scala:42:6 
Error:  42 |      r.readValueOnce += { test = _ }
Error:     |      ^^^^^^^^^^^^^^^
Error:     |Found:    Nothing
Error:     |Required: ?{ += : ? }
Error:     |Note that implicit conversions were not tried because the result of an implicit conversion
Error:     |must be more specific than ?{ += : [applied to (
Error:     |  {
Error:     |    _$4 => test = _$4
Error:     |  }
Error:     |) returning <?>] }
Error:     |
Error:     | longer explanation available when compiling with `-explain`
Error:  -- [E007] Type Mismatch Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/static/signals/SignalMacro.scala:258:32 
Error:  258 |      val selected = source.map(mapping.get).flatten.latest().flatten(flattenImplicitForsignal)
Error:      |                                ^^^^^^^^^^^
Error:      |  Found:    String => Option[engine.Var[String]]
Error:      |  Required: T => Option[engine.Var[String]]
Error:      |
Error:      |  The following import might make progress towards fixing the problem:
Error:      |
Error:      |    import sourcecode.Text.generate
Error:      |
Error:      |
Error:      | longer explanation available when compiling with `-explain`
Error:  -- [E172] Type Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/static/signals/SignalMacro.scala:258:44 
Error:  258 |      val selected = source.map(mapping.get).flatten.latest().flatten(flattenImplicitForsignal)
Error:      |                                            ^
Error:      |Could not find capability to create reactives. Maybe a missing import?.
Error:      |I found:
Error:      |
Error:      |    rescala.core.CreationTicket.fromScope[EventCompatBundle.this.State](
Error:      |      rescala.core.ScopeSearch.fromTicketImplicit[EventCompatBundle.this.State](
Error:      |        /* missing */summon[rescala.core.StaticTicket[EventCompatBundle.this.State]]
Error:      |        ),
Error:      |    rescala.core.ReInfo)
Error:      |
Error:      |But no implicit values were found that match type rescala.core.StaticTicket[EventCompatBundle.this.State].
Error:  -- [E007] Type Mismatch Error: /build/repo/Modules/Reactives/shared/src/test/scala/tests/rescala/testtools/ReevaluationTracker.scala:17:48 
Error:  17 |      case event: Event[_]   => event.map(reev)(turnSource)
Error:     |                                                ^^^^^^^^^^
Error:     |    Found:    (ReevaluationTracker.this.turnSource :
Error:     |      ReevaluationBundle.this.api.CreationTicket)
Error:     |    Required: EventCompatBundle.this.CreationTicket
Error:     |
Error:     |    The following import might make progress towards fixing the problem:
Error:     |
Error:     |      import sourcecode.Text.generate
Error:     |
Error:     |
Error:     | longer explanation available when compiling with `-explain`
Error:  62 errors found

Expectation

Probably should compile

@WojciechMazur WojciechMazur added itype:bug area:typer stat:needs minimization Needs a self contained minimization area:implicits related to implicits regression This worked in a previous version but doesn't anymore labels Jul 6, 2023
@WojciechMazur
Copy link
Contributor Author

Related issue (same bisect result) #17233

@odersky
Copy link
Contributor

odersky commented Jul 7, 2023

8d65f19 fixed a basic problem in type computations. Looking at it again, I cannot find anything wrong with it. It does affect type inference, but maybe the failing projects have to be fixed instead.

One would have to minimize to see whether anything can reasonably be done here.

@WojciechMazur
Copy link
Contributor Author

Reproduction involves multi-stage compilation, the problem is present when compiling tests (different compilation unit), but not when compilng main sources

// repro.scala
object core {
  final class CreationTicket[State[_]]
}

trait ReadAs[S[_], +A] { type State[V] = S[V] }

trait EventCompatBundle {
  bundle: Operators =>

  trait EventCompat[+T] extends ReadAs[State, Option[T]] {
    selfType: Event[T] =>
    final inline def map[B](inline expression: T => B)(implicit ticket: CreationTicket): Event[B] =  ???
  }
}

trait EventBundle extends EventCompatBundle { self: Operators =>
  trait Event[+T] extends EventCompat[T]:
    final override type State[V] = self.State[V]
}
trait Operators extends EventBundle {
  type State[_]
  type CreationTicket = core.CreationTicket[State]
}
trait RescalaInterface extends Operators
// repro.test.scala
class SynchronizedReevaluation
class SynchronizedReevaluationApi[Api <: RescalaInterface](val api: Api){
  import api._

  def SynchronizedReevaluation[A](evt: Event[A])(implicit
      turnSource: CreationTicket
  ): (SynchronizedReevaluation, Event[A]) = {
    val sync = new SynchronizedReevaluation
    (sync, evt.map(identity)(turnSource))
  }
}

Can be reproduced using scala-cli using scala-cli compile --test repro.scala repro.test.scala

@WojciechMazur WojciechMazur removed stat:needs minimization Needs a self contained minimization area:implicits related to implicits labels Jul 10, 2023
@WojciechMazur
Copy link
Contributor Author

The issue might be related to dependant types. The api.CreationTicket and EventComatBundle.this.CreationTicket are the same type.

Compilation error:

[error] ./main.test.scala:9:30
[error] Found:    (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)
[error] Required: EventCompatBundle.this.CreationTicket
[error]     (sync, evt.map(identity)(turnSource))
[error]                              ^^^^^^^^^^
Error compiling project (test, Scala 3.3.1-RC3, JVM)

@odersky
Copy link
Contributor

odersky commented Jul 10, 2023

Thanks for the minimization! I tried with -explain:

-- [E007] Type Mismatch Error: Test.scala:9:29 ---------------------------------
9 |    (sync, evt.map(identity)(turnSource))
  |                             ^^^^^^^^^^
  |Found:    (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)
  |Required: EventCompatBundle.this.CreationTicket
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  |
  | Tree: turnSource
  | I tried to show that
  |   (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)
  | conforms to
  |   EventCompatBundle.this.CreationTicket
  | but the comparison trace ended with `false`:
  |
  |   ==> (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)  <:  EventCompatBundle.this.CreationTicket
  |     ==> (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)  <:  core.CreationTicket[EventCompatBundle.this.State]
  |       ==> core.CreationTicket[SynchronizedReevaluationApi.this.api.State]  <:  core.CreationTicket[EventCompatBundle.this.State] (left is approximated)
  |         ==> core.type  <:  core.type
  |         <== core.type  <:  core.type = true
  |         ==> EventCompatBundle.this.State  <:  SynchronizedReevaluationApi.this.api.State
  |           ==> (EventCompatBundle.this : Operators & EventCompatBundle)  <:  (SynchronizedReevaluationApi.this.api : Api)
  |             ==> Operators & EventCompatBundle  <:  (SynchronizedReevaluationApi.this.api : Api) (left is approximated)
  |               ==> Operators  <:  (SynchronizedReevaluationApi.this.api : Api) (left is approximated)
  |               <== Operators  <:  (SynchronizedReevaluationApi.this.api : Api) (left is approximated) = false
  |               ==> EventCompatBundle  <:  (SynchronizedReevaluationApi.this.api : Api) (left is approximated)
  |               <== EventCompatBundle  <:  (SynchronizedReevaluationApi.this.api : Api) (left is approximated) = false
  |             <== Operators & EventCompatBundle  <:  (SynchronizedReevaluationApi.this.api : Api) (left is approximated) = false
  |           <== (EventCompatBundle.this : Operators & EventCompatBundle)  <:  (SynchronizedReevaluationApi.this.api : Api) = false
  |           ==> EventCompatBundle.this.State  <:  Nothing (right is approximated)
  |           <== EventCompatBundle.this.State  <:  Nothing (right is approximated) = false
  |           ==> [_] =>> Any  <:  SynchronizedReevaluationApi.this.api.State (left is approximated)
  |             ==> [_] =>> Any  <:  Nothing (left is approximated) (right is approximated)
  |             <== [_] =>> Any  <:  Nothing (left is approximated) (right is approximated) = false
  |             ==> Any  <:  SynchronizedReevaluationApi.this.api.State[_]
  |               ==> Any  <:  Nothing (right is approximated)
  |               <== Any  <:  Nothing (right is approximated) = false
  |             <== Any  <:  SynchronizedReevaluationApi.this.api.State[_] = false
  |           <== [_] =>> Any  <:  SynchronizedReevaluationApi.this.api.State (left is approximated) = false
  |         <== EventCompatBundle.this.State  <:  SynchronizedReevaluationApi.this.api.State = false
  |       <== core.CreationTicket[SynchronizedReevaluationApi.this.api.State]  <:  core.CreationTicket[EventCompatBundle.this.State] (left is approximated) = false
  |     <== (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)  <:  core.CreationTicket[EventCompatBundle.this.State] = false
  |   <== (turnSource : SynchronizedReevaluationApi.this.api.CreationTicket)  <:  EventCompatBundle.this.CreationTicket = false
  |
  | The tests were made under a constraint with:
  |  uninstantiated variables: T1, T2, T1, T2, B
  |  constrained types: [T1, T2](_1: T1, _2: T2): (T1, T2),
  |   [T1, T2](_1: T1, _2: T2): (T1, T2),
  |   [B]
  |     (expression: T => B)
  |       (implicit ticket: EventCompatBundle.this.CreationTicket):
  |         EventCompatBundle.this.Event[B]
  |   ,
  |   [B]
  |     (expression: T => B)
  |       (implicit ticket: EventCompatBundle.this.CreationTicket):
  |         EventCompatBundle.this.Event[B]
  |  bounds:
  |      T1
  |      T2
  |      T1 >: (sync : SynchronizedReevaluation) <: SynchronizedReevaluation
  |      T2 <: SynchronizedReevaluationApi.this.api.Event[A]
  |      B
  |      B >: T
  |  ordering:
  |  co-deps:
  |  contra-deps:
   -----------------------------------------------------------------------------
1 error found

The failing comparison is

EventCompatBundle.this.State  <:  SynchronizedReevaluationApi.this.api.State

Indeed, I don't see how the compiler could prove that this comparison is true.

Previously, the compiler sometimes mispredicted when the prefix had to be updated and used a cached prefix instead. This could hide errors like the one detected here.

@odersky odersky self-assigned this Jul 12, 2023
odersky added a commit to dotty-staging/dotty that referenced this issue Jul 13, 2023
infoDependsOnPrefix now also considers non-final term members. Before
8d65f19 it only considered abstract types. Constructors were classified
as non-final, which caused regression. We now exclude constructors
specifically. Maybe we should instead classify them as effectively final.

Fixes scala#18160
smarter added a commit that referenced this issue Jul 14, 2023
infoDependsOnPrefix now also considers non-final term members. Before
8d65f19 it only considered abstract types. Constructors were classified
as non-final, which caused regressions. We now exclude constructors
specifically in a separate
clause in infoDependsOnPrefix. Maybe we should instead classify them as
effectively final.

Fixes #18160
@Kordyjan Kordyjan added this to the 3.4.0 milestone Aug 1, 2023
Kordyjan pushed a commit that referenced this issue Aug 16, 2023
infoDependsOnPrefix now also considers non-final term members. Before
8d65f19 it only considered abstract types. Constructors were classified
as non-final, which caused regression. We now exclude constructors
specifically. Maybe we should instead classify them as effectively final.

Fixes #18160
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:typer itype:bug regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants