diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2020-06-04 11:53:13 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-04 11:53:13 -0700 |
| commit | f3d637ba4d90bc2e23db07f1a9df5a6be7533f08 (patch) | |
| tree | 3dfe2fd73309ed4caf4ad6d4e8ee7a138296dfc3 /source/slang/slang-ast-modifier.h | |
| parent | 1b8731c809761c4e2dbec81dcee207f8a4621903 (diff) | |
First steps toward inheritance for struct types (#1366)
* First steps toward inheritance for struct types
This change adds the ability for a `struct` type to declare a base type that is another `struct`:
```hlsl
struct Base
{
int baseMember;
}
struct Derived : Base
{
int derivedMember;
}
```
The semantics of the feature are that code like the above desugars into code like:
```hlsl
struct Base
{
int baseMember;
}
struct Derived
{
Base _base;
int derivedMember;
}
```
At points where a member from the base type is being projected out, or the value is being implicitly cast to the base type, the compiler transforms the code to reference the implicitly-generated `_base` member. That means code like this:
```hlsl
void f(Base b);
...
Derived d = ...;
int x = d.baseMember;
f(d);
```
gets transformed into a form like this:
```hlsl
void f(Base b);
...
Derived d = ...;
int x = d._base.baseMember;
f(d._base);
```
Note that as a result of this choice, the behavior when passing a `Derived` value to a function that expects a `Base` (including to inherited member functions) is that of "object shearing" from the C++ world: the called function can only "see" the `Base` part of the argument, and any operations performed on it will behave as if the value was indeed a `Base`. There is no polymorphism going on because Slang doesn't currently have `virtual` methods.
In an attempt to work toward inheritance being a robust feature, this change adds a bunch of more detailed logic for checking the bases of various declarations:
* An `interface` declaration is only allowed to inherit from other `interface`s
* An `extension` declaration can only introduce inheritance from `interface`s
* A `struct` declaration can only inherit from at most one other `struct`, and that `struct` must be the first entry in the list of bases
This change also adds a mechanism to control whether a `struct` or `interface` in one module can inherit from a `struct` or `interface` declared in another module:
* If the base declaration is marked `[open]`, then the inheritance is allowed
* If the base declaration is marked `[sealed]`, then the inheritance is allowed
* If it is not marked otherwise, a `struct` is implicitly `[sealed]`
* If it is not marked otherwise, an `interface` is implicitly `[open]`
These seem like reasonable defaults. In order to safeguard the standard library a bit, the interfaces for builtin types have been marked `[sealed]` to make sure that a user cannot declare a `struct` and then mark it as a `BuiltinFloatingPointType`. This step should bring us a bit closer to being able to document and expose these interfaces for built-in types so that users can write code that is generic over them.
There are some big caveats with this work, such that it really only represents a stepping-stone toward a usable inheritance feature. The most important caveats are:
* If a `Derived` type tries to conform to an interface, such that one or more interface requirements are satisfied with members inherited from the `Base` type, that is likely to cause a crash or incorrect code generation.
* If a `Derived` type tries to inherit from a `Base` type that conforms to one or more interfaces, the witness table generated for the conformance of `Derived` to that interface is likely to lead to a crash or incorrect code generation.
It is clear that solving both of those issues will be necessary before we can really promote `struct` inheritance as a feature for users to try out.
* fixup: trying to appease clang error
* fixups: review feedback
Diffstat (limited to 'source/slang/slang-ast-modifier.h')
| -rw-r--r-- | source/slang/slang-ast-modifier.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 065118c7a..4badbd02a 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -873,4 +873,14 @@ class UnsafeForceInlineEarlyAttribute : public Attribute SLANG_CLASS(UnsafeForceInlineEarlyAttribute) }; + /// An attribute that marks a type declaration as either allowing or + /// disallowing the type to be inherited from in other modules. +class InheritanceControlAttribute : public Attribute { SLANG_CLASS(InheritanceControlAttribute) }; + + /// An attribute that marks a type declaration as allowing the type to be inherited from in other modules. +class OpenAttribute : public InheritanceControlAttribute { SLANG_CLASS(OpenAttribute) }; + + /// An attribute that marks a type declaration as disallowing the type to be inherited from in other modules. +class SealedAttribute : public InheritanceControlAttribute { SLANG_CLASS(SealedAttribute) }; + } // namespace Slang |
