chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.77k stars 416 forks source link

Function hijacking #8077

Open mppf opened 6 years ago

mppf commented 6 years ago

CHIP 20 describes several examples where the Chapel language allows "function hijacking" - that is, a situation when a library might unintentionally change behavior based upon changes in other libraries or in code using that library.

This issue tracks discussion related to that CHIP.

mppf commented 6 years ago

CHIP 20 suggests, for the case of hijacking by (accidentally) implementing a more specific function, that it might be possible to simply put 'more visible' before 'more specific' in the list of disambiguation rules.

That strategy is challenging when working some generally overloaded function, such as _getIterator, _cast, _new, init, this, these, etc. that should be overridden specifically for each type. In particular, in the event that there is a generic function providing a default implementation, the default implementation might be selected instead of one specifically tailored to the type in question. (That pattern can be handled with FLAG_LAST_RESORT).

Additionally, this approach presents problems with promotion. If promotion is less important than visibility, some obvious programs don't work (Say a module defines CustomRecord.rank and then they have Array:[1..n] CustomRecord - then Array.rank will resolve to the promoted rank over the array rather than returning the Array.rank). If promotion is more important than visibility, programs relying on a promoted foo(x:int) call might accidentally start calling a foo(x:[] int) provided by a library. (but overloads sets would solve that last problem).

In fact I tried the simple reordering on this branch: https://github.com/mppf/chapel/tree/reorder-disambiguation-visible and many simple programs compile and run.

Here is a snippet that doesn't work as intended, anymore:

// Define a ``*`` operator on any two types that returns a tuple of those types.
proc *(left : ?ltype, right : ?rtype): (ltype, rtype) {
  writeln("\tIn our '*' overload!");
  return (left, right);
}

writeln(1 * "a"); // Uses our ``*`` operator.
writeln(1 * 2);   // Uses the default ``*`` operator.

I think it'd be reasonable to "opt in" to having 1 2 consider both the existing `` operators and the new one.

vasslitvinov commented 4 years ago

The adjustment to the POI rule in #15948, currently being implemented in #16158, prefers "more visible" over more specific.

For example, this test:

test/functions/ferguson/hijacking/Application4.chpl

which was a future prior to #16158, with that PR exhibits the behavior expected by the .good .