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

"cannot resolve reference to type" when type member of self-type appears in method type #11226

Closed
andreaTP opened this issue Jan 27, 2021 · 8 comments · Fixed by #20477
Closed

Comments

@andreaTP
Copy link
Contributor

Compiler version

3.0.0-M3

Minimized code

I haven't managed to minimize the problem but is reproducible here:
https://github.com/akka/akka/tree/repro-scala3

sbt -Dakka.build.scalaVersion=3.0 akka-actor/compile

Output

[error] -- Error: /Users/andreatp/workspace/tmp/akka/akka-actor/src/main/scala/akka/event/ActorClassificationUnsubscriber.scala:61:6 
[error] 61 |      bus.unsubscribe(actor)
[error]    |      ^
[error]    |cannot resolve reference to type (ActorClassificationUnsubscriber.this.bus : 
[error]    |  akka.event.ManagedActorClassification
[error]    |).Subscriber
[error]    |the classfile defining the type might be missing from the classpath
[error] one error found

Expectation

Compiles as with scalac 2.12 - 2.13

@griggt
Copy link
Contributor

griggt commented Jan 27, 2021

Minimized:

trait ActorRef

trait ActorEventBus {
  type Subscriber = ActorRef
}

trait ManagedActorClassification { this: ActorEventBus =>
  def unsubscribe(subscriber: Subscriber, from: Any): Unit
  def unsubscribe(subscriber: Subscriber): Unit
}

class Unsubscriber(bus: ManagedActorClassification) {
  def test(a: ActorRef): Unit = bus.unsubscribe(a)
}

Output from Scala compiler version 3.0.0-RC1-bin-SNAPSHOT-git-8d3275c:

cannot take signature of MethodType(List(subscriber), List(TypeRef(TermRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),class Unsubscriber)),val bus),Subscriber)), TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object scala),class Unit))
-- Error: i11226.scala:13:32 ---------------------------------------------------
13 |  def test(a: ActorRef): Unit = bus.unsubscribe(a)
   |                                ^
   |cannot resolve reference to type (Unsubscriber.this.bus : ManagedActorClassification).Subscriber
   |the classfile defining the type might be missing from the classpath

@griggt griggt removed the stat:needs minimization Needs a self contained minimization label Jan 27, 2021
@smarter smarter changed the title cannot resolve reference to type "cannot resolve reference to type" when type member of self-type appears in method type Jan 27, 2021
@smarter
Copy link
Member

smarter commented Jan 27, 2021

@odersky Should we disallow references to members of the self-type in the types of public methods?

@griggt
Copy link
Contributor

griggt commented Jan 27, 2021

Without the overload, the error is

-- [E007] Type Mismatch Error: i11226.scala:12:48 ------------------------------
12 |  def test(a: ActorRef): Unit = bus.unsubscribe(a)
   |                                                ^
   |                              Found:    (a : ActorRef)
   |                              Required: Unsubscriber.this.bus.Subscriber

@FlorianCassayre
Copy link
Contributor

I came across this bug today, here is the minimization I came up with:

trait A {
  class T()
}
trait B {
  this: A =>
  def f(a: Int = 0): Any
}
trait C extends B {
  this: A =>
  def f(t: T): Any
}

Interestingly, removing the default value solves the problem.

@smarter
Copy link
Member

smarter commented Apr 26, 2022

This might be the same bug as #15030

@cchantep
Copy link
Contributor

The issue seems still there is one form or another.
Since 3.3.0 up to 3.4.1 this code can no longer be compiled and the compiler crashes with the following error.

cannot resolve reference to type reactivemongo.api.collections.GenericCollectionWithCommands[P]#pack.type.Writer

The following declaration seems like a possible workaround.

private[api] trait GenericCollectionWithCommands[P <: SerializationPack] {
  //self: GenericCollection[P] =>

  // Workaround for self-type issue with Scala 3
  // https://github.com/scala/scala3/issues/11226
  protected def selfCollection: GenericCollection[P]

odersky added a commit to dotty-staging/dotty that referenced this issue May 27, 2024
We run into problems when referring to a member of a self type of a class
that it not also a member of the class from outside via an asSeenFrom.

One example is in 11226.scala where we see:
```scala
trait ManagedActorClassification { this: ActorEventBus =>
  def unsubscribe(subscriber: Subscriber): Unit
}

class Unsubscriber(bus: ManagedActorClassification) {
  def test(a: ActorRef): Unit = bus.unsubscribe(a) // error
}
```
The problem is that `unsubscribe` refers to the type `Subscriber` which
is not resolvable as a member of `bus`. one idea could be to rule out
type signatures like `unsubscribe`, similar how we rule out public signatures
referring to private members. But this could rule out existing valid programs.
For instance, the `unsubscribe` signature is unproblematic if it gets only
called with prefixes that inherit `ActorEventBus`. You could say that the
problem was instead that the type of `bus` was not specific enough.

In the long term, maybe restructing the signature is the right move. But for
now, we just try to give better error messages in the case of existing failures.

Fixes scala#11226
@odersky
Copy link
Contributor

odersky commented May 27, 2024

It's different from #15030.

@odersky
Copy link
Contributor

odersky commented May 27, 2024

See #20477 for an attempt to give better error messages for these failures. It turns out the program in #11226 (comment) compiles in main, so I added a pos test for it.

odersky added a commit to dotty-staging/dotty that referenced this issue May 28, 2024
We run into problems when referring to a member of a self type of a class
that it not also a member of the class from outside via an asSeenFrom.

One example is in 11226.scala where we see:
```scala
trait ManagedActorClassification { this: ActorEventBus =>
  def unsubscribe(subscriber: Subscriber): Unit
}

class Unsubscriber(bus: ManagedActorClassification) {
  def test(a: ActorRef): Unit = bus.unsubscribe(a) // error
}
```
The problem is that `unsubscribe` refers to the type `Subscriber` which
is not resolvable as a member of `bus`. one idea could be to rule out
type signatures like `unsubscribe`, similar how we rule out public signatures
referring to private members. But this could rule out existing valid programs.
For instance, the `unsubscribe` signature is unproblematic if it gets only
called with prefixes that inherit `ActorEventBus`. You could say that the
problem was instead that the type of `bus` was not specific enough.

In the long term, maybe restructing the signature is the right move. But for
now, we just try to give better error messages in the case of existing failures.

Fixes scala#11226
odersky added a commit that referenced this issue May 28, 2024
We run into problems when referring to a member of a self type of a
class that it not also a member of the class from outside via an
asSeenFrom.

One example is in 11226.scala where we see:
```scala
trait ManagedActorClassification { this: ActorEventBus =>
  def unsubscribe(subscriber: Subscriber): Unit
}

class Unsubscriber(bus: ManagedActorClassification) {
  def test(a: ActorRef): Unit = bus.unsubscribe(a) // error
}
```
The problem is that `unsubscribe` refers to the type `Subscriber` which
is not resolvable as a member of `bus`. one idea could be to rule out
type signatures like `unsubscribe`, similar how we rule out public
signatures referring to private members. But this could rule out
existing valid programs. For instance, the `unsubscribe` signature is
unproblematic if it gets only called with prefixes that inherit
`ActorEventBus`. You could say that the problem was instead that the
type of `bus` was not specific enough.

In the long term, maybe restricting the signature is the right move. But
for now, we just try to give better error messages in the case of
existing failures.

Fixes #11226
@Kordyjan Kordyjan added this to the 3.5.1 milestone Jul 3, 2024
WojciechMazur pushed a commit that referenced this issue Jul 8, 2024
We run into problems when referring to a member of a self type of a class
that it not also a member of the class from outside via an asSeenFrom.

One example is in 11226.scala where we see:
```scala
trait ManagedActorClassification { this: ActorEventBus =>
  def unsubscribe(subscriber: Subscriber): Unit
}

class Unsubscriber(bus: ManagedActorClassification) {
  def test(a: ActorRef): Unit = bus.unsubscribe(a) // error
}
```
The problem is that `unsubscribe` refers to the type `Subscriber` which
is not resolvable as a member of `bus`. one idea could be to rule out
type signatures like `unsubscribe`, similar how we rule out public signatures
referring to private members. But this could rule out existing valid programs.
For instance, the `unsubscribe` signature is unproblematic if it gets only
called with prefixes that inherit `ActorEventBus`. You could say that the
problem was instead that the type of `bus` was not specific enough.

In the long term, maybe restructing the signature is the right move. But for
now, we just try to give better error messages in the case of existing failures.

Fixes #11226

[Cherry-picked 21261c0]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants