First problem - the logic used constraint system, which shouldn't
be required, second - it expects the type to be always present in
`ContextualTypeInfo` but that's not the case for some patterns.
Resolves: rdar://131819800
Previously we could end up with a
ContextualMismatch fix and a MissingConformance fix
for different elements of the `matchTypes` disjunction,
leading to an ambiguity. Instead, avoid recording
the ContextualMismatch if we're matching an
existential, and tweak the MissingConformance
failure to have a custom diagnostic for
EnumElementPattern matching.
Prior to the introduction of typed throws, a `do..catch` always had a caught
error type of `any Error`, even if there were no throwing sites within
the `do` body. With typed throws, such a `do..catch` would have a
caught error type of `Never`, because it never throws. Unfortunately,
this causes code like the following to produce an error, because
`Never` cannot be pattern-matched to `HomeworkError.forgot`:
func test() {
do {
try nonthrowing()
} catch HomeworkError.forgot {
} catch {
}
}
For source-compatibility reasons, adjust the caught error type to
`any Error` in this case, so we continue to accept the code above.
Don't do this adjustment under `FullTypedThrows`, because it's only
there for compatibility.
Fixes rdar://121526201.
For `CTP_Initialization`, there's no contextual
type to record if the pattern is not a
`TypedPattern`. As such, tweak
`RequirementFailure::getDeclRef` to handle this
case.
We probably ought to reconsider how we handle
contextual types here, using a ContextualType
locator when there is no contextual type recorded
seems a bit weird, though in most cases we want
to treat initializations the same regardless of
if a TypedPattern was used. For now I'm leaving
that as future work.
rdar://111009224
Previously if the cast was unresolved, we would
emit a warning and bail with `nullptr`. This is
wrong, because the caller expects a `nullptr`
return to mean we emitted an error. Change the
diagnostic to an error to fix this. This may
appear source breaking, but in reality previously
we were failing to add the cast at all in this case,
which lead to a crash in SILGen. We really do
want to reject these cases as errors, as this
will give us a better opportunity to fall back to
type-checking as ExprPatterns, and better matches
the constraint solver type-checking.
Also while we're here, change the diagnostic for
the case where we don't have an existential context
type from the confusing "enum doesn't have member"
diagnostic to the pattern mismatch diagnostic.
rdar://107420031
Previously we would wait until CSApply, which
would trigger their type-checking in
`coercePatternToType`. This caused a number of
bugs, and hampered solver-based completion, which
does not run CSApply. Instead, form a conjunction
of all the ExprPatterns present, which preserves
some of the previous isolation behavior (though
does not provide complete isolation).
We can then modify `coercePatternToType` to accept
a closure, which allows the solver to take over
rewriting the ExprPatterns it has already solved.
This then sets the stage for the complete removal
of `coercePatternToType`, and doing all pattern
type-checking in the solver.
This shouldn't be necessary, we should be able to
solve with type variables instead. This makes sure
we don't end up with weird special cases that only
occur when an external type is present.
It's not clear to me why it was ever set this way,
but it prevents IUOs from working with the match
operator. Unset it, and let pre-checking correctly
assign it a `FunctionRefKind::SingleApply`.
In cases like `.<name>(_)`, the `_` sub-pattern should not assume
locator of the parent paren, just like it doesn't in case of tuple
i.e. `.<name>(_, ...)` where each element gets a `PatternMatch(<elt>)`
locator.
when we have an optional type. This uncovered an error with unresolved member lookup where we allowed an unresolved value member constraint to fail if lookup failed in an optional type wrapping a type variable.
This resolves SR-13357.
The VDUC was missing a class of AST nodes that can bind variables:
patterns in switch statements. For these, it was falling back to
requesting a simple replacement of the bound variable name with _. But
for patterns, this means there's a two-step dance the user has to go
through where the first fixit does this:
.pattern(let x) -> .pattern(let _)
Then a second round of compilation would emit a fixit to do this:
.pattern(let _) -> .pattern(_)
Instead, detect "simple" variable bindings - for now, variable patterns
that are immediately preceded by a `let` or `var` binding pattern - and
collapse two steps into one.
Resolves rdar://47240768
Currently `generateInitPatternConstraints` assumes that all
patterns have types but it's not the case for patterns that
e.g. reference unknown types or have other structural issues.
Let's fail `generateInitPatternConstraints` if constraint
generation fails.
Resolves: rdar://problem/64157451
Instead of requiring sub-classes of `ContextualMismatch` to implement
`diagnoseForAmbiguity` let's implement it directly on `ContextualMismatch`
itself and check whether all of the aggregated fixes have same types on
both sides and if so, diagnose as-if it was a single fix.
Instead of assuming type of its sub-pattern `is` should be able
to infer type from context and then propagate that to the sub-pattern
via conversion. This enables support for patterns like `.foo(_ as Foo)`
where `is` would have a type different from `_` which gets inferred
from associated value of `foo` and converted to `Foo` that becomes
a type of `_` pattern.
Resolves: rdar://problem/63510989
Consider following example:
```swift
enum E {
case foo((x: Int, y: Int))
case bar(x: Int, y: Int)
}
func test(e: E) {
if case .foo(let x, let y) = e {}
if case .bar(let tuple) = e {}
}
```
Both of `if case` expressions have to be supported:
1. `case .foo(let x, let y) = e` allows a single tuple
parameter to be "destructured" into multiple arguments.
2. `case .bar(let tuple) = e` allows to match multiple
parameters with a single tuple argument.
Resolves: rdar://problem/60061646
Since constraint system now handles pattern matching it has
to preverse label matching semantics which existed in original
code: if pattern element has a label it has to match the one
in the tuple type it's matched against.
Resolves: rdar://problem/60048356
Generate a complete set of constraints for EnumElement patterns, e.g.,
case let .something(x, y)
Most of the complication here comes from the implicit injection of optionals,
e.g., this case can be matched to an optional of the enum type of which
`something` is a member. To effect this change, introduce a locator for
pattern matching and use it to permit implicit unwrapping during member
lookup without triggering an error.
Note also labels are dropped completely when performing the match,
because labels can be added or removed when pattern matching. Label
conflict are currently diagnosed as part of coercePatternToType, which
suffices so long as overloading cases based on argument labels is not
permitted.
The primary observable change from this commit is in diagnostics: rather
than diagnostics being triggered by `TypeChecker::coercePatternToType`,
diagnostics for matching failures here go through the diagnostics machinery
of the constraint solver. This is currently a regression, because
there are no custom diagnostics for pattern match failures within the
constraint system. This regression will be addressed in a subsequent
commit; for now, leave those tests failing.
all cases of missing generic parameters.
In `ComponentStep::take` when there are no bindings or disjunctions, use hole
propagation to default remaining free type variables that aren't for generic
parameters and continue solving. Rather than using a defaultable constraint for
holes, assign a fixed type directly when we have no bindings to try.
Patch up all the places that are making a syntactic judgement about the
isInvalid() bit in a ValueDecl. They may continue to use that query,
but most guard themselves on whether the interface type has been set.
This is an amalgam of simplifications to the way VarDecls are checked
and assigned interface types.
First, remove TypeCheckPattern's ability to assign the interface and
contextual types for a given var decl. Instead, replace it with the
notion of a "naming pattern". This is the pattern that semantically
binds a given VarDecl into scope, and whose type will be used to compute
the interface type. Note that not all VarDecls have a naming pattern
because they may not be canonical.
Second, remove VarDecl's separate contextual type member, and force the
contextual type to be computed the way it always was: by mapping the
interface type into the parent decl context.
Third, introduce a catch-all diagnostic to properly handle the change in
the way that circularity checking occurs. This is also motivated by
TypeCheckPattern not being principled about which parts of the AST it
chooses to invalidate, especially the parent pattern and naming patterns
for a given VarDecl. Once VarDecls are invalidated along with their
parent patterns, a large amount of this diagnostic churn can disappear.
Unfortunately, if this isn't here, we will fail to catch a number of
obviously circular cases and fail to emit a diagnostic.
Use the adjacencies implied by the constraints of a node rather than looking
at the "adjacency" list, and try to simplify this code path a bit. The
diagnostic change is because we are now uniformly recording the
members of the equivalence class.