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

FQN method calls may need clarification #129

Closed
vrurg opened this issue Nov 13, 2019 · 2 comments
Closed

FQN method calls may need clarification #129

vrurg opened this issue Nov 13, 2019 · 2 comments
Assignees
Labels
6.e Related to the next 6.e language release language Changes to the Raku Programming Language rakudo Big changes to Rakudo

Comments

@vrurg
Copy link
Contributor

vrurg commented Nov 13, 2019

The current Rakudo approach of resolving a FQN method call is to search for the requested method using method's self.WHAT (roughly). This leads to a number of ambiguities and possibly need reconsideration.

Example 1:

role R {
    has $!a = 0;

    method inc-a { $!a++ };
    method a { $!a }
    method info {
        say "R::info ::?CLASS: ", ::?CLASS;
    }
}

class Foo does R {
    method foo {
        self.R::inc-a;
        say "Foo a==", self.R::a;
        say "Foo!a: ", $!a;
        self.Foo::R::info;
    }
}

class Bar is Foo does R {
    method foo {
        self.R::inc-a;
        say "1. Bar a==", self.a;
        callsame;
        say "2. Bar a==", self.a;
    }
}

say "--- Foo::foo";
Foo.new.foo;
say "--- Bar::foo";
Bar.new.foo;

In a nutshell, what happens here is that Bar and Foo get two different conretizations of role R with two different copies of private attribute $!a. A qualified call to R::inc-a from Foo eventually gets dispatched to inc-a method on Bar's concretization and, correspondingly, increments Bar's copy of $!a. This could result in very frustating bugs related to intermix of qualified calls to roles and use of private attributes in class code.

While trying to fix this issue experimented with providing information about a method caller which we have at compile time. In other words, when dispatcher:<::> get's called it can request it's context package and perform lookup on that package. In the example above it would be class Foo. In more complex situations, that could as well be a role if a FQN call belongs to that role code.

Unfortunately, that's only a part of the problem. While working on implementation of #110 I also realized that dispatcher is actually unable to locate the correct type object to perform method lookup without actually known the concrete type (or concretization for that matter) of the caller code. Let's consider the following example:

role R1[::T] {
   method foo { do-work }
}

role R2[::T] does R1[::T] {
   method foo {
       self.R1::foo
   }
}

role R2 does R1[Type1] {
   method foo {
      self.R1::foo
   }
}

class Foo does R1[Type2] does R2[Type3] {
    method foo {
        self.R2::foo;
    }
}

class Bar is Foo does R2 {
    method foo {
        callsame;
    }
}

To make long story short, my experiment with providing compile-time information about the caller type didn't help the dispatcher to locate to correct method object and Foo.new.foo was ending up resolving to R1[Type1] concretization despite Bar not being involved in any way except by consuming R2.

While the final outcome is rathe incidental here, it reveals the main problem: concretization isn't known at the compile time. Thus, dispatch is forced to operate on unparameterized role and therefore the result of method lookup is not guaranteed to be correct.

I can foresee one simple solution to this: fail as R1 is being applied twice and this can be considered ambiguous relaxed FQN lookup. But let's look at it from the point of view of distributed development where each role in question is being developed by independent people or organizations. The consuming class is, in turn, developed by a third party. From the point of view of the R2 developer there is no ambiguity in the name resolution. The same apply to the class developer: he doesn't see an immediate conflict. Moreover, his code could stem from the times when R2 did not do R1 consumption. Abrupt breakage of the code after a module update could come as a very unpleasant surprise. Sure, this could possibly be fixed by puning R1. But if it has stubs then rewrite would require an intermediate class which Foo can then inherit from. Hm...

So, here is the issue as I see it.

@vrurg vrurg added the rakudo Big changes to Rakudo label Nov 13, 2019
@vrurg vrurg added the language Changes to the Raku Programming Language label Nov 13, 2019
@vrurg
Copy link
Contributor Author

vrurg commented Nov 13, 2019

Adding language as the outcome of this topic could result in more roast tests.

With regard to rakudo label, the problem is related to the implementation details of MOP. So far, experimenting in this area led me to a conclusion that the issue could be resolved by preserving concrete caller type object for subsequent dispatcher calls. The type object could be anything with HOW doing Metamodel::MethodContainer role.

The exact way of providing this information is yet to be determined. For experimental purposes I was considering fetching type information from find_method_qualified method or from a new method with similar functionality. Unfortunately, this solution is incomplete.

More correct path would be to have a symbol containing the type object in lexical scope of the FQN call. For parameterized roles it could possibly be done similarly to how type captures are provided. But this path I didn't explore yet and have no idea how things work here.

@vrurg vrurg added the 6.e Related to the next 6.e language release label Nov 27, 2019
@vrurg vrurg added this to In Development in v6.e Release Nov 27, 2019
@vrurg
Copy link
Contributor Author

vrurg commented Dec 29, 2019

Resolved.

@vrurg vrurg closed this as completed Dec 29, 2019
v6.e Release automation moved this from In Development to Done Dec 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.e Related to the next 6.e language release language Changes to the Raku Programming Language rakudo Big changes to Rakudo
Projects
v6.e Release
  
Done
Development

No branches or pull requests

2 participants