Skip to content

Commit d74f515

Browse files
committed
[CS] Handle placeholder in buildDisjunctionForOptionalVsUnderlying
If we encounter a placeholder type here, propagate it to the type variable, as we don't know whether it should be optional or non-optional, and we would have already recorded a fix for it. SR-15219 rdar://83352038
1 parent 11617b1 commit d74f515

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,6 +2605,16 @@ void ConstraintSystem::buildDisjunctionForOptionalVsUnderlying(
26052605
ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
26062606
locator->getPath().back().getKind() ==
26072607
ConstraintLocator::DynamicLookupResult);
2608+
assert(!ty->is<InOutType>());
2609+
auto rvalueTy = ty->getWithoutSpecifierType();
2610+
2611+
// If the type to bind is a placeholder, we can propagate it, as we don't know
2612+
// whether it can be optional or non-optional, and we would have already
2613+
// recorded a fix for it.
2614+
if (rvalueTy->isPlaceholder()) {
2615+
addConstraint(ConstraintKind::Bind, boundTy, ty, locator);
2616+
return;
2617+
}
26082618

26092619
// Create the constraint to bind to the optional type and make it the favored
26102620
// choice.
@@ -2615,8 +2625,7 @@ void ConstraintSystem::buildDisjunctionForOptionalVsUnderlying(
26152625
Type underlyingType;
26162626
if (auto *fnTy = ty->getAs<AnyFunctionType>())
26172627
underlyingType = replaceFinalResultTypeWithUnderlying(fnTy);
2618-
else if (auto *typeVar =
2619-
ty->getWithoutSpecifierType()->getAs<TypeVariableType>()) {
2628+
else if (auto *typeVar = rvalueTy->getAs<TypeVariableType>()) {
26202629
auto *locator = typeVar->getImpl().getLocator();
26212630

26222631
// If `ty` hasn't been resolved yet, we need to allocate a type variable to
@@ -2632,14 +2641,13 @@ void ConstraintSystem::buildDisjunctionForOptionalVsUnderlying(
26322641
addConstraint(ConstraintKind::OptionalObject, typeVar, underlyingType,
26332642
locator);
26342643
} else {
2635-
underlyingType = ty->getWithoutSpecifierType()->getOptionalObjectType();
2644+
underlyingType = rvalueTy->getOptionalObjectType();
26362645
}
26372646

26382647
assert(underlyingType);
26392648

26402649
if (ty->is<LValueType>())
26412650
underlyingType = LValueType::get(underlyingType);
2642-
assert(!ty->is<InOutType>());
26432651

26442652
auto *bindToUnderlying = Constraint::create(*this, ConstraintKind::Bind,
26452653
boundTy, underlyingType, locator);

test/Constraints/iuo.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,12 @@ struct CurriedIUO {
238238
let _: Int = CurriedIUO.silly(self)()
239239
}
240240
}
241+
242+
// SR-15219 (rdar://83352038): Make sure we don't crash if an IUO param becomes
243+
// a placeholder.
244+
func rdar83352038() {
245+
func foo(_: UnsafeRawPointer) -> Undefined {} // expected-error {{cannot find type 'Undefined' in scope}}
246+
let _ = { (cnode: AlsoUndefined!) -> UnsafeMutableRawPointer in // expected-error {{cannot find type 'AlsoUndefined' in scope}}
247+
return foo(cnode)
248+
}
249+
}

0 commit comments

Comments
 (0)