#1056 It-block parameters have incorrect reflection signature

brian Sat 3 Apr 2010

It looks like the compiler is not maintaining |This| parameter signatures correctly for methods which take an it-block:

class Foo
{
  new make(|This| f) {} 
  Void bar(|This| f) {}
  static Void main()
  {
    t := Foo#
    echo(t.method("make").params.first.type)
    echo(t.method("bar").params.first.type)
  }
}

// prints
C:\dev\fan\src>play
|play_0::Foo->sys::Void|
|play_0::Foo->sys::Void|

For constructors This is always the same as the declaring class, so this isn't a problem. For for a method like bar or Obj.with the parameter will be incorrectly typed.

brian Sat 3 Apr 2010

Promoted to ticket #1056 and assigned to brian

tactics Sat 3 Apr 2010

The This type isn't allowed as a parameter type anywhere else. Obj.with is the only exception.

brian Sat 3 Apr 2010

The This type isn't allowed as a parameter type anywhere else. Obj.with is the only exception.

Actually I do allow any method to have a it-block function signature. A good example would be if we added OutStream.use:

OutStream.use(|This| f)

WebOutStream(out).use 
{
  // it typed as WebOutStream
}

So I think we want to allow that.

tcolar Sat 3 Apr 2010

Right, I put a workaround for now in my IDE for with(), which is currently the only place a THIS parameter is used in the fantom distro code.

But you are allowed to write your own (as it says in the "closure" page), so it would be good to fix it at some point.

tactics Tue 6 Apr 2010

Actually I do allow any method to have a it-block function signature.

This seems like a small inconsistency in the type system. Maybe you can explain.

This code does not compile.

class Main
{
  static Void main()
  { }

  static Void test(This f)
  { }
}

The error is that the test method cannot take a This parameter. Yet it has the same signature as an it-block.

It seems as if the |This| is not literally a function of This. Rather it's a special case.

andy Tue 6 Apr 2010

I would assume thats cause its a static method - so error seems correct here - haven't looked thru the code tho.

tactics Tue 6 Apr 2010

I would assume thats cause its a static method

That's not the case. I tried it both ways (but I figured to demonstrate it here as static because a static method is closer to a function semantically than a non-static method.

The it-blocks are handy, but they sure do complicate the language.

brian Wed 7 Apr 2010

The error is that the test method cannot take a This parameter. Yet it has the same signature as an it-block.

Using This in a parameter position is contra-variant (or a weird variation of it) which is why I don't support it. Functions work in a flipped variance mode, so it works out ok for |This|. Of course nothing is actually based on a formally proved type system.

tactics Wed 7 Apr 2010

I wish I had gotten farther in my B. Pierce type theory book :)

I think I understand. To preserve the method's contract, you have to be more forgiving in what you accept as input and stricter in output. Since This takes on a stricter type when called from a subclass, it breaks the contract. (But returning This is perfectly acceptable).

In the case of a function, the This type doesn't really make sense, since a function is not associated with a type. So like I said above, |This| isn't really related to covariance. It's just syntax for an it block.

This makes more sense to me now.

Edit: I'm trying to work this out from the specs I understand about type theory, and I take back what I said. |This| does seem to make sense exactly as it is. It's just weird :) When you pass a This block, you end up with a type that looks like this (using ML-like sytnax): (This -> a) -> b (for some types a and b). This type is something like "double contravariant", which is just covariant, and thus, contract preserving.

You learn something new every day :)

brian Tue 11 May 2010

Ticket resolved in 1.0.53

Fix reflection to use correct it-block signature

Login or Signup to reply.