Commit Graph

138 Commits

Author SHA1 Message Date
Pavel Yaskevich
c25952fa0d [CSStep] Conjunction: Drop element scores in ambiguity cases 2021-10-21 16:26:58 -07:00
Pavel Yaskevich
2b875c59fe [CSStep] Conjunction: Reset current/best score only on failure
Successful conjunction should preseve a score set by a follow-up
solve with outer context. Failure should reset the score back to
original one pre-conjunction.
2021-10-21 15:22:12 -07:00
Hamish Knight
d3618ef73c Merge pull request #39302 from hamishknight/iuo-a-refactoring 2021-10-15 23:35:47 +01:00
Pavel Yaskevich
2ee5b3005f [CSStep] Conjunction: Extract constraint system state restoration into a method
In preparation to handle ambiguities in the elements, it's useful
to extract the logic dealing with constraint system state restoration
into a separate logical entity.
2021-10-14 11:20:54 -07:00
Hamish Knight
287fa8e8de [CS] Refactor IUO handling
The current IUO design always forms a disjunction
at the overload reference, for both:

- An IUO property `T!`, forming `$T := T? or T`
- An IUO-returning function `() -> T!`, forming `$T := () -> T? or () -> T`

This is simple in concept, however it's suboptimal
for the latter case of IUO-returning functions for
a couple of reasons:

- The arguments cannot be matched independently of
  the disjunction
- There's some awkwardness when it comes e.g wrapping
  the overload type in an outer layer of optionality
  such as `(() -> T!)?`:
  - The binding logic has to "adjust" the correct
    reference type after forming the disjunction.
  - The applicable fn solving logic needs a special
    case to handle such functions.
- The CSApply logic needs various hacks such as
  ImplicitlyUnwrappedFunctionConversionExpr to
  make up for the fact that there's no function
  conversion for IUO functions, we can only force
  unwrap the function result.
  - This lead to various crashes in cases where
    we we'd fail to detect the expr and peephole
    the force unwrap.
  - This also lead to crashes where the solver
    would have a different view of the world than
    CSApply, as the former would consider an
    unwrapped IUO function to be of type `() -> T`
    whereas CSApply would correctly see the overload
    as being of type `() -> T?`.

To remedy these issues, IUO-returning functions no
longer have their disjunction formed at the overload
reference. Instead, a disjunction is formed when
matching result types for the applicable fn
constraint, using the callee locator to determine
if there's an IUO return to consider. CSApply then
consults the callee locator when finishing up
applies, and inserts the force unwraps as needed,
eliminating ImplicitlyUnwrappedFunctionConversionExpr.

This means that now all IUO disjunctions are of the
form `$T := T? or T`. This will hopefully allow a
further refactoring away from using disjunctions
and instead using type variable binding logic to
apply the correct unwrapping.

Fixes SR-10492.
2021-10-12 14:14:33 +01:00
Pavel Yaskevich
10fa811cee [CSStep] Conjunctions representing closures affect declaration context
While solving a conjunction that represents a (multi-statement) closure
constraint system should use such closure as its declaration context,
otherwise member lookup would produce incorrect results.
2021-10-08 10:08:03 -07:00
Pavel Yaskevich
c554fca5f7 [CSStep] Isolated conjunctions can't see outer solutions
All of the previously deduced solutions should be hidden
until isolated conjunction is successfully solved.
2021-10-08 10:08:03 -07:00
Pavel Yaskevich
98a6a8441c [CSStep] Conjunction: integrate isolation scope into snapshot
It helps to simply handling of outer constrants because they have
to be added to the constraint system before scope is created but
constraint graph have to get updated after to make sure that
incremental binding inference already knows about types inferred
from conjunction.
2021-10-08 10:08:02 -07:00
Pavel Yaskevich
405034f416 [CSStep] Always restore snapshot once isolated conjunction step is done
Turn `SolverSnapshot::restore` into a destructor to make sure that
constraints are always returned when optional is reset.
2021-10-08 10:08:01 -07:00
Pavel Yaskevich
1fa7e1d72c [CSStep] Fail conjunction if element attempt fails 2021-10-08 10:08:01 -07:00
Pavel Yaskevich
28d1bacdce [ConstraintSystem] Implement conjunction step
Iterate over all of the elements one-by-one and make sure that
each results in a single solution, otherwise fail the conjunction step.

Once all of the elements are handled either stop or,
if conjunction step has been performed in isolation,
return all of the outer constraints back to the system
and attempt to solve for outer context - that should
produce one or more solutions for conjunction to be
considered successfully solved.
2021-10-08 10:08:01 -07:00
Pavel Yaskevich
27275f6214 [CSStep] Add an implementation of ConjunctionStep
It behavies similar to `DisjunctionStep` but attempts all of
its elements unless there is an inference failure.
2021-10-08 10:08:00 -07:00
Alex Hoppen
c3ce40ddb6 [Sema] Use different solution vectors for ComponentSteps created by DependentComponentSplitterStep
Currently all `ComponentSteps` created by `DependentComponentSplitterStep` share the same `Solutions` vector. Because of this, the `ComponentStep`s might modify solutions created by previous `ComponentStep`s. Use different `Solutions` vectors for each `ComponentStep` to avoid sharing information between the `ComponentStep`s.

The concrete manifestation in the added test case is that the `Bar` overload gets added to `Solutions`, it’s score gets reduced by its `ComponentStep` original score, then the `Foo` overload gets added to `Solutions` and both solutions have their score decreased by the `OriginalScore` of `Foo`’s `ComponentStep`, causing `Bar`’s score to underflow.

Fixes rdar://78780840 [SR-14692]
2021-06-18 15:17:11 +02:00
Pavel Yaskevich
df7af0078f [CSBindings] Separate inference storage from final product usable by the solver
`PotentialBindings` lost most of its responsibilities,
and are no longer comparable. Their main purpose now
is binding and metadata tracking (introduction/retraction).

New `BindingSet` type is something that represents a set
of bindings at the current step of the solver.
2021-02-24 10:37:20 -08:00
Holly Borla
1ef2174bc2 Merge pull request #35025 from hborla/generic-overload-search-space
[ConstraintSystem] Implement heuristics for pruning the generic operator overload search space
2021-01-22 09:12:50 -08:00
Pavel Yaskevich
72888ca29b [ConstraintSystem] NFC: Extract PotentialBindings and auxiliary struct from ConstraintSystem
This opens up a posibility of using `PotentialBindings`
in `ConstraintGraphNode` and other places in `ConstraintGraph`.
2021-01-15 15:03:54 -08:00
Pavel Yaskevich
afec25271e [ConstraintSystem] Extract PotentialBinding and its auxiliary classes into a separate header
Create a new namespace - `swift::constraints::inference` and associate
`PotentialBinding` with it. This way it would be possible for constraint
graph to operate on `PotentialBinding(s)` in the future.
2021-01-15 15:03:24 -08:00
Holly Borla
a3957b987e [ConstraintSystem] Only do the work of partitioning the generic operator
overloads if generic operators are not going to be skipped.
2021-01-14 13:49:57 -08:00
Holly Borla
e24ac86eaf [ConstraintSystem] Cache applied disjunction constraints in the
constraint system to use later in DisjunctionStep.
2021-01-06 13:36:38 -08:00
Holly Borla
50212a0ea4 [ConstraintSystem] If the solver has already found a solution with a
disjunction choice that does not introduce conversions, check to see
if known argument types satisfy generic operator conformance requirements
early, and skip the overload choice if any requirements fail.

This helps the solver avoid exploring way too much search space when
the right solution involves a generic operator, but the argument types
are known up front, such as `collection + collection + collection`.
2021-01-06 13:36:38 -08:00
Pavel Yaskevich
8e4207e0d8 [ConstraintSystem] NFC: Simplify type var producer/step by referencing constraint system from bindings 2020-12-11 00:30:39 -08:00
Pavel Yaskevich
4e321320cf [CSStep] Don't retain multiple copies of the same bindings just for printing 2020-12-09 13:34:01 -08:00
Luciano Almeida
72b594b3fd [NFC][ConstraintGraph] Address fixme and switch CG::Component dependencies type to SmallVector<unsigned> 2020-11-09 19:49:29 -03:00
Holly Borla
423d6bdff0 [ConstraintSystem] Re-instate the operator type variable merging
hacks for now.

There's some more disjunction pruning work to be done before we can
remove this.
2020-10-29 19:49:47 -07:00
Holly Borla
b9e08b23fb [ConstraintSystem] Allow the solver to find other solutions after
successfully finding a solution by favoring operators already bound
elsewhere.

Favoring existing operator bindings often lets the solver find a solution
fast, but it's not necessarily the best solution.
2020-10-29 14:33:29 -07:00
Holly Borla
cb64d7f715 [ConstraintSystem] Fix build failures. 2020-10-15 13:30:46 -07:00
gregomni
34fa9c2786 Merge typevars of operators with shared decls after finding a solution to speed up further searching 2020-10-15 09:08:50 -07:00
Holly Borla
c84bd00819 [ConstraintSystem] Move getResolvedOverloads() from CSStep to ConstraintSystem. 2020-10-15 09:03:45 -07:00
gregomni
2edba9dfbd Instead of chaining binops, favor disjunctions with op overloads whose types match existing binding choices 2020-10-15 09:03:45 -07:00
Pavel Yaskevich
461eafff54 [ConstraintSystem] NFC: Move ConstraintSystem.h to include/swift/Sema 2020-10-08 10:45:47 -07:00
Pavel Yaskevich
6ba7ecb7c2 [ConstraintSystem] NFC: Move Constraint.h to include/swift/Sema 2020-10-08 10:45:32 -07:00
Pavel Yaskevich
ab951c208a [ConstraintSystem] NFC: Move ConstraintGraph{Scope}.h to include/swift/Sema 2020-10-08 10:42:58 -07:00
Robert Widmann
afe8f2b63f Drop TypeCheckerDebugConsumer 2020-05-18 22:49:55 -07:00
Robert Widmann
2bca013457 Move "isDebugMode" into ConstraintSystem
This eliminates the final source of mutation of the TypeCheckerFlags on the ASTContext.
2020-05-13 09:13:44 -07:00
Hamish Knight
b517aa13ef [CS] Explore additional bindings for fixes
Previously we could skip default literal or
supertype bindings if we had already found a solution
with fixes, which could lead us to miss bindings
that produce better diagnostics.

Tweak the logic such that we continue exploring if
we're in diagnostic mode.

Resolves SR-12399.
2020-03-28 17:03:41 -07:00
Pavel Yaskevich
0ecedfa5ea Revert "[ConstraintSystem] Make it possible to infer subtype bindings through argument conversions"
Reverts apple/swift#30006. It caused a regression that we'd like to address before re-landing:

```swift
struct X {
  var cgf: CGFloat
}

func test(x: X?) {
  let _ = (x?.cgf ?? 0) <= 0.5
}
```

This reverts commit 0a6b444b49.
This reverts commit ed255596a6.
This reverts commit 3e01160a2f.
This reverts commit 96297b7e39.

Resolves: rdar://problem/60185506
2020-03-07 20:16:56 -08:00
Hamish Knight
39d988da9c [CS] Remove ReturnAllDiscoveredSolutions flag
This is now no longer used.
2020-03-02 14:50:16 -08:00
Pavel Yaskevich
96297b7e39 [CSStep] Always attempt literal bindings in diagnostic mode
In case of contextual failures such bindings could produce
better solutions with fewer fixes.
2020-02-21 17:47:39 -08:00
Joe Groff
fb34044408 Merge remote-tracking branch 'origin/master' into master-next 2019-12-10 12:46:41 -08:00
Hamish Knight
a97328dcbf [CS] Use a MapVector to cache resolved overloads
Rather than maintaining a linked list of overload
choices, which must be linearly searched each time
we need to lookup an overload at a given callee
locator, use a MapVector which can be rolled back
at the end of a scope.

Remove ResolvedOverloadSetListItem in favor of
using SelectedOverload, which avoids the need to
convert between them when moving from
ConstraintSystem to Solution.
2019-12-05 14:47:52 -08:00
swift-ci
5fc1d17bf9 Merge remote-tracking branch 'origin/master' into master-next 2019-11-13 09:10:56 -08:00
Robert Widmann
d890b8ad41 Remove some save-and-restores
An awful pattern we use throughout the compiler is to save and restore global flags just for little things.  In this case, it was just to turn on some extra options in AST printing for type variables. The kicker is that the ASTDumper doesn't even respect this flag. Add this as a PrintOption and remove the offending save-and-restores.

This doesn't quite get them all: we appear to have productized this pattern in the REPL.
2019-11-13 07:37:12 -08:00
Robert Widmann
f4d333d066 Sink a bunch of semantic options into TypeCheckerOptions
Sink
- DebugConstraintSolver
- DebugConstraintSolverAttempt
- DebugConstraintSolverOnLines
- DebugGenericSignatures
- DebugForbidTypecheckPrefix
- SolverMemoryThreshold
- SolverBindingThreshold
- SolverShrinkUnsolvedThreshold
- SolverDisableShrink
- EnableOperatorDesignatedTypes
- DisableConstraintSolverPerformanceHacks
- SolverEnableOperatorDesignatedTypes
2019-11-12 22:39:49 -08:00
swift-ci
673447ad89 Merge remote-tracking branch 'origin/master' into master-next 2019-10-30 15:10:24 -07:00
Robert Widmann
972e755e9b Give ConstraintSystem's outlet to the ASTContext
Make it less tempting to ask for the type checker embedded into
ConstraintSystem by using the accessor to the ASTContext.
2019-10-30 12:55:42 -07:00
swift-ci
c1d8b1b6b4 Merge remote-tracking branch 'origin/master' into master-next 2019-08-16 22:49:39 -07:00
Doug Gregor
da267bf7ca [Constraint system] Switch TypeVariables to a SetVector.
There were a few places where we wanted fast testing to see whether a
particular type variable is currently of interest. Instead of building
local hash tables in those places, keep type variables in a SetVector
for efficient testing.
2019-08-16 14:13:15 -07:00
Jonas Devlieghere
b4d268e9e1 Migrate llvm::make_unique to std::make_unique
Now that we've moved to C++14, we no longer need the llvm::make_unique
implementation from STLExtras.h. This patch is a mechanical replacement
of (hopefully) all the llvm::make_unique instances in the swift repo.
2019-08-15 11:32:39 -07:00
Doug Gregor
3c69f6a305 [Constraint solver] Introduce one-way constraints.
Introduce the notion of "one-way" binding constraints of the form

  $T0 one-way bind to $T1

which treats the type variables $T0 and $T1 as independent up until
the point where $T1 simplifies down to a concrete type, at which point
$T0 will be bound to that concrete type. $T0 won't be bound in any
other way, so type information ends up being propagated right-to-left,
only. This allows a constraint system to be broken up in more
components that are solved independently. Specifically, the connected
components algorithm now proceeds as follows:

1. Compute connected components, excluding one-way constraints from
consideration.
2. Compute a directed graph amongst the components using only the
one-way constraints, where an edge A -> B indicates that the type
variables in component A need to be solved before those in component
B.
3. Using the directed graph, compute the set of components that need
to be solved before a given component.

To utilize this, implement a new kind of solver step that handles the
propagation of partial solutions across one-way constraints. This
introduces a new kind of "split" within a connected component, where
we collect each combination of partial solutions for the input
components and (separately) try to solve the constraints in this
component. Any correct solution from any of these attempts will then
be recorded as a (partial) solution for this component.

For example, consider:

  let _: Int8 = b ? Builtin.one_way(int8Or16(17)) :
  Builtin.one_way(int8Or16(42\
))

where int8Or16 is overloaded with types `(Int8) -> Int8` and
`(Int16) -> Int16`. There are two one-way components (`int8Or16(17)`)
and (`int8Or16(42)`), each of which can produce a value of type `Int8`
or `Int16`. Those two components will be solved independently, and the
partial solutions for each will be fed into the component that
evaluates the ternary operator. There are four ways to attempt that
evaluation:

```
  [Int8, Int8]
  [Int8, Int16]
  [Int16, Int8]
  [Int16, Int16]

To test this, introduce a new expression builtin `Builtin.one_way(x)` that
introduces a one-way expression constraint binding the result of the
expression 'x'. The builtin is meant to be used for testing purposes,
and the one-way constraint expression itself can be synthesized by the
type checker to introduce one-way constraints later on.

Of these two, there are only two (partial) solutions that can work at
all, because the types in the ternary operator need a common
supertype:

  [Int8, Int8]
  [Int16, Int16]

Therefore, these are the partial solutions that will be considered the
results of the component containing the ternary expression. Note that
only one of them meets the final constraint (convertibility to
`Int8`), so the expression is well-formed.

Part of rdar://problem/50150793.
2019-08-13 11:48:42 -07:00
Doug Gregor
dec149ce62 [Constraint graph] Move component sorting into connected components. 2019-08-11 21:49:08 -07:00