mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Spelling docs (#42437)
* spelling: any Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: associated Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: async Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: classes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: clonability Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: conspicuously Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: constituent Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: constraint Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: contains Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: definition Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: digestible Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: for Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: github Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: javascript Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: manually Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: much Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: multi Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: occasionally Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: outputs Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: overriding Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: partition Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: propagation Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: protocol Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: quandary Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: redundant Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: responsible Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: right Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: specifically Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: suppose Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: that Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: the Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: with Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
This commit is contained in:
@@ -305,7 +305,7 @@ witness functions for a type.
|
||||
AUTODIFF-FUNCTION-KIND ::= 'd' // differential
|
||||
AUTODIFF-FUNCTION-KIND ::= 'p' // pullback
|
||||
|
||||
``<AUTODIFF-FUNCTION-KIND>`` differentiates the kinds of functions assocaited
|
||||
``<AUTODIFF-FUNCTION-KIND>`` differentiates the kinds of functions associated
|
||||
with a differentiable function used for differentiable programming.
|
||||
|
||||
::
|
||||
@@ -596,7 +596,7 @@ Types
|
||||
FUNCTION-KIND ::= 'zB' C-TYPE // objc block type with non-canonical C type
|
||||
FUNCTION-KIND ::= 'L' // objc block function type with canonical C type (escaping) (DWARF only; otherwise use 'B' or 'zB' C-TYPE)
|
||||
FUNCTION-KIND ::= 'C' // C function pointer / C++ method type
|
||||
FUNCTION-KIND ::= 'zC' C-TYPE // C function pointer / C++ method type with with non-canonical C type
|
||||
FUNCTION-KIND ::= 'zC' C-TYPE // C function pointer / C++ method type with non-canonical C type
|
||||
FUNCTION-KIND ::= 'A' // @auto_closure function type (escaping)
|
||||
FUNCTION-KIND ::= 'E' // function type (noescape)
|
||||
|
||||
|
||||
@@ -1625,7 +1625,7 @@ is ergonomics.
|
||||
|
||||
While Swift structs are a bad match for non-movable C++ classes, Swift classes
|
||||
match semantics better. For example, instances of Swift classes, once allocated,
|
||||
stay at the same address until `deinit`. Instances of Swift clasess are always
|
||||
stay at the same address until `deinit`. Instances of Swift classes are always
|
||||
worked with indirectly, eliminating the need to move them around in memory.
|
||||
|
||||
Although user-defined Swift classes have a certain memory layout determined by
|
||||
@@ -2524,7 +2524,7 @@ there the Swift compiler infers the attribute for all users.
|
||||
This analysis relies on over-approximating the dynamic callgraph with the static
|
||||
callgraph. The static callgraph is feasible to compute in most cases, since
|
||||
Swift has very limited ways to abstract over an unspecialized generic function.
|
||||
Speicifically, Swift does not have generic closures. Swift does allow protocols
|
||||
Specifically, Swift does not have generic closures. Swift does allow protocols
|
||||
to have requirements for generic functions though.
|
||||
|
||||
### Function templates: importing as real generic functions
|
||||
@@ -2963,7 +2963,7 @@ This brief sketch obviously leaves many questions unanswered on the detailed
|
||||
semantics that a `throws!` feature would have, for example whether user-written
|
||||
Swift code should be allowed to use `throws!` -- see also [this forum
|
||||
discussion](https://forums.swift.org/t/handling-c-exceptions/34823). Before we
|
||||
take any steps towards implementing C++ exception proagation, we will submit a
|
||||
take any steps towards implementing C++ exception propagation, we will submit a
|
||||
formal Swift Evolution proposal for the `throws!` feature.
|
||||
|
||||
The other question to answer is how we would map the C++ exception to a
|
||||
|
||||
@@ -18,7 +18,7 @@ This document is designed to get you started with bidirectional API-level intero
|
||||
```
|
||||
//In module.modulemap
|
||||
module Cxx {
|
||||
//note that your header should be the file that containts your method implementations
|
||||
//note that your header should be the file that contains your method implementations
|
||||
header "Cxx.hpp"
|
||||
requires cplusplus
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ are bridged as value types. ⚠️ This will change as soon as Swift has a way t
|
||||
|
||||
Currently, lifetimes are extended to the end of the lexical scope if any unsafe pointers are used in that scope. TODO:
|
||||
this should be updated to extend lifetimes whenever a C++ type is used in that scope. Currently, if there is no
|
||||
unsafe pointer used in teh scope, then normal Swift lifetime rules apply.
|
||||
unsafe pointer used in the scope, then normal Swift lifetime rules apply.
|
||||
|
||||
**Borrowing Self**
|
||||
|
||||
|
||||
@@ -599,7 +599,7 @@ find MyProject/Sources -name '*.swift' -type f > input-files.txt
|
||||
# In some cases, projects may use multiple files with the same
|
||||
# name but in different directories (for different schemes),
|
||||
# which can be a problem. Having a file list makes working around
|
||||
# this convenient as you can manually manually edit out the files
|
||||
# this convenient as you can manually edit out the files
|
||||
# that are not of interest at this stage.
|
||||
|
||||
mkdir Output
|
||||
|
||||
@@ -42,7 +42,7 @@ Given the size of artifacts generated, you might also want to bump the cache siz
|
||||
|
||||
You can run some compiles to see if it is actually doing something by running `sccache --show-stats`. Depending on the exact compilation task you're running, you might see very different cache hit rates. For example, `sccache` is particularly effective if you're rebuilding LLVM, which doesn't change so frequently from the Swift compiler's perspective. On the other hand, if you're changing the compiler's AST, the cache hit rate is likely to be much lower.
|
||||
|
||||
One known issue with `sccache` is that you might occassionally get an "error: Connection to server timed out", even though you didn't stop the server. Simply re-running the build command usually works.
|
||||
One known issue with `sccache` is that you might occasionally get an "error: Connection to server timed out", even though you didn't stop the server. Simply re-running the build command usually works.
|
||||
|
||||
## Memory usage
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ Describes contributions which fix code that is not executed
|
||||
Provides context for interpreting a type that may have generic parameters
|
||||
in it. Generic parameter types are normally just represented as "first
|
||||
generic parameter in the outermost context" (or similar), so it's up to the
|
||||
generic environment to note that that type must be a Collection. (Another
|
||||
generic environment to note that type must be a Collection. (Another
|
||||
way of looking at it is that the generic environment connects
|
||||
[interface types](#interface-type) with
|
||||
[contextual types](#contextual-type)).
|
||||
|
||||
@@ -183,7 +183,7 @@ sources all together at once. This allows the optimizer to have module
|
||||
wide visibility when compiling individual declarations. Since an
|
||||
internal declaration is not visible outside of the current module, the
|
||||
optimizer can then infer `final` by automatically discovering all
|
||||
potentially overridding declarations.
|
||||
potentially overriding declarations.
|
||||
|
||||
NOTE: Since in Swift the default access control level is ``internal``
|
||||
anyways, by enabling Whole Module Optimization, one can gain
|
||||
|
||||
@@ -393,7 +393,7 @@ called function where it isn't obviously using its `inout`
|
||||
argument. Perhaps we should track accesses to `inout` arguments
|
||||
at a finer-grained level, within the callee, instead of attempting
|
||||
to enforce the Law of Exclusivity in the caller. The problem
|
||||
is that that idea is simply too dynamic to be efficiently
|
||||
is that idea is simply too dynamic to be efficiently
|
||||
implemented.
|
||||
|
||||
A caller-side rule for `inout` has one key advantage: the
|
||||
@@ -1163,7 +1163,7 @@ here because, as mentioned above, the entire co-routine
|
||||
must logically execute within the scope of an access to the
|
||||
base value. If, as is common for generators, the generator
|
||||
function actually returns some sort of generator object,
|
||||
the compiler must ensure that that object does not escape
|
||||
the compiler must ensure that object does not escape
|
||||
that enclosing access. This is a significant source of
|
||||
complexity.
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ available for emission into clients with deployment targets lower than the
|
||||
ABI availability of the function. When the client's deployment target is
|
||||
before the function's ABI availability, the compiler replaces calls to that
|
||||
function with a call to a thunk that checks at runtime whether the original
|
||||
library function is available. If the the original is available then it is
|
||||
library function is available. If the original is available then it is
|
||||
called. Otherwise, the fallback copy of the function that was emitted into the
|
||||
client is called instead.
|
||||
|
||||
@@ -640,7 +640,7 @@ Here are the necessary changes:
|
||||
This ensures when an app is built for deployment targets prior to the symbols' move,
|
||||
the app will look for these symbols in ToasterKit instead of ToasterKitCore.
|
||||
|
||||
More generally, mutliple availabilities can be specified, like so:
|
||||
More generally, multiple availabilities can be specified, like so:
|
||||
|
||||
```swift
|
||||
@available(toasterOS 42, bowlOS 54, mugOS 54, *)
|
||||
|
||||
@@ -218,7 +218,7 @@ func minimum<S>(of elements: S) -> S.Iterator.Element
|
||||
\end{Verbatim}
|
||||
A particularly powerful kind of generic requirement---and perhaps the entire reason the requirement machine exists---is the same-type requirement.
|
||||
|
||||
Supppose you're working with $\genericparam{S}$, a generic parameter ranging over $\proto{Sequence}$. Writing $\genericparam{S}.\namesym{Iterator}.\namesym{Element}$ everywhere will get awkward fast. As I mentioned, the real version of $\proto{Sequence}$ in the standard library is slightly more complex. Indeed, it defines an $\namesym{Element}$ associated type in the protocol itself, so that the user can write $\genericparam{S}.\namesym{Element}$. Simply adding the associated type definition is not enough, because now $\genericparam{S}.\namesym{Element}$ and $\genericparam{S}.\namesym{Iterator}.\namesym{Element}$ are \emph{different} type parameters and cannot be used interchangeably.
|
||||
Suppose you're working with $\genericparam{S}$, a generic parameter ranging over $\proto{Sequence}$. Writing $\genericparam{S}.\namesym{Iterator}.\namesym{Element}$ everywhere will get awkward fast. As I mentioned, the real version of $\proto{Sequence}$ in the standard library is slightly more complex. Indeed, it defines an $\namesym{Element}$ associated type in the protocol itself, so that the user can write $\genericparam{S}.\namesym{Element}$. Simply adding the associated type definition is not enough, because now $\genericparam{S}.\namesym{Element}$ and $\genericparam{S}.\namesym{Iterator}.\namesym{Element}$ are \emph{different} type parameters and cannot be used interchangeably.
|
||||
|
||||
\index{same-type requirement}
|
||||
To express this restriction that concrete types conforming to $\proto{Sequence}$ must provide an iterator type compatible with the element type, a \texttt{where} clause in the protocol can state a same-type requirement:
|
||||
@@ -261,7 +261,7 @@ But in this case, you may as well just peel off the $\namesym{Array}\langle\bull
|
||||
\[\genericparam{T}.\namesym{Element} == \namesym{Int}.\]
|
||||
|
||||
\index{power set}
|
||||
One more small language feature is worth mentioning. You might want to define a function that constructs the the set of all subsets of a set, i.e., the power set. The $\namesym{Set}\langle\bullet\rangle$ type constructor requires that its argument conforms to $\proto{Hashable}$:
|
||||
One more small language feature is worth mentioning. You might want to define a function that constructs the set of all subsets of a set, i.e., the power set. The $\namesym{Set}\langle\bullet\rangle$ type constructor requires that its argument conforms to $\proto{Hashable}$:
|
||||
\begin{Verbatim}
|
||||
struct Set<Element : Hashable> {...}
|
||||
\end{Verbatim}
|
||||
@@ -1390,7 +1390,7 @@ Finally, I can formalize the notion of ``reducing'' terms by making them ``small
|
||||
\begin{definition}[Reduction relation]\label{transinvdef} If $A^*$ is equipped with a reduction order $<$, then a relation $\rightarrow$ is a \emph{reduction relation} with respect to $<$ if $x\rightarrow y$ implies that $y<x$. Another equivalent definition is that a reduction relation $\rightarrow$ is a \emph{sub-relation} of $>$, the inverse relation of $<$.
|
||||
\end{definition}
|
||||
\index{rewrite system}
|
||||
As you saw in the previous example, a reduction relation for a finitely-presented monoid can be constructed by orienting the equations from the presentation with respect to some reduction order, a process which converts the equations into rewrite rules. Such a set of rewrite rules is called a \emph{rewrite system}. There is a simple algorithm for for reducing a term into an irreducible form:
|
||||
As you saw in the previous example, a reduction relation for a finitely-presented monoid can be constructed by orienting the equations from the presentation with respect to some reduction order, a process which converts the equations into rewrite rules. Such a set of rewrite rules is called a \emph{rewrite system}. There is a simple algorithm for reducing a term into an irreducible form:
|
||||
\begin{algorithm}[Reducing a term]\label{reducingaterm} Let $t$ be a term in some rewrite system $R$.
|
||||
\begin{enumerate}
|
||||
\item Initialize the boolean flag to false.
|
||||
@@ -2208,7 +2208,7 @@ t&\leftrightarrow ab\\
|
||||
u&\leftrightarrow a\\
|
||||
v&\leftrightarrow b
|
||||
\end{align*}
|
||||
This means that adding a new \emph{generator} to $M$ made the presentation convergent. What does this generator represent in the world of Swift? Well, $u\in M'$ is $a\in M$, which is $\protosym{View}$ in Swift; and $v\in M'$ is $b\in M$, which is $\namesym{Body}$. Therefore $t\in M'$ is $ab\in M$, which is $\protosym{View}.\namesym{Body}$. You may guess that $t$ could be a new kind of symbol, perhaps representing a ``bound'' associated type inside a specific protcol.
|
||||
This means that adding a new \emph{generator} to $M$ made the presentation convergent. What does this generator represent in the world of Swift? Well, $u\in M'$ is $a\in M$, which is $\protosym{View}$ in Swift; and $v\in M'$ is $b\in M$, which is $\namesym{Body}$. Therefore $t\in M'$ is $ab\in M$, which is $\protosym{View}.\namesym{Body}$. You may guess that $t$ could be a new kind of symbol, perhaps representing a ``bound'' associated type inside a specific protocol.
|
||||
|
||||
\index{associated type symbol}
|
||||
The crux of the issue is that name symbols like $\namesym{Body}$ don't carry any information, and little can be said about them unless they're prefixed with some other term that is known to conform to a protocol. Thus, you cannot simply add a rewrite rule to say that $\namesym{Body}$ conforms to $\protosym{View}$:
|
||||
@@ -2369,7 +2369,7 @@ Conformance validity has some useful properties.
|
||||
\end{proof}
|
||||
|
||||
\iffalse
|
||||
This solves the quandry presented at the beginning of this chapter, where the earlier formulation of the rewrite system that lacked associated type symbols had no apparent way of implementing the \texttt{getCanonicalTypeInContext()} generic signature query.
|
||||
This solves the quandary presented at the beginning of this chapter, where the earlier formulation of the rewrite system that lacked associated type symbols had no apparent way of implementing the \texttt{getCanonicalTypeInContext()} generic signature query.
|
||||
|
||||
Now that a term containing name symbols reduces to a canonical term with associated type symbols, it appears that mapping terms back to fully resolved type parameters is now a possibility. Unfortunately, the reality is a little bit more complicated. The inherited associated type construction I will introduce in the next section once again breaks the correspondence between terms and canonical types; this will be repaired in Section \ref{implqueries}.
|
||||
\fi
|
||||
@@ -3674,7 +3674,7 @@ Now, the time has finally come to describe the implementation of the four proper
|
||||
\item[\texttt{getRequiredProtocols()}] The list of protocol requirements satisfied by a type parameter $T$ is recorded in the form of protocol symbols in the property map. This list is transformed into a minimal canonical list of protocols using Definition~\ref{minimalproto}.
|
||||
\index{layout constraints}
|
||||
\index{join of layout constraints}
|
||||
\item[\texttt{getLayoutContraint()}] A type parameter $T$ might be subject to multiple layout constraints, in which case the property map entry will store a list of layout constraints $L_1,\ldots,L_n$. This query needs to compute their join, which is the largest layout constraint that simultaneously satisfies all of them:
|
||||
\item[\texttt{getLayoutConstraint()}] A type parameter $T$ might be subject to multiple layout constraints, in which case the property map entry will store a list of layout constraints $L_1,\ldots,L_n$. This query needs to compute their join, which is the largest layout constraint that simultaneously satisfies all of them:
|
||||
\[L_1\wedge\cdots\wedge L_n.\]
|
||||
Some layout constraints are disjoint on concrete types, meaning their join is the uninhabited ``bottom'' layout constraint, which precedes all other layout constraints in the partial order. In this case, the original generic signature is said to have conflicting requirements. While such a signature does not violate the requirement machine's invariants, it cannot be satisfied by any valid set of concrete substitutions. Detecting and diagnosing conflicting requirements is discussed later.
|
||||
|
||||
|
||||
14
docs/SIL.rst
14
docs/SIL.rst
@@ -1748,7 +1748,7 @@ with partitioned defs/uses annotated inline::
|
||||
return %kls1Casted : $SuperKlass
|
||||
}
|
||||
|
||||
Notice how every value in the SIL above has a partionable set of uses with
|
||||
Notice how every value in the SIL above has a partitionable set of uses with
|
||||
normal uses always before consuming uses. Any such violations of ownership
|
||||
semantics would trigger a SILVerifier error allowing us to know that we
|
||||
do not have any leaks or use-after-frees in the above code.
|
||||
@@ -1802,7 +1802,7 @@ This lattice is applied to SIL by requiring well formed SIL to:
|
||||
the same for all instances of an instruction) or dynamic (e.x.: forwarding
|
||||
instructions set their ownership upon construction). We call this subset of
|
||||
OwnershipKind to be the set of `Value Ownership Kind`_: `None`_, `Unowned`_,
|
||||
`Guaranteed`_, `Owned`_ (note conspiciously missing `Any`). This is because
|
||||
`Guaranteed`_, `Owned`_ (note conspicuously missing `Any`). This is because
|
||||
in our model `Any` represents an unknown ownership semantics and since our
|
||||
model is strict, we do not allow for values to have unknown ownership.
|
||||
|
||||
@@ -2168,7 +2168,7 @@ payload from an enum, can consume the entire enum+payload.
|
||||
|
||||
To handle cases where we want to use `struct_extract`_ in a consuming way, we
|
||||
instead are able to use the `destructure_struct`_ instruction that consumes the
|
||||
entire struct at once and gives one back the structs individual constituant
|
||||
entire struct at once and gives one back the structs individual constituent
|
||||
parts::
|
||||
|
||||
struct KlassPair {
|
||||
@@ -2282,7 +2282,7 @@ classify uses directly. Instead the verifier:
|
||||
Note that typically instructions in category (1) are instructions whose uses do
|
||||
not propagate the pointer value, so they are safe. In contrast, some other
|
||||
instructions in category (1) are escaping uses of the address such as
|
||||
`pointer_to_address`_. Those uses are unsafe--the user is reponsible for
|
||||
`pointer_to_address`_. Those uses are unsafe--the user is responsible for
|
||||
managing unsafe pointer lifetimes and the compiler must not extend those pointer
|
||||
lifetimes.
|
||||
|
||||
@@ -2515,7 +2515,7 @@ blocks. Operationally, this implies that:
|
||||
terminate in a `return`_ or `throw`_. In contrast, a SIL value does not need to
|
||||
have a lifetime ending use along paths that end in an `unreachable`_.
|
||||
|
||||
* `end_borrow`_ and `destroy_value`_ are redundent, albeit legal, in blocks
|
||||
* `end_borrow`_ and `destroy_value`_ are redundant, albeit legal, in blocks
|
||||
where all paths through the block end in an `unreachable`_.
|
||||
|
||||
Consider the following legal SIL where we leak ``%0`` in blocks prefixed with
|
||||
@@ -2563,7 +2563,7 @@ Consider the following legal SIL where we leak ``%0`` in blocks prefixed with
|
||||
// This block is also live, but since we do not return %0, we must insert a
|
||||
// destroy_value to cleanup %0.
|
||||
//
|
||||
// NOTE: The copy_value/destroy_value here is redundent and can be removed by
|
||||
// NOTE: The copy_value/destroy_value here is redundant and can be removed by
|
||||
// the optimizer. The author left it in for illustrative purposes.
|
||||
%1 = copy_value %0 : $Klass
|
||||
destroy_value %0 : $Klass
|
||||
@@ -3673,7 +3673,7 @@ a field declaration -- which references the desired sub-field in source variable
|
||||
debug_value %1 : $Int, var, (name "the_struct", loc "file.swift":8:7), type $MyStruct, expr op_fragment:#MyStruct.y, loc "file.swift":9:4
|
||||
|
||||
In the snippet above, source variable "the_struct" has an aggregate type ``$MyStruct`` and we use a SIL DIExpression with ``op_fragment`` operator to associate ``%1`` to the ``y`` member variable (via the ``#MyStruct.y`` directive) inside "the_struct".
|
||||
Note that the extra source location directive follows rigt after ``name "the_struct"`` indicate that "the_struct" was originally declared in line 8, but not until line 9 -- the current ``debug_value`` instruction's source location -- does member ``y`` got updated with SSA value ``%1``.
|
||||
Note that the extra source location directive follows right after ``name "the_struct"`` indicate that "the_struct" was originally declared in line 8, but not until line 9 -- the current ``debug_value`` instruction's source location -- does member ``y`` got updated with SSA value ``%1``.
|
||||
|
||||
It is worth noting that a SIL DIExpression is similar to
|
||||
`!DIExpression <https://www.llvm.org/docs/LangRef.html#diexpression>`_ in LLVM debug
|
||||
|
||||
@@ -160,9 +160,9 @@ To ease reading/understanding type declarations, we prefer to define members in
|
||||
|
||||
Please keep all stored properties together in a single uninterrupted list, followed immediately by the type's most crucial initializer(s). Put these as close to the top of the type declaration as possible -- we don't want to force readers to scroll around to find these core definitions.
|
||||
|
||||
We also have some recommendations for defining other members. These aren't strict rules, as the best way to present definitions varies; but it usually makes sense to break up the implementation into easily digestable, logical chunks.
|
||||
We also have some recommendations for defining other members. These aren't strict rules, as the best way to present definitions varies; but it usually makes sense to break up the implementation into easily digestible, logical chunks.
|
||||
|
||||
- In general, it is a good idea to keep the main `struct`/`class` definiton as short as possible: preferably it should consist of the type's stored properties and a handful of critical initializers, and nothing else.
|
||||
- In general, it is a good idea to keep the main `struct`/`class` definition as short as possible: preferably it should consist of the type's stored properties and a handful of critical initializers, and nothing else.
|
||||
|
||||
- Everything else should go in standalone extensions, arranged by logical theme. For example, it's often nice to define protocol conformances in dedicated extensions. If it makes sense, feel free to add a comment to title these sectioning extensions.
|
||||
|
||||
@@ -172,7 +172,7 @@ We also have some recommendations for defining other members. These aren't stric
|
||||
|
||||
- It's okay for the core type declaration to forward reference large nested types or static members that are defined in subsequent extensions. It's often a good idea to define these in an extension immediately following the type declaration, but this is not a strict rule.
|
||||
|
||||
Extensions are a nice way to break up the implementation into easily digestable chunks, but they aren't the only way. The goal is to make things easy to understand -- if a type is small enough, it may be best to list every member directly in the `struct`/`class` definition, while for huge types it often makes more sense to break them up into a handful of separate source files instead.
|
||||
Extensions are a nice way to break up the implementation into easily digestible chunks, but they aren't the only way. The goal is to make things easy to understand -- if a type is small enough, it may be best to list every member directly in the `struct`/`class` definition, while for huge types it often makes more sense to break them up into a handful of separate source files instead.
|
||||
|
||||
```swift
|
||||
// BAD (a jumbled mess)
|
||||
|
||||
@@ -12,7 +12,7 @@ Then we hit a snag: naming guidelines. We wanted argument labels to be something
|
||||
|
||||
As seen earlier in the thread, argument labels don't make for good tuple element labels. Especially with the Swift 3 guidelines, argument labels usually don't make sense without the context provided by the base name, and two methods that happen to share argument labels might not actually be very similar, while two methods that are duals of each other might have different argument labels due to, well, English (e.g. `add(to:)` vs. `remove(from:)`).
|
||||
|
||||
The real blow, however, came with that very first idea: that we could treat methods with different argument labels as simple overloads in type. This led to poor diagnostics where the compiler couldn't decide whether to believe the types or the argument labels, and might tell you you have the wrong argument labels rather than a type mismatch. For pretty much every Apple API, this was the wrong decision. On top of all that, it was really hard to refer to a method when you didn't want to call it. (Most methods with the same base name still have unique labels, so you don't need the types to disambiguate.)
|
||||
The real blow, however, came with that very first idea: that we could treat methods with different argument labels as simple overloads in type. This led to poor diagnostics where the compiler couldn't decide whether to believe the types or the argument labels, and might tell you that you have the wrong argument labels rather than a type mismatch. For pretty much every Apple API, this was the wrong decision. On top of all that, it was really hard to refer to a method when you didn't want to call it. (Most methods with the same base name still have unique labels, so you don't need the types to disambiguate.)
|
||||
|
||||
So we introduced the notion of "full names", which are the things you see written as `move(from:to:)` (and which are represented by DeclName in the compiler). Almost immediately diagnostics got better, testing optional protocol requirements got shorter, and a lot of compiler implementation got simpler.
|
||||
|
||||
|
||||
@@ -1236,7 +1236,7 @@ SEARCHENGINE = @enable_searchengine@
|
||||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a PHP enabled web server instead of at the web client
|
||||
# using Javascript. Doxygen will generate the search PHP script and index
|
||||
# using JavaScript. Doxygen will generate the search PHP script and index
|
||||
# file to put on the web server. The advantage of the server
|
||||
# based approach is that it scales better to large projects and allows
|
||||
# full text search. The disadvantage is that it is more difficult to setup
|
||||
|
||||
@@ -59,7 +59,7 @@ amounts of language sugar it's given, vends initializers corresponding to
|
||||
}
|
||||
|
||||
This pattern of boilerplate also occurs in third-party frameworks that make
|
||||
heavy use of enums. Some examples from Github:
|
||||
heavy use of enums. Some examples from GitHub:
|
||||
|
||||
- https://github.com/antitypical/Manifold/blob/ae94eb96085c2c8195d457e06df485b1cca455cb/Manifold/Name.swift
|
||||
- https://github.com/antitypical/TesseractCore/blob/73099ae5fa772b90cefa49395f237290d8363f76/TesseractCore/Symbol.swift
|
||||
|
||||
@@ -132,7 +132,7 @@ typestate, so that we can talk not only about a list of files, but also about a
|
||||
list of *open* files".
|
||||
|
||||
|
||||
You should be allowed to declare typestate transitions on "self" any any by-ref
|
||||
You should be allowed to declare typestate transitions on "self" any by-ref
|
||||
arguments/ret values on functions. In Plaid syntax::
|
||||
|
||||
public void open() [ClosedFile>>OpenFile]
|
||||
|
||||
@@ -219,7 +219,7 @@ can be performed. For example, "a.getvalue()" would be fine so long as the
|
||||
result is ignored or if the value is in an explicit async block structure.
|
||||
|
||||
From an implementation perspective, the code above corresponds directly to GCD's
|
||||
dispatch_asynch on a per-actor queue.
|
||||
dispatch_async on a per-actor queue.
|
||||
|
||||
Performing synchronous operations
|
||||
---------------------------------
|
||||
@@ -254,7 +254,7 @@ couple of interesting observations:
|
||||
mutable data or is shared. Mutable data (e.g. normal objects) can be ref
|
||||
counted with non-atomic reference counting, which is 20-30x faster than
|
||||
atomic adjustments. Actors are shared, so they'd have to have atomic ref
|
||||
counts, but they should be much much less common than the normal objects in
|
||||
counts, but they should be much less common than the normal objects in
|
||||
the program. Immutable data is shared (and thus needs atomic reference
|
||||
counts) but there are optimizations that can be performed since the edges in
|
||||
the pointer graph can never change and cycles aren't possible in immutable
|
||||
|
||||
@@ -364,7 +364,7 @@ Objective-C Interoperability
|
||||
Clonable Objective-C classes
|
||||
-----------------------------
|
||||
|
||||
In Cocoa, a notion similar to cloneability is captured in the ``NSCopying`` and
|
||||
In Cocoa, a notion similar to clonability is captured in the ``NSCopying`` and
|
||||
``NSMutableCopying`` protocols, and a notion similar to ``val`` instance
|
||||
variables is captured by the behavior of ``(copy)`` properties. However, there
|
||||
are some behavioral and semantic differences that need to be taken into account.
|
||||
|
||||
@@ -300,7 +300,7 @@ with (2). It passes if the two are identical, otherwise the test fails.
|
||||
3 }
|
||||
4 // RUN: rm -rf %t.result && mkdir -p %t.result
|
||||
5 // RUN: %refactor -localize-string -source-filename %s -pos=2:14 > %t.result/localized.swift
|
||||
6 // RUN: diff -u %S/Iutputs/localized.swift.expected %t.result/localized.swift
|
||||
6 // RUN: diff -u %S/Outputs/localized.swift.expected %t.result/localized.swift
|
||||
~~~
|
||||
|
||||
~~~swift
|
||||
|
||||
Reference in New Issue
Block a user