<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slang.git/tests/diagnostics/enum-implicit-conversion.slang.expected, branch master</title>
<subtitle>Making it easier to work with shaders</subtitle>
<id>https://git.yummers.dev/slang.git/atom?h=master</id>
<link rel='self' href='https://git.yummers.dev/slang.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/'/>
<updated>2024-04-01T22:56:02+00:00</updated>
<entry>
<title>Allow bit operators on enum types. (#3862)</title>
<updated>2024-04-01T22:56:02+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2024-04-01T22:56:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=2c4f9810327d58023e9ec44f579cd78adf56317b'/>
<id>urn:sha1:2c4f9810327d58023e9ec44f579cd78adf56317b</id>
<content type='text'>
* Allow bit operators on enum types.

* Fix.</content>
</entry>
<entry>
<title>Fix erroneous error claiming variable is being used before its declaration (#2958)</title>
<updated>2023-07-06T19:52:00+00:00</updated>
<author>
<name>Ellie Hermaszewska</name>
<email>ellieh@nvidia.com</email>
</author>
<published>2023-07-06T19:52:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=cdfea42f1b28c6ec7b13500a64be823f67bf8e0a'/>
<id>urn:sha1:cdfea42f1b28c6ec7b13500a64be823f67bf8e0a</id>
<content type='text'>
* Simplify type of diagnoseImpl

* Show source line for Note diagnostics, opting out of this where appropriate

* Make declared after use diagnostic clearer

* Fix erroneous error claiming variable is being used before its declaration

Closes https://github.com/shader-slang/slang/issues/2936

* Fix build on msvc

---------

Co-authored-by: jsmall-nvidia &lt;jsmall@nvidia.com&gt;</content>
</entry>
<entry>
<title>Be lenient on same-size unsigend-&gt;signed conversion. (#2913)</title>
<updated>2023-06-01T20:53:31+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2023-06-01T20:53:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=16cd361dd67471bcc355d1b3b72b0b022518088f'/>
<id>urn:sha1:16cd361dd67471bcc355d1b3b72b0b022518088f</id>
<content type='text'>
* Be lenient on same-size unsigend-&gt;signed conversion.

* Fix tests.

* Use 250.

* wip

* Fix.

* Fix tests.

* Fix.

---------

Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Warning on lossy implicit casts. (#2367)</title>
<updated>2022-08-18T06:08:34+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2022-08-18T06:08:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=adaea0e993fd8db351b5dad92802e47ed6d0ec77'/>
<id>urn:sha1:adaea0e993fd8db351b5dad92802e47ed6d0ec77</id>
<content type='text'>
* Warning on bool to float conversion.

* Fix test cases.

* Improve.

* LanguageServer: don't show constant value for non constant variables.

* Fix tests.

* Fix warnings in tests.

Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Diagnostic location highlighting (#1700)</title>
<updated>2021-02-12T19:31:56+00:00</updated>
<author>
<name>jsmall-nvidia</name>
<email>jsmall@nvidia.com</email>
</author>
<published>2021-02-12T19:31:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=369279e91dde1b056d8d0e3bb83e7ba3f96321af'/>
<id>urn:sha1:369279e91dde1b056d8d0e3bb83e7ba3f96321af</id>
<content type='text'>
* #include an absolute path didn't work - because paths were taken to always be relative.

* WIP: First pass in supporting output of line error information.

* Add support for lexing to better be able to indicate SourceLocation information.

* Fix lexer usage in DiagnosticSink in C++ extractor.

* Update diagnostics tests to have line location info.

* Fixed test expected output that now have source location information in them.

* Better handling of tab.

* Fix test expected results for tabbing change.

* DiagnosticLexer -&gt; DiagnosticSink::SourceLocationLexer
Added line continuation tests.

* Fix typo.

* Added String::appendRepeatedChar

* Change to rerun tests.

Co-authored-by: Tim Foley &lt;tfoleyNV@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>Define compound intrinsic ops in the standard library (#1273)</title>
<updated>2020-03-16T16:03:19+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2020-03-16T16:03:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=256a20a163ef6ee93a817472adcb24c076b0c0dc'/>
<id>urn:sha1:256a20a163ef6ee93a817472adcb24c076b0c0dc</id>
<content type='text'>
* Define compound intrinsic ops in the standard library

The current stdlib code has a notion of "compound" intrinsic ops, which use the `__intrinsic_op` modifier but don't actually map to a single IR instruction.
Instead, most* of these map to multiple IR instructions using hard-coded logic in `slang-ir-lower.cpp`.

(* One special case is `kCompoundOp_Pos` that is used for unary `operator+` and that maps to *zero* IR instructions)

All of the opcodes that used to use the `kCompoundOp_` enumeration values now have definitions directly in the stdlib and use the new `[__unsafeForceInlineEarly]` attribute to ensure that they get inlined into their use sites so that the output code is as close as possible to the original.

For the most part, generating the stdlib definitions for the compound ops is straightforward, but here's some notes:

* The unary `operator+` I just defined directly in Slang code, since it doesn't share much structure with other cases

* The unary increment/decrement ops are generated as a cross product of increment/decrement and prefix/postfix. The logic is a bit messy but given that we have scalar, vector, and matrix versions to deal with it still saves code overall

* Because all the compound/assignment cases got moved out, the existing code for generating unary/binary ops can be simplified a bit

* All the no-op bit-cast operations like `asfloat(float)` are now inline identity functions

* A few other small cleanups are made by not having to worry about the compound ops (which used to be called "pseudo ops") sometimes being encoded in to the same type of value as a real IR opcode.

The one big detail here is a fix for how IR lowering works for `let` declarations: they were previously being `materialize()`d which only guarantees that they've been placed in a contiguous and addressable location, but doesn't actually convert them to an r-value. As a result a `let` declaration could accidentally capture a mutable location by reference, which is definitely *not* what we wanted it to do. Fixing this was needed to make the new postfix `++` definition work (several existing tests end up covering this).

One important forward-looking note:

One subtle (but significant) choice in this change is that we actually reduce the number of declarations in the stdlib, because instead of having the compound operators include both per-type and generic overloads (just listing scalar cases for now):

    float operator+=(in out float left, float right) { ... }
    int operator+=(in out int left, int right) { ... }
    ...
    T operator+= &lt;T:__BuiltinBlahBlah&gt;(in out T left, T right) { ... }

We now have *only* the single generic version:

    T operator+= &lt;T:__BuiltinBlahBlah&gt;(in out T left, T right) { ... }

In running our current tests, this change didn't lead to any regressions (perhaps surprisingly).

Given that we were able to reduce the number of overloads for `operator+=` by a factor of N (where N is the number of built-in types), it seems worth considering whether we could also reduce the number of overloads of `operator+` by the same factor by only having generic rather than per-type versions.

One concern that this forward-looking question raises is whether the quality of diagnostic messages around bad calls to the operators might suffer when there are only generic overloads instead of per-type overloads. In order to feel out this problem I added a test case that includes some bad operator calls both to `+=` (which is now only generic with this change) and `+` (which still has per-type overloads). Overall, I found the quality of the error messages (in terms of the candidates that get listed) isn't perfect for either, but personally I prefer the output in the generic case.

As part of adding that test, I also added some fixups to how overload resolution messages get printed, to make sure the function name is printed in more cases, and also that the candidates print more consistently. These changes affected the expected output for one other diagnostic test.

* fixup: disable bad operator test on non-Windows targets</content>
</entry>
<entry>
<title>Expand range of definitions that can be moved into stdlib (#1259)</title>
<updated>2020-03-06T19:37:36+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2020-03-06T19:37:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=18be2d81fd2740d3f0c06fc407cff1702b93d468'/>
<id>urn:sha1:18be2d81fd2740d3f0c06fc407cff1702b93d468</id>
<content type='text'>
The actual definitions that got moved into the stdlib here are pretty few:

* `clip()`
* `cross()`
* `dxx()`, `ddy()` etc.
* `degrees()`
* `distance()`
* `dot()`
* `faceforward()`

The meat of the change is infrastructure changes required to support these new declarations

* Generic versions of the standard operators (e.g., `operator+`) were added that are generic for a type `T` that implements the matching `__Builtin`-prefixed interface. An open question is whether we can now drop the non-generic versions in favor of just having these generic operators.

* A `__BuiltinLogicalType` interface was added to capture the commonality between integers and `bool`

* `__BuiltinArithmeticType` was extended so that implementations must support initialization from an `int`

* `__BuiltinFloatingPointType` was extended to require an accessor that returns the value of pi for the given type, and the concrete floating-point types were extended to provide definitions of this value.

* It turns out that our logic for checking if two functions have the same signature (and should thus count as redeclarations/redefinitions) wasn't taking generic constraints into account at all. That was fixed with a stopgap solution that checks if the generic constraints are pairwise identical, but I didn't implement the more "correct" fix that would require canonicalizing the constraints.

* When doing overload resolution and considering potential callees, logic was added so that a non-generic candidate should always be selected over a generic one (generally the Right Thing to do), and also so that a generic candidate with fewer parameters will be selected over one with more (an approximation of the much more complicated rule we'd ideally have).

* The formatting of declarations/overloads for "ambiguous overload" errors was fleshed out a bit to include more context (the "kind" of declaration where appropriate, the return type for function declarations) and to properly space thing when outputting specialization of operator overloads that end with `&lt;` (so that we print `func &lt; &lt;int&gt;(int, int)` instead of just `func &lt;&lt;int,int&gt;(int,int)`).

* The core lookup routines were heavily refactored and reorganized to try to make them bottleneck more effectively so that all paths handle all the nuances of inheritance, extensions, etc.

* Because of the refactoring to lookup logic, the semantic checking logic related to checking if a type conforms to an interface was updated to be driven based on the `Type` that is supposed to be conforming, rather than a `DeclRef` to the type's declaration. This allows it to use the type-based lookup entry point and eliminates one special-case entry point for lookup.

In addition to the various core changes, this change also refactors some of the existing stdlib code to favor writing more things in actual Slang syntax, and less in C++ code that uses `StringBuilder` to construct the Slang syntax. There is a lot more that could be done along those lines, but even pushing this far is showing that the current approach that `slang-generate` takes for how to separate meta-level C++ and Slang code isn't really ideal, so a revamp of the generator code is probably needed before I continue pushing.

One surprising casualty of the refactoring of lookup is that we no longer have the `lookedUpDecls` field in `LookupResult`. That field probably didn't belong there anyway, but the role it served was important. The idea of `lookedUpDecls` was to avoid looking up in the same interface more than once in cases where a type might have a "diamond" inheritance pattern. Removing that field doesn't appear to affect correctness of any of our existing tests, but by adding a specific test for "diamond" inheritance I could see that the refactoring introduced a regression and made looking up a member inherited along multiple paths ambiguous.

Rather than add back `lookedUpDecls` I went for a simpler (but arguably even hackier) solution where when ranking candidates from a `LookupResult` we check for identical `DeclRef`s and arbitrarily favor one over the other. One complication that arises here is that when comparing `DeclRef`s inherited along different paths they might have a `ThisTypeSubstitution` for the same type, but with different subtype witnesses (because different inheritance paths could lead to different transitive subtype witnesses: e.g., `A : B : D` and `A : C : D`).</content>
</entry>
<entry>
<title>Support conversion from int/uint to enum types (#1147)</title>
<updated>2019-12-06T23:50:32+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2019-12-06T23:50:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=2e52217cb870b4101c1639fed78224f89bf119b3'/>
<id>urn:sha1:2e52217cb870b4101c1639fed78224f89bf119b3</id>
<content type='text'>
* Support conversion from int/uint to enum types

The basic feature here is tiny, and is summarized in the code added to the stdlib:

```
extension __EnumType
{
	__init(int val);
	__init(uint val);
}
```

The front-end already makes all `enum` types implicitly conform to `__EnumType` behind the scenes, and this `extension` makes it so that all such types inherit some initializers (`__init` declarations, aka. "constructors") that take `int` and `uint`.

(Note: right now all `__init` declarations in Slang are assumed to be implemented as intrinsics using `kIROp_Construct`. This obviously needs to change some day, especially so that we can support user-defined initializers.)

Actually making this *work* required a bit of fleshing out pieces of the compiler that had previously been a bit ad hoc to be a bit more "correct." Most of the rest of this description is focused on those details, since the main feature is not itself very exciting.

When overload resolution sees an attempt to "call" a type (e.g., `MyType(3.0)`) it needs to add appropriate overload candidates for the initializers in that type, which may take different numbers and types of parameters. The existing code for handling this case was using an ad hoc approach to try to enumerate the initializer declarations to consider, which might be found via inheritance, `extension` declarations, etc.

In practice, the ad hoc logic for looking up initializers was just doing a subset of the work that already goes into doing member lookup. Changing the code so that it effectively does lookup for `MyType.__init` allows us to look up initializers in a way that is consistent with any other case of member lookup. Generalizing this lookup step brings us one step closer to being able to go from an `enum` type `E` to an initializer defined on an `extension` of an `interface` that `E` conforms to.

One casualty of using the ordinary lookup logic for initializers is that we used to pass the type being constructed down into the logic that enumerated the initializers, which made it easier to short-circuit the part of overload resolution that usually asks "what type does this candidate return."

It might seem "obvious" that an initializer/constructor on type `Foo` should return a value of type `Foo`, but that isn't necessarily true.
Consider the `__BuiltinFloatingPointType` interface, which requires all the built-in floating-point types (`float`, `double`, `half`) to have an initializer that can take a `float`.
If we call that interface in a generic context for `T : __BuiltinFloatingPointType`, then we want to treat that initializer as returning `T` and not `__BuiltinFloatingPointType`.
Without the ad hoc logic in initializer overload resolution, this is the exact problem that surfaced for the stdlib definition of `clamp`.

The solution to the "what type does an initializer return" problem was to introduce a notion of a `ThisType`, which refers to the type of `this` in the body of an interface.
More generally, we will eventually want to have the keyword `This` be the type-level equivalent of `this`, and be usable inside any type.
The `calcThisType` function introduced here computes a reasonable `Type` to represent the value of `This` within a given declaration.
Inside of concrete type it refers to the type itself, while in an `interface` it will always be a `ThisType`.
The existing `ThisTypeSubstitution`s, previously only applied to associated types, now apply to `ThisType`s as well, in the same situations.

The next roadblock for making the simple declarations for `__EnumType` work was that the lookup logic was only doing lookup through inheritance relationships when the type being looked up in was an `interface`.
The logic in play was reasonable: if you are doing lookup in a type `T` that inherits from `IFoo`, then why bother looking for `IFoo::bar` when there must be a `T::bar` if `T` actually implements the interface?

The catch in this case is that `IFoo::bar` might not be a requirement of `IFoo`, but rather a concrete method added via an `extension`, in which case `T` need not have its own concrete `bar`.
The simple/obvious fix here was to make the lookup logic always include inherited members, even when looking up through a concrete type.

Of course, if we allow lookup to see `IFoo::bar` when looking up on `T`, then we have the problem that both `T::bar` and `IFoo::bar` show up in the lookup results, and potentially lead to an "ambiguous overload" error.
This problem arises for any interface rquirement (so both methods and associated types right now).
In order to get around it, I added a somewhat grungy check for comparing overload candidates (during overload resolution) or `LookupResultItem`s (during resolution of simple overloaded identifiers) that considers a member of a concrete type as automatically "better" than a member of an interface.
The Right Way to solve this problem in the long run requires some more subtlety, but for now this check should Just Work.

One final wrinkle is that due to our IR lowering pass being a bit overzealous, we currently end up trying to emit IR for those new `__init` declarations, which ends up causing us to try and emit IR for a `ThisType`.
That is a case that will require some subtlty to handle correctly down the line, for for now we do the expedient thing and emit the `ThisType` for `IFoo` as `IFoo` itself, which is not especially correct, but doesn't matter since the concrete initializer won't ever be called.

* testing: add more debug output to Unix process launch function

* testing: increase timeout when running command-line tests
</content>
</entry>
<entry>
<title>Overhaul the core routines for implicit conversion (#927)</title>
<updated>2019-03-27T14:50:46+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2019-03-27T14:50:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=047adbd4dd3dd6e3098adcb63a8ac475ae06d20d'/>
<id>urn:sha1:047adbd4dd3dd6e3098adcb63a8ac475ae06d20d</id>
<content type='text'>
* Overhaul the core routines for implicit conversion

The main user-visible change is that we have fixed the bug where conversions that should only be allowed explicitly were being allowed implicitly. This might be seen as a regression by users, so we'll have to be careful when rolling out the fix.

The core of that fix involves checking whether an `init` declaration that will be invoked as an implicit conversion actually supports implicit conversions.

The main visible change in the code is some renamings to try and help make the core type-coercion routines better fit our naming conventions.

The main cleanup is to enforce the invariant that any of the implicit-conversion core routines will always emit a diagnostic (or have a subroutine it calls do so) when conversion fails and the `outToExpr` parameter is non-null. This is a small change, but should improve the user experience if an implicit conversion fails in the context of a single element of an initializer list (the error should point at the line in question, and not at the whole list).

The big thing that is impacted by removing the ability to use explicit conversions implicitly is conversion of `enum` types to integers. This was intended to be explicit (a la `enum class` in C++), but the bug made it so that implicit conversion was allowed.

Closing up that gap meant that some of the checking around user-defined attributes got wonky, because we attempt to check that the attribute argument is an integer constant expression, but an `enum` case can't possible be an integer constant - it is a value of the `enum` type. I added code to work around that issue by having a parallel path for checking compile-time-constant expressions of `enum` type, but it is clear that a more general solution is needed eventually.

* fixup: test case needs explicit cast
</content>
</entry>
</feed>
