This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Confused with "illegal cyclic reference involving type W" error

12 replies
Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.

Hello,

I'm getting an error that I don't understand.

Here are my definitions:

package org.apache.cocoon.pipeline.scala

sealed abstract class Event[+T];

//here type bounds are used explicitly even if not needed due to following bug:
//http://lampsvn.epfl.ch/trac/scala/ticket/430
final case class SomeEvent[+T >: Nothing <: Any](event : T) extends Event[T];
case object Continue extends Event[Nothing];
case object Nothing extends Event[Nothing];

-------------------------------------------
package org.apache.cocoon.pipeline.scala

trait PipelineComponent[T <: Event[_], U <: Event[_]] {
def execute(event : T) : U;
}

-------------------------------------------
package org.apache.cocoon.pipeline.scala

trait Pipeline[T <: Event[_], U <: Event[_]] {
def addComponent[W <: Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W];
def | [W <: Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W] = addComponent(component);

def execute(event : Event[T]) : Event[U];

implicit def PipelineComponent2Pipeline[A,B](component : PipelineComponent[A,B]) : Pipeline[A,B];
}

I'm getting following error while trying to compile that code:
[WARNING] /home/grek/asf/git/cocoon3/cocoon-pipeline/src/main/scala/org/apache/cocoon/pipeline/scala/Pipeline.scala:4:
error: illegal cyclic reference involving type W
[WARNING] def addComponent[W <: Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W];
[WARNING] ^
[WARNING] /home/grek/asf/git/cocoon3/cocoon-pipeline/src/main/scala/org/apache/cocoon/pipeline/scala/Pipeline.scala:5:
error: illegal cyclic reference involving type W
[WARNING] def | [W <: Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W] = addComponent(component);
[WARNING] ^
[WARNING] /home/grek/asf/git/cocoon3/cocoon-pipeline/src/main/scala/org/apache/cocoon/pipeline/scala/Pipeline.scala:5:
error: illegal cyclic reference involving type _$4
[WARNING] def | [W <: Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W] = addComponent(component);
[WARNING] ^
[WARNING] three errors found

Any hints on what this error means and how to achieve what I want?

Matt Hellige
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"

On Wed, Jan 28, 2009 at 10:28 AM, Grzegorz Kossakowski
wrote:
>
> Any hints on what this error means and how to achieve what I want?
>

I'm not sure why you're using all the existentials here... It seems
that you want to build components from events, and compose them into
pipelines. It doesn't seem to me that you want to lose track of the
actual types of the individual events. I would probably write it like
this:

trait PipelineComponent[T, U] {
def execute(event : Event[T]) : Event[U];
}

trait Pipeline[T, U] {
def addComponent[W](component : PipelineComponent[U,W]) : Pipeline[T,W];
def | [W](component : PipelineComponent[U,W]) : Pipeline[T,W] =
addComponent(component);

def execute(event : Event[T]) : Event[U];

implicit def PipelineComponent2Pipeline[A,B](component :
PipelineComponent[A,B]) : Pipeline[A,B];
}

This has at least one advantage: it compiles. But maybe I don't really
understand what you're trying to do.

Hope that helps...
Matt

Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"

Hello Matt,

Thanks for your answer.

Matt Hellige pisze:
> On Wed, Jan 28, 2009 at 10:28 AM, Grzegorz Kossakowski
> wrote:
>> Any hints on what this error means and how to achieve what I want?
>>
>
> I'm not sure why you're using all the existentials here... It seems
> that you want to build components from events, and compose them into
> pipelines. It doesn't seem to me that you want to lose track of the
> actual types of the individual events. I would probably write it like
> this:
>
> trait PipelineComponent[T, U] {
> def execute(event : Event[T]) : Event[U];
> }
>
> trait Pipeline[T, U] {
> def addComponent[W](component : PipelineComponent[U,W]) : Pipeline[T,W];
> def | [W](component : PipelineComponent[U,W]) : Pipeline[T,W] =
> addComponent(component);
>
> def execute(event : Event[T]) : Event[U];
>
> implicit def PipelineComponent2Pipeline[A,B](component :
> PipelineComponent[A,B]) : Pipeline[A,B];
> }
>
> This has at least one advantage: it compiles. But maybe I don't really
> understand what you're trying to do.

What you presented was my first approach. There is a problem with it, though.

How I can now say that I have a component that accepts only Nothing events? It's like saying I don't care about the
input (and it's type) because I'm going to generate events.

Maybe the whole type hierarchy is wrong but what I want to build are type-safe pipelines where I can combine my components.

Usually, the pipeline will accept only Nothing events which represents the idea that the first component is a generator
and generates events using some internal logic. How to build a proper type definitions?

PS. If I change:
def addComponent[W <: Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W];
into:
def addComponent[W <% Event[_]](component : PipelineComponent[U,W]) : Pipeline[T,W];

Then the code compiles. I have no idea why yet but I'll try to analyze meaning of <: and <% more carefully.

Matt Hellige
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"

On Wed, Jan 28, 2009 at 12:35 PM, Grzegorz Kossakowski
wrote:
> What you presented was my first approach. There is a problem with it, though.
>
> How I can now say that I have a component that accepts only Nothing events? It's like saying I don't care about the
> input (and it's type) because I'm going to generate events.
>
> Maybe the whole type hierarchy is wrong but what I want to build are type-safe pipelines where I can combine my components.
>
> Usually, the pipeline will accept only Nothing events which represents the idea that the first component is a generator
> and generates events using some internal logic. How to build a proper type definitions?

I believe you, but I guess I still don't see the problem. What's wrong
with this?
trait Generator[U] extends PipelineComponent[Nothing, U]

Matt

Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"

Matt Hellige pisze:
> On Wed, Jan 28, 2009 at 12:35 PM, Grzegorz Kossakowski
> wrote:
>> What you presented was my first approach. There is a problem with it, though.
>>
>> How I can now say that I have a component that accepts only Nothing events? It's like saying I don't care about the
>> input (and it's type) because I'm going to generate events.
>>
>> Maybe the whole type hierarchy is wrong but what I want to build are type-safe pipelines where I can combine my
components.
>>
>> Usually, the pipeline will accept only Nothing events which represents the idea that the first component is a generator
>> and generates events using some internal logic. How to build a proper type definitions?
>
> I believe you, but I guess I still don't see the problem. What's wrong
> with this?
> trait Generator[U] extends PipelineComponent[Nothing, U]

I'm really newbie with Scala (started to learn it yesterday) so this may look like wild chasing but type inferences
seems to not work the way I would like it.

The example:
package org.apache.cocoon.pipeline.scala.demo

import org.apache.cocoon.pipeline.scala._;

class DemoGenerator(howMany : Int) extends PipelineComponent[Nothing, HelloWorld] {

var counter = howMany;

def execute(event : Event[Nothing]) = {
if (counter > 0) {
counter = counter - 1;
new SomeEvent(new HelloWorld("Greetings from DemoGenerator"));
} else NothingEvent;
}
}

object RunPipeline {
def main(args : Array[String]) : Unit = {

def PipelineComponent2Pipeline[A,B](component : PipelineComponent[A,B]) = new SingleComponentPipeline[A,B](component);

val pipeline1 : Pipeline[Nothing, HelloWorld] = PipelineComponent2Pipeline(new DemoGenerator(5));
}
}

This won't work. The error msg is:
type mismatch; found : org.apache.cocoon.pipeline.scala.demo.DemoGenerator required:
PipelineComponent[A,org.apache.cocoon.pipeline.scala.demo.HelloWorld]

When I change it into:
val pipeline1 : Pipeline[Nothing, HelloWorld] = PipelineComponent2Pipeline[Nothing,HelloWorld](new DemoGenerator(5));

It works correctly. I don't know why type interference does not work here but this effectively eliminates possible use
of implicit converters which is not an option for me.

BTW. Having all these cryptic compiler msgs from Scala compiler I'm little bit sceptical. Am I just extremely unlucky
and touch some really edge cases?

Matt Hellige
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"

On Wed, Jan 28, 2009 at 1:45 PM, Grzegorz Kossakowski wrote:
> It works correctly. I don't know why type interference does not work here but this effectively eliminates possible use
> of implicit converters which is not an option for me.

I don't know either, and in fact it really surprises me. I'm really
surprised that the following case doesn't work:
object RunPipeline {
def PC2P[A,B](component : PipelineComponent[A,B]): Pipeline[A,B] =
new SingleComponentPipeline[A,B](component)

def main(args : Array[String]) : Unit = {
val pc: PipelineComponent[Nothing, HelloWorld] = new DemoGenerator(5)
val p: Pipeline[Nothing, HelloWorld] = PC2P(pc)
()
}
}

It does work if you write the type arguments to PC2P
(PC2P[Nothing,HelloWorld](pc)). More interestingly, it also works
properly if you just change all the Nothings to something else (Unit
or Int, for instance). I don't see why this is necessary... It's
almost as if Scala is trying to avoid inferring the Nothing type
argument. Why?

In any case, I think you may do best to avoid using Nothing in this
case. You don't lose anything by replacing it with Unit, and in fact
it more accurately models your intention, I would guess.

But I'm still curious why the Nothings in the above confuse type inference...

Matt

James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"
https://lampsvn.epfl.ch/trac/scala/ticket/1570

On Wed, Jan 28, 2009 at 1:10 PM, Matt Hellige <matt [at] immute [dot] net> wrote:

I don't know either, and in fact it really surprises me. I'm really
surprised that the following case doesn't work:


It does work if you write the type arguments to PC2P
(PC2P[Nothing,HelloWorld](pc)). More interestingly, it also works
properly if you just change all the Nothings to something else (Unit
or Int, for instance). I don't see why this is necessary... It's
almost as if Scala is trying to avoid inferring the Nothing type
argument.


Matt Hellige
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"

On Wed, Jan 28, 2009 at 3:34 PM, James Iry wrote:
> https://lampsvn.epfl.ch/trac/scala/ticket/1570

Kinda figured, but I couldn't find a thread about it... Has there been
any explanation?

Matt

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"
Trac detected an internal error:
OperationalError: database is locked


On Wed, Jan 28, 2009 at 10:34 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:
https://lampsvn.epfl.ch/trac/scala/ticket/1570

On Wed, Jan 28, 2009 at 1:10 PM, Matt Hellige <matt [at] immute [dot] net> wrote:

I don't know either, and in fact it really surprises me. I'm really
surprised that the following case doesn't work:


It does work if you write the type arguments to PC2P
(PC2P[Nothing,HelloWorld](pc)). More interestingly, it also works
properly if you just change all the Nothings to something else (Unit
or Int, for instance). I don't see why this is necessary... It's
almost as if Scala is trying to avoid inferring the Nothing type
argument.





--
Viktor Klang
Senior Systems Analyst
James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"
There's a "Yo dawg" joke about bugs in there somewhere.

On Wed, Jan 28, 2009 at 1:39 PM, Viktor Klang <viktor [dot] klang [at] gmail [dot] com> wrote:
Trac detected an internal error:
OperationalError: database is locked


On Wed, Jan 28, 2009 at 10:34 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:
https://lampsvn.epfl.ch/trac/scala/ticket/1570

On Wed, Jan 28, 2009 at 1:10 PM, Matt Hellige <matt [at] immute [dot] net> wrote:

I don't know either, and in fact it really surprises me. I'm really
surprised that the following case doesn't work:


It does work if you write the type arguments to PC2P
(PC2P[Nothing,HelloWorld](pc)). More interestingly, it also works
properly if you just change all the Nothings to something else (Unit
or Int, for instance). I don't see why this is necessary... It's
almost as if Scala is trying to avoid inferring the Nothing type
argument.





--
Viktor Klang
Senior Systems Analyst

James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Confused with "illegal cyclic reference involving type W"
Not that I know of.

On Wed, Jan 28, 2009 at 1:45 PM, Matt Hellige <matt [at] immute [dot] net> wrote:
On Wed, Jan 28, 2009 at 3:34 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:
> https://lampsvn.epfl.ch/trac/scala/ticket/1570

Kinda figured, but I couldn't find a thread about it... Has there been
any explanation?

Matt

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Confused with "illegal cyclic reference involving type W"

On Wed, Jan 28, 2009 at 10:45 PM, Matt Hellige wrote:
> On Wed, Jan 28, 2009 at 3:34 PM, James Iry wrote:
>> https://lampsvn.epfl.ch/trac/scala/ticket/1570
>
> Kinda figured, but I couldn't find a thread about it... Has there been
> any explanation?

I have not looked it up in detail, but Nothing is used as a marker in
type inference for the case where no type could be inferred and the
type checker decides to defer variable instantiation. So it could well
have to do with that.

Cheers

malinova
Joined: 2010-11-01,
User offline. Last seen 1 year 48 weeks ago.
После <a href="

После короткой передышки одна из собак встала и лениво направилась в близлежащие кусты; мы слышали ее громкое фырканье и звон бубенчиков Неожиданно раздались дикий вой и громкий треск кустов; вся свора вскочила и с заливистым лаем бросилась вслед за первой собакой

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland