[Issue 15624] opApply with @safe and @system variants can't be used with foreach syntax

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sat Nov 6 01:02:11 UTC 2021


https://issues.dlang.org/show_bug.cgi?id=15624

--- Comment #5 from Dlang Bot <dlang-bot at dlang.rocks> ---
dlang/dmd pull request #13226 "Rework fix for attribute based opApply overloads
(issue 15624)" was merged into master:

- a28680a845a06d0cac476442c25e7c7fe8e0d16d by MoonlightSentinel:
  Rework fix for attribute based opApply overloads (issue 15624)

  The old implementation uses `Type.covariant` to suppress overzealous
  ambiguity errors for `opApply` specialisations. Deferring the ambiguity
  checks after the attribute inference on the loop body allows for
  `opApply` overloads with different attributes, e.g. `@safe / @system` for
  `@safe / @system` delegates.

  Example:
  ```d
  struct Collection
  {
      /* A. */ int opApply(int delegate(int) @safe dg) @safe;

      /* B. */ int opApply(int delegate(int) @system dg) @system;
  }

  void main() @safe
  {
      Collection col;
      foreach (entry; col) {} // Resolves to A.
  }
  ```

  The previous code achieved this by checking whether the previously
  selected `opApply` and the current overload are covariant in any
  direction (i.e. `A.covariant(B)` or `B.covariant(A)`).

  This implementation builds on the flawed assumption that the `opApply`
  functions in this example are covariant - which they are not
  (falsely reported due to a bug in `Type.covariant`).

  Consider the types of the `opApply` overloads:
  ```d
  A: int function(int delegate(int) @safe dg) @safe;
  B: int function(int delegate(int) @system dg) @system;
  ```

  Neither of those is an appropriate substitute for the other:

  - A <= B is invalid due to the `opApply`'s attributes. A `@system`
      function may not appear in place of a `@safe` function
  - A => B is invalid due to the parameter types (`dg` attributes).
      A function expecting a `@safe` delegate may not be treated as a
      function accepting `@system` callbacks. Otherwise it could silently
      execute a `@system` callback which is disallowed in `@safe` functions.

  Note that `Type.covariant` already rejects covariance when using
  `function` instead of `delegate` for the callbacks in the example.

  ---

  The new implementation does not rely on the buggy behaviour of
  `Type.covariant`. It checks two different aspects to defer the
  `opApply` resolution:

  1. different attributes on the `opApply` function
  2. different attributes on the `opApply` function
  3. covariance of the callbacks receiving the foreach body

  (2) should handle different qualifiers on the foreach body
  because missmatched parameter types are usually rejected by
  `matchParamsToOpApply`.

  ---

  This patch enables us to fix the aforementioned bug without breaking
  existing code. It also enables the code added the test case wich
  is valid despite being utterly useless.

https://github.com/dlang/dmd/pull/13226

--


More information about the Digitalmars-d-bugs mailing list