Skip to content

Commit 51fb112

Browse files
authored
Merge pull request #31233 from LucianoPAlmeida/SR-12425-to-5-3
[5.3][SR-12425] Improving diagnostics for key path application on non-convertible root type
2 parents 2e0fdc6 + 6275b2c commit 51fb112

File tree

7 files changed

+99
-6
lines changed

7 files changed

+99
-6
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,9 @@ ERROR(expr_keypath_subscript_index_not_hashable, none,
580580
ERROR(expr_smart_keypath_application_type_mismatch,none,
581581
"key path of type %0 cannot be applied to a base of type %1",
582582
(Type, Type))
583+
ERROR(expr_keypath_root_type_mismatch, none,
584+
"key path with root type %0 cannot be applied to a base of type %1",
585+
(Type, Type))
583586
ERROR(expr_swift_keypath_anyobject_root,none,
584587
"the root type of a Swift key path cannot be 'AnyObject'", ())
585588
WARNING(expr_deprecated_writable_keypath,none,

lib/Sema/CSDiagnostics.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6224,3 +6224,15 @@ bool CoercionAsForceCastFailure::diagnoseAsError() {
62246224
.highlight(getSourceRange());
62256225
return true;
62266226
}
6227+
6228+
bool KeyPathRootTypeMismatchFailure::diagnoseAsError() {
6229+
auto locator = getLocator();
6230+
assert(locator->isKeyPathRoot() && "Expected a key path root");
6231+
6232+
auto baseType = getFromType();
6233+
auto rootType = getToType();
6234+
6235+
emitDiagnostic(diag::expr_keypath_root_type_mismatch,
6236+
rootType, baseType);
6237+
return true;
6238+
}

lib/Sema/CSDiagnostics.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,24 @@ class CoercionAsForceCastFailure final : public ContextualFailure {
20222022

20232023
bool diagnoseAsError() override;
20242024
};
2025+
2026+
/// Diagnose a key path root type that cannot be applied to an instance
2027+
/// base that has another type.
2028+
///
2029+
/// \code
2030+
/// func f(_ bar: Bar , keyPath: KeyPath<Foo, Int> ) {
2031+
/// bar[keyPath: keyPath]
2032+
/// }
2033+
/// \endcode
2034+
class KeyPathRootTypeMismatchFailure final : public ContextualFailure {
2035+
public:
2036+
KeyPathRootTypeMismatchFailure(const Solution &solution, Type lhs, Type rhs,
2037+
ConstraintLocator *locator)
2038+
: ContextualFailure(solution, lhs, rhs, locator) {}
2039+
2040+
bool diagnoseAsError() override;
2041+
};
2042+
20252043
} // end namespace constraints
20262044
} // end namespace swift
20272045

lib/Sema/CSFix.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,3 +1293,17 @@ AllowCoercionToForceCast::create(ConstraintSystem &cs, Type fromType,
12931293
return new (cs.getAllocator())
12941294
AllowCoercionToForceCast(cs, fromType, toType, locator);
12951295
}
1296+
1297+
bool AllowKeyPathRootTypeMismatch::diagnose(const Solution &solution,
1298+
bool asNote) const {
1299+
KeyPathRootTypeMismatchFailure failure(solution, getFromType(), getToType(),
1300+
getLocator());
1301+
return failure.diagnose(asNote);
1302+
}
1303+
1304+
AllowKeyPathRootTypeMismatch *
1305+
AllowKeyPathRootTypeMismatch::create(ConstraintSystem &cs, Type lhs, Type rhs,
1306+
ConstraintLocator *locator) {
1307+
return new (cs.getAllocator())
1308+
AllowKeyPathRootTypeMismatch(cs, lhs, rhs, locator);
1309+
}

lib/Sema/CSFix.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@ enum class FixKind : uint8_t {
251251

252252
/// A warning fix that allows a coercion to perform a force-cast.
253253
AllowCoercionToForceCast,
254+
255+
/// Allow key path root type mismatch when applying a key path that has a
256+
/// root type not convertible to the type of the base instance.
257+
AllowKeyPathRootTypeMismatch,
254258
};
255259

256260
class ConstraintFix {
@@ -1768,6 +1772,32 @@ class AllowCoercionToForceCast final : public ContextualMismatch {
17681772
ConstraintLocator *locator);
17691773
};
17701774

1775+
/// Attempt to fix a key path application where the key path type cannot be
1776+
/// applied to a base instance of another type.
1777+
///
1778+
/// \code
1779+
/// func f(_ bar: Bar , keyPath: KeyPath<Foo, Int> ) {
1780+
/// bar[keyPath: keyPath]
1781+
/// }
1782+
/// \endcode
1783+
class AllowKeyPathRootTypeMismatch : public ContextualMismatch {
1784+
protected:
1785+
AllowKeyPathRootTypeMismatch(ConstraintSystem &cs, Type lhs, Type rhs,
1786+
ConstraintLocator *locator)
1787+
: ContextualMismatch(cs, FixKind::AllowKeyPathRootTypeMismatch, lhs, rhs,
1788+
locator) {}
1789+
1790+
public:
1791+
std::string getName() const override {
1792+
return "allow key path root type mismatch";
1793+
}
1794+
1795+
bool diagnose(const Solution &solution, bool asNote = false) const override;
1796+
1797+
static AllowKeyPathRootTypeMismatch *
1798+
create(ConstraintSystem &cs, Type lhs, Type rhs, ConstraintLocator *locator);
1799+
};
1800+
17711801
} // end namespace constraints
17721802
} // end namespace swift
17731803

lib/Sema/CSSimplify.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3577,6 +3577,13 @@ bool ConstraintSystem::repairFailures(
35773577
break;
35783578
}
35793579

3580+
case ConstraintLocator::KeyPathRoot: {
3581+
conversionsOrFixes.push_back(AllowKeyPathRootTypeMismatch::create(
3582+
*this, lhs, rhs, getConstraintLocator(locator)));
3583+
3584+
break;
3585+
}
3586+
35803587
case ConstraintLocator::FunctionArgument: {
35813588
auto *argLoc = getConstraintLocator(
35823589
locator.withPathElement(LocatorPathElt::SynthesizedArgument(0)));
@@ -7829,8 +7836,9 @@ ConstraintSystem::simplifyKeyPathApplicationConstraint(
78297836
rootTy = getFixedTypeRecursive(rootTy, flags, /*wantRValue=*/false);
78307837

78317838
auto matchRoot = [&](ConstraintKind kind) -> bool {
7832-
auto rootMatches = matchTypes(rootTy, kpRootTy, kind,
7833-
subflags, locator);
7839+
auto rootMatches =
7840+
matchTypes(rootTy, kpRootTy, kind, subflags,
7841+
locator.withPathElement(LocatorPathElt::KeyPathRoot()));
78347842
switch (rootMatches) {
78357843
case SolutionKind::Error:
78367844
return false;
@@ -9392,6 +9400,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
93929400
case FixKind::SpecifyBaseTypeForContextualMember:
93939401
case FixKind::CoerceToCheckedCast:
93949402
case FixKind::SpecifyObjectLiteralTypeImport:
9403+
case FixKind::AllowKeyPathRootTypeMismatch:
93959404
case FixKind::AllowCoercionToForceCast: {
93969405
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
93979406
}

test/attr/attr_dynamic_member_lookup.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -811,9 +811,16 @@ internal var rightStructInstance: SR12425_R = SR12425_R()
811811

812812
public extension SR12425_R {
813813
subscript<T>(dynamicMember member: WritableKeyPath<SR12425_S, T>) -> T {
814-
// TODO(Diagnostics): bad diagnostic for member assign.
815-
// A better diagnostic would be: key path of type WritableKeyPath<SR12425_S, T> cannot be applied to a base of type SR12425_R
816-
get { rightStructInstance[keyPath: member] } // expected-error {{cannot convert return expression of type 'Any?' to return type 'T'}}
817-
set { rightStructInstance[keyPath: member] = newValue } // expected-error {{type of expression is ambiguous without more context}}
814+
get { rightStructInstance[keyPath: member] } // expected-error {{key path with root type 'SR12425_S' cannot be applied to a base of type 'SR12425_R'}}
815+
set { rightStructInstance[keyPath: member] = newValue } // expected-error {{key path with root type 'SR12425_S' cannot be applied to a base of type 'SR12425_R'}}
816+
}
817+
}
818+
819+
@dynamicMemberLookup
820+
public struct SR12425_R1 {}
821+
822+
public extension SR12425_R1 {
823+
subscript<T>(dynamicMember member: KeyPath<SR12425_R1, T>) -> T {
824+
get { rightStructInstance[keyPath: member] } // expected-error {{key path with root type 'SR12425_R1' cannot be applied to a base of type 'SR12425_R'}}
818825
}
819826
}

0 commit comments

Comments
 (0)