Synthesizing Equatable, Hashable, and Comparable for tuple types

I don’t know what the answer to your question is, nor do I know what the current list of priorities are. :-)

-Chris

···

On Nov 21, 2017, at 9:06 AM, David Hart <david@hartbit.com> wrote:

On 21 Nov 2017, at 03:17, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Yes, I agree, we need variadic generics before we can have tuples conform :-(

At the end of the day, you want to be able to treat “(U, V, W)” as sugar for Tuple<U,V,W> just like we handle array sugar. When that is possible, Tuple is just a type like any other in the system (but we need variadics to express it).

Eye-opening! Now I understand how important variadic generics are. Somebody should add that example to the Generics Manifesto. Questions:

• Doesn’t this simplification of the type system hoist Variadic Generics back up the list of priorities?

Not above conditional and recursive conformances.

Correct. But recursive conformances are implemented and conditional conformances are on the way. To rephrase my question: doesn't this simplification of the type system hoist Variadic Generics to be the next big priority after conditional conformances are finished?

Yes, I agree, we need variadic generics before we can have tuples conform :-(

At the end of the day, you want to be able to treat “(U, V, W)” as sugar for Tuple<U,V,W> just like we handle array sugar. When that is possible, Tuple is just a type like any other in the system (but we need variadics to express it).

Eye-opening! Now I understand how important variadic generics are. Somebody should add that example to the Generics Manifesto.

It’s in there under “extensions of structural types”, here: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#extensions-of-structural-types

with this example:

  extension<...Elements : Equatable> (Elements...) : Equatable { // extending the tuple type "(Elements...)" to be Equatable
}

Questions:

• Doesn’t this simplification of the type system hoist Variadic Generics back up the list of priorities?

Not above conditional and recursive conformances.

Right, and we don’t have bandwidth to take on Another Major Generics Feature this year.

• Would it be desirable to implement them before ABI stability to “remove” tuples from the ABI?

Tuples are structural types in the ABI (and type system), and should remain that way. So, I disagree with Chris’s suggestion that (U, V, W) will become Tuple<U, V, W>. The most relevant comparison today is Optional, which is technically a nominal type but is treated as a special case basically everywhere in the compiler (and ABI) because it should have been a structural type. I expect optionals to become structural types in the future (the ABI is designed for that) and tuples to remain structural types.

Can somebody explain to me what are
nominal and structural types and why Optional should really be a structural type?

···

On 21 Nov 2017, at 22:44, Douglas Gregor <dgregor@apple.com> wrote:

On Nov 20, 2017, at 10:31 PM, Chris Lattner <clattner@nondot.org> wrote:
On Nov 20, 2017, at 10:24 PM, David Hart <david@hartbit.com> wrote:
On 21 Nov 2017, at 03:17, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

• If not, is the current ABI already flexible enough to support them if they are implemented later on?

I am not the expert on this (Doug Gregor is), but I think we can add it later in an ABI additive way.

Yes, we can add it to the ABI later.

  - Doug

-Chris

Once you have that, then you could write conformances in general, as well as conditional conformances that depend on (e.g.) all the element types being equatable.

We also need that to allow functions conform to protocols, because functions aren’t "T1->T2” objects, the actual parameter list is an inseparable part of the function type, and the parameter list needs variadics.

-Chris

On Nov 20, 2017, at 6:10 PM, Slava Pestov <spestov@apple.com> wrote:

Ignoring synthesized conformances for a second, think about how you would manually implement a conformance of a tuple type to a protocol. You would need some way to statically “iterate” over all the component types of the tuple — in fact this is the same as having variadic generics.

If we had variadic generics, we could implement tuples conforming to protocols, either by refactoring the compiler to allow conforming types to be non-nominal, or by reworking things so that a tuple is a nominal type with a single variadic generic parameter.

Slava

On Nov 20, 2017, at 9:06 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

This is something I've wanted to look at for a while. A few weeks ago I pushed out Synthesize ==/hashValue for tuple fields/payloads by allevato · Pull Request #12598 · apple/swift · GitHub to extend the existing synthesis to handle structs/enums when a field/payload has a tuple of things that are Equatable/Hashable, and in that PR it was (rightly) observed, as Chris just did, that making tuples conform to protocols would be a more general solution that solves the same problem you want to solve here.

I'd love to dig into this more, but last time I experimented with it I got stuck on places where the protocol conformance machinery expects NominalTypeDecls, and I wasn't sure where the right place to hoist that logic up to was (since tuples don't have a corresponding Decl from what I can tell). Any pointers?

On Mon, Nov 20, 2017 at 5:51 PM Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 20, 2017, at 5:48 PM, Kelvin Ma <kelvin13ma@gmail.com> wrote:
the end goal here is to use tuples as a compatible currency type, to that end it makes sense for these three protocols to be handled as “compiler magic” and to disallow users from manually defining tuple conformances themselves. i’m not a fan of compiler magic, but Equatable, Hashable, and Comparable are special because they’re the basis for a lot of standard library functionality so i think the benefits of making this a special supported case outweigh the additional language opacity.

I understand your goal, but that compiler magic can’t exist until there is something to hook it into. Tuples can’t conform to protocols right now, so there is nothing that can be synthesized.

-Chris

On Mon, Nov 20, 2017 at 8:42 PM, Chris Lattner <clattner@nondot.org> wrote:

On Nov 20, 2017, at 5:39 PM, Kelvin Ma via swift-evolution <swift-evolution@swift.org> wrote:

when SE-185 went through swift evolution, it was agreed that the next logical step is synthesizing these conformances for tuple types, though it was left out of the original proposal to avoid mission creep. I think now is the time to start thinking about this. i’m also tacking on Comparable to the other two protocols because there is precedent in the language from SE-15 that tuple comparison is something that makes sense to write.

EHC conformance is even more important for tuples than it is for structs because tuples effectively have no workaround whereas in structs, you could just manually implement the conformance.

In my opinion, you’re approaching this from the wrong direction. The fundamental problem here is that tuples can’t conform to a protocol. If they could, synthesizing these conformances would be straight-forward.

If you’re interested in pushing this forward, the discussion is “how do non-nominal types like tuples and functions conform to protocols”?

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

they use packed buffers of floats, which for type safety are better
rebound to a structured type. right now (Float, Float, Float) works because
the tuple is laid out contiguously and the GPU can’t tell the difference
but it’s not guaranteed. also you’re ignoring all the CPU stages that occur
before anything even gets sent to the GPU.

Precisely, there is no guarantee of performance if you call these APIs
with an array of Swift tuples.

which is exactly why i support a dedicated language-level vector type
which guarantees contiguous, fixed storage, and which the compiler knows
about so it can vectorize operations on them.

That's an entirely separate discussion.

tuples right now try to fill too many roles and that makes life
difficult for both the compiler and the programmer. however, until then, we
need some kind of common, fixed layout currency type for vector data, and
by implementation-detail, *tuples are our best option* since for some
reason everyone is so opposed to the simple solution of baking vec2,
vec3, … vec5 into the language and the generic integer Vector<Float, k>
solution everyone wants likely isn’t going to materialize for the
foreseeable future.

Disagree. If you want a particular memory layout, define your type in C.
Swift's interop story is very good, and your type will have a fixed layout
forever.

“*write it in c and import it*” is *not* a solution,, it is a workaround.

Yes, that’s what we’re talking about here: workarounds to lack of a fixed
layout type. I’m saying C is the “best option” workaround, not tuples.

plus since it lives across the module boundary, it’s effectively opaque to

compiler optimizations.

What sorts of optimizations are you referring to? Recall that we are
talking about taking a value and unsafe bitcasting for the purposes of
calling other C APIs.

···

On Tue, Nov 28, 2017 at 00:32 Kelvin Ma <kelvin13ma@gmail.com> wrote:

On Mon, Nov 27, 2017 at 9:43 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Mon, Nov 27, 2017 at 5:56 PM, Kelvin Ma <kelvin13ma@gmail.com> wrote:

On Mon, Nov 27, 2017 at 4:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Mon, Nov 27, 2017 at 15:46 Taylor Swift <kelvin13ma@gmail.com> >>>> wrote:

Right. Optionals are a tricky case because we wanted them to be nominal so we could write extensions on them and make them conform to protocols, but, they’re so integral to the language that they are really treated like a structural type.

  - Doug

···

On Nov 21, 2017, at 3:05 PM, Slava Pestov <spestov@apple.com> wrote:

On Nov 21, 2017, at 6:02 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

Can somebody explain to me what are
nominal and structural types and why Optional should really be a structural type?

Nominal types are structs, enums, protocols and classes. They have declarations in source and are uniquely identified by their name. Structural types are functions, meta types, protocol compositions, and tuples.

The distinction is not as clear as you might think because as Chris said, you can imagine tuple being implemented as ‘struct Tuple<T…>’, similarly functions and meta types could also be written as such. It is mostly a syntactic distinction in the language, but it has far-reaching consequences in internal representations, which is why for now it would be tricky to have structural types conform to protocols.

Nominal types are structs, enums, protocols and classes. They have declarations in source and are uniquely identified by their name. Structural types are functions, meta types, protocol compositions, and tuples.

The distinction is not as clear as you might think because as Chris said, you can imagine tuple being implemented as ‘struct Tuple<T…>’, similarly functions and meta types could also be written as such. It is mostly a syntactic distinction in the language, but it has far-reaching consequences in internal representations, which is why for now it would be tricky to have structural types conform to protocols.

Slava

···

On Nov 21, 2017, at 6:02 PM, David Hart <david@hartbit.com> wrote:

Can somebody explain to me what are
nominal and structural types and why Optional should really be a structural type?

Does that mean that once structural types can conform to protocols, would the core team want to remove Optional as a nominal type and just use “T?”?

Yes; at least, it’s a direction we’ve discussed a number of times.

Or has that ship sailed because of source compatibility and you just don’t want to introduce any new nominals that shadow structurals?

typealias Optional<T> = T?

Should address source compatibility.

  - Doug

···

Sent from my iPhone

On Nov 21, 2017, at 3:46 PM, Tony Allevato <tony.allevato@gmail.com> wrote:

On Tue, Nov 21, 2017 at 3:10 PM Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 3:05 PM, Slava Pestov <spestov@apple.com> wrote:

On Nov 21, 2017, at 6:02 PM, David Hart <david@hartbit.com> wrote:

Can somebody explain to me what are
nominal and structural types and why Optional should really be a structural type?

Nominal types are structs, enums, protocols and classes. They have declarations in source and are uniquely identified by their name. Structural types are functions, meta types, protocol compositions, and tuples.

The distinction is not as clear as you might think because as Chris said, you can imagine tuple being implemented as ‘struct Tuple<T…>’, similarly functions and meta types could also be written as such. It is mostly a syntactic distinction in the language, but it has far-reaching consequences in internal representations, which is why for now it would be tricky to have structural types conform to protocols.

Right. Optionals are a tricky case because we wanted them to be nominal so we could write extensions on them and make them conform to protocols, but, they’re so integral to the language that they are really treated like a structural type.

  - Doug

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

-Chris

···

On Nov 21, 2017, at 7:19 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Sent from my iPhone

On Nov 21, 2017, at 3:46 PM, Tony Allevato <tony.allevato@gmail.com <mailto:tony.allevato@gmail.com>> wrote:

Does that mean that once structural types can conform to protocols, would the core team want to remove Optional as a nominal type and just use “T?”?

Yes; at least, it’s a direction we’ve discussed a number of times.

Or has that ship sailed because of source compatibility and you just don’t want to introduce any new nominals that shadow structurals?

typealias Optional<T> = T?

Should address source compatibility.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

  - Doug

···

On Nov 21, 2017, at 9:21 PM, Chris Lattner <clattner@nondot.org> wrote:

On Nov 21, 2017, at 7:19 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sent from my iPhone

On Nov 21, 2017, at 3:46 PM, Tony Allevato <tony.allevato@gmail.com <mailto:tony.allevato@gmail.com>> wrote:

Does that mean that once structural types can conform to protocols, would the core team want to remove Optional as a nominal type and just use “T?”?

Yes; at least, it’s a direction we’ve discussed a number of times.

Or has that ship sailed because of source compatibility and you just don’t want to introduce any new nominals that shadow structurals?

typealias Optional<T> = T?

Should address source compatibility.

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

I’m totally aware of that and mentioned it upthread. There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

-Chris

···

On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com> wrote:

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

  - Doug

···

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org> wrote:
On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

Does that mean that once structural types can conform to protocols, would
the core team want to remove Optional as a nominal type and just use “T?”?
Or has that ship sailed because of source compatibility and you just don’t
want to introduce any new nominals that shadow structurals?

···

On Tue, Nov 21, 2017 at 3:10 PM Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 3:05 PM, Slava Pestov <spestov@apple.com> wrote:

On Nov 21, 2017, at 6:02 PM, David Hart <david@hartbit.com> wrote:

Can somebody explain to me what are
nominal and structural types and why Optional should really be a
structural type?

Nominal types are structs, enums, protocols and classes. They have
declarations in source and are uniquely identified by their name.
Structural types are functions, meta types, protocol compositions, and
tuples.

The distinction is not as clear as you might think because as Chris said,
you can imagine tuple being implemented as ‘struct Tuple<T…>’, similarly
functions and meta types could also be written as such. It is mostly a
syntactic distinction in the language, but it has far-reaching consequences
in internal representations, which is why for now it would be tricky to
have structural types conform to protocols.

Right. Optionals are a tricky case because we wanted them to be nominal so
we could write extensions on them and make them conform to protocols, but,
they’re so integral to the language that they are really treated like a
structural type.

- Doug

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Just throwing an idea out: what about

      Function<Double, InoutParam<String>, Param<Int>>

or

      Function<Double, Param<String, .inout>, Param<String>>

The latter assuming we had generics with value parameters (which is another common topic on this list) and defaults.
The first example might have the advantage of making use of inheritance between InoutParam and Param (which would require variance for type parameters, another common topic).

-Thorsten

···

Am 22.11.2017 um 06:25 schrieb Douglas Gregor via swift-evolution <swift-evolution@swift.org>:

On Nov 21, 2017, at 9:21 PM, Chris Lattner <clattner@nondot.org> wrote:

On Nov 21, 2017, at 7:19 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Sent from my iPhone

On Nov 21, 2017, at 3:46 PM, Tony Allevato <tony.allevato@gmail.com> wrote:

Does that mean that once structural types can conform to protocols, would the core team want to remove Optional as a nominal type and just use “T?”?

Yes; at least, it’s a direction we’ve discussed a number of times.

Or has that ship sailed because of source compatibility and you just don’t want to introduce any new nominals that shadow structurals?

typealias Optional<T> = T?

Should address source compatibility.

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

Can somebody explain to me what is less ugly about that? I would have naturally thought that the language would be simpler as a whole if there only existed nominal types and all structural types were just sugar over them.

···

On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org> wrote:
On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com> wrote:

  - Doug

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

Can somebody explain to me what is less ugly about that? I would have naturally thought that the language would be simpler as a whole if there only existed nominal types and all structural types were just sugar over them.

See Thorsten’s response with, e.g.,

        Function<Double, InoutParam<String>, Param<Int>>

which handles “inout” by adding wrappers around the parameter types (which one would have to cope with in any user of Function), but still doesn’t handle argument labels. To handle argument labels, we would need something like strings as generic arguments. We’d also need to handle calling conventions and anything else we invent for function types.

Oh ok, I get. The ugliness comes from trying to shoehorn structural types into nominal types.

···

On 22 Nov 2017, at 07:54, Douglas Gregor <dgregor@apple.com> wrote:

On Nov 21, 2017, at 10:48 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:
On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

  - Doug

Oh, good! A use case for “literals as generic parameters” other than Vectors and Fixed-Size Arrays!

- Dave Sweeris

···

On Nov 21, 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 10:48 PM, David Hart <david@hartbit.com> wrote:

On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org> wrote:

On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com> wrote:

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

Can somebody explain to me what is less ugly about that? I would have naturally thought that the language would be simpler as a whole if there only existed nominal types and all structural types were just sugar over them.

See Thorsten’s response with, e.g.,

        Function<Double, InoutParam<String>, Param<Int>>

which handles “inout” by adding wrappers around the parameter types (which one would have to cope with in any user of Function), but still doesn’t handle argument labels. To handle argument labels, we would need something like strings as generic arguments.

I think this thread derailed quite a bit — it might have even been a good thing that some discussion accidentally went off-list ;-)

Personally, I think it's nice if tuples and structs would converge more, so that either struct is seen as an extension of the tuple-concept, or tuple is considered to be an (restricted) anonymous struct.
E.g.

struct StructPoint {
  let x: Float
  let y: Float
}

typealias TuplePoint = (x: Float, y: Float)

would more or less have the same abilities (allowing extensions and protocol-conformance).
Constructors for tuples would afaics be easy, and maybe it would even be possible to initialize some structs from tuple-literals.

story until the very last step, when you send the buffer to the drawing
library (cairo, opengl, etc). all the stages that come before are swift and
involve passing data between two swift interfaces.

···

On Tue, Nov 28, 2017 at 3:18 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Tue, Nov 28, 2017 at 00:32 Kelvin Ma <kelvin13ma@gmail.com> wrote:

On Mon, Nov 27, 2017 at 9:43 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Mon, Nov 27, 2017 at 5:56 PM, Kelvin Ma <kelvin13ma@gmail.com> wrote:

On Mon, Nov 27, 2017 at 4:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Mon, Nov 27, 2017 at 15:46 Taylor Swift <kelvin13ma@gmail.com> >>>>> wrote:

they use packed buffers of floats, which for type safety are better
rebound to a structured type. right now (Float, Float, Float) works because
the tuple is laid out contiguously and the GPU can’t tell the difference
but it’s not guaranteed. also you’re ignoring all the CPU stages that occur
before anything even gets sent to the GPU.

Precisely, there is no guarantee of performance if you call these APIs
with an array of Swift tuples.

which is exactly why i support a dedicated language-level vector type
which guarantees contiguous, fixed storage, and which the compiler knows
about so it can vectorize operations on them.

That's an entirely separate discussion.

tuples right now try to fill too many roles and that makes life
difficult for both the compiler and the programmer. however, until then, we
need some kind of common, fixed layout currency type for vector data, and
by implementation-detail, *tuples are our best option* since for some
reason everyone is so opposed to the simple solution of baking vec2,
vec3, … vec5 into the language and the generic integer Vector<Float, k>
solution everyone wants likely isn’t going to materialize for the
foreseeable future.

Disagree. If you want a particular memory layout, define your type in C.
Swift's interop story is very good, and your type will have a fixed layout
forever.

“*write it in c and import it*” is *not* a solution,, it is a workaround.

Yes, that’s what we’re talking about here: workarounds to lack of a fixed
layout type. I’m saying C is the “best option” workaround, not tuples.

plus since it lives across the module boundary, it’s effectively opaque to

compiler optimizations.

What sorts of optimizations are you referring to? Recall that we are
talking about taking a value and unsafe bitcasting for the purposes of
calling other C APIs.

you misunderstand the use-case. C and C APIs usually don’t show up in the

See Thorsten’s response with, e.g.,

        Function<Double, InoutParam<String>, Param<Int>>

which handles “inout” by adding wrappers around the parameter types (which one would have to cope with in any user of Function), but still doesn’t handle argument labels. To handle argument labels, we would need something like strings as generic arguments. We’d also need to handle calling conventions and anything else we invent for function types.

  - Doug

···

On Nov 21, 2017, at 10:48 PM, David Hart <david@hartbit.com> wrote:

On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:

On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

Can somebody explain to me what is less ugly about that? I would have naturally thought that the language would be simpler as a whole if there only existed nominal types and all structural types were just sugar over them.

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

Can somebody explain to me what is less ugly about that? I would have naturally thought that the language would be simpler as a whole if there only existed nominal types and all structural types were just sugar over them.

What confuses me is that I always thought that T? was sugar for Optional<T> by design, and found that to be quite elegant. But now you’re telling me that its just a hack to allow conformance on Optionals until it can be made structural. I would have thought that it would be cleaner to have specific concepts (optionals, tuples, etc…) represented in terms of more general concepts (enum, struct) so that the compiler had less to reason about. I’m just trying to understand :-)

···

On 22 Nov 2017, at 07:48, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:
On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

  - Doug

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Do not forget the use case of typed units (e.g. 9.81 m/s^2) which was discussed long ago on this list where integers as generic parameters would store the exponent of each base unit.

-Thorsten

···

Am 23.11.2017 um 01:50 schrieb David Sweeris via swift-evolution <swift-evolution@swift.org>:

On Nov 21, 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 10:48 PM, David Hart <david@hartbit.com> wrote:

On 22 Nov 2017, at 07:41, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 21, 2017, at 10:37 PM, Chris Lattner <clattner@nondot.org> wrote:

On Nov 21, 2017, at 9:25 PM, Douglas Gregor <dgregor@apple.com> wrote:

Or alternatively, one could decide to make the generics system *only and forever* work on nominal types, and make the syntactic sugar just be sugar for named types like Swift.Tuple, Function, and Optional. Either design could work.

We don’t have a way to make it work for function types, though, because of parameter-passing conventions. Well, assuming we don’t invent something that allows:

  Function<Double, inout String>

to exist in the type system. Tuple labels have a similar problem.

I’m totally aware of that and mentioned it upthread.

Eh, sorry I missed it.

There are various encoding tricks that could make this work depending on how you want to stretch the current generics system…

I think it’s straightforward and less ugly to make structural types allow extensions and protocol conformances.

Can somebody explain to me what is less ugly about that? I would have naturally thought that the language would be simpler as a whole if there only existed nominal types and all structural types were just sugar over them.

See Thorsten’s response with, e.g.,

        Function<Double, InoutParam<String>, Param<Int>>

which handles “inout” by adding wrappers around the parameter types (which one would have to cope with in any user of Function), but still doesn’t handle argument labels. To handle argument labels, we would need something like strings as generic arguments.

Oh, good! A use case for “literals as generic parameters” other than Vectors and Fixed-Size Arrays!