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