fix: validate protocol impl method signatures vs the protocol declaration (issue 0178)
The issue-0176 conformance gate was name-only, so an impl P for T with a mismatched return/param type (or arity) built a wrong-ABI thunk that silently miscompiled (exit 0, wrong value). firstUnimplementedMethod now validates arity (after self), each param type, and the return type against the protocol declaration, substituting protocol Self->concrete via resolveProtoTypeSubSelf (recurses through pointer/many-pointer/ optional/slice/array so []Self<->[]T match; conservative .unresolved for Self-in-generic-arg). Comparison is by structural formatTypeName (alias/module/spelling independent); typesClearlyDiffer skips when either side has an unresolved leaf at any depth, biasing against false-positives. Regressions: diagnostics/1201 (negative), protocols/0420 (positive, []Self param). Verified by 3+3 adversarial reviews (a mid-fix []Self false-positive was found and closed); suite 792/0.
This commit is contained in:
33
examples/protocols/0420-protocol-self-in-slice-param.sx
Normal file
33
examples/protocols/0420-protocol-self-in-slice-param.sx
Normal file
@@ -0,0 +1,33 @@
|
||||
// `Self` nested inside a SLICE in a protocol-method param resolves
|
||||
// correctly: the conformance gate substitutes `Self → T` THROUGH the
|
||||
// `[]` wrapper (and the `*Self` receiver), so a correct `[]T` impl is
|
||||
// accepted and dispatched — not falsely rejected as `[]Self` ≠ `[]T`.
|
||||
//
|
||||
// Regression (issue 0178 adversarial review): the signature gate's
|
||||
// `Self`-substitution originally only reached the bare leaf and a
|
||||
// one-level pointer/optional wrapper, so `[]Self` resolved to a real
|
||||
// slice named `[]Self` and a correct `[]T` impl was WRONGLY flagged.
|
||||
#import "modules/std.sx";
|
||||
|
||||
P :: protocol {
|
||||
// `*Self` receiver + `[]Self` slice param + `Self` value param.
|
||||
total :: (self: *Self, xs: []Self, extra: Self) -> i64;
|
||||
}
|
||||
|
||||
T :: struct { n: i64 = 0; }
|
||||
|
||||
impl P for T {
|
||||
total :: (self: *T, xs: []T, extra: T) -> i64 {
|
||||
sum := self.n + extra.n;
|
||||
for xs (x) { sum = sum + x.n; }
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
main :: () {
|
||||
t := T.{ n = 10 };
|
||||
p : P = t;
|
||||
arr : [3]T = .{ T.{ n = 1 }, T.{ n = 2 }, T.{ n = 3 } };
|
||||
// 10 (self) + 1+2+3 (slice) + 100 (extra) = 116
|
||||
print("{}\n", p.total(arr[..], T.{ n = 100 }));
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
116
|
||||
Reference in New Issue
Block a user