From d7a06284d362c7d94bdb6bad3fb5e0e3f9a49970 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 28 May 2024 15:45:03 -0700 Subject: [PATCH 1/2] [CSBindings] Optional object type variable should be connected to the optional If both sides of an `OptionalObject` constraint are un-inferred, their binding sets need to correctly reflect adjacency - a type variable that represents optional would get "object" as an adjacency through its potential binding (the binding is - "object" wrapped in a single level of optional) and "object" type variable needs to get its parent optional type variable added to its adjacency list explicitly. Without this it would be possible to prematurely pick "object" before its parent optional type variable. Resolves: https://github.com/apple/swift/issues/73207 Resolves: rdar://126960579 --- lib/Sema/CSBindings.cpp | 10 ++++++++++ test/stmt/foreach.swift | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 8eaeacc32d4df..09c2407bb32f2 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1671,6 +1671,16 @@ PotentialBindings::inferFromRelational(Constraint *constraint) { break; } + case ConstraintKind::OptionalObject: { + // Type variable that represents an object type of + // an un-inferred optional is adjacent to a type + // variable that presents such optional (`bindingTypeVar` + // in this case). + if (kind == AllowedBindingKind::Supertypes) + AdjacentVars.insert({bindingTypeVar, constraint}); + break; + } + default: break; } diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift index 043fafb0c0a02..a0745a41125f1 100644 --- a/test/stmt/foreach.swift +++ b/test/stmt/foreach.swift @@ -341,3 +341,13 @@ do { } } } + +// https://github.com/apple/swift/issues/73207 +do { + func test(_ levels: [Range]) { + for (i, leaves): (Int, Range) in levels[8 ..< 15].enumerated() { // Ok + _ = i + _ = leaves + } + } +} From 243cc1641dfab9ed5013749281214c15f496d82d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 28 May 2024 15:52:53 -0700 Subject: [PATCH 2/2] [CSSimplify] Don't pile up fixes for incorrect optional chaining If the contextual type propagated into the optional chain mismatches with the inner type formed from its member references and that inner type is a result of some fix, let's consider that un-salvageable and avoid producing additional "ignore contextual type" fixes which only lead to subpar solutions. --- lib/Sema/CSSimplify.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 6bb8b50f2d855..251f6e74818cb 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -5424,8 +5424,14 @@ bool ConstraintSystem::repairFailures( auto contextualTy = simplifyType(rhs)->getOptionalObjectType(); if (!lhs->getOptionalObjectType() && !lhs->hasTypeVariable() && contextualTy && !contextualTy->isTypeVariableOrMember()) { - conversionsOrFixes.push_back(IgnoreContextualType::create( - *this, lhs, rhs, getConstraintLocator(OEE->getSubExpr()))); + auto *fixLocator = getConstraintLocator(OEE->getSubExpr()); + // If inner expression already has a fix, consider this two-way + // mismatch as un-salvageable. + if (hasFixFor(fixLocator)) + return false; + + conversionsOrFixes.push_back( + IgnoreContextualType::create(*this, lhs, rhs, fixLocator)); return true; } }