Commit Graph

505 Commits

Author SHA1 Message Date
Doug Gregor
f7b5d9d69e [Type checker] Allow bridging conversions to more-optional types.
The prior formulation of bridging conversions allowed conversion to
more-optional types, e.g., converting an "NSDate" to "Date?", which
was broken by my recent refactoring in this area. Allow bridging
conversions to more-optional types by introducing extra optional
injections at the end.

Fixes rdar://problem/29780527.
2016-12-22 10:02:41 -08:00
Doug Gregor
dcdef4f7f5 [Type checker] Improve "downcast only unwraps optionals" diagnostics.
Specialize and improve the "downcast only unwraps optionals"
diagnostic to provide specific diagnostics + Fix-Its for the various
casts of forced cast, conditional cast, and "isa" check. Specifically:

* With a forced cast, customize the diagnostic. We still insert the
  appropriate number of !'s, but now we remove the 'as! T' (if an
  implicit conversion would suffice) or replace the 'as!' with 'as'
  (if we still need a bridge)

* With a conditional cast, only emit a diagnostic if we're removing
  just one level of optional. In such cases, we either have a no-op
  (an implicit conversion would do) or we could just use 'as' to the
  optional type, so emit a customized warning to do that. If we are
  removing more than one level of optional, don't complain:
  conditional casts can remove optionals. Add the appropriate Fix-Its
  here.

* With an 'is' expression, only emit a diagnostic if we're removing
  just one level of optional. In this case, the 'is' check is
  equivalent to '!= nil'. Add a Fix-It for that.

Across the board, reduce the error to a warning. These are
semantically-well-formed casts, it's just that they could be written
better.

Fixes rdar://problem/28856049 and rdar://problem/22275685.
2016-12-21 13:47:19 -08:00
Doug Gregor
fa47d57b4e [AST] Remove CheckedCastKind::BridgeFromObjectiveC.
It's not handled any differently from ValueCast, so simplify it away.
2016-12-21 13:46:14 -08:00
Doug Gregor
d9843899c4 [Type checker] Clean up handling of checked casts (as!/as?/is).
The type checker implements logic for handling checked casts in two
places: the constraint solver (for type-checking expressions
containing "as!" or "as?") and as a top-level entrypoint for
type-checking as?/as! for diagnostics and is/as patterns. Needless to
say, the two implementations were inconsistent, and in fact both were
wrong, leading to various problems---rejecting perfectly-valid "as!"
and "as?" casts outright, bogus warnings that particular as!/as? casts
always-succeed or always-fail when they wouldn't, and so on.

Start detangling the mess in two ways. First, drastically simplify the
handling of checked casts in the constraint solver, eliminating the
unprincipled "subtype" constraint checks that (among other things)
broke the handling of checked casts that involved bridging or optional
unwrapping. The simpler code is more permissive and more correct; it
essentially accepts that the user knows what she is doing with the
cast.

Second, make the type checker's checking of casts far more thorough,
which includes:

* When we're performing a collection cast, actually check that the
  element types (and key types, for a dictionary) are castable, rather
  than assuming all collection casts are legitimate. This means we'll
  get more useful "always fails" and "always succeeds" diagnostics for
  array/set/dictionary.

* Handle casts from a bridged value type to a subclass of the
  corresponding bridged class type. Previously, these would be
  incorrectly classified as "always fails".

While I'm here, eliminate a spurious diagnostic that occurs when using
a conditional cast ("as?") that could have been a coercion/bridging
conversion ("as"). The optional injection we synthesize to get the
resulting type correct was getting diagnosed as an implicit coercion,
but shouldn't have been.
2016-12-21 13:46:14 -08:00
Doug Gregor
e97ab635ea [Constraint solver] Separate bridging conversions from other conversions.
Previously, bridging conversions were handled as a form of "explicit
conversion" that was treated along the same path as normal
conversions in matchTypes(). Historically, this made some
sense---bridging was just another form of conversion---however, Swift
now separates out bridging into a different kind of conversion that is
available only via an explicit "as". This change accomplishes a few
things:

* Improves type inference around "as" coercions. We were incorrectly
  inferring type variables of the "x" in "x as T" in cases where a
  bridging conversion was expected, which cause some type inference
  failures (e.g., the SR-3319 regression).

* Detangles checking for bridging conversions from other conversions,
  so it's easier to isolate when we're applying a bridging
  conversion.

* Explicitly handle optionals when dealing with bridging conversions,
  addressing a number of problems with incorrect diagnostics, e.g.,
  complains about "unrelated type" cast failures that would succeed at
  runtime.

Addresses rdar://problem/29496775 / SR-3319 / SR-2365.
2016-12-21 13:46:14 -08: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
Mark Lacey
170dc8acd7 Do not penalize binding or equality constraints involving Any.
We currently have an element in the solution score related to whether we
had a binding or equality constraint involving Any.

Doing this yields some strange results, e.g. if overload resolution
results in a property declared as Any we end up discarding that solution
in favor of solutions that involve other overloads that are not declared
as Any but are also not actually better solutions (e.g. overloads that
are declared as function types).

We really want to retain both solutions in this case and allow the
ranking step of the solver to decide on the better choice.

Fixes rdar://problem/29374163, rdar://problem/29691909.
2016-12-20 13:38:14 -08:00
Slava Pestov
4ed17f0f63 AST: Add a new 'isBeingValidated' flag to replace a couple of other flags
Previously, validateDecl() would check if the declaration had an
interface type and use that as an indication not to proceed.

However for functions we can only set an interface type after
checking the generic signature, so a recursive call to validateDecl()
on a function would "steal" the outer call and complete validation.

For generic types, this meant we could have a declaration with a
valid interface type but no generic signature.

Both cases were problematic, so narrow workarounds were put in
place with additional new flags. This made the code harder to
reason about.

This patch consolidates the flags and establishes new invariants:

- If validateDecl() returns and the declaration has no interface
  type and the isBeingValidated() flag is not set, it means one
  of the parent contexts is being validated by an outer recursive
  call.

- If validateDecl() returns and the declaration has the
  isBeingValidated() flag set, it may or may not have an interface
  type. In this case, the declaration itself is being validated
  by an outer recursive call.

- If validateDecl() returns and the declaration has an interface
  type and the isBeingValidated() flag is not set, it means the
  declaration and all of its parent contexts are fully validated
  and ready for use.

In general, we still want name lookup to find things that have an
interface type but are not in a valid generic context, so for this
reason nominal types and associated types get an interface type as
early as possible.

Most other code only wants to see fully formed decls, so a new
hasValidSignature() method returns true iff the interface type is
set and the isBeingValidated() flag is not set.

For example, while resolving a type, we can resolve an unqualified
reference to a nominal type without a valid signature. However, when
applying generic parameters, the hasValidSignature() flag is used
to ensure we error out instead of crashing if the generic signature
has not yet been formed.
2016-12-19 01:38:23 -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
Slava Pestov
a384b2a677 Don't call VarDecl::getType() on deserialized VarDecls 2016-12-15 22:46:15 -08:00
Slava Pestov
30c4235193 Sema: Horrific simulation of Swift 3 bug with argument labels for Swift 3 mode
In Swift 3.0.1, argument labels are ignored when calling a function
having a single parameter of 'Any' type. That is, if we have:

func foo(_: Any) {}

Both of the following were accepted in a no-assert build (an assert
build would crash, but the GM builds of Xcode ship with asserts off):

foo(123)
foo(data: 123)

This behavior was fixed by 578e36a7e1,
but unfortunately we have to revert to the old behavior *and* defeat
the assertion when in Swift 3 mode.

Swift 4 mode still has the correct behavior, where the second call
'foo(data: 123)' produces a diagnostic.

Now, I have to pour myself a strong drink to forget this ever happened.

Fixes <rdar://problem/28952837>.
2016-12-14 01:45:14 -08:00
Slava Pestov
3ede1ab205 Sema: New implementation of SE-0110
Fix matchTypes() to be more careful about stripping off ParenType
sugar, in order to match the behavior outlined in SE-0110.

Note that the new logic only executes in Swift 4 mode; there's
no functional change here in Swift 3 mode.

This makes a second copy of the tuple_arguments test:

- Compatibility/tuple_arguments is a test for Swift 3, updated to
  note differences with Swift 3.

- Constraints/tuple_arguments has been updated for the new Swift 4
  mode behavior.

Fixes <rdar://problem/27383557>.
2016-12-13 23:20:16 -08:00
Slava Pestov
aaaded5b11 AST: Remove TypeBase::isEmptyExistentialComposition()
This is made redundant by TypeBase::isAny().
2016-12-04 21:15:03 -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
7cfe0e6401 Sema: getType() => getInterfaceType() 2016-11-29 03:05:27 -07: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
e20464a02c [Constraint solver] Remove 'type member' constraint.
Only some fallback code in the for-each binding checking code was
using this constraint. Implement those checks more directly.
2016-11-06 23:14:15 -08: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
swift-ci
675f70e04f Merge pull request #5568 from DougGregor/allow-member-int-eq 2016-10-31 16:55:57 -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
Alex Hoppen
b0e67da844 [TypeChecker] Add error message when accessing a type's destructor
Provide error messages when the destructor is accessed using foo.deinit
instead of crashing

This resolves SR-2652 and SR-3043
2016-10-30 19:43:57 +00: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
Doug Gregor
4cc41e5e64 [Constraint solver] Perform the "occurs" check properly.
We've been performing the "occurs" check when computing potential
bindings for type variables, but we weren't actually performing the
check for bindings that *must* occur. Perform the occurs check before
binding type variables, which fixes a few crashers and is far more principled.

Note that this obviates the need for tracking the type variables we've
substituted in simplifyType(), so simplify that as well.

Fixes rdar://problem/27879334 / SR-2351.
2016-10-25 13:32:06 -07:00
Doug Gregor
b484cbb6b9 [Constraint solver] Eliminate TypeMatchKind. NFC
It's no more than a subset of ConstraintKind with a bunch of
boilerplate to convert back and forth. Just use ConstraintKind.
2016-10-24 23:26:07 -07:00
Doug Gregor
a65812c558 [Constraint solver] Add ConstraintKind::BindToPointerType.
This matches up with TypeMatchKind::BindToPointerType.
2016-10-24 21:24:49 -07:00
Doug Gregor
d790291c48 [Constraint solver] Replace a use of simplifyType() with getFixedTypeRecursive()
The latter is cheaper to compute, and suitable for the
is-it-a-metatype check.
2016-10-24 13:19:58 -07:00
Doug Gregor
7f6654001b [Constraint solver] Handle 'bind' constraints lazily. 2016-10-23 22:27:33 -07:00
Doug Gregor
50cb31c5c4 [Constraint solver] Make 'defaultable' constraint creation lazy. 2016-10-23 00:15:50 -07:00
Doug Gregor
1b8d4399f3 [Constraint solver] Make optional object constraint construction lazy. 2016-10-23 00:15:50 -07:00
Doug Gregor
12b6894849 [Constraint solver] Address some of Mark's comments. NFC 2016-10-22 23:27:41 -07:00
Doug Gregor
d2cb83b4c7 [Constraint solver] Make checked cast constraint generation lazy.
Fixes rdar://problem/27148148.
2016-10-22 22:57:25 -07:00
Doug Gregor
af4d44e013 [Constraint solver] Lazily handle conformance-related constraints.
The code was already there for them; make sure we use it
consistently.
2016-10-22 22:20:03 -07:00
Doug Gregor
8451536e89 [Constraint solver] Lazily allocate DynamicTypeOf constraints. 2016-10-22 22:20:03 -07:00
Doug Gregor
ed71fd08c3 [Constraint solver] Lazily construct ApplicableFunction constraints. 2016-10-22 22:20:03 -07:00
Doug Gregor
41cd760682 [Constraint solver] Clean up existential metatype handling.
Our existential metatype conversion/conformance handling in the type
checker was tripped up the refactoring to lazily introduce
constraints, because it dependended on the otherwise-unused
TypeMatchKind::ConformsTo. Eliminate TypeMatchKind::ConformsTo and
simplify the code here.
2016-10-21 14:31:11 -07:00
Doug Gregor
7519d83007 [Constraint solver] Start lazily building relational constraints.
Start migrating the main ConstraintSolver::addConstraint() entrypoint
for relational constraints over to the model where it simplifies
first, then only creates a new constraint if the constraint it built
cannot be solved. This covers only the main relational
constraints--there are a number of other relational constraint kinds
to handle this way.
2016-10-21 14:03:56 -07:00
Doug Gregor
bdd27e9982 [Constraint solver] Lazily generate member constraints.
When adding a new member constraint, try to immediately simplify it,
generating a constraint when it cannot be resolved. Note that we also
generate constraints in top-level failure cases, so that the
diagnostics machinery can find it after-the-fact.
2016-10-21 14:03:56 -07:00
Doug Gregor
337558dcb9 [Constraint solver] Allocate 'restricted' constraints lazily.
When adding a 'restricted' constraint, go straight into the 'simplify'
operation. A new constraint will only be allocated and recorded if it
cannot be immediately simplified. To get here, be more rigorous about passing TMF_GenerateConstraints through simplifyRestrictedConstraint().
2016-10-21 14:03:56 -07:00
Doug Gregor
a4fc0aaad2 [Constraint solver] Don't reprocess constraints known to be unsolvable.
When we're creating a new constraint because we couldn't solve it (and
need to record the result), do so without trying to simplify it yet
again. It's just wasted work.
2016-10-21 14:03:56 -07:00
Doug Gregor
b69d01eef2 [Constraint solver] Remove unused 'class' constraints. NFC
We're not using these now. Someday, maybe, but it will be easy to
bring back this code if we find that we need it later.
2016-10-21 14:03:56 -07:00
Doug Gregor
483dfdcaa1 [Constraint solver] Remove 'archetype' constraint kind. NFC
Archetype constraints haven't been needed since we implemented SE-0091.
2016-10-21 14:03:56 -07:00
Doug Gregor
14a4fdbc50 [Constraint solver] Use OptionSet rather an 'unsigned'. NFC 2016-10-21 14:03:56 -07:00
Doug Gregor
e094adb50a [Constraint solver] Use custom addConstraint entrypoints consistently.
When adding constraints into the constraint system, don't immediately
allocate a Constraint and add it via the most-general
addConstraint(). Instead, go through a more specific entrypoint (e.g.,
addValueMemberConstraint, addRestrictedConstraint, etc.), so we can
start phasing out the general "add an already-formed constraint"
function. NFC
2016-10-21 14:03:56 -07:00
swift-ci
a4104d87d5 Merge pull request #5300 from DougGregor/constraint-solver-cleanups 2016-10-14 16:59:09 -07:00
Pavel Yaskevich
578e36a7e1 [Type Checker] SR-2505: Fix "Call arguments did not match up" assertion
Always check arguments of the tuple type against corresponding parameters,
otherwise for a single argument functions e.g. foo(_ a: Any) after SE-0046
type checker is going to produce incorrect solution.
2016-10-14 13:27:33 -07:00
Doug Gregor
2e800f4acc [Constraint system] Centralize the handling of "unsolved" returns in matchTypes. 2016-10-14 10:28:20 -07:00
Doug Gregor
49b833b51a [Type checker] Eliminate the 'literalConformanceProto' state on type variables.
The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).

(cherry picked from commit 6bdd9cfae5)
2016-10-13 16:22:01 -07:00