Skip to content

Commit

Permalink
Some improvements
Browse files Browse the repository at this point in the history
Mention type aliases
Mention differences between unit structs / tuple struct constructors and `const` / `fn` items.
Add more use cases for `TS{0: expr}`/`TS{0: pat}`
  • Loading branch information
petrochenkov committed Feb 28, 2016
1 parent 82bb5a0 commit dfbf8cb
Showing 1 changed file with 30 additions and 18 deletions.
48 changes: 30 additions & 18 deletions text/0000-adt-kinds.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ Braced structs have 0 or more user-named fields and are defined only in type nam
Braced structs can be used in struct expressions `S{field1: expr, field2: expr}`, including
functional record update (FRU) `S{field1: expr, ..s}`/`S{..s}` and with struct patterns
`S{field1: pat, field2: pat}`/`S{field1: pat, ..}`/`S{..}`.
In all cases the path `S` of the expression or pattern is looked up in the type namespace.
In all cases the path `S` of the expression or pattern is looked up in the type namespace (so these
expressions/patterns can be used with type aliases).
Fields of a braced struct can be accessed with dot syntax `s.field1`.

Note: struct *variants* are currently defined in the value namespace in addition to type namespace,
Expand All @@ -63,7 +64,7 @@ Unit structs can be thought of as a single declaration for two things: a basic s
struct US {}
```

and a constant with the same name
and a constant with the same name<sup>Note 1</sup>

```
const US: US = US{};
Expand All @@ -74,15 +75,16 @@ constant `US`) namespaces.

As a basic struct, a unit struct can participate in struct expressions `US{}`, including FRU
`US{..s}` and in struct patterns `US{}`/`US{..}`. In both cases the path `US` of the expression
or pattern is looked up in the type namespace.
or pattern is looked up in the type namespace (so these expressions/patterns can be used with type
aliases).
Fields of a unit struct could also be accessed with dot syntax, but it doesn't have any fields.

As a constant, a unit struct can participate in unit struct expressions `US` and unit struct
patterns `US`, both of these are looked up in the value namespace in which the constant `US` is
defined.
defined (so these expressions/patterns cannot be used with type aliases).

Note 1: the constant is not exactly a `const` item, there are subtle differences, but it's a close
approximation.
Note 1: the constant is not exactly a `const` item, there are subtle differences (e.g. with regards
to `match` exhaustiveness), but it's a close approximation.
Note 2: the constant is pretty weirdly namespaced in case of unit *variants*, constants can't be
defined in "enum modules" manually.

Expand All @@ -103,7 +105,7 @@ struct TS {
}
```

and a constructor function with the same name
and a constructor function with the same name<sup>Note 2</sup>

```
fn TS(arg0: Type0, arg1: Type1, arg2: Type2) -> TS {
Expand All @@ -117,17 +119,21 @@ and the value (the constructor function `TS`) namespaces.
As a basic struct, a tuple struct can participate in struct expressions `TS{0: expr, 1: expr}`,
including FRU `TS{0: expr, ..ts}`/`TS{..ts}` and in struct patterns
`TS{0: pat, 1: pat}`/`TS{0: pat, ..}`/`TS{..}`.
In both cases the path `TS` of the expression or pattern is looked up in the type namespace.
Fields of a braced tuple can be accessed with dot syntax `ts.0`.
In both cases the path `TS` of the expression or pattern is looked up in the type namespace (so
these expressions/patterns can be used with type aliases).
Fields of a tuple struct can be accessed with dot syntax `ts.0`.

As a constructor, a tuple struct can participate in tuple struct expressions `TS(expr, expr)` and
tuple struct patterns `TS(pat, pat)`/`TS(..)`, both of these are looked up in the value namespace
in which the constructor `TS` is defined. Tuple struct expressions `TS(expr, expr)` are usual
in which the constructor `TS` is defined (so these expressions/patterns cannot be used with type
aliases). Tuple struct expressions `TS(expr, expr)` are usual
function calls, but the compiler reserves the right to make observable improvements to them based
on the additional knowledge, that `TS` is a constructor.

Note: the automatically assigned field names are quite interesting, they are not identifiers
lexically (they are integer literals), so such fields can't be defined manually.
Note 1: the automatically assigned field names are quite interesting, they are not identifiers
lexically (they are integer literals), so such fields can't be defined manually.
Note 2: the constructor function is not exactly a `fn` item, there are subtle differences (e.g. with
regards to privacy checks), but it's a close approximation.

## Summary of the changes.

Expand All @@ -143,15 +149,21 @@ implement as well.
This also means that `S{..}` patterns can be used to match structures and variants of any kind.
The desire to have such "match everything" patterns is sometimes expressed given
that number of fields in structures and variants can change from zero to non-zero and back during
development.
development.
An extra benefit is ability to match/construct tuple structs using their type aliases.

New: Permit using tuple structs and tuple variants in braced struct patterns and expressions
requiring naming their fields - `TS{0: expr}`/`TS{0: pat}`/etc. This change looks a bit worse from
the cost/benefit point of view. There's not much motivation for it besides consistency and probably
shortening patterns like `ItemFn(name, _, _, _, _, _)` into something like `ItemFn{0: name, ..}`.
Automatic code generators (e.g. syntax extensions like `derive`) can probably benefit from the
requiring naming their fields - `TS{0: expr}`/`TS{0: pat}`/etc.
While this change is important for consistency, there's not much motivation for it in hand-written
code besides shortening patterns like `ItemFn(name, _, _, _, _, _)` into something like
`ItemFn{0: name, ..}` and ability to match/construct tuple structs using their type aliases.
However, automatic code generators (e.g. syntax extensions) can benefit from the
ability to generate uniform code for all structure kinds as well.
The author of the RFC is ready to postpone or drop this particular extension at any moment.
`#[derive]` for example, currently has separate code paths for generating expressions and patterns
for braces structs (`ExprStruct`/`PatKind::Struct`), tuple structs
(`ExprCall`/`PatKind::TupleStruct`) and unit structs (`ExprPath`/`PatKind::Path`). With proposed
changes `#[derive]` could simplify its logic and always generate braced forms for expressions and
patterns.

# Drawbacks
[drawbacks]: #drawbacks
Expand Down

0 comments on commit dfbf8cb

Please sign in to comment.