Commit Graph

310 Commits

Author SHA1 Message Date
Slava Pestov
b22f9ea487 AST: Remove SubstitutionMap::getMap()
We don't want to expose the fact that SubstitutionMaps are
backed by a DenseMap, since that's going to change soon.
2017-02-06 19:43:33 -08:00
Slava Pestov
811e7eea55 Merge pull request #7251 from slavapestov/subst-map-impl-hiding
Start cleaning up SubstitutionMap construction
2017-02-06 17:05:54 -08:00
Slava Pestov
2f9bd597bb AST: Clean up duplicated code in GenericSignature.cpp 2017-02-06 16:14:07 -08:00
Doug Gregor
2b9260cdb5 [AST] Add GenericSignature::createGenericEnvironment().
This will eventually be the canonical way to create new generic environments. For now, it’s mainly aspirational.
2017-02-05 21:23:44 -08:00
Slava Pestov
cf4043b668 AST: Get rid of old form of Type::subst()
First, add some new utility methods to create SubstitutionMaps:

- GenericSignature::getSubstitutionMap() -- provides a new
  way to directly build a SubstitutionMap. It takes a
  TypeSubstitutionFn and LookupConformanceFn. This is
  equivalent to first calling getSubstitutions() with the two
  functions to create an ArrayRef<Substitution>, followed by
  the old form of getSubstitutionMap() on the result.

- TypeBase::getContextSubstitutionMap() -- replacement for
  getContextSubstitutions(), returning a SubstitutionMap.

- TypeBase::getMemberSubstitutionMap() -- replacement for
  getMemberSubstitutions(), returning a SubstitutionMap.

With these in place, almost all existing uses of subst() taking
a ModuleDecl can now use the new form taking a SubstitutionMap
instead. The few remaining cases are explicitly written to use a
TypeSubstitutionFn and LookupConformanceFn.
2017-02-03 19:55:40 -08:00
Slava Pestov
fc3244b2f2 Sema: Remove some redundant conformance lookup callbacks
Now we have LookUpConformanceInModule and
LookUpConformanceInSubstitutionMap.
2017-02-03 19:55:40 -08:00
Doug Gregor
ee00acf3d0 [AST] Remove GenericSignature::getRepresentative(). NFC
This entrypoint is unused and is a Bad Idea (TM). Remove it.
2017-02-02 21:25:29 -08:00
Doug Gregor
ded7e83aab [Archetype builder] Make canonicalization of dependent types deterministic.
The canonicalization of dependent member types had some
nondeterminism. The root of the problem was that we couldn't
round-trip dependent member types through the archetype
builder---resolving them to a potential archetype lost the specific
associated type that was recorded in the dependent member type, which
affected canonicalization. Maintain that information, make sure that
we always get the right archetype anchor, and tighten up the
canonicalization logic within a generic signature.

Fixes rdar://problem/30274260 and should unblock some other work
that depends on sanity from the archetype builder and generic
signature canonicalization.
2017-02-02 21:25:29 -08:00
Doug Gregor
f7f703ad04 [Archetype builder] Canonicalize and minimize same-type constraints.
Introduce an algorithm to canonicalize and minimize same-type
constraints. The algorithm itself computes the equivalence classes
that would exist if all explicitly-provided same-type constraints are
ignored, and then forms a minimal, canonical set of explicit same-type
constraints to reform the actual equivalence class known to the type
checker. This should eliminate a number of problems we've seen with
inconsistently-chosen same-type constraints affecting
canonicalization.
2017-02-01 10:51:02 -08:00
Doug Gregor
1f9406915b [Archetype builder] Make the "archetype anchor" use a total order.
Make the "archetype anchor" algorithm use the same total order used to
compare dependent types in a generic signature, so that it is a
dependable total order. Tighten up the compareDependentTypes() logic
(and checking of it) a bit now that it's being used more frequently.

The weird code around GenericSignature::isCanonicalTypeInContext() is
due to a longstanding issue where

  ArchetypeBuilder::resolveArchetype(t)->getDependentType()

is not the identity function when the incoming type is a
DependentMemberType with known associated types. We want to establish
this behavior at some point going forward, in which case we can go
back to the prior implementation of
GenericSignature::isCanonicalTypeInContext().
2017-01-24 19:36:44 -08:00
Slava Pestov
f93c59fdcb AST: Don't canonicalize replacement type in substitutions
A change was recently made to canonicalize replacement types in
GenericSignature::getSubstitutions().

This resulted in ParenType being stripped off, which triggered
the 'tuple splat' diagnostic on code that was accepted in Swift 3.0.

I believe this canonicalization step is unnecessary; we
canonicalize using a brand-new ArchetypeBuilder that has no
generic signature added to it, so this is just equivalent to a
call to getCanonicalType().

Also adding the generic signature in question to the builder is
not the right answer either; the replacement types might be
written in terms of a different generic signature, or possibly
in terms of archetypes.

Taking this out seems to have no effect except changing a few
SIL dumps to contain sugared types, which should be harmless.

Part of fixing <rdar://problem/29739905>.
2017-01-19 20:07:05 -08:00
Doug Gregor
e305b2017b [AST] Allow computation of erroneous substitutions.
Be more tolerant of substitutions for erroneous types; the type
checker will diagnose these issues, but later code paths might still
form these substititions. Put in error types rather than crashing.
2017-01-19 10:43:24 -08:00
Doug Gregor
91af1d6af5 [AST] Use Type::transformRec() when getting a canonical type in context.
NFC cleanup
2017-01-19 10:35:07 -08:00
Slava Pestov
24b2531e5f AST: Have SubstitutionMaps manage the memory for the conformance array 2017-01-18 00:15:59 -08:00
Doug Gregor
a232b41f87 [Archetype builder] Use archetype anchors exclusively in requirements.
When enumerating requirements, always use the archetype anchors to
express requirements. Unlike "representatives", which are simply there
to maintain the union-find data structure used to track equivalence
classes of potential archetypes, archetype anchors are the
ABI-stable canonical types within a fully-formed generic signature.

The test case churn comes from two places. First, while
representatives are *often* the same as the archetype anchors, they
aren't *always* the same. Where they differ, we'll see a change in
both the printed generic signature and, therefore, it's
mangling.

Additionally, requirement inference now takes much greater
care to make sure that the first types in the requirement follow
archetype anchor ordering, so actual conformance requirements occur in
the requirement list at the archetype anchor---not at the first type
that is equivalent to the anchor---which permits the simplification in
IRGen's emission of polymorphic arguments.
2017-01-12 11:07:05 -08:00
swift-ci
808c48401f Merge pull request #6743 from swiftix/wip-partial-pre-specializations-wip-layout-constraints 2017-01-12 10:12:44 -08:00
Roman Levenstein
29180ca1a0 Add support for layout requirements with layout constraints.
This commit introduces new kind of requirements: layout requirements.

This kind of requirements allows to expose that a type should satisfy certain layout properties, e.g. it should be a trivial type, have a given size and alignment, etc.
2017-01-11 19:21:45 -08:00
Pavel Yaskevich
c158f49417 [Diagnostics] Improve diagnostics for generic types with unfulfilled requirements 2017-01-11 15:25:16 -08:00
Slava Pestov
7731d4c6cb Sema: Remove some unnecessary calls to getCanonicalType() 2017-01-08 21:01:13 -08:00
practicalswift
6d1ae2a39c [gardening] 2016 → 2017 2017-01-06 16:41:22 +01:00
Doug Gregor
16585992f6 [AST] Strengthen signature of SubstututionMap::addSubstitution().
It requires a CanSubstitutableType internally, so use that in the
signature and fix up all of the callers.
2017-01-05 16:04:19 -08:00
Slava Pestov
3cbc08cc4e AST/SIL: Fix problems if protocol requirement signature makes Self : P conformance implicit
Fixes assertion failures in SILGen and the optimizer with this
exotic setup:

protocol P {
  associatedtype T : Q
}

protocol Q {
  func requirement<U : P>(u: U) where U.T == Self
}

Here, we only have a U : P conformance, and not Self : Q,
because Self : Q is available as U.T : Q.

There were three problems here:

- The SIL verifier was too strict in verifying the generic signature.
  All that matters is we can get the Self parameter conformance, not
  that it's the first requirement, etc.

- GenericSignature::getSubstitutionMap() had a TODO concerning handling
  of same-type constraints -- this is the first test-case I've found
  that triggered the problem.

- GenericEnvironment::getSubstitutionMap() incorrectly ignored
  same-type constraints where one of the two types was a generic
  parameter.

Fixes <https://bugs.swift.org/browse/SR-3321>.
2017-01-04 02:28:55 -08:00
Slava Pestov
064fda52d2 AST: Remove Type::getCanonicalTypeOrNull()
Not sure why but this was another "toxic utility method".
Most of the usages fell into one of three categories:

- The base value was always non-null, so we could just call
  getCanonicalType() instead, making intent more explicit

- The result was being compared for equality, so we could
  skip canonicalization and call isEqual() instead, removing
  some boilerplate

- Utterly insane code that made no sense

There were only a couple of legitimate uses, and even there
open-coding the conditional null check made the code clearer.

Also while I'm at it, make the SIL open archetypes tracker
more typesafe by passing around ArchetypeType * instead of
Type and CanType.
2017-01-04 01:08:29 -08:00
Slava Pestov
caa7045ae5 AST: Remove unnecessary ModuleDecl parameter from GenericSignature::getSubstitutions() 2016-12-22 14:33:00 -05:00
Slava Pestov
fb0f372e94 AST: Move mapType{In,OutOf}Context() out of ArchetypeBuilder and clean up headers
- The DeclContext versions of these methods have equivalents
  on the DeclContext class; use them instead.

- The GenericEnvironment versions of these methods are now
  static methods on the GenericEnvironment class. Note that
  these are not made redundant by the instance methods on
  GenericEnvironment, since the static methods can also be
  called with a null GenericEnvironment, in which case they
  just assert that the type is fully concrete.

- Remove some unnecessary #includes of ArchetypeBuilder.h
  and GenericEnvironment.h. Now changes to these files
  result in a lot less recompilation.
2016-12-18 19:55:41 -08:00
Joe Groff
88d064523a Change TypeSubstitutionFn-based subst to use a LookupConformanceFn instead of a ModuleDecl.
This is a more flexible interface that allows substitution operations to avoid needing an eager SubstitutionMap without relying on module-based conformance lookup. NFC yet.
2016-12-15 09:21:29 -08:00
Joe Groff
ccfabd1118 Make LookupConformanceFn callbacks return Optional<ProtocolConformanceRef>.
NFC yet, but this is a step toward centralizing error handling policy for failed conformance lookups instead of leaving it ad-hoc.
2016-12-14 18:04:35 -08:00
Doug Gregor
9e465fa03d [AST] Add a form of Type::subst() that takes an arbitrary substitution function
The "core" data structure used to record the substitutions to be
performed is a TypeSubstitutionMap, which is a DenseMap. This is a
fairly heavyweight, static data structure for something where

* We occasionally want a more dynamic, lazily-populated data structure, and
* We can usually provide more efficient storage than a DenseMap.

So, introduce a Type::subst() variant that takes a TypeSubstitutionFn,
which is just a function that maps a SubstitutableType * to a Type (or
nothing). Use this as the core variant of subst(). with an adapter for
existing TypeSubstitutionMaps. Over time, TypeSubstitutionMap should
go away.
2016-12-01 10:35:17 -08:00
Doug Gregor
6f64658346 [AST] Stash an archetype builder in an "incomplete" generic environment.
This eliminates the really gross registration of archetype builders
within the ASTContext, and is another little step toward lazily
constructing archetypes.
2016-12-01 10:35:17 -08:00
Doug Gregor
10ccafde73 [Archetype builder] Replace MapVector with parallel SmallVectors.
In the archetype builder, separate out the generic parameters (which
were the keys of the MapVector) from the potential archetypes (which
where the values of the MapVector) into two parallel
SmallVectors. This saves on storage, lets us avoid building up a
SmallVector of GenericTypeParamTypes, and helps flesh out this pattern
as a way of eliminating DenseMaps in favor of arrays.
2016-11-30 15:44:14 -08:00
Doug Gregor
79812aa073 [Archetype builder] (Almost) decouple PotentialArchetype from generic params.
The root potential archetypes in an archetype builder are associated
with generic parameters. Start decoupling potential archetypes from a
specific GenericTypeParamType and instead work with the abstracted
depth/index. The goal here is to allow the same archetype builder to
be used within different generic environments (which includes both
different generic parameters and different archetypes).

As part of this, boost the archetype builder's GenericTypeParamKey
from a local type to a more generic GenericParamKey that can be used
in other interfaces that want to work with abstracted generic
parameters.
2016-11-30 15:44:14 -08:00
Doug Gregor
581a4de97d [Archetype builder] Eliminate 'builder' parameter to getDependentType(). 2016-11-29 10:45:30 -08:00
Doug Gregor
d1066d16a2 [IRGen] Use a canonical generic environment rather than an archetype builder.
Rather than directly using the ArchetypeBuilder associated with a
canonical generic signature, use a canonical GenericEnvironment
associated with that canonical generic signature. This has a few
benefits:

* It's cleaner to not have IRGen working with archetype builders;
  GenericEnvironment is the right abstraction for mapping between
  dependent types and archetypes for a specific context.
* It helps us separate the archetype builder from a *specific*
  set of archetypes. This is an ongoing refactor that is intended to
  allow us to re-use archetype builders across different generic
  environments.

As part of this, ArchetypeBuilder::substDependentType() has gone away
in favor of GenericEnvironment::mapTypeIntoContext().
2016-11-29 09:24:27 -08:00
practicalswift
797b80765f [gardening] Use the correct base URL (https://swift.org) in references to the Swift website
Remove all references to the old non-TLS enabled base URL (http://swift.org)
2016-11-20 17:36:03 +01:00
Doug Gregor
85ba4fe40f [AST] Narrow TypeSubstitutionMap to SubstitutableType keys.
Type substitution works on a fairly narrow set of types: generic type
parameters (to, e.g., use a generic) and archetypes (to map out of a
generic context). Historically, it was also used with
DependentMemberTypes, but recent refactoring to eliminate witness
markers eliminate that code path.

Therefore, narrow TypeSubstitutionMap's keys to SubstitutableType,
which covers archetypes and generic type parameters. NFC
2016-11-15 11:34:09 -08:00
Doug Gregor
84d70a2284 Eliminate witness markers. NFC 2016-11-09 19:22:51 -08:00
Doug Gregor
974cfa87cb [Generic signatures] Eliminate our reliance on witness markers.
Introduce a new operation on generic signatures,
enumeratePairedRequirements(), which invokes a callback with each
(dependent type, set-of-conformance-requirements) pair that needs to
be recorded within substitutions. Switch the last two remaining
consumers of witness markers (GenericSignature::getAllDependentTypes()
and GenericSignature::getSubstitutions()) over to this new entrypoint.
2016-11-09 19:22:51 -08:00
Doug Gregor
66e20116f2 Extend ErrorType with an "original type" and use it to clean up substitution.
Type::subst()'s "IgnoreMissing" option was fairly unprincipled, dropping
unsubstituted types into the resulting AST without any indication
whatsoever that anything went wrong. Replace this notion with a new
form of ErrorType that explicitly tracks which substituted type caused
the problem. It's still an ErrorType, but it prints like the
substituted type (which is important for code completion) and allows
us to step back to the substituted type if needed (which is used by
associated type inference). Then, allow Type::subst(), when the new
UseErrorTypes flag is passed, to form partially-substituted types that
contain errors, which both code completion and associated type
inference relied on.

Over time, I hope we can use error-types-with-original-types more
often to eliminate "<<error type>>" from diagnostics and teach
Type::subst() never to return a "null" type. Clients can check
"hasError()" to deal with failure cases rather than checking null.
2016-10-06 16:40:28 -07:00
Slava Pestov
a993e36c06 AST: Add a new SubstitutionMap data structure
This replaces the TypeSubstitutionMap / ConformanceMap pair that
has been appearing more and more lately.
2016-09-08 21:59:11 -07:00
Slava Pestov
6e77f62585 AST: Add some handy assertions to GenericSignature 2016-09-06 11:52:24 -07:00
Slava Pestov
3b1721795f AST: Nuke GenericSignature::getCanonicalManglingSignature()
Now that the previous patches have shaken out implicit assumptions
about the order of generic requirements and substitutions, we can
make a more radical change, dropping redundant protocol requirements
when building the original generic signature.

This means that the canonical ordering and minimization that we
used to only perform when building the mangling signature is done
all of the time, and hence getCanonicalManglingSignature() can go
away.

Usages now either call getCanonicalSignature(), or operate on the
original signature directly.
2016-09-06 11:51:14 -07:00
Slava Pestov
7a7af62012 ArchetypeBuilder: use enumerateRequirements() in getGenericSignature()
Instead of walking over PotentialArchetypes representatives directly
and using a separate list to record same-type constraints, just use
enumerateRequirements() and check the RequirementSource to drop
redundant requirements.

This means getGenericSignature() and getCanonicalManglingSignature()
can share the same logic for collecting requirements; the only
differences are the following:

- both drop requirements from Redundant sources, but mangling
  signatures also drop requirements from Protocol sources

- mangling signatures also canonicalize the types appearing in the
  final requirement
2016-09-06 11:51:14 -07:00
Slava Pestov
f19192d498 ArchetypeBuilder: Sort requirements in enumerateRequirements()
Move the sorting algorithm from construction of the canonical mangling
signature to requirement enumeration.

This also changes how same-type constraints pick representatives, using
the more canonical total order.
2016-09-06 11:51:13 -07:00
Slava Pestov
71cf5919c6 ArchetypeBuilder: More principled usage of RequirementSource
We used RequirementSources to identify redundant requirements
when building the canonical mangling signature. There were a
few problems with how this worked:

- We used the Inferred requirement source for both requirements
  that were inferred from function parameter and result types
  (for example, T : Hashable in `func foo<T, U>(dict: [T : U])`
  and some completely unrelated things, like same-type
  constraints imposed on nested types by existing same-type
  constraints on the outer types.

- We used the Protocol requirement source for associated type
  requirements on protocols as well as conformance requirements
  on inherited protocols.

- Introducing a new Redundant requirement did not mark existing
  Explicit requirements as Redundant.

None of these were an issue because of how canonical mangling
signature construction works:

- We already started with a canonical signature, so there were
  no Inferred requirements of the first kind (which we *do* want
  to keep here)

- We dropped both Protocol and Redundant requirements, so it
  didn't matter that the distinction here was not sufficiently
  fine-grained

- We never introduced Explicit requirements that would be later
  superceded by a Redundant requirement, because we always
  started with an existing canonical signature where such Explicit
  requirements were already dropped.

However, I want to use the same algorithm for building the
original signature as the canonical mangling signature, so this
patch introduces these changes:

- The Inferred source is now only used for inferred requirements of
  the first kind; the second kind are now Redundant

- The Protocol source is now only used for associated type
  requirements; inherited protocol conformances are now Redundant

- updateRequirementSource() now does the right thing with
  introduced Redundant requirements

For now, this doesn't change much, but an upcoming patch
refactors ArchetypeBuilder::getGenericSignature() to also
use enumerateRequirements(), except dropping Redundant
requirements only, and not Protocol.
2016-09-06 11:51:13 -07:00
Slava Pestov
fbe9573598 AST: Add some utility methods to GenericSignature
These will be more useful once substitutions in protocol conformances
are moved to use interface types.

At first, these are only going to be used by the SIL optimizer.
2016-09-06 11:51:12 -07:00
Slava Pestov
1c1ab0b83a AST: Introduce new GenericEnvironment class
A GenericEnvironment stores the mapping between GenericTypeParamTypes
and context archetypes (or eventually, concrete types, once we allow
extensions to constrain a generic parameter to a concrete type).

The goals here are two-fold:

- Eliminate the GenericTypeParamDecl::getArchetype() method, and
  always use mapTypeIntoContext() instead

- Replace SILFunction::ContextGenericParams with a GenericEnvironment

This patch adds the new data type as well as serializer and AST
verifier support. but nothing else uses it yet.

Note that GenericSignature::get() now asserts if there are no
generic parameters, instead of returning null. This requires a
few tweaks here and there.
2016-08-28 13:51:36 -07:00
Slava Pestov
9489294fb8 AST: Add GenericSignature::getSubstitutions()
This is the opposite of GenericSignature::getSubstitutionMap(),
transforming an interface type substitution mapping into
a Substitution array.

Previously, Substitution arrays were built with hand-rolled
logic, usually relying on a GenericParamList's AllArchetypes
list. We want to stop using the AllArchetypes list, instead
using the requirements array from a GenericSignature.

Nothing calls this method yet; existing code will be refactored
to call it in the next few patches.
2016-08-22 10:45:49 -07:00
John McCall
fdd25a3c0c Canonicalize the components of a GenericFunctionType in the context of the generic signature.
This is obviously the right thing to do in terms of ensuring
that two different expressions of the same signature always result
in the same type.  It also has the pleasant side-effect of causing
the canonical function type to never be expressed in terms of type
parameters which have been equated with concrete types, which means
that various consumers that work primarily with canonical types
(such as SILGen and IRGen) no longer have to worry about such types,
at least when decomposing a generic function signature.
2016-06-21 14:22:03 -07:00
John McCall
12b8a92e9d In generic functions, derive local type data for associated types
from the witness tables for their associations rather than passing
them separately.

This drastically reduces the number of physical arguments required
to invoke a generic function with a complex protocol hierarchy.  It's
also an important step towards allowing recursive protocol
constraints.  However, it may cause some performance problems in
generic code that we'll have to figure out ways to remediate.

There are still a few places in IRGen that rely on recursive eager
expansion of associated types and protocol witnesses.  For example,
passing generic arguments requires us to map from a dependent type
back to an index into the all-dependent-types list in order to
find the right Substitution; that's something we'll need to fix
more generally.  Specific to IRGen, there are still a few abstractions
like NecessaryBindings that use recursive expansion and are therefore
probably extremely expensive under this patch; I intend to fix those
up in follow-ups to the greatest extent possible.

There are also still a few things that could be made lazier about
type fulfillment; for example, we eagerly project the dynamic type
metadata of class parameters rather than waiting for the first place
we actually need to do so.  We should be able to be lazier about
that, at least when the parameter is @guaranteed.

Technical notes follow.  Most of the basic infrastructure I set up
for this over the last few months stood up, although there were
some unanticipated complexities:

The first is that the all-dependent-types list still does not
reliably contain all the dependent types in the minimized signature,
even with my last patch, because the primary type parameters aren't
necessarily representatives.  It is, unfortunately, important to
give the witness marker to the primary type parameter because
otherwise substitution won't be able to replace that parameter at all.
There are better representations for all of that, but it's not
something I wanted to condition this patch on; therefore, we have to
do a significantly more expensive check in order to figure out a
dependent type's index in the all-dependent-types list.

The second is that the ability to add requirements to associated
types in protocol refinements means that we have to find the *right*
associatedtype declaration in order to find the associated witness
table.  There seems to be relatively poor AST support for this
operation; maybe I just missed it.

The third complexity (so far) is that the association between an
archetype and its parent isn't particularly more important than
any other association it has.  We need to be able to recover
witness tables linked with *all* of the associations that lead
to an archetype.  This is, again, not particularly well-supported
by the AST, and we may run into problems here when we eliminate
recursive associated type expansion in signatures.

Finally, it's a known fault that this potentially leaves debug
info in a bit of a mess, since we won't have any informaton for
a type parameter unless we actually needed it somewhere.
2016-02-22 01:02:31 -08:00
Joe Groff
26e55ce465 Sema: Initial parsing and synthesis for properties with behaviors.
Parse 'var [behavior] x: T', and when we see it, try to instantiate the property's
implementation in terms of the given behavior. To start out, behaviors are modeled
as protocols. If the protocol follows this pattern:

  ```
  protocol behavior {
    associatedtype Value
  }
  extension behavior {
    var value: Value { ... }
  }
  ```

then the property is instantiated by forming a conformance to `behavior` where
`Self` is bound to the enclosing type and `Value` is bound to the property's
declared type, and invoking the accessors of the `value` implementation:

  ```
  struct Foo {
    var [behavior] foo: Int
  }

  /* behaves like */

  extension Foo: private behavior {
    @implements(behavior.Value)
    private typealias `[behavior].Value` = Int

    var foo: Int {
      get { return value }
      set { value = newValue }
    }
  }
  ```

If the protocol requires a `storage` member, and provides an `initStorage` method
to provide an initial value to the storage:

  ```
  protocol storageBehavior {
    associatedtype Value

    var storage: Something<Value> { ... }
  }
  extension storageBehavior {
    var value: Value { ... }

    static func initStorage() -> Something<Value> { ... }
  }
  ```

then a stored property of the appropriate type is instantiated to witness the
requirement, using `initStorage` to initialize:

  ```
  struct Foo {
    var [storageBehavior] foo: Int
  }

  /* behaves like */

  extension Foo: private storageBehavior {
    @implements(storageBehavior.Value)
    private typealias `[storageBehavior].Value` = Int
    @implements(storageBehavior.storage)
    private var `[storageBehavior].storage`: Something<Int> = initStorage()

    var foo: Int {
      get { return value }
      set { value = newValue }
    }
  }
  ```

In either case, the `value` and `storage` properties should support any combination
of get-only/settable and mutating/nonmutating modifiers. The instantiated property
follows the settability and mutating-ness of the `value` implementation. The
protocol can also impose requirements on the `Self` and `Value` types.

Bells and whistles such as initializer expressions, accessors,
out-of-line initialization, etc. are not implemented. Additionally, behaviors
that instantiate storage are currently only supported on instance properties.
This also hasn't been tested past sema yet; SIL and IRGen will likely expose
additional issues.
2016-02-20 15:01:05 -08:00