Commit Graph

265 Commits

Author SHA1 Message Date
Mark Lacey
8520b579db Merge pull request #11494 from rudkx/add-type-checker-perf-tests
Add type checker performance tests.
2017-08-16 21:32:06 -07:00
Mark Lacey
a133807601 Add type checker performance tests.
Add type checker performance tests under
validation-test/Sema/type_checker_perf.

Under ./fast/ we have tests that compile reasonably quickly now but at
one point did not.

Under ./slow/ we have tests that are still very slow to compile.

Some tests use %scale-test and others
-solver-expression-time-threshold to determine if they are scaling
well or compiling fast enough.

I've got several more tests gathered that have not yet been set up to
run in our test system. Those are forthcoming!

Further contributions welcome.

Thanks go to @xedin who helped collect most of the test cases.
2017-08-16 21:02:50 -07:00
Huon Wilson
10cc96b781 [validation-test] Add some type checker scale-tests. 2017-08-15 17:38:51 -07:00
Alex Hoppen
f8c2692f79 Introduce special decl names
Special DeclNames represent names that do not have an identifier in the
surface language. This implies serializing the information about whether
a name is special together with its identifier (if it is not special)
in both the module file and the swift lookup table.
2017-07-11 19:04:13 +02:00
Robert Widmann
71bf312a25 Migrate the rest of the tests to %empty-directory 2017-06-04 11:08:39 -07:00
Pavel Yaskevich
5998cd645f [ConstraintSolver] Penalize conversions from String to UnsafePointer
There are possible situations when we find solutions with String
and String -> UnsafePointer conversions at the same time for
expressions with default string literals. In order to disambiguite
such situations let's prefer solutions without String -> UnsafePointer
conversions if possible.
2017-06-01 14:43:43 -07:00
Pavel Yaskevich
1bc7a1edb9 [ConstraintSolver] Skip generic overloads only if non-generic choices produce higher score solutions
Restrict skipping of the generic overloads only to the situations
when non-generic solution doesn't have any restrictions/fixes, because
there is a possibility that generic overload could produce a better
solution.

Resolves: rdar://problem/32204609.
2017-06-01 14:43:43 -07:00
Mark Lacey
bc7dff5c9f Revert "Re-instate "Improve disjunction selection""
This reverts commit
ecfa406fc5, which was reinstating
3c5b393e0c.

It does not revert one test change from that commit, because
inexplicably one of the tests is still failing, probably due to some
other changes that have happened since. I'm leaving a ticket open to
investigate.

I've added one of the new cases that is failing as a result of this
change.

This is being reverted not because of bugs in this particular commit,
but because it seems to be exposing other bugs in the type checker that
are resulting in source compatibility problems. We need to shake these
other bugs out of the type checker before bringing this change back.
2017-05-15 11:27:11 -07:00
Mark Lacey
ecfa406fc5 Re-instate "Improve disjunction selection"
Thie reinstates 3c5b393e0c, which was
backed out due to it exposing an ambiguous expression in a recent stdlib
commit.
2017-04-29 17:53:13 -07:00
Mark Lacey
1de530e229 Revert "Improve disjunction selection" 2017-04-29 10:45:15 -07:00
Mark Lacey
3c5b393e0c [Constraint solver] Rework how we select the next disjunction to visit.
We previously used a simple heuristic of visiting the disjunction with
the fewest number of elements in it.

Instead, this commit introduces a new way to select the best disjunction
to explore based on attempting disjunctions based on either how much
information we have about the associated type variables (e.g. how many
of the arguments of a function call in the case of bind overload
disjunctions) or by other criteria that help constraint the search or
split the connected components (e.g. coercions and calls to
initializers).

A key part of the improvement here is allowing the type checker to
attempt bindings of types to type variables when there are still
argument conversion constraints between type variables in the
system. The insight here is if there are no other constraints blocking
an attempt to bind types and we have types to try, we will be able to
test those types against active conformance constraints and potentially
fail much earlier while solving.

Visiting disjunctions in a different order exposed some other problems
with the type checker including a couple cases where map is used that
are now considered ambiguous due to problems in how we are ranking
solutions.

I measured an 11-13% reduction in type checking time for the standard
library using a release build of the compiler.
2017-04-28 00:50:16 -07:00
Mark Lacey
e4f19a10c2 [Constraint solver] Type checker perf test with mixed dictionary/closures.
This is now compiling reasonably quickly (rather than "expression was
too complex"), so ensure it does not regress.
2017-04-16 09:45:20 -07:00
Mark Lacey
e19ab8077a [Constraint solver] Enable a type checker performance test.
This now passes with constraint propagation enabled.
2017-04-16 08:50:37 -07:00
Mark Lacey
ee7bedde3f Remove -O from a couple type checker perf tests, and add another test.
We don't need -O here. The new test is another known failure.
2017-04-11 23:55:57 -07:00
Mark Lacey
81fca31ef4 Add a typecheck perf test for inferring array-of-tuples. 2017-02-23 12:39:32 -08:00
Mark Lacey
b026a07fd8 Add a scale-test counter for expression type checking.
Also add the first example of using the counter to test for
known-exponential typechecking behavior for nil-coalescing.
2017-02-23 12:08:30 -08:00
Doug Gregor
40b6764e80 [Constraint solver] Handle disjunctions as separate connected components.
The constraint graph models type variables (as the nodes) and
constraints (as the multi-edges connecting nodes). The connected
components within this (multi-)graph are independent subproblems that
are solved separately; the results from each subproblem are then
combined. The approach helps curtail exponential behavior, because
(e.g.) the disjunctions/type variables in one component won't ever be
explored while solving for another component

This approach assumes that all of the constraints that cannot be
immediately solved are associated with one or more type
variables. This is almost entirely true---constraints that don't
involve type variables are immediately simplified.

Except for disjunctions. A disjunction involving no type variables
would not appear *at all* in the constraint graph. Worse, it's
independence from other constraints could not be established, so the
constraint solver would go exponential for every one of these
constraints. This has always been an issue, but it got worse with the
separation of type checking of "as" into the "coercion" case and the
"bridging" case, which introduced more of these disjunctions. This led
to counterintuitive behavior where adding "as Foo" would cause the
type checking to take *more* time than leaving it off, if both sides
of the "as" were known to be concrete. rdar://problem/30545483
captures a case (now in the new test case) where we saw such
exponential blow-ups.

Teach the constraint graph to keep track of "orphaned" constraints
that don't reference any type variables, and treat each "orphaned"
constraint as a separate connected component. That way, they're solved
independently.

Fixes rdar://problem/30545483 and will likely curtain other
exponential behavior we're seeing in the solver.
2017-02-20 17:18:18 -08:00
Doug Gregor
fbb7dcf971 Replace concrete init(stringInterpolationSegment:)'s with generic ones
Remove 16 concrete init(stringInterpolationSegment:) overloads and
replace them with 3 generic overloads, significantly reducing the
exponential blow-up from larger string interpolations.

Fixes rdar://problem/29389887.
2017-02-08 21:01:09 -08:00
Doug Gregor
e387361194 Revert "Replace concrete init(stringInterpolationSegment:)'s with generic ones"
This reverts commit f6cac54606.
2017-02-08 13:38:11 -08:00
Jordan Rose
37774eb97e Fix the TypeChecker's omitNeedlessWords to use interface types. (#7193)
...avoiding a crash when trying to detect near misses of protocol
requirements. Unfortunately I can't come up with a test case for the
VarDecl changes; everything I try seems to already work. But using
interface types is more correct anyway.

https://bugs.swift.org/browse/SR-3812
2017-02-02 14:26:29 -08:00
Doug Gregor
f6cac54606 Replace concrete init(stringInterpolationSegment:)'s with generic ones
Remove 16 concrete init(stringInterpolationSegment:) overloads and
replace them with 3 generic overloads, significantly reducing the
exponential blow-up from larger string interpolations.

Fixes rdar://problem/29389887.
2017-01-27 21:54:59 -08:00
Jordan Rose
7c8117301a In Swift 3 mode, allow "tuple unsplatting" in certain cases. (#7077)
Swift 3.0 allowed constructing an enum or calling a function-typed
property with multiple arguments even when a single argument of tuple
type was expected. Emulate that in Swift 3 mode by wrapping in an
extra level of parentheses when the situation comes up.

Last vestiges of fallout from SE-0110. Hopefully last, anyway. A nice
follow-up to this commit might be to /warn/ in Swift 3 mode when this
happens.

rdar://problem/30171399
2017-01-27 11:19:07 -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
Jordan Rose
49e6c06eef [validation-test] Remove "REQUIRES: asserts" from /fixed/ crash cases. (#6156) 2016-12-08 19:06:32 -08:00
Mark Lacey
1342223894 Merge pull request #6057 from xedin/rdar28235248
[QoI] When adding archetype requirements don't expect all of the members to be resolved
2016-12-07 19:37:58 -08:00
Slava Pestov
a1c213d4ee Update a diagnostic string in a -verify test
The old diagnostic was misleading; the closure really does take
one argument, but we're _returning_ a value that doesn't match
the contextual return type. And the suggestion to wrap the
argument in parens makes no sense either.

The new diagnostic is totally useless, but at least isn't not
misleading.
2016-12-07 14:16:43 -08:00
Pavel Yaskevich
91e8a0ccdb [QoI] When adding archetype requirements don't expect all of the members to be resolved
Some of the type members might be unresolved because they are misspelled or
do not exist (represented by DependentMemberType), so when trying to add
requirements to the nested types don't expect that all of the members have
their associated types resolved.

Resolves: <rdar://problem/28235248>.
2016-12-03 23:19:51 -08:00
Slava Pestov
4ebac86895 AST: Type::subst(): try harder to preserve sugar
If a sugared type desugars to a substitutable type, we would
return the replacement type without the sugar. I think in
practice this meant that ParenType would be lost sometimes.

Preserving this correctly is required for an upcoming CSDiag
change.

Note that there's a minor source-breaking change with enum
case constructors here. I've filed <rdar://problem/27261929>
to track sorting it out in Swift 3 mode.

Also an upcoming patch fixes another related issue and adds more
tests for case constructors.
2016-11-29 03:05:28 -07:00
xedin
2f3b5ad318 [QoI] Handle coercions involving ImplicitlyUnwrappedOptional<T> as 'from' type (#5900)
Add a case to ExprRewriter.coerceToType which tries to look through
ImplicitlyUnwrappedOptional<T> and apply 'to-value' transformation
before coercing to required 'to' type.

Resolves: <rdar://problem/28023899>.
2016-11-29 16:08:34 +09:00
Pavel Yaskevich
d111e9b4be [Diagnostics] When building a subscript don't assume that overload is always present
This handles situation when overload for the subscript hasn't been resolved
by constraint solver, such might happen, for example, if solver was allowed to
produce solutions with free or unresolved type variables (e.g. when running diagnostics).

Resolves: <rdar://problem/27329076>, <rdar://problem/28619118>, <rdar://problem/2778734>.
2016-11-28 19:18:44 -08:00
David Farler
b7d17b25ba Rename -parse flag to -typecheck
A parse-only option is needed for parse performance tracking and the
current option also includes semantic analysis.
2016-11-28 10:50:55 -08:00
Pavel Yaskevich
965d2d6d87 [QoI] Coerce tuple type elements to RValue before erasure
When trying to convert tuple type to existential look through
it's elements and convert found LValues to RValues (via load)
before applying erasure.

Resolves: <rdar://problem/27575060>.
2016-11-21 00:42:45 -08:00
Doug Gregor
dc70877465 Merge pull request #5834 from xedin/rdar27464577
[TypeChecker] Don't assume that cast expressions always have sub-expressions
2016-11-18 13:00:01 -08:00
Doug Gregor
585e065c90 Handle requirement environments with concrete same-type constraints.
It is possible to have requirement environments in which substitution
of the conforming type for Self into the requirement's signature would
result in substituted same-type requirements that no longer involve
type parameters. This triggered an assertion in the construction of
the requiremet environement; instead, just drop the requirement
because it is no longer interesting. Witness matching will simply fail
later one.

With this fix, it now because possible to add generic requirements to
a protocol that were unsatisfiable for certain models. For example,
the following protocol:

    protocol P {
      associatedtype A
      associatedtype B

      func f<T: P>(_: T) where T.A == Self.A, T.A == Self.B
    }

can only be satisfied by conforming types for which Self.A ==
Self.B. SE-0142 will introduce a proper way to add such requirements
onto associated types. This commit makes any such attempt to add
requirements onto "Self" (or its associated types) ill-formed, so we
will reject the protocol P above with a diagnostic such as:

    error: instance method requirement 'f' cannot add constraint
    'Self.A == Self.B' on 'Self'

Fixes rdar://problem/29075927.
2016-11-17 23:53:10 -08:00
Pavel Yaskevich
351ae5bde9 [TypeChecker] Don't assume that cast expressions always have sub-expressions
When cast expressions (conditional or forced downcasts) are part
of the closure expression with invalid parameters or return type,
they are not going be to folded by PreCheckExpression, which means
that they are not going to have sub-expression (from) set.

Resolves: <rdar://problem/27464577>.
2016-11-16 23:58:03 -08:00
Pavel Yaskevich
ad0b1c7383 [TypeChecker] Disallow solutions with free type variables when finalizing witness match
Disallows solutions containing free type variables on the final step of
witness matching, because that would yield incorrect results when witness
type has free type variables as well.

Resolves: <rdar://problem/27249691>.
2016-11-15 13:43:31 -08:00
Pavel Yaskevich
28777a3c7e [Diagnostics] Coerce closure arguments to contextual type only if it is valid
Modify TypeChecker::coerceParameterListToType to always validate and consider only
valid contextual types (contains: no undefined, error, or type variables etc.) for
argument type coercion, such logic prevents erasure of important explicitly specified
type information attached to parameters of the closure expressions being diagnosed.

Resolves: SR-2994.
2016-11-11 10:31:30 -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
Mark Lacey
c7f448f972 Do not assume Set/Dictionary are always bound generic types.
In cases where we cannot infer the types they won't be, so we don't want
to just cast to BoundGenericType when we see these.

Fixes rdar://problem/28317710 and at least one dup (and I think a few
more).
2016-11-03 00:42:03 -07:00
Doug Gregor
33ad7a8473 [Constraint solver] Remove erroneous constraints from the constraint graph.
When a constraint fails, we retire it... but we also need to remove it
from the constraint graph. Otherwise, we break invariants when
diagnostic generation attempts to continue simplification.

Fixes rdar://rdar28145033.
2016-10-27 21:35:14 -07:00
Doug Gregor
2ce30d32c4 Add a few more type-checker crasher addressed by the "occurs" check.
For rdar://problem/19343997, rdar://problem/19924870, and rdar://problem/20771765.
2016-10-25 23:26:07 -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
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
d2cb83b4c7 [Constraint solver] Make checked cast constraint generation lazy.
Fixes rdar://problem/27148148.
2016-10-22 22:57:25 -07:00
Mark Lacey
f95e5db2c6 Add a crasher for rdar://problem/27017206. 2016-10-15 10:42:24 -07:00
Mark Lacey
dda3521ba4 Add a crasher for rdar://problem/27249691. 2016-10-15 10:32:34 -07:00
Mark Lacey
b7b8245e1f Add a crasher for rdar://problem/28023899. 2016-10-15 10:14:50 -07:00
Mark Lacey
a3dff973ea Add some more known type checker crashers.
Minimized tests from:
  rdar://problem/28145033
  rdar://problem/28221883
  rdar://problem/28235248
2016-10-14 23:53:38 -07:00
Mark Lacey
bea2aabf11 Add a crasher for rdar://problem/28619118. 2016-10-12 11:32:43 -07:00
Doug Gregor
c2b9759cd3 Simplify ConstraintSystem::getFixedTypeRecursive and use it consistently.
We had a few places that were performing ad hoc variants of
ConstraintSystem::getFixedTypeRecursive(); simplify it's interface so
we can use it everywhere consistently. Fixes rdar://problem/27261929.
2016-10-11 17:08:52 -07:00