Introduce a new expression type for representing the result of an unresolved member chain. Use this expression type instead of an implicit ParenExpr for giving unresolved member chain result types representation in the AST during type checking.
In order to give unresolved member chain result types visibility in the AST, we inject an implicit ParenExpr in CSGen that lives only for the duration of type checking, and gets removed during solution application.
Remove the tracking of unresolved base types from the constraint system, and place it entirely within the generation phase. We have other ways of getting at the base types after generation.
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.
Unlike \keypath expressions, only the property components of #keypath
expressions were being resolved, so index wouldn't pick up references for their
qualifying types.
Also fixes a code completion bug where it was reporting members from the Swift
rather than ObjC side of bridged types.
Resolves rdar://problem/61573935
bindSwitchCasePatternVars() was introduced as a simpler way to wire up
the "parent" links for case variables with same-named case variables
from the previous case item, and is used in the function builders code
to handle switch statements. It duplicated some logic from the
statement checker that did the same thing using a more complicated
algorithm.
Switch (ha ha) the logic in the statement checker over to using
bindSwitchCasePatternVars(), fixing a bug involving unresolved
patterns along the way, and remove the old code that incrementally
wired up the parent links. The resulting code is simpler and is
unified across the various code paths.
Unlike \keypath expressions, only the property components of #keypath
expressions were being resolved, so index wouldn't pick up references for their
qualifying types.
Also fixes a code completion bug where it was reporting members from the Swift
rather than ObjC side of bridged types.
Resolves rdar://problem/61573935
Since the two ExtInfos share a common ClangTypeInfo, and C++ doesn't let us
forward declare nested classes, we need to hoist out AnyFunctionType::ExtInfo
and SILFunctionType::ExtInfo to the top-level.
We also add some convenience APIs on (AST|SIL)ExtInfo for frequently used
withXYZ methods. Note that all non-default construction still goes through the
builder's build() method.
We do not add any checks for invariants here; those will be added later.
Rather than type-checking captures as separate declarations during
pre-check, generate constraints and apply solutions to captures in
the same manner as other pattern bindings within a constraint
system.
Fixes SR-3186 / rdar://problem/64647232.
Introduce 'TypeCheckSingleASTNode' mode that only type checks single body
element and dependent necessities (i.e. referencing ValueDecls and their
dependencies).
Renamed swift::typeCheckAbstractFunctionBodyAtLoc() to
swift::typeCheckASTNodeAtLoc(DeclContext *, SourceLoc). That type checks
innermost 'ASTNode' at the location. Also, 'TypeCheckSingleASTNode' mode
skips type checking any "body" of the node (i.e. BraceStmt elements for
function body, if statement body, closure body, etc.)
Added on-demand type checking using it:
- VarDecl in TapExpr
- ParamDecl in ClosureExpr
- Return type of ClosureExpr
- Binding value in control statements
(e.g. ForEachStmt, SwitchStmt, DoCatchStmt, etc.)
rdar://problem/63932852
With the constraint solver preferring backward scanning to forward
scanning, there is no need to point out the ambiguity: we will
always, consistently warn about backward scanning when it produced a
result that was different from the forward scan.
Whenever we form a call that relies on the deprecated "backward" scan,
produce a warning to note the deprecation along with a Fix-It to label
the parameter appropriately (and suppress the warning). For example:
warning: backward matching of the unlabeled trailing closure is
deprecated; label the argument with 'g' to suppress this warning
trailingClosureEitherDirection { $0 * $1 }
^
(g: )
To better preserve source compatibility, teach the constraint
solver to try both the new forward scanning rule as well as the
backward scanning rule when matching a single, unlabeled trailing
closure. In the extreme case, where the unlabeled trailing closure
matches different parameters with the different rules, and yet both
produce a potential match, introduce a disjunction to explore both
possibilities.
Prefer solutions that involve forward scans to those that involve
backward scans, so we only use the backward scan as a fallback.
SE-0248 changes the backward-scan matching behavior for the unlabeled
trailing closure into a forward scan. In circumstances where this
could silently change the meaning of a call to a particular
function, i.e., when there are two defaulted closure parameters such
that a given closure to match either one of them, produce an warning
that describes the change in behavior. For example:
t4.swift:2:24: warning: since Swift 5.3, unlabeled trailing
closure argument matches parameter 'x' rather than parameter 'z'
trailingClosureSingle2 { $0 }
^
t4.swift:2:24: note: label the argument with 'z' to retain the
pre-Swift 5.3 behavior
trailingClosureSingle2 { $0 }
^
(z: )
t4.swift:2:24: note: label the argument with 'x' to silence this
warning for Swift 5.3 and newer
trailingClosureSingle2 { $0 }
^
(x: )
t4.swift:1:6: note: 'trailingClosureSingle2(x:y:z:)' contains
defaulted closure parameters 'x' and 'z'
func trailingClosureSingle2(x: (Int) -> Int = { $0 } , y: (Int) ->
Int = { $0 }, z: (Int) -> Int = { $0 }) {}
^ ~
This explains the (rare) case where SE-0286 silently changes the
meaning of a program, offering Fix-Its to either restore the
pre-SE-0286 behavior or silence the warning, as appropriate.
Introsuce a new "forward" algorithm for trailing closures where
the unlabeled trailing closure argument matches the next parameter in
the parameter list that can accept an unlabeled trailing closure.
The "can accept an unlabeled trailing closure" criteria looks at the
parameter itself. The parameter accepts an unlabeled trailing closure
if all of the following are true:
* The parameter is not 'inout'
* The adjusted type of the parameter (defined below) is a function type
The adjusted type of the parameter is the parameter's type as
declared, after performing two adjustments:
* If the parameter is an @autoclosure, use the result type of the
parameter's declared (function) type, before performing the second
adjustment.
* Remove all outer "optional" types.
For example, the following function illustrates both adjustments to
determine that the parameter "body" accepts an unlabeled trailing
closure:
func doSomething(body: @autoclosure () -> (((Int) -> String)?))
This is a source-breaking change. However, there is a "fuzzy" matching
rule that that addresses the source break we've observed in practice,
where a defaulted closure parameter precedes a non-defaulted closure
parameter:
func doSomethingElse(
onError: ((Error) -> Void)? = nil,
onCompletion: (Int) -> Void
) { }
doSomethingElse { x in
print(x)
}
With the existing "backward" scan rule, the trailing closure matches
onCompletion, and onError is given the default of "nil". With the
forward scanning rule, the trailing closure matches onError, and there
is no "onCompletion" argument, so the call fails.
The fuzzy matching rule proceeds as follows:
* if the call has a single, unlabeled trailing closure argument, and
* the parameter that would match the unlabeled trailing closure
argument has a default, and
* there are parameters *after* that parameter that require an argument
(i.e., they are not variadic and do not have a default argument)
then the forward scan skips this parameter and considers the next
parameter that could accept the unlabeled trailing closure.
Note that APIs like doSomethingElse(onError:onCompletion:) above
should probably be reworked to put the defaulted parameters at the
end, which works better with the forward scan and with multiple
trailing closures:
func doSomethingElseBetter(
onCompletion: (Int) -> Void,
onError: ((Error) -> Void)? = nil
) { }
doSomethingElseBetter { x in
print(x)
}
doSomethingElseBetter { x in
print(x)
} onError: { error in
throw error
}
After the TypeLocs were removed here, the TypeRepr from the IsExpr was
the only thing providing access to syntactic information from the parent
IsExpr. In order to support this, it was possible to construct a bizarre
ConditionalCheckedCastExpr that contained both semantic and syntactic
information. This doesn't comport with the rest of the casting nodes,
which force you to pick one or the other.
Since we're rewriting an IsExpr into a EnumIsCaseExpr, let's just stash
the syntactic information there. This unblocks a bit of cleanup.
Detect that result type of the overload choice is l-value and preserve
that information through the forced unwrap operation so it's possible
to load the value implicitly during solution application.
Resolves: rdar://problem/61337704