Commit Graph

723 Commits

Author SHA1 Message Date
John McCall
39b65f49a0 Track the actual DC of a member access in the constraint system.
Without this, CSGen/CSSimplify and CSApply may have differing
opinions about whether e.g. a let property is settable, which
can lead to invalid ASTs.

Arguably, a better fix would be to remove the dependency on the
exact nested DC.  For example, we could treat lets as settable
in all contexts and then just complain later about invalid
attempts to set them.  Or we could change CSApply to directly
use the information it already has about how an l-value is used,
rather than trying to figure out whether it *might* be getting set.
But somehow, tracking a new piece of information through the
entire constraint system seems to be the more minimal change.

Fixes rdar://29810997.
2017-01-26 00:14:21 -05:00
Slava Pestov
8de0ca54e5 Sema: Merge the two implementations of simplifyType()
ConstraintSystem::simplifyType() replaced types with their fixed types
from the global map.

Solution::simplifyType() replaced types with their fixed types from the
current bindings.

There were some minor differences between the two, and some dead code.
2017-01-19 20:07:06 -08:00
Slava Pestov
a22b46244c Sema: Don't canonicalize base type in member lookup
We would lose ParenType sugar in function types as a result.

Fixes part of <rdar://problem/29739905>.
2017-01-19 20:07:05 -08:00
Hugh Bellamy
2445862e1b FIx recently introduced MSVC control path warnings 2017-01-14 12:40:41 +00: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
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
Slava Pestov
edeb157964 Sema: Fix call to Self-returning methods with refined protocols
Regression from the following commit:

<9db06ee36d>

Fixes <rdar://problem/29868979>.
2017-01-04 15:48:38 -08:00
Slava Pestov
18adb53226 Sema: Tighten up name lookup routines to not look through metatypes/lvalues/etc
Previously all of the following would strip off varying amounts of
MetatypeType, LValueType, InOutType, DynamicSelfType, etc:

- ConstraintSystem::performMemberLookup()
- ConstraintSystem::lookupMember()
- TypeChecker::lookupMember()
- DeclContext::lookupQualified()
- Type::getContextSubstitutions()

The problem is that the higher level methods that took a lookup type
would call the lower level methods, and post-process the result using
the given lookup type. Since different levels of sugar were stripped,
it made the code hard to reason about and opened up edge cases, eg
if a DynamicSelfType or InOutType appears where we didn't expect it.

Since filtering out static/instance and mutating/nonmutating members
is done at higher levels, there's no reason for these name lookup
operations to accept anything other than nominal types, existentials
and archetypes.

Make this so with assertions, and deal with the fallout.
2017-01-04 01:40:19 -08:00
Slava Pestov
71df32fd7d Sema: Add some asserts 2017-01-04 01:08:28 -08:00
Slava Pestov
e455085d94 Sema: When opening an UnboundGenericType, don't put replacements in the same map
When inserting a new value, assert that there's no existing
value at that key, and to avoid the assert firing when
opening up UnboundGenericTypes, put those replacements in
their own map. We don't need them later.
2017-01-03 23:40:46 -08:00
Slava Pestov
9db06ee36d Sema: Fixes for handling of 'Self'-returning methods
Protocol methods returning optionals, metatypes and functions
returning 'Self' are now handled correctly in Sema when
accessed with a base of existential type, eg:

protocol Clonable {
  func maybeClone() -> Self?
  func cloneMetatype() -> Self.Type
  func getClonerFunc() -> () -> Self
}

let c: Clonable = ...
let _: Clonable = c.maybeClone()
let _: Clonable.Type = c.cloneMetatype()

Previously, we were unable to model this properly, for
several reasons:

- When opening the function type, we replaced the return
  value in openedFullType _unconditionally_ with the
  existential type. This was broken if the return type
  was not the 'Self' parameter, but rather an optional,
  metatype or function type involving the 'Self' parameter.

- It was also broken because we lost information; if the
  return type originally contained an existential, we had
  no way to draw the distinction. The 'hasArchetypeSelf()'
  method was a hint that the original type contained a
  type parameter, but it was inaccurate in some subtle cases.

- Since we performed this replacement on both the
  'openedFullType' and 'openedType', CSApply had to "undo"
  it to replace the existential type with the opened
  existential archetype. This is because while the formal
  type of the access returns the existential type, in
  reality it returns the opened type, and CSApply has to
  insert the correct ErasureExpr.

  This was also done unconditionally, but even if it were
  done more carefully, it would do the wrong thing because
  of the 'loss of information' above.

- There was something fishy going on when we were dealing
  with a constructor that was declared on the Optional type
  itself, as seen in the fixed type_checker_crasher.

- TypeBase::eraseOpenedExistential() would transform a
  MetatypeType of an opened existential into a MetatypeType
  of an existential, rather than an ExistentialMetatypeType
  of the existential type.

The new logic has the following improvements:

- When opening a function type, we replace the 'Self' type
  parameter with the existential type in 'openedType', but
  *not* 'openedFullType'. This simplifies CSApply, since it
  doesn't have to "undo" this transformation when figuring
  out what coercions to perform.

- We now only use replaceCovariantResultType() when working
  with Self-returning methods on *classes*, which have more
  severe restrictions than protocols. For protocols, we walk
  the type using Type::transform() and handle all the cases
  properly.

- Not really related to the above, but there was a whole
  pile of dead code here concerning associated type references.

Note that SILGen still needs support for function conversions
involving an existential erasure; in the above Clonable example,
Sema now models this properly but SILGen still crashes:

let _: () -> Clonable = c.getClonerFunc()

Fixes <rdar://problem/28048391>, progress on <rdar://problem/21391055>.
2017-01-03 21:49:00 -08:00
Slava Pestov
eb78182afb Merge pull request #6510 from xedin/crasher-28592
[QoI] Fix recursive propagation of materializability to look through optional types
2017-01-03 18:58:16 -08:00
Joe Groff
796df2dc44 Merge pull request #6429 from jckarter/type-of-by-overload-resolution
`withoutActuallyEscaping`
2017-01-03 18:47:29 -08:00
Slava Pestov
bd53d2acd4 Merge pull request #6491 from xedin/crasher-28544
[TypeChecker] Fix isAnyHashableType to check type variables
2017-01-03 18:13:28 -08:00
Slava Pestov
a598ed68e6 Sema: Fixes for generic typealiases and nested type lookup
This patch contains several intertwined changes:

- Remove some unnecessary complexity and duplication.

- Adds a new TypeChecker::lookupUnqualifiedType() which bypasses most of
  the logic in TypeChecker::lookupUnqualified(), such as the
  LookupResultBuilder. Use this when resolving unqualified references
  to types.

- Fixes for generic typealiases to better preserve the type parameters of
  the parent type, and clean up the logic for applying the inner generic
  arguments. Some uses of generic typealiases that used to crash now work,
  and those tests have been uncommented.

- Avoid an unnecessary desugaring of TypeAliasDecls which map directly
  to GenericTypeParamTypes. Once again this perturbs the source-stability
  test.

- When looking up a nested type of a base class with a derived class base,
  always use the base class as the parent of the nested type. This fixes
  a recent regression where in some cases we were using the wrong parent.

Fixes <rdar://problem/29782186>.
2017-01-03 16:57:42 -08:00
Pavel Yaskevich
8c4b8715c6 [QoI] Fix recursive propagation of materializability to look through optional types
If T0 must be materializable and it's bound to T1, when matching T0 to
possibly optinal T1, look through optinality when setting materializability of the binding.
2016-12-29 22:55:12 -08:00
Pavel Yaskevich
dab14d3759 [TypeChecker] Fix isAnyHashableType to check type variables
Currently isAnyHashableType method validates only structs but
it doesn't account for situation when type is represented via type
variable with type already fixed to AnyHashable, that results in
infinite loop in the solver because restriction [hashable-to-
anyhashable] is going to add new type variable recursively.
2016-12-26 01:16:56 -08:00
Joe Groff
0c9297862f Sema: Handle type-checking for withoutActuallyEscaping.
withoutActuallyEscaping has a signature like `<T..., U, V, W> (@nonescaping (T...) throws<U> -> V, (@escaping (T...) throws<U> -> V) -> W) -> W, but our type system for functions unfortunately isn't quite that expressive yet, so we need to special-case it. Set up the necessary type system when resolving an overload set to reference withoutActuallyEscaping, and if a type check succeeds, build a MakeTemporarilyEscapableExpr to represent it in the type-checked AST.
2016-12-22 17:51:26 -08:00
Joe Groff
1889fde228 Resolve type(of:) by overload resolution rather than parse hackery.
`type(of:)` has behavior whose type isn't directly representable in Swift's type system, since it produces both concrete and existential metatypes. In Swift 3 we put in a parser hack to turn `type(of: <expr>)` into a DynamicTypeExpr, but this effectively made `type(of:)` a reserved name. It's a bit more principled to put `Swift.type(of:)` on the same level as other declarations, even with its special-case type system behavior, and we can do this by special-casing the type system we produce during overload resolution if `Swift.type(of:)` shows up in an overload set. This also lays groundwork for handling other declarations we want to ostensibly behave like normal declarations but with otherwise inexpressible types, viz. `withoutActuallyEscaping` from SE-0110.
2016-12-22 16:28:31 -08:00
Doug Gregor
8afeadc5ee Merge pull request #6309 from DougGregor/as-coercions-bridging
[Type checker] Clean up as/as!/as?/is casting
2016-12-21 15:53:18 -08:00
practicalswift
b253b21014 [gardening] Make sure argument names in comments match the actual parameter names 2016-12-21 22:56:01 +01:00
Doug Gregor
642c8ed3eb [Constraint solver] Collapse getBaseTypeFor(Array|Set)Type into is(Array|Set)Type.
Follow the pattern set by isDictionaryType() of performing the query
and extracting the underlying key/element types directly. We often
need both regardless. NFC
2016-12-21 13:46:13 -08: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
practicalswift
38be6125e5 [gardening] C++ gardening: Terminate namespaces, fix argument names, ...
Changes:
* Terminate all namespaces with the correct closing comment.
* Make sure argument names in comments match the corresponding parameter name.
* Remove redundant get() calls on smart pointers.
* Prefer using "override" or "final" instead of "virtual". Remove "virtual" where appropriate.
2016-12-17 00:32:42 +01:00
Slava Pestov
2c6b9f71b6 AST: Change TypeAliasDecls to store an interface type as their underlying type
- TypeAliasDecl::getAliasType() is gone. Now, getDeclaredInterfaceType()
  always returns the NameAliasType.

- NameAliasTypes now always desugar to the underlying type as an
  interface type.

- The NameAliasType of a generic type alias no longer desugars to an
  UnboundGenericType; call TypeAliasDecl::getUnboundGenericType() if you
  want that.

- The "lazy mapTypeOutOfContext()" hack for deserialized TypeAliasDecls
  is gone.

- The process of constructing a synthesized TypeAliasDecl is much simpler
  now; instead of calling computeType(), setInterfaceType() and then
  setting the recursive properties in the right order, just call
  setUnderlyingType(), passing it either an interface type or a
  contextual type.

  In particular, many places weren't setting the recursive properties,
  such as the ClangImporter and deserialization. This meant that queries
  such as hasArchetype() or hasTypeParameter() would return incorrect
  results on NameAliasTypes, which caused various subtle problems.

- Finally, add some more tests for generic typealiases, most of which
  fail because they're still pretty broken.
2016-12-15 22:46:15 -08:00
Doug Gregor
f68f87a56a [Constraint solver] After binding a type variable, activate affected constraints
Once we've bound a type variable, we find those inactive constraints
that mention the type variable and make them active, so they'll be
simplified again. However, we weren't finding *all* constraints that
could be affected---in particular, we weren't searching everything
related to the type variables in the equivalence class, which meant
that some constraints would not get visited... and we would to
type-check simply because we didn't look at a constraint again when we
should have.

Fixes rdar://problem/29633747.
2016-12-14 20:18:04 -08:00
Slava Pestov
a4afb993f1 AST: Make Type::transform() more robust with ParenTypes
There is never any reason for a transform to treat a ParenType
differently from the underlying type itself. Calling the given
function with ParenTypes is a source of bugs where they get
desugared on accident. Make transform() skip the function
entirely for ParenTypes, and remove a spot where we were
checking explicitly.
2016-12-12 21:10:07 -08:00
Slava Pestov
e063e8297c Sema: Some fixes for the ITC
- In functions called from resolveType(), consistently
  use a Type() return value to indicate 'unsatisfied
  dependency', and ErrorType to indicate failure.

- Plumb the unsatisfiedDependency callback through the
  resolution of the arguments of BoundGenericTypes, and
  also pass down the options.

- Before doing a conformance check on the argument of a
  BoundGenericType, kick off a TypeCheckSuperclass request
  if the type in question is a class. This ensures we don't
  recurse through NominalTypeDecl::prepareConformanceTable(),
  which wants to see a class with a valid superclass.

- The ResolveTypeOfDecl request was assuming that
  the request was satisfied after calling validateDecl().
  This is not the case when the ITC is invoked from a
  recursive call to validateDecl(), hack this up by returning
  *true* from isResolveTypeDeclSatisfied(); otherwise we
  assert in satisfy(), and we can't make forward progress
  in this case anyway.

- Fix a bug in cycle breaking; it seems if we don't invoke
  the cycle break callback on all pending requests, we end
  up looping forever in an outer call to satisfy().

- Remove unused TR_GlobalTypeAlias option.
2016-12-09 17:36:49 -08:00
Slava Pestov
198c13501c Merge pull request #6069 from slavapestov/remove-substituted-type
Remove SubstitutedType
2016-12-07 16:14:55 -08:00
Doug Gregor
ea067c0346 [AST] Eliminate ArchetypeType::NestedType.
Now that we no longer distinguish outer archetypes from inner
archetypes, we can replace NestedType with just Type.
2016-12-07 14:27:49 -08:00
Slava Pestov
ed75fdacab Sema: Fix for accidental desugaring in simplifyType()
When called with a ParenType wrapping a DependentMemberType,
we would drop the ParenType because we used type->getAs<ParenType>()
rather than dyn_cast<ParenType>(type.getPointer()).

This fixes an existing QoI issue with closure argument tuples,
and prevents another regression once SubstitutedType is removed.
2016-12-07 14:16:43 -08:00
Slava Pestov
9caaad442b AST: Don't call hasType()/getType()/setType() on TypeDecls 2016-12-01 13:00:19 -08:00
Slava Pestov
2d83a79c2c AST: Remove TypeDecl::getDeclaredType()
A pointless use of polymorphism -- the result values are not
interchangeable in any practical sense:

- For GenericTypeParamDecls, this returned getDeclaredInterfaceType(),
  which is an interface type.

- For AssociatedTypeDecls, this returned the sugared AssociatedTypeType,
  which desugars to an archetype.

- For TypeAliasDecls, this returned TypeAliasDecl::getAliasType(),
  which desugars to a type containing archetypes.

- For NominalTypeDecls, this returned NominalTypeDecl::getDeclaredType(),
  which is the unbound generic type, a special case used for inferring
  generic arguments when they're not written in source.
2016-12-01 13:00:18 -08:00
Hugh Bellamy
48109f2a64 Fix errors and warnings building libSwiftSema on Windows using MSVC 2016-11-29 11:24:13 +00:00
Slava Pestov
835472b14f AST: Remove PolymorphicFunctionType 2016-11-29 03:05:35 -07:00
Slava Pestov
6cbb494ad2 AST: Give all ValueDecls an interface type
Previously, getInterfaceType() would return getType() if no
interface type was set. Instead, always set an interface type
explicitly.

Eventually we want to remove getType() altogether, and this
brings us one step closer to this goal.

Note that ParamDecls are excempt from this treatment, because
they don't have a proper interface type yet. Cleaning this up
requires more effort.
2016-11-29 03:05:25 -07:00
Graydon Hoare
7c1dc18b64 Revert "Give all declarations an explicit interface type" 2016-11-24 09:55:27 -08:00
Slava Pestov
ee56292808 AST: Give all ValueDecls an interface type
Previously, getInterfaceType() would return getType() if no
interface type was set. Instead, always set an interface type
explicitly.

Eventually we want to remove getType() altogether, and this
brings us one step closer to this goal.

Note that ParamDecls are excempt from this treatment, because
they don't have a proper interface type yet. Cleaning this up
requires more effort.
2016-11-24 02:35:21 -05: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
Mark Lacey
a4a6c0d5e0 Clean-up solver state management for a constraint system.
Make SolverState manage whether the ConstraintSystem it belongs to has a
current SolverState.

Also a couple minor formatting fixes for ternary expressions involving
solverState.
2016-11-15 17:06:20 -08:00
Doug Gregor
e045429471 [Type Checker] Improve interface to TypeChecker::conformsToProtocol().
This function had a weird, pre-ProtocolConformanceRef interface that
returned true when the type conformed to the protocol, then had a
separate indirect return value for the concrete conformance (if there
is one). Refactor this API, and the similar
TypeChecker::containsProtocol(), to produce an optional
ProtocolConformanceRef, which is far more idiomatic and easier to
use. Push ProtocolConformanceRef into a few more places. Should be NFC
2016-11-14 16:00:58 -08:00
Doug Gregor
84d70a2284 Eliminate witness markers. NFC 2016-11-09 19:22:51 -08:00
Doug Gregor
ba06709eca [Constraint solver] Dependent members don't "involve type variables".
The constraint solver tries not to solve for type variables that
"involve other type variables", which handles the case where we have
seen a constraint that mentions the type variable under consideration
as well as a different type variable, but in a constraint that we
cannot capture in a binding. Solving for such type variables too early
can lead to missed solutions, so we avoid it.

Tweak the logic for this computation to not consider type variables
mentioned within dependent member types (e.g., $T0.Iterator.Element),
because such types do not affect type inference at all, and therefore
shouldn't prevent solving for the type variable in question.
2016-11-05 23:20:28 -07:00
Doug Gregor
4a5402849b Remove the now-unnecessary "get member type" callback.
The ASTContext had a wacky "get member type" callback that actually
called back into the constraint system (!) to build member types. This
callback was obsoleted by the change that started representing nested
types as DependentMemberTypes.
2016-11-05 23:20:28 -07:00
Doug Gregor
f168e7270c [Type checker] Use DependentMemberType instead of type variables for nested types.
In the constraint solver, we've traditionally modeled nested type via
a "type member" constraint of the form

  $T1 = $T0.NameOfTypeMember

and treated $T1 as a type variable. While the solver did generally try
to avoid attempting bindings for $T1 (it would wait until $T0 was
bound, which solves the constraint), on occasion we would get weird
behavior because the solver did try to bind the type
variable.

With this commit, model nested types via DependentMemberType, the same
way we handle (e.g.) the nested type of a generic type parameter. This
solution maintains more information (e.g., we know specifically which
associated type we're referring to), fits in better with the type
system (we know how to deal with dependent members throughout the type
checker, AST, and so on), and is easier to reason able.

This change is a performance optimization for the type checker for a
few reasons. First, it reduces the number of type variables we need to
deal with significantly (we create half as many type variables while
type checking the standard library), and the solver scales poorly with
the number of type variables because it visits all of the
as-yet-unbound type variables at each solving step. Second, it
eliminates a number of redundant by-name lookups in cases where we
already know which associated type we want.

Overall, this change provides a 25% speedup when type-checking the
standard library.
2016-11-05 23:20:28 -07:00
Doug Gregor
a66b35d79b [Constraint solver] Allow constraint regeneration when inputs are simplified.
When we process a constraint, the first step is generally to call
getFixedTypeRecursive() to look through type variables. When this
operation actually does non-trivial work, we could save
that result by considering the current constraint "solved" and
generating a new constraint (if needed!) with the simplified types.

This commit adds the infrastructure to do that, because it's important
when getFixedTypeRecursive() starts performing more interesting
substitutions (e.g., handling member types of type
variables). However, enabling for the common case of looking through a
type variable isn't profitable (it's ~2% slower to type-check the
standard library). Stage in this infrastructure change now.
2016-10-31 09:27:22 -07:00
Doug Gregor
99daad0f30 Rework witness matching for generic requirements.
Reimplement the witness matching logic used for generic requirements
so that it properly models the expectations required of the witness,
then captures the results in the AST. The new approach has a number of
advantages over the existing hacks:

* The constraint solver no longer requires hacks to try to tangle
  together the innermost archetypes from the requirement with the
  outer archetypes of the context of the protocol
  conformance. Instead, we create a synthetic set of archetypes that
  describes the requirement as it should be matched against
  witnesses. This eliminates the infamous 'SelfTypeVar' hack.
* The type checker no longer records substitutions involving a weird
  mix of archetypes from different contexts (see above), so it's
  actually plausible to reason about the substitutions of a witness. A
  new `Witness` class contains the declaration, substitutions, and all
  other information required to interpret the witness.
* SILGen now uses the substitution information for witnesses when
  building witness thunks, rather than computing all of it from
  scratch. ``substSelfTypeIntoProtocolRequirementType()` is now gone
  (absorbed into the type checker, and improved from there), and the
  witness-thunk emission code is simpler. A few other bits of SILGen
  got simpler because the substitutions can now be trusted.
* Witness matching and thunk generation involving generic requirements
  and nested generics now works, based on some work @slavapestov was
  already doing in this area.
* The AST verifier can now verify the archetypes that occur in witness substitutions.
* Although it's not in this commit, the `Witness` structure is
  suitable for complete (de-)serialization, unlike the weird mix of
  archetypes previously present.

Fixes rdar://problem/24079818 and cleans up an area that's been messy
and poorly understood for a very, very long time.
2016-10-30 23:15:43 -07:00
Doug Gregor
b295106830 [Constraint solver] Use the type representative in the "occurs" check.
When performing the occurs check, look for the *representative* of the
type variable we're about to bind, rather than the type variable
itself. Fixes rdar://problem/26845038, SR-1512, SR-1902, SR2635,
SR-2852, and SR-2766.
2016-10-25 22:37:21 -07:00
Doug Gregor
c58aafdce5 [Constraint solver] Unify the two typeVarOccursInType implementations.
NFC, thanks @CodaFi!
2016-10-25 14:13:31 -07:00