From 87940a649e3b4f757905015de95225d57ec2f27c Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Fri, 24 Jul 2020 18:12:41 -0700 Subject: Fix bugs related to mutating implementations of interface methods (#1461) There are two main bug fixes here: * We were failing to diagnose when code calls a `[mutating]` method on a value that doesn't support mutation (that is an r-value instead of an l-value). * We had a bug in the synthesis logic for interface requirements where we used the *result* type of the requirement in place of each of the *parameter* types. The second bug made synthesis often produce incorrect signatures with `void` parameters. The first bug meant that even though a `[mutating]` method should not be able to satisfy a non-`[mutating]` method (and we had code to enforce this for the "exact match" case), when we go on to try and synthesize a non-`[mutating]` method that satisfies the requirement by delegating to the user-written one, it would end up succeeding, because nothing was stopping a non-`[mutating]` method from calling a `[mutating]` one. In each case this code adds a fix and a test case to confirm it. --- .../mutating-impl-of-non-mutating-req.slang | 42 ++++++++++++++++++++++ ...utating-impl-of-non-mutating-req.slang.expected | 6 ++++ .../methods/mutating-method-on-rvalue.slang | 26 ++++++++++++++ .../mutating-method-on-rvalue.slang.expected | 8 +++++ 4 files changed, 82 insertions(+) create mode 100644 tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang create mode 100644 tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang.expected create mode 100644 tests/diagnostics/methods/mutating-method-on-rvalue.slang create mode 100644 tests/diagnostics/methods/mutating-method-on-rvalue.slang.expected (limited to 'tests/diagnostics') diff --git a/tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang b/tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang new file mode 100644 index 000000000..2dbe45ccb --- /dev/null +++ b/tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang @@ -0,0 +1,42 @@ +// mutating-impl-of-non-mutating-req.slang + +//DIAGNOSTIC_TEST:SIMPLE:-target hlsl -entry main + +interface IThing +{ + int processValue(int inValue); +} + +struct Counter : IThing +{ + int state; + + [mutating] int processValue(int inValue) + { + int result = state; + state += inValue; + return state; + } +} + +int helper(T thing, int value) +{ + return thing.processValue(value); +} + +int test(int value) +{ + Counter counter = { value }; + return helper(counter, value); +} + +cbuffer C +{ + int gValue; +} + +[shader("fragment")] +int main() : SV_Target +{ + return test(gValue); +} \ No newline at end of file diff --git a/tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang.expected b/tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang.expected new file mode 100644 index 000000000..922a6c826 --- /dev/null +++ b/tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang.expected @@ -0,0 +1,6 @@ +result code = -1 +standard error = { +tests/diagnostics/interfaces/mutating-impl-of-non-mutating-req.slang(10): error 38100: type 'Counter' does not provide required interface member 'processValue' +} +standard output = { +} diff --git a/tests/diagnostics/methods/mutating-method-on-rvalue.slang b/tests/diagnostics/methods/mutating-method-on-rvalue.slang new file mode 100644 index 000000000..ab51244aa --- /dev/null +++ b/tests/diagnostics/methods/mutating-method-on-rvalue.slang @@ -0,0 +1,26 @@ +// mutating-method-on-rvalue.slang + +//DIAGNOSTIC_TEST:SIMPLE:-target hlsl -entry main + +struct Counter +{ + int count; + + [mutating] void increment() { count++; } + + void bad() + { + increment(); + } +} + +cbuffer C +{ + Counter gCounter; +} + +[shader("compute")] +void main() +{ + gCounter.increment(); +} \ No newline at end of file diff --git a/tests/diagnostics/methods/mutating-method-on-rvalue.slang.expected b/tests/diagnostics/methods/mutating-method-on-rvalue.slang.expected new file mode 100644 index 000000000..878882bd3 --- /dev/null +++ b/tests/diagnostics/methods/mutating-method-on-rvalue.slang.expected @@ -0,0 +1,8 @@ +result code = -1 +standard error = { +tests/diagnostics/methods/mutating-method-on-rvalue.slang(13): error 30050: mutating method 'increment' cannot be called on an immutable value +tests/diagnostics/methods/mutating-method-on-rvalue.slang(13): note 30049: a 'this' parameter is an immutable parameter by default in Slang; apply the `[mutating]` attribute to the function declaration to opt in to a mutable `this` +tests/diagnostics/methods/mutating-method-on-rvalue.slang(25): error 30050: mutating method 'increment' cannot be called on an immutable value +} +standard output = { +} -- cgit v1.2.3