https://github.com/shader-slang/slang
Revision f3d637ba4d90bc2e23db07f1a9df5a6be7533f08 authored by Tim Foley on 04 June 2020, 18:53:13 UTC, committed by GitHub on 04 June 2020, 18:53:13 UTC
* 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
1 parent 1b8731c
History
Tip revision: f3d637ba4d90bc2e23db07f1a9df5a6be7533f08 authored by Tim Foley on 04 June 2020, 18:53:13 UTC
First steps toward inheritance for struct types (#1366)
Tip revision: f3d637b
File Mode Size
docs
examples
external
prelude
source
tests
tools
.editorconfig -rw-r--r-- 937 bytes
.gitattributes -rw-r--r-- 95 bytes
.gitignore -rw-r--r-- 480 bytes
.gitmodules -rw-r--r-- 774 bytes
.travis.yml -rw-r--r-- 1.7 KB
CODE_OF_CONDUCT.md -rw-r--r-- 3.1 KB
LICENSE -rw-r--r-- 1.1 KB
README.md -rw-r--r-- 7.4 KB
appveyor.yml -rw-r--r-- 4.0 KB
premake5.lua -rw-r--r-- 34.8 KB
slang-com-helper.h -rw-r--r-- 4.8 KB
slang-com-ptr.h -rw-r--r-- 4.8 KB
slang-tag-version.h -rw-r--r-- 36 bytes
slang.h -rw-r--r-- 128.0 KB
slang.sln -rw-r--r-- 11.7 KB
test.bat -rw-r--r-- 1.4 KB
travis_build.sh -rw-r--r-- 460 bytes
travis_test.sh -rw-r--r-- 435 bytes

README.md

back to top