Files
sx/examples/generics/0218-generics-ufcs-receiver-specificity.sx
agra 6ee4d066b3 fibers: address adversarial review of the B1 changes (6 findings)
UFCS generic overload resolution (issue 0157 follow-ups):
- P1-a: call planning (calls.zig) used the last-wins fn_ast_map winner
  while lowering reselected by receiver, so the planned result type
  could disagree with the dispatched function and misbox the result.
  Both now share selectUfcsGenericByReceiver(.., fd0).
- P1-b: selection scanned module_decls globally, flagging a
  transitively-hidden same-named overload as a false ambiguity. Now
  two-tier: directly-visible authors first (ambiguity only among
  those), global fallback for receiver-reachable namespaced methods
  (e.g. Task.cancel) that defers to fd0 on a hidden tie.
- P2-b: boolean specificity tied *$T with *Box($T). Now peels pointer
  layers so the structurally-narrower receiver wins.

Scheduler (sched.sx):
- P1-c: a second concurrent Task.wait overwrote the single waiter slot
  -> silent deadlock. Now one-awaiter-per-task loud abort.
- P2-c: sleep(negative) rewound the monotonic virtual clock. Rejected
  loudly.

(P2-a, non-generic-winner-hides-generic, did not reproduce -- the
non-generic arm already falls through.)

Regressions: examples/generics/0218 (receiver specificity +
plan/lowering agreement), examples/concurrency/1818 (negative-sleep
abort), 1819 (double-wait abort). Suite green 758/0.
2026-06-21 22:05:22 +03:00

29 lines
1.3 KiB
Plaintext

// A more-specific UFCS receiver overload must win over a fully-generic one
// (`*Box($T)` beats `*$T`), AND call planning must agree with lowering on which
// overload is dispatched — else the result is typed by one function but produced
// by another, misboxing it.
//
// Regression (issue 0157 review, P1-a + P2-b): the planner (calls.zig) used the
// last-wins `fn_ast_map` winner while lowering reselected by receiver, so a
// `*$T->string` winner could type a call that lowering dispatched to
// `*Box($T)->i64` — boxing the i64 as a string pointer. And boolean specificity
// treated `*$T` and `*Box($T)` as equal (false ambiguity). Fixed by sharing one
// receiver-aware, pointer-peeling selection between planner and lowering.
#import "modules/std.sx";
#import "0218-generics-ufcs-receiver-specificity/0218-shared.sx";
#import "0218-generics-ufcs-receiver-specificity/anyref.sx";
// More-specific receiver than the imported `pick(x: *$T)`.
pick :: ufcs (b: *Box($T)) -> i64 { return 7; }
// Generic passthrough — its result type is the PLANNED type of its argument, so
// a planner/lowering disagreement on `pick`'s return type surfaces here.
echo :: (x: $U) -> $U { return x; }
main :: () -> i64 {
b : Box(i64) = ---; b.v = 0;
r := echo((@b).pick()); // *Box wins → i64 7; plan must agree (else misbox)
print("r: {}\n", r);
return 0;
}