@@ -2189,43 +2189,54 @@ namespace {
21892189 }
21902190 }
21912191
2192- if (!varType)
2192+ if (!varType) {
21932193 varType = CS.createTypeVariable (CS.getConstraintLocator (locator),
21942194 TVO_CanBindToNoEscape);
21952195
2196+ // If this is either a `weak` declaration or capture e.g.
2197+ // `weak var ...` or `[weak self]`. Let's wrap type variable
2198+ // into an optional.
2199+ if (optionality == ReferenceOwnershipOptionality::Required)
2200+ varType = TypeChecker::getOptionalType (var->getLoc (), varType);
2201+ }
2202+
21962203 // When we are supposed to bind pattern variables, create a fresh
21972204 // type variable and a one-way constraint to assign it to either the
21982205 // deduced type or the externally-imposed type.
21992206 Type oneWayVarType;
22002207 if (bindPatternVarsOneWay) {
22012208 oneWayVarType = CS.createTypeVariable (
22022209 CS.getConstraintLocator (locator), TVO_CanBindToNoEscape);
2203- CS.addConstraint (
2204- ConstraintKind::OneWayEqual, oneWayVarType,
2205- externalPatternType ? externalPatternType : varType, locator);
2206- }
2207-
2208- // If there is an externally-imposed type.
22092210
2210- switch (optionality) {
2211- case ReferenceOwnershipOptionality::Required:
2212- // If the externally-imposed type is already optional,
2213- // let's not add optionality to the pattern.
2214- if (!externalPatternType ||
2215- !externalPatternType->getOptionalObjectType ()) {
2216- varType = TypeChecker::getOptionalType (var->getLoc (), varType);
2217- assert (!varType->hasError ());
2211+ // If there is an externally-imposed pattern type and the
2212+ // binding/capture is marked as `weak`, let's make sure
2213+ // that the imposed type is optional.
2214+ //
2215+ // Note that there is no need to check `varType` since
2216+ // it's only "externally" bound if this pattern isn't marked
2217+ // as `weak`.
2218+ if (externalPatternType &&
2219+ optionality == ReferenceOwnershipOptionality::Required) {
2220+ // If the type is not yet known, let's add a constraint
2221+ // to make sure that it can only be bound to an optional type.
2222+ if (externalPatternType->isTypeVariableOrMember ()) {
2223+ auto objectTy = CS.createTypeVariable (
2224+ CS.getConstraintLocator (locator.withPathElement (
2225+ ConstraintLocator::OptionalPayload)),
2226+ TVO_CanBindToLValue | TVO_CanBindToNoEscape);
22182227
2219- if (oneWayVarType) {
2220- oneWayVarType =
2221- TypeChecker::getOptionalType (var->getLoc (), oneWayVarType);
2228+ CS.addConstraint (ConstraintKind::OptionalObject,
2229+ externalPatternType, objectTy, locator);
2230+ } else if (!externalPatternType->getOptionalObjectType ()) {
2231+ // TODO(diagnostics): A tailored fix to indiciate that `weak`
2232+ // should have an optional type.
2233+ return Type ();
22222234 }
22232235 }
2224- break ;
22252236
2226- case ReferenceOwnershipOptionality::Allowed:
2227- case ReferenceOwnershipOptionality::Disallowed:
2228- break ;
2237+ CS. addConstraint (ConstraintKind::OneWayEqual, oneWayVarType,
2238+ externalPatternType ? externalPatternType : varType,
2239+ locator) ;
22292240 }
22302241
22312242 // If we have a type to ascribe to the variable, do so now.
0 commit comments