Adding custom attributes

Hello Swift Team,

As it’s my first post on this mailing list, let me introduce my self. My name is Radek Smogura, and for 10 year I work as developer, mainly Java and I know C and C++. I would like to join Swift community and work on Swift language. Previously for hobby I added properties syntax to it and full closure support (you can find it here https://bitbucket.org/radoslaw_smogura/java-closures-silver-jdk9-langtools/wiki/Home\).

I would like to propose custom attributes support, as it would make Swift more robust language, by allowing dependency injection and managed objects (ie. for Core Data or some trivial example like defining JSON structures for REST). I would as well to contribute to this feature to Swift language if possible as fork or branch.

My general high level plan is as follow:
- add experimental feature switch to add parsing custom attributes,
- define and implement attribute syntax,
- compile attributes and store those,
- add validation and compilation to attribute declarations
- - (optionally) refactor current code
- enjoy.

Waiting for your thoughts,
Radek

Custom attributes are an interesting direction that already came up on
this list, but there was no concrete proposal with syntax and
semantics. Before you spend time implementing something extensive, I
would strongly recommend you to float the idea on swift-evolution, and
follow-up with a formal proposal if there is consensus.

Dmitri

···

On Sat, Dec 26, 2015 at 12:55 PM, Radosław Smogura <swift-evolution@swift.org> wrote:

Hello Swift Team,

As it’s my first post on this mailing list, let me introduce my self. My name is Radek Smogura, and for 10 year I work as developer, mainly Java and I know C and C++. I would like to join Swift community and work on Swift language. Previously for hobby I added properties syntax to it and full closure support (you can find it here https://bitbucket.org/radoslaw_smogura/java-closures-silver-jdk9-langtools/wiki/Home\).

I would like to propose custom attributes support, as it would make Swift more robust language, by allowing dependency injection and managed objects (ie. for Core Data or some trivial example like defining JSON structures for REST). I would as well to contribute to this feature to Swift language if possible as fork or branch.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

Attributes on attributes (optional).

Best regards,
Radek

···

On 26 Dec 2015, at 13:35, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Sat, Dec 26, 2015 at 12:55 PM, Radosław Smogura > <swift-evolution@swift.org> wrote:

Hello Swift Team,

As it’s my first post on this mailing list, let me introduce my self. My name is Radek Smogura, and for 10 year I work as developer, mainly Java and I know C and C++. I would like to join Swift community and work on Swift language. Previously for hobby I added properties syntax to it and full closure support (you can find it here https://bitbucket.org/radoslaw_smogura/java-closures-silver-jdk9-langtools/wiki/Home\).

I would like to propose custom attributes support, as it would make Swift more robust language, by allowing dependency injection and managed objects (ie. for Core Data or some trivial example like defining JSON structures for REST). I would as well to contribute to this feature to Swift language if possible as fork or branch.

Custom attributes are an interesting direction that already came up on
this list, but there was no concrete proposal with syntax and
semantics. Before you spend time implementing something extensive, I
would strongly recommend you to float the idea on swift-evolution, and
follow-up with a formal proposal if there is consensus.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

Dmitri

···

On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com> wrote:

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Maybe we could implement a template system like C++

···

On Sat, Dec 26, 2015 at 3:20 PM, Dmitri Gribenko via swift-evolution < swift-evolution@swift.org> wrote:

On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com> > wrote:
> So,
>
> What do you think about syntax like this:
>
> // Declaration
> @AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into
binary
> @AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
> @attribute JSONProperty {
> var name:String!;
> var serializable:Bool? = true;
> var deserializable:Bool? = true;
> }

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

> // Usage
> @JSONProperty(name=“id”)
> var id:Int;
>
>
> Attributes should be module aware (actual attributes should be redefined
as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

> The attribute’s name have to be unique in module. It’s compile time
error if attribute, class, enum, struct, etc has same name.
>
> Attribute’s properties are read only and can’t be assigned - so during
reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

> Attribute’s properties can only support basic types: primitives,
strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

> When declaring attributes, properties can be set to constant values
(static let) or enum values, however the final value is stored in binary,
not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

> The compiler has build in support for core attributes, which can affect
code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
 Wizard
james@supmenow.com
+44 7523 279 698

Sorry, it is not clear what you're hinting at, please elaborate.

Dmitri

···

On Sat, Dec 26, 2015 at 4:24 PM, James Campbell <james@supmenow.com> wrote:

Maybe we could implement a template system like C++

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Hi Dimitir,

Thanks for your questions, as you pointed me to deeper considerations and better description of idea.

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

It’s really good concern and I have to describe attribute concept in more details. The _implementation_ of attributes would and should use existing constructs like structs or classes - I prefer classes as it will allow attributes to subclass some common class (Attribute?), so in future new functionality can be added.

Let’s consider attributes, and marking struct with @Attrbute.

On runtime attributes will be passed as references or value objects (just to keep contract programming) and assignment to attribute properties should be prohibited:
- if attribute is bound to type, than attribute would be nothing more than extension of static context of that type,
- it’s error prone for developers, as someone could change i.e. JSON property name.

Attributes are metadata, and do not require methods (however methods could be interesting and innovative addition). So attribute’s properties should be declared with let, instead of var, to prevent modification of those, but from other hand we would like to set default values for some properties, I just think that declaration like this would be confusing:
@Attribute
struct JSONProperty {
/* … */
let deserializable:Bool? = true;
}

Additionally having attributes as a new construct will give us more flexibility on changing syntax and adding new features in future.

I think this implies that attribute can’t be considered as struct (on language level), and should be treated as new language construct.

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

Attributes should be in module. So modules can define attributes with same name. Right now attributes are global.

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

I think attributes should be treated as new language construct, regardless how those will be implemented on runtime - it can be struct or class.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

By basic type I meant a types which can be serialised to format which will not change in future. Numbers, strings, type names, arrays of those can be stored in binaries without risks of backward incompatibility, objects and structs are more fragile. I think next answer will clarify more.

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

It’s another good question. By const I mean virtual concept of static let declaration. My motivation is to keep attributes as static metadata.

Let’s consider three levels of attributes:
- source - those attributes are present only in source file and are not put in binary, such attributes can be used to mark pieces of code for external tools like visual UI designers, UMLs, etc
- compile - those attributes are present in output binary, but have not meaning on runtime - ie. @Deprecated,
- runtime - those attributes are present on runtime, and can be inspected by libraries to affect execution, ie.: @JSONProperty, @NSManaged

My other concern is related to attribute storage (let’s skip implementation of this). Suppose you want to centralise some values, ie. messages with following pice of code
CommonMessages {
  static var genericError = “Something went wrong :(“
}

And you want to bound a property to message when validation fails.
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

- For runtime referencing variables can be confusing, as some one seeing above notion can think that changing genericError will change message on runtime (annotations are static, so it will not work),
- For compilation level attributes compiler has limited possibilities to evaluate what genericMessage is, as there is no application runtime (it will be compiled), so only simple traversals through source can be performed. Even for const it can be hard right now.

The other question arises here, suppose CommonMessages are in external library,. What should happen if it changes, should a genericError be referenced or it’s value copied and stored in binary? Referencing could be quite interesting topic.

We can consider allowing simple or more complicated expressions in attribute properties
@Size(width=20+50+sqrt(12))
As long as those refer static context.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

I would like to focus on syntax, semantic and parsing. This will require answering question how to store attributes (and I would like to move this to separate chain, as it will be long discussion). From the other hand, some questions still should be answered, ie.

How attribute should behave in such a case:
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

Should genericValue be copied or referenced (see above consideration), this implies what and how to store.

···

On 26 Dec 2015, at 16:20, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com> wrote:

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Consider reading the Property Behaviors <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003148.html&gt; proposal, as attributes overlap with it. (Warning: loooooooong thread)

Félix

···

Le 26 déc. 2015 à 13:57:04, JOSE MARIA GOMEZ CAMA via swift-evolution <swift-evolution@swift.org> a écrit :

Dear all,

Let me answer inlined.

El 26/12/2015, a las 19:15, Radosław Smogura via swift-evolution <swift-evolution@swift.org> escribió:

Hi Dimitir,

Thanks for your questions, as you pointed me to deeper considerations and better description of idea.

On 26 Dec 2015, at 16:20, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com> wrote:

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

It’s really good concern and I have to describe attribute concept in more details. The _implementation_ of attributes would and should use existing constructs like structs or classes - I prefer classes as it will allow attributes to subclass some common class (Attribute?), so in future new functionality can be added.

Let’s consider attributes, and marking struct with @Attrbute.

On runtime attributes will be passed as references or value objects (just to keep contract programming) and assignment to attribute properties should be prohibited:
- if attribute is bound to type, than attribute would be nothing more than extension of static context of that type,
- it’s error prone for developers, as someone could change i.e. JSON property name.

Attributes are metadata, and do not require methods (however methods could be interesting and innovative addition). So attribute’s properties should be declared with let, instead of var, to prevent modification of those, but from other hand we would like to set default values for some properties, I just think that declaration like this would be confusing:
@Attribute
struct JSONProperty {
/* … */
let deserializable:Bool? = true;
}

Additionally having attributes as a new construct will give us more flexibility on changing syntax and adding new features in future.

I think this implies that attribute can’t be considered as struct (on language level), and should be treated as new language construct.

I do not agree that attributes should only provide metadata. I think they shall also provide means, like in Java or Python, to modify the behavior in runtime. For this, mirroring would be needed.

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

Attributes should be in module. So modules can define attributes with same name. Right now attributes are global.

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

I think attributes should be treated as new language construct, regardless how those will be implemented on runtime - it can be struct or class.

I do not see why it should be a new construct, in Java it is, but in case of Python it is not. Another option would be to define the attribute @attribute that would identify a class or a struct as an attribute.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

By basic type I meant a types which can be serialised to format which will not change in future. Numbers, strings, type names, arrays of those can be stored in binaries without risks of backward incompatibility, objects and structs are more fragile. I think next answer will clarify more.

I think this is always the case when you have a compiled language, you always store information as a binary when you have a library.

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

It’s another good question. By const I mean virtual concept of static let declaration. My motivation is to keep attributes as static metadata.

Let’s consider three levels of attributes:
- source - those attributes are present only in source file and are not put in binary, such attributes can be used to mark pieces of code for external tools like visual UI designers, UMLs, etc
- compile - those attributes are present in output binary, but have not meaning on runtime - ie. @Deprecated,
- runtime - those attributes are present on runtime, and can be inspected by libraries to affect execution, ie.: @JSONProperty, @NSManaged

My other concern is related to attribute storage (let’s skip implementation of this). Suppose you want to centralise some values, ie. messages with following pice of code
CommonMessages {
     static var genericError = “Something went wrong :(“
}

And you want to bound a property to message when validation fails.
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

- For runtime referencing variables can be confusing, as some one seeing above notion can think that changing genericError will change message on runtime (annotations are static, so it will not work),
- For compilation level attributes compiler has limited possibilities to evaluate what genericMessage is, as there is no application runtime (it will be compiled), so only simple traversals through source can be performed. Even for const it can be hard right now.

The other question arises here, suppose CommonMessages are in external library,. What should happen if it changes, should a genericError be referenced or it’s value copied and stored in binary? Referencing could be quite interesting topic.

We can consider allowing simple or more complicated expressions in attribute properties
@Size(width=20+50+sqrt(12))
As long as those refer static context.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

I would like to focus on syntax, semantic and parsing. This will require answering question how to store attributes (and I would like to move this to separate chain, as it will be long discussion). From the other hand, some questions still should be answered, ie.

How attribute should behave in such a case:
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

Should genericValue be copied or referenced (see above consideration), this implies what and how to store.

Probably, in this case it would be good to have a look on Java annotations. This can provide some hints on how to store the compiled information.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>>*/

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

Aquest correu electrònic i els annexos poden contenir informació confidencial o protegida legalment i està adreçat exclusivament a la persona o entitat destinatària. Si no sou el destinatari final o la persona encarregada de rebre’l, no esteu autoritzat a llegir-lo, retenir-lo, modificar-lo, distribuir-lo, copiar-lo ni a revelar-ne el contingut. Si heu rebut aquest correu electrònic per error, us preguem que n’informeu al remitent i que elimineu del sistema el missatge i el material annex que pugui contenir. Gràcies per la vostra col·laboració.

Este correo electrónico y sus anexos pueden contener información confidencial o legalmente protegida y está exclusivamente dirigido a la persona o entidad destinataria. Si usted no es el destinatario final o la persona encargada de recibirlo, no está autorizado a leerlo, retenerlo, modificarlo, distribuirlo, copiarlo ni a revelar su contenido. Si ha recibido este mensaje electrónico por error, le rogamos que informe al remitente y elimine del sistema el mensaje y el material anexo que pueda contener. Gracias por su colaboración.

This email message and any documents attached to it may contain confidential or legally protected material and are intended solely for the use of the individual or organization to whom they are addressed. We remind you that if you are not the intended recipient of this email message or the person responsible for processing it, then you are not authorized to read, save, modify, send, copy or disclose any of its contents. If you have received this email message by mistake, we kindly ask you to inform the sender of this and to eliminate both the message and any attachments it carries from your account. Thank you for your collaboration.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Dear all,

Let me answer inlined.

Hi Dimitir,

Thanks for your questions, as you pointed me to deeper considerations and better description of idea.

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

It’s really good concern and I have to describe attribute concept in more details. The _implementation_ of attributes would and should use existing constructs like structs or classes - I prefer classes as it will allow attributes to subclass some common class (Attribute?), so in future new functionality can be added.

Let’s consider attributes, and marking struct with @Attrbute.

On runtime attributes will be passed as references or value objects (just to keep contract programming) and assignment to attribute properties should be prohibited:
- if attribute is bound to type, than attribute would be nothing more than extension of static context of that type,
- it’s error prone for developers, as someone could change i.e. JSON property name.

Attributes are metadata, and do not require methods (however methods could be interesting and innovative addition). So attribute’s properties should be declared with let, instead of var, to prevent modification of those, but from other hand we would like to set default values for some properties, I just think that declaration like this would be confusing:
@Attribute
struct JSONProperty {
/* … */
let deserializable:Bool? = true;
}

Additionally having attributes as a new construct will give us more flexibility on changing syntax and adding new features in future.

I think this implies that attribute can’t be considered as struct (on language level), and should be treated as new language construct.

I do not agree that attributes should only provide metadata. I think they shall also provide means, like in Java or Python, to modify the behavior in runtime. For this, mirroring would be needed.

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

Attributes should be in module. So modules can define attributes with same name. Right now attributes are global.

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

I think attributes should be treated as new language construct, regardless how those will be implemented on runtime - it can be struct or class.

I do not see why it should be a new construct, in Java it is, but in case of Python it is not. Another option would be to define the attribute @attribute that would identify a class or a struct as an attribute.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

By basic type I meant a types which can be serialised to format which will not change in future. Numbers, strings, type names, arrays of those can be stored in binaries without risks of backward incompatibility, objects and structs are more fragile. I think next answer will clarify more.

I think this is always the case when you have a compiled language, you always store information as a binary when you have a library.

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

It’s another good question. By const I mean virtual concept of static let declaration. My motivation is to keep attributes as static metadata.

Let’s consider three levels of attributes:
- source - those attributes are present only in source file and are not put in binary, such attributes can be used to mark pieces of code for external tools like visual UI designers, UMLs, etc
- compile - those attributes are present in output binary, but have not meaning on runtime - ie. @Deprecated,
- runtime - those attributes are present on runtime, and can be inspected by libraries to affect execution, ie.: @JSONProperty, @NSManaged

My other concern is related to attribute storage (let’s skip implementation of this). Suppose you want to centralise some values, ie. messages with following pice of code
CommonMessages {
      static var genericError = “Something went wrong :(“
}

And you want to bound a property to message when validation fails.
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

- For runtime referencing variables can be confusing, as some one seeing above notion can think that changing genericError will change message on runtime (annotations are static, so it will not work),
- For compilation level attributes compiler has limited possibilities to evaluate what genericMessage is, as there is no application runtime (it will be compiled), so only simple traversals through source can be performed. Even for const it can be hard right now.

The other question arises here, suppose CommonMessages are in external library,. What should happen if it changes, should a genericError be referenced or it’s value copied and stored in binary? Referencing could be quite interesting topic.

We can consider allowing simple or more complicated expressions in attribute properties
@Size(width=20+50+sqrt(12))
As long as those refer static context.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

I would like to focus on syntax, semantic and parsing. This will require answering question how to store attributes (and I would like to move this to separate chain, as it will be long discussion). From the other hand, some questions still should be answered, ie.

How attribute should behave in such a case:
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

Should genericValue be copied or referenced (see above consideration), this implies what and how to store.

Probably, in this case it would be good to have a look on Java annotations. This can provide some hints on how to store the compiled information.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

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

Aquest correu electrònic i els annexos poden contenir informació confidencial o protegida legalment i està adreçat exclusivament a la persona o entitat destinatària. Si no sou el destinatari final o la persona encarregada de rebre’l, no esteu autoritzat a llegir-lo, retenir-lo, modificar-lo, distribuir-lo, copiar-lo ni a revelar-ne el contingut. Si heu rebut aquest correu electrònic per error, us preguem que n’informeu al remitent i que elimineu del sistema el missatge i el material annex que pugui contenir. Gràcies per la vostra col·laboració.

Este correo electrónico y sus anexos pueden contener información confidencial o legalmente protegida y está exclusivamente dirigido a la persona o entidad destinataria. Si usted no es el destinatario final o la persona encargada de recibirlo, no está autorizado a leerlo, retenerlo, modificarlo, distribuirlo, copiarlo ni a revelar su contenido. Si ha recibido este mensaje electrónico por error, le rogamos que informe al remitente y elimine del sistema el mensaje y el material anexo que pueda contener. Gracias por su colaboración.

This email message and any documents attached to it may contain confidential or legally protected material and are intended solely for the use of the individual or organization to whom they are addressed. We remind you that if you are not the intended recipient of this email message or the person responsible for processing it, then you are not authorized to read, save, modify, send, copy or disclose any of its contents. If you have received this email message by mistake, we kindly ask you to inform the sender of this and to eliminate both the message and any attachments it carries from your account. Thank you for your collaboration.

···

El 26/12/2015, a las 19:15, Radosław Smogura via swift-evolution <swift-evolution@swift.org> escribió:

On 26 Dec 2015, at 16:20, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com> wrote:

Dear all,

Let me answer inlined.

Hi Dimitir,

Thanks for your questions, as you pointed me to deeper considerations and better description of idea.

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

It’s really good concern and I have to describe attribute concept in more details. The _implementation_ of attributes would and should use existing constructs like structs or classes - I prefer classes as it will allow attributes to subclass some common class (Attribute?), so in future new functionality can be added.

Let’s consider attributes, and marking struct with @Attrbute.

On runtime attributes will be passed as references or value objects (just to keep contract programming) and assignment to attribute properties should be prohibited:
- if attribute is bound to type, than attribute would be nothing more than extension of static context of that type,
- it’s error prone for developers, as someone could change i.e. JSON property name.

Attributes are metadata, and do not require methods (however methods could be interesting and innovative addition). So attribute’s properties should be declared with let, instead of var, to prevent modification of those, but from other hand we would like to set default values for some properties, I just think that declaration like this would be confusing:
@Attribute
struct JSONProperty {
/* … */
let deserializable:Bool? = true;
}

Additionally having attributes as a new construct will give us more flexibility on changing syntax and adding new features in future.

I think this implies that attribute can’t be considered as struct (on language level), and should be treated as new language construct.

I do not agree that attributes should only provide metadata. I think they shall also provide means, like in Java or Python, to modify the behavior in runtime. For this, mirroring would be needed.

My bad, I think I unnesessary used a word ‘metadata’ word. It may be confusing.

You are right it is something we would like to achieve, but attribute alone is disconnected from mean. Mean (with some exceptions), similar like in Java, should be defined by library / container which inspects annotations on given object.

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

Attributes should be in module. So modules can define attributes with same name. Right now attributes are global.

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

I think attributes should be treated as new language construct, regardless how those will be implemented on runtime - it can be struct or class.

I do not see why it should be a new construct, in Java it is, but in case of Python it is not. Another option would be to define the attribute @attribute that would identify a class or a struct as an attribute.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

By basic type I meant a types which can be serialised to format which will not change in future. Numbers, strings, type names, arrays of those can be stored in binaries without risks of backward incompatibility, objects and structs are more fragile. I think next answer will clarify more.

I think this is always the case when you have a compiled language, you always store information as a binary when you have a library.

I wanted to explain different topic here. In generally representation of primitive types do not change over time, which is in oposition to composite types where properties can be added or removed or it order can be changed.

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

It’s another good question. By const I mean virtual concept of static let declaration. My motivation is to keep attributes as static metadata.

Let’s consider three levels of attributes:
- source - those attributes are present only in source file and are not put in binary, such attributes can be used to mark pieces of code for external tools like visual UI designers, UMLs, etc
- compile - those attributes are present in output binary, but have not meaning on runtime - ie. @Deprecated,
- runtime - those attributes are present on runtime, and can be inspected by libraries to affect execution, ie.: @JSONProperty, @NSManaged

My other concern is related to attribute storage (let’s skip implementation of this). Suppose you want to centralise some values, ie. messages with following pice of code
CommonMessages {
     static var genericError = “Something went wrong :(“
}

And you want to bound a property to message when validation fails.
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

- For runtime referencing variables can be confusing, as some one seeing above notion can think that changing genericError will change message on runtime (annotations are static, so it will not work),
- For compilation level attributes compiler has limited possibilities to evaluate what genericMessage is, as there is no application runtime (it will be compiled), so only simple traversals through source can be performed. Even for const it can be hard right now.

The other question arises here, suppose CommonMessages are in external library,. What should happen if it changes, should a genericError be referenced or it’s value copied and stored in binary? Referencing could be quite interesting topic.

We can consider allowing simple or more complicated expressions in attribute properties
@Size(width=20+50+sqrt(12))
As long as those refer static context.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

I would like to focus on syntax, semantic and parsing. This will require answering question how to store attributes (and I would like to move this to separate chain, as it will be long discussion). From the other hand, some questions still should be answered, ie.

How attribute should behave in such a case:
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

Should genericValue be copied or referenced (see above consideration), this implies what and how to store.

Probably, in this case it would be good to have a look on Java annotations. This can provide some hints on how to store the compiled information.

In Java compiler traverses references and stores copy of calculated values. The types of value is limited. The internal representation of annotation element value can be found here :)
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.16.1

And we can create something more. I like Java, but I have to admit that some concepts could be improved.

···

On 26 Dec 2015, at 19:57, JOSE MARIA GOMEZ CAMA <jm.gomez@ub.edu> wrote:

El 26/12/2015, a las 19:15, Radosław Smogura via swift-evolution <swift-evolution@swift.org> escribió:

On 26 Dec 2015, at 16:20, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com> wrote:
Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

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

Aquest correu electrònic i els annexos poden contenir informació confidencial o protegida legalment i està adreçat exclusivament a la persona o entitat destinatària. Si no sou el destinatari final o la persona encarregada de rebre’l, no esteu autoritzat a llegir-lo, retenir-lo, modificar-lo, distribuir-lo, copiar-lo ni a revelar-ne el contingut. Si heu rebut aquest correu electrònic per error, us preguem que n’informeu al remitent i que elimineu del sistema el missatge i el material annex que pugui contenir. Gràcies per la vostra col·laboració.

Este correo electrónico y sus anexos pueden contener información confidencial o legalmente protegida y está exclusivamente dirigido a la persona o entidad destinataria. Si usted no es el destinatario final o la persona encargada de recibirlo, no está autorizado a leerlo, retenerlo, modificarlo, distribuirlo, copiarlo ni a revelar su contenido. Si ha recibido este mensaje electrónico por error, le rogamos que informe al remitente y elimine del sistema el mensaje y el material anexo que pueda contener. Gracias por su colaboración.

This email message and any documents attached to it may contain confidential or legally protected material and are intended solely for the use of the individual or organization to whom they are addressed. We remind you that if you are not the intended recipient of this email message or the person responsible for processing it, then you are not authorized to read, save, modify, send, copy or disclose any of its contents. If you have received this email message by mistake, we kindly ask you to inform the sender of this and to eliminate both the message and any attachments it carries from your account. Thank you for your collaboration.

Hi all,

I tried to create some MVP for syntax, and put in on Wiki (as Akiva suggested). Everything is on table and can be discussed. Here please find link to it https://github.com/rsmogura/swift/wiki/Attributes-Proposal and below there is a copy of page

What do you think about defining for MVP, which outcome should be minimal consensus about syntax, as follow:
- parsing minimised attribute declaration, enabled by command line feature switch
- producing some AST
- validate attribute tree

After this we can start thinking how use attributes, store those and mirror (I believe there is a plenty of options)?

Best regards,
Radek

PS. I noticed we switched thread

Attribute Declaration Syntax

Attribute can be declared similar to class or struct, however as attribute is not class, nor struct and it's differently treated on runtime, it's a separate language construction. The example attribute is presented below:

@target(AttributeTarget.PROPERTY)
@available(AttributeAvailibility.RUNTIME)
@attribute JSONProperty {
    var name:String?;
    var readable:Bool? = true;
    var writeable:Bool? = true;
}
<https://github.com/rsmogura/swift/wiki/Attributes-Proposal/_edit#formal-syntax&gt;Formal syntax

TBD Formal syntax description

<https://github.com/rsmogura/swift/wiki/Attributes-Proposal/_edit#attribute-types-properties&gt;Attribute types properties

The attribute supports following types for its properties:

Int
Double
Bool
String
Enum values
Arrays of above
Later, when there will be consensus how to store attributes, and how the set properties, list of supported types can be extended

<https://github.com/rsmogura/swift/wiki/Attributes-Proposal/_edit#attribute-target&gt;Attribute target

Attribute can be described with specifier determining on which language elements attribute can be used. Following enum defines possible target

enum AttributeTarget {
case ATTRIBUTE
case CLASS
case STRUCT
case INITIALIZER
case METHOD
case ENUM
case ENUM_VALUE
case PROPERTY
}
It's compile time error if attribute is used on different elements than it was declared.

<https://github.com/rsmogura/swift/wiki/Attributes-Proposal/_edit#attribute-destination&gt;Attribute destination

Attribute destination describes where attribute will be available - if it's should be present in source, during compilation or during runtime. Some attributes do not have to be visible on runtime, ie. external tools can mark specific pieces of code to find those faster. The deprecated or availability attributes should be available during compilation time, so compiler can report appropriate warnings or error, but have no meaning on runtime.

Attribute destination is described by following enum:

enum AttributeAvailibility {
   case SOURCE
   case COMPILE
   case RUNTIME
}

···

On 26 Dec 2015, at 20:31, Radosław Smogura via swift-evolution <swift-evolution@swift.org> wrote:

On 26 Dec 2015, at 19:57, JOSE MARIA GOMEZ CAMA <jm.gomez@ub.edu <mailto:jm.gomez@ub.edu>> wrote:

Dear all,

Let me answer inlined.

El 26/12/2015, a las 19:15, Radosław Smogura via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> escribió:

Hi Dimitir,

Thanks for your questions, as you pointed me to deeper considerations and better description of idea.

On 26 Dec 2015, at 16:20, Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>> wrote:

On Sat, Dec 26, 2015 at 3:59 PM, Radosław Smogura <rsmogura@icloud.com <mailto:rsmogura@icloud.com>> wrote:

So,

What do you think about syntax like this:

// Declaration
@AttributeUsage(RUNTIME) //Can be SOURCE - attribute not emitted into binary
@AttributeTarget(PROPERTY) //Other CLASS, ENUM, METHOD, INIT
@attribute JSONProperty {
var name:String!;
var serializable:Bool? = true;
var deserializable:Bool? = true;
}

Is this a new declaration kind? Do you think we could make it work
with existing language constructs instead, like structs? Any
downsides to that?

It’s really good concern and I have to describe attribute concept in more details. The _implementation_ of attributes would and should use existing constructs like structs or classes - I prefer classes as it will allow attributes to subclass some common class (Attribute?), so in future new functionality can be added.

Let’s consider attributes, and marking struct with @Attrbute.

On runtime attributes will be passed as references or value objects (just to keep contract programming) and assignment to attribute properties should be prohibited:
- if attribute is bound to type, than attribute would be nothing more than extension of static context of that type,
- it’s error prone for developers, as someone could change i.e. JSON property name.

Attributes are metadata, and do not require methods (however methods could be interesting and innovative addition). So attribute’s properties should be declared with let, instead of var, to prevent modification of those, but from other hand we would like to set default values for some properties, I just think that declaration like this would be confusing:
@Attribute
struct JSONProperty {
/* … */
let deserializable:Bool? = true;
}

Additionally having attributes as a new construct will give us more flexibility on changing syntax and adding new features in future.

I think this implies that attribute can’t be considered as struct (on language level), and should be treated as new language construct.

I do not agree that attributes should only provide metadata. I think they shall also provide means, like in Java or Python, to modify the behavior in runtime. For this, mirroring would be needed.

My bad, I think I unnesessary used a word ‘metadata’ word. It may be confusing.

You are right it is something we would like to achieve, but attribute alone is disconnected from mean. Mean (with some exceptions), similar like in Java, should be defined by library / container which inspects annotations on given object.

// Usage
@JSONProperty(name=“id”)
var id:Int;

Attributes should be module aware (actual attributes should be redefined as Swift attribute, for beginning still can be hardcoded).

Sorry, I'm not sure what this means.

Attributes should be in module. So modules can define attributes with same name. Right now attributes are global.

The attribute’s name have to be unique in module. It’s compile time error if attribute, class, enum, struct, etc has same name.

Attribute’s properties are read only and can’t be assigned - so during reflection no-one would change ‘shared’ values.

I think using structs and requiring that attributes are value types
would solve both issues.

I think attributes should be treated as new language construct, regardless how those will be implemented on runtime - it can be struct or class.

I do not see why it should be a new construct, in Java it is, but in case of Python it is not. Another option would be to define the attribute @attribute that would identify a class or a struct as an attribute.

Attribute’s properties can only support basic types: primitives, strings, types, and other attributes (optional).

Well, there is no such thing as "basic types" in Swift. Strings,
integers etc. are defined in the standard library and the compiler
does not know anything special about them.

By basic type I meant a types which can be serialised to format which will not change in future. Numbers, strings, type names, arrays of those can be stored in binaries without risks of backward incompatibility, objects and structs are more fragile. I think next answer will clarify more.

I think this is always the case when you have a compiled language, you always store information as a binary when you have a library.

I wanted to explain different topic here. In generally representation of primitive types do not change over time, which is in oposition to composite types where properties can be added or removed or it order can be changed.

When declaring attributes, properties can be set to constant values (static let) or enum values, however the final value is stored in binary, not a reference to it.

Again, given that strings are defined in the standard library, and
that the language does not have a notion of a constant expression, I'm
not sure how this would work. I'm not saying it can't, I'm just
saying you need to introduce a lot of new language concepts and
compiler machinery.

It’s another good question. By const I mean virtual concept of static let declaration. My motivation is to keep attributes as static metadata.

Let’s consider three levels of attributes:
- source - those attributes are present only in source file and are not put in binary, such attributes can be used to mark pieces of code for external tools like visual UI designers, UMLs, etc
- compile - those attributes are present in output binary, but have not meaning on runtime - ie. @Deprecated,
- runtime - those attributes are present on runtime, and can be inspected by libraries to affect execution, ie.: @JSONProperty, @NSManaged

My other concern is related to attribute storage (let’s skip implementation of this). Suppose you want to centralise some values, ie. messages with following pice of code
CommonMessages {
     static var genericError = “Something went wrong :(“
}

And you want to bound a property to message when validation fails.
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

- For runtime referencing variables can be confusing, as some one seeing above notion can think that changing genericError will change message on runtime (annotations are static, so it will not work),
- For compilation level attributes compiler has limited possibilities to evaluate what genericMessage is, as there is no application runtime (it will be compiled), so only simple traversals through source can be performed. Even for const it can be hard right now.

The other question arises here, suppose CommonMessages are in external library,. What should happen if it changes, should a genericError be referenced or it’s value copied and stored in binary? Referencing could be quite interesting topic.

We can consider allowing simple or more complicated expressions in attribute properties
@Size(width=20+50+sqrt(12))
As long as those refer static context.

The compiler has build in support for core attributes, which can affect code generation. Compiler may perform additional checks on core attributes.

OK.

Another question is, how would you inspect attributes at runtime?

I would like to focus on syntax, semantic and parsing. This will require answering question how to store attributes (and I would like to move this to separate chain, as it will be long discussion). From the other hand, some questions still should be answered, ie.

How attribute should behave in such a case:
@ValidationMessage(message=CommonMessages.genericError)
var id:Int;

Should genericValue be copied or referenced (see above consideration), this implies what and how to store.

Probably, in this case it would be good to have a look on Java annotations. This can provide some hints on how to store the compiled information.

In Java compiler traverses references and stores copy of calculated values. The types of value is limited. The internal representation of annotation element value can be found here :)
Chapter 4. The class File Format

And we can create something more. I like Java, but I have to admit that some concepts could be improved.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>>*/

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

Aquest correu electrònic i els annexos poden contenir informació confidencial o protegida legalment i està adreçat exclusivament a la persona o entitat destinatària. Si no sou el destinatari final o la persona encarregada de rebre’l, no esteu autoritzat a llegir-lo, retenir-lo, modificar-lo, distribuir-lo, copiar-lo ni a revelar-ne el contingut. Si heu rebut aquest correu electrònic per error, us preguem que n’informeu al remitent i que elimineu del sistema el missatge i el material annex que pugui contenir. Gràcies per la vostra col·laboració.

Este correo electrónico y sus anexos pueden contener información confidencial o legalmente protegida y está exclusivamente dirigido a la persona o entidad destinataria. Si usted no es el destinatario final o la persona encargada de recibirlo, no está autorizado a leerlo, retenerlo, modificarlo, distribuirlo, copiarlo ni a revelar su contenido. Si ha recibido este mensaje electrónico por error, le rogamos que informe al remitente y elimine del sistema el mensaje y el material anexo que pueda contener. Gracias por su colaboración.

This email message and any documents attached to it may contain confidential or legally protected material and are intended solely for the use of the individual or organization to whom they are addressed. We remind you that if you are not the intended recipient of this email message or the person responsible for processing it, then you are not authorized to read, save, modify, send, copy or disclose any of its contents. If you have received this email message by mistake, we kindly ask you to inform the sender of this and to eliminate both the message and any attachments it carries from your account. Thank you for your collaboration.

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