Skip to content

Commit 0cf1bf2

Browse files
authored
[Diagnostics]: Add diagnostics for incorrect property wrapper references in function args (#25889)
1 parent aca716e commit 0cf1bf2

File tree

3 files changed

+90
-51
lines changed

3 files changed

+90
-51
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ ERROR(cannot_pass_inout_arg_to_subscript,none,
10131013

10141014
ERROR(incorrect_property_wrapper_reference,none,
10151015
"cannot convert value %0 of type %1 to expected type %2, "
1016-
"use %select{wrapper| wrapped value}3 instead",
1016+
"use %select{wrapper|wrapped value}3 instead",
10171017
(Identifier, Type, Type, bool))
10181018
ERROR(incorrect_property_wrapper_reference_member,none,
10191019
"referencing %0 %1 requires %select{wrapper|wrapped value of type}2 %3",

lib/Sema/CSSimplify.cpp

Lines changed: 70 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,44 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
20772077
llvm_unreachable("covered switch");
20782078
}
20792079

2080+
static ConstraintFix *fixPropertyWrapperFailure(
2081+
ConstraintSystem &cs, Type baseTy, Expr *anchor, ConstraintLocator *locator,
2082+
llvm::function_ref<bool(ResolvedOverloadSetListItem *, VarDecl *, Type)>
2083+
attemptFix,
2084+
Optional<Type> toType = None) {
2085+
auto resolvedOverload = cs.findSelectedOverloadFor(anchor);
2086+
if (!resolvedOverload)
2087+
return nullptr;
2088+
2089+
if (auto storageWrapper =
2090+
cs.getStorageWrapperInformation(resolvedOverload)) {
2091+
if (attemptFix(resolvedOverload, storageWrapper->first,
2092+
storageWrapper->second))
2093+
return UsePropertyWrapper::create(
2094+
cs, storageWrapper->first,
2095+
/*usingStorageWrapper=*/true, baseTy,
2096+
toType.getValueOr(storageWrapper->second), locator);
2097+
}
2098+
2099+
if (auto wrapper = cs.getPropertyWrapperInformation(resolvedOverload)) {
2100+
if (attemptFix(resolvedOverload, wrapper->first, wrapper->second))
2101+
return UsePropertyWrapper::create(
2102+
cs, wrapper->first,
2103+
/*usingStorageWrappeer=*/false, baseTy,
2104+
toType.getValueOr(wrapper->second), locator);
2105+
}
2106+
2107+
if (auto wrappedProperty =
2108+
cs.getWrappedPropertyInformation(resolvedOverload)) {
2109+
if (attemptFix(resolvedOverload, wrappedProperty->first,
2110+
wrappedProperty->second))
2111+
return UseWrappedValue::create(
2112+
cs, wrappedProperty->first, baseTy,
2113+
toType.getValueOr(wrappedProperty->second), locator);
2114+
}
2115+
return nullptr;
2116+
}
2117+
20802118
/// Attempt to repair typing failures and record fixes if needed.
20812119
/// \return true if at least some of the failures has been repaired
20822120
/// successfully, which allows type matcher to continue.
@@ -2185,13 +2223,31 @@ bool ConstraintSystem::repairFailures(
21852223
switch (elt.getKind()) {
21862224
case ConstraintLocator::LValueConversion:
21872225
case ConstraintLocator::ApplyArgToParam: {
2226+
auto loc = getConstraintLocator(locator);
21882227
if (repairByInsertingExplicitCall(lhs, rhs))
21892228
return true;
21902229

21912230
if (lhs->getOptionalObjectType() && !rhs->getOptionalObjectType()) {
21922231
conversionsOrFixes.push_back(
2193-
ForceOptional::create(*this, lhs, lhs->getOptionalObjectType(),
2194-
getConstraintLocator(locator)));
2232+
ForceOptional::create(*this, lhs, lhs->getOptionalObjectType(), loc));
2233+
}
2234+
2235+
if (elt.getKind() != ConstraintLocator::ApplyArgToParam)
2236+
break;
2237+
2238+
auto anchor = simplifyLocatorToAnchor(*this, loc);
2239+
2240+
if (auto *fix = fixPropertyWrapperFailure(
2241+
*this, lhs, anchor, loc,
2242+
[&](ResolvedOverloadSetListItem *overload, VarDecl *decl,
2243+
Type newBase) {
2244+
return matchTypes(newBase, rhs, ConstraintKind::Subtype,
2245+
TypeMatchFlags::TMF_ApplyingFix,
2246+
overload->Locator)
2247+
.isSuccess();
2248+
},
2249+
rhs)) {
2250+
conversionsOrFixes.push_back(fix);
21952251
}
21962252
break;
21972253
}
@@ -4815,45 +4871,15 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
48154871
if (auto dotExpr =
48164872
dyn_cast_or_null<UnresolvedDotExpr>(locator->getAnchor())) {
48174873
auto baseExpr = dotExpr->getBase();
4818-
4819-
if (auto resolvedOverload = findSelectedOverloadFor(baseExpr)) {
4820-
if (auto storageWrapper =
4821-
getStorageWrapperInformation(resolvedOverload)) {
4822-
auto wrapperTy = storageWrapper->second;
4823-
auto result =
4824-
solveWithNewBaseOrName(wrapperTy, member, /*allowFixes=*/false);
4825-
if (result == SolutionKind::Solved) {
4826-
auto *fix = UsePropertyWrapper::create(*this, storageWrapper->first,
4827-
/*usingStorageWrapper=*/true,
4828-
baseTy, wrapperTy, locator);
4829-
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
4830-
}
4831-
}
4832-
4833-
if (auto wrapper = getPropertyWrapperInformation(resolvedOverload)) {
4834-
auto wrapperTy = wrapper->second;
4835-
auto result =
4836-
solveWithNewBaseOrName(wrapperTy, member, /*allowFixes=*/false);
4837-
if (result == SolutionKind::Solved) {
4838-
auto *fix = UsePropertyWrapper::create(
4839-
*this, wrapper->first,
4840-
/*usingStorageWrappeer=*/false, baseTy, wrapperTy, locator);
4841-
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
4842-
}
4843-
}
4844-
4845-
if (auto wrappedProperty =
4846-
getWrappedPropertyInformation(resolvedOverload)) {
4847-
auto wrappedTy = wrappedProperty->second;
4848-
auto result =
4849-
solveWithNewBaseOrName(wrappedTy, member, /*allowFixes=*/false);
4850-
4851-
if (result == SolutionKind::Solved) {
4852-
auto *fix = UseWrappedValue::create(*this, wrappedProperty->first,
4853-
baseTy, wrappedTy, locator);
4854-
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
4855-
}
4856-
}
4874+
if (auto *fix = fixPropertyWrapperFailure(
4875+
*this, baseTy, baseExpr, locator,
4876+
[&](ResolvedOverloadSetListItem *overload, VarDecl *decl,
4877+
Type newBase) {
4878+
return solveWithNewBaseOrName(newBase, member,
4879+
/*allowFixes=*/false) ==
4880+
SolutionKind::Solved;
4881+
})) {
4882+
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
48574883
}
48584884
}
48594885

@@ -6806,7 +6832,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
68066832
case FixKind::SkipSuperclassRequirement:
68076833
case FixKind::ContextualMismatch:
68086834
case FixKind::AddMissingArguments:
6809-
case FixKind::SkipUnhandledConstructInFunctionBuilder: {
6835+
case FixKind::SkipUnhandledConstructInFunctionBuilder:
6836+
case FixKind::UsePropertyWrapper:
6837+
case FixKind::UseWrappedValue: {
68106838
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
68116839
}
68126840

@@ -6827,8 +6855,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
68276855
case FixKind::TreatKeyPathSubscriptIndexAsHashable:
68286856
case FixKind::AllowInvalidRefInKeyPath:
68296857
case FixKind::ExplicitlySpecifyGenericArguments:
6830-
case FixKind::UsePropertyWrapper:
6831-
case FixKind::UseWrappedValue:
68326858
case FixKind::GenericArgumentsMismatch:
68336859
llvm_unreachable("handled elsewhere");
68346860
}

test/decl/var/property_wrappers.swift

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ extension Bar where V == String { // expected-note {{where 'V' = 'Bool'}}
968968
}
969969

970970
struct V {
971-
func onWrapperValue() {}
971+
func onProjectedValue() {}
972972
}
973973

974974
struct W {
@@ -980,7 +980,13 @@ struct MissingPropertyWrapperUnwrap {
980980
@Foo var x: Int
981981
@Bar<Int, Bool> var y: Int
982982
@Bar<Int, String> var z: Int
983-
@Baz var usesWrapperValue: W
983+
@Baz var usesProjectedValue: W
984+
985+
func a<T>(_: Foo<T>) {}
986+
func a<T>(named: Foo<T>) {}
987+
func b(_: Foo<Int>) {}
988+
func c(_: V) {}
989+
func d(_: W) {}
984990

985991
func baz() {
986992
self.x.foo() // expected-error {{referencing instance method 'foo()' requires wrapper 'Foo<Int>'}}{{10-10=_}}
@@ -990,11 +996,18 @@ struct MissingPropertyWrapperUnwrap {
990996
self.y.barWhereVIsString() // expected-error {{referencing instance method 'barWhereVIsString()' requires wrapper 'Bar<Int, Bool>'}}{{10-10=_}}
991997
// expected-error@-1 {{referencing instance method 'barWhereVIsString()' on 'Bar' requires the types 'Bool' and 'String' be equivalent}}
992998
self.z.barWhereVIsString() // expected-error {{referencing instance method 'barWhereVIsString()' requires wrapper 'Bar<Int, String>'}}{{10-10=_}}
993-
self.usesWrapperValue.onPropertyWrapper() // expected-error {{referencing instance method 'onPropertyWrapper()' requires wrapper 'Baz<W>'}}{{10-10=_}}
999+
self.usesProjectedValue.onPropertyWrapper() // expected-error {{referencing instance method 'onPropertyWrapper()' requires wrapper 'Baz<W>'}}{{10-10=_}}
9941000

9951001
self._w.onWrapped() // expected-error {{referencing instance method 'onWrapped()' requires wrapped value of type 'W'}}{{10-11=}}
996-
self.usesWrapperValue.onWrapperValue() // expected-error {{referencing instance method 'onWrapperValue()' requires wrapper 'V'}}{{10-10=$}}
997-
self.$usesWrapperValue.onWrapped() // expected-error {{referencing instance method 'onWrapped()' requires wrapped value of type 'W'}}{{10-11=}}
998-
self._usesWrapperValue.onWrapped() // expected-error {{referencing instance method 'onWrapped()' requires wrapped value of type 'W'}}{{10-11=}}
1002+
self.usesProjectedValue.onProjectedValue() // expected-error {{referencing instance method 'onProjectedValue()' requires wrapper 'V'}}{{10-10=$}}
1003+
self.$usesProjectedValue.onWrapped() // expected-error {{referencing instance method 'onWrapped()' requires wrapped value of type 'W'}}{{10-11=}}
1004+
self._usesProjectedValue.onWrapped() // expected-error {{referencing instance method 'onWrapped()' requires wrapped value of type 'W'}}{{10-11=}}
1005+
1006+
a(self.w) // expected-error {{cannot convert value 'w' of type 'W' to expected type 'Foo<W>', use wrapper instead}}{{12-12=_}}
1007+
b(self.x) // expected-error {{cannot convert value 'x' of type 'Int' to expected type 'Foo<Int>', use wrapper instead}}{{12-12=_}}
1008+
b(self.w) // expected-error {{cannot convert value 'w' of type 'W' to expected type 'Foo<Int>', use wrapper instead}}{{12-12=_}}
1009+
c(self.usesProjectedValue) // expected-error {{cannot convert value 'usesProjectedValue' of type 'W' to expected type 'V', use wrapper instead}}{{12-12=$}}
1010+
d(self.$usesProjectedValue) // expected-error {{cannot convert value '$usesProjectedValue' of type 'V' to expected type 'W', use wrapped value instead}}{{12-13=}}
1011+
d(self._usesProjectedValue) // expected-error {{cannot convert value '_usesProjectedValue' of type 'Baz<W>' to expected type 'W', use wrapped value instead}}{{12-13=}}
9991012
}
10001013
}

0 commit comments

Comments
 (0)