Skip to content

Commit db38727

Browse files
committed
[ConstraintSystem] Don't allow dollar prefixes in argument labels unless
the parameter has an attached property wrapper.
1 parent c29eecd commit db38727

File tree

6 files changed

+47
-17
lines changed

6 files changed

+47
-17
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5490,6 +5490,10 @@ NOTE(property_wrapper_declared_here,none,
54905490
ERROR(property_wrapper_param_no_projection,none,
54915491
"cannot use property wrapper projection parameter; "
54925492
"wrapper %0 does not have a 'projectedValue'", (Type))
5493+
ERROR(property_wrapper_param_no_wrapper,none,
5494+
"cannot use property wrapper projection argument; "
5495+
"parameter does not have an attached property wrapper",
5496+
())
54935497
ERROR(property_wrapper_param_projection_invalid,none,
54945498
"cannot use property wrapper projection argument; "
54955499
"pass wrapped value type %0 instead", (Type))

lib/Sema/CSDiagnostics.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3310,10 +3310,14 @@ bool MissingProjectedValueFailure::diagnoseAsError() {
33103310
}
33113311

33123312
bool MissingPropertyWrapperAttributeFailure::diagnoseAsError() {
3313-
emitDiagnostic(diag::invalid_implicit_property_wrapper, wrapperType);
3313+
if (auto *param = getAsDecl<ParamDecl>(getAnchor())) {
3314+
emitDiagnostic(diag::invalid_implicit_property_wrapper, wrapperType);
33143315

3315-
// FIXME: emit a note and fix-it to add '@propertyWrapper' if the
3316-
// type is a nominal and in the same module.
3316+
// FIXME: emit a note and fix-it to add '@propertyWrapper' if the
3317+
// type is a nominal and in the same module.
3318+
} else {
3319+
emitDiagnostic(diag::property_wrapper_param_no_wrapper);
3320+
}
33173321

33183322
return true;
33193323
}

lib/Sema/CSGen.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4061,6 +4061,18 @@ ConstraintSystem::applyPropertyWrapperParameter(
40614061
anchor = apply->getFn();
40624062
}
40634063

4064+
if (argLabel.hasDollarPrefix() && (!param || !param->hasAttachedPropertyWrapper())) {
4065+
if (!shouldAttemptFixes())
4066+
return getTypeMatchFailure(locator);
4067+
4068+
addConstraint(matchKind, paramType, wrapperType, locator);
4069+
auto *fix = AddPropertyWrapperAttribute::create(*this, wrapperType, getConstraintLocator(locator));
4070+
if (recordFix(fix))
4071+
return getTypeMatchFailure(locator);
4072+
4073+
return getTypeMatchSuccess();
4074+
}
4075+
40644076
PropertyWrapperInitKind initKind;
40654077
if (argLabel.hasDollarPrefix()) {
40664078
auto attemptProjectedValueFix = [&](ConstraintFix *fix) -> ConstraintSystem::TypeMatchResult {

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,9 +1420,10 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
14201420
cs, cs.getConstraintLocator(loc)));
14211421
}
14221422

1423-
if (auto *param = paramInfo.getPropertyWrapperParam(argIdx)) {
1424-
auto argLabel = argInfo->Labels[argIdx];
1425-
if (cs.applyPropertyWrapperParameter(paramTy, argTy, const_cast<ParamDecl *>(param),
1423+
auto *wrappedParam = paramInfo.getPropertyWrapperParam(argIdx);
1424+
auto argLabel = argument.getLabel();
1425+
if (wrappedParam || argLabel.hasDollarPrefix()) {
1426+
if (cs.applyPropertyWrapperParameter(paramTy, argTy, const_cast<ParamDecl *>(wrappedParam),
14261427
argLabel, subKind, locator).isFailure()) {
14271428
return cs.getTypeMatchFailure(loc);
14281429
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,10 +1162,8 @@ static FunctionType *
11621162
unwrapPropertyWrapperParameterTypes(ConstraintSystem &cs, AbstractFunctionDecl *funcDecl,
11631163
FunctionRefKind functionRefKind, FunctionType *functionType,
11641164
ConstraintLocatorBuilder locator) {
1165-
// Only apply property wrappers to unapplied references to functions
1166-
// with wrapped parameters.
1167-
if (!AnyFunctionRef(funcDecl).hasPropertyWrapperParameters() ||
1168-
!(functionRefKind == FunctionRefKind::Compound ||
1165+
// Only apply property wrappers to unapplied references to functions.
1166+
if (!(functionRefKind == FunctionRefKind::Compound ||
11691167
functionRefKind == FunctionRefKind::Unapplied)) {
11701168
return functionType;
11711169
}
@@ -1187,12 +1185,6 @@ unwrapPropertyWrapperParameterTypes(ConstraintSystem &cs, AbstractFunctionDecl *
11871185
}
11881186

11891187
for (unsigned i : indices(*paramList)) {
1190-
auto *paramDecl = paramList->get(i);
1191-
if (!paramDecl->hasAttachedPropertyWrapper()) {
1192-
adjustedParamTypes.push_back(paramTypes[i]);
1193-
continue;
1194-
}
1195-
11961188
Identifier argLabel;
11971189
if (functionRefKind == FunctionRefKind::Compound) {
11981190
auto &context = cs.getASTContext();
@@ -1201,6 +1193,12 @@ unwrapPropertyWrapperParameterTypes(ConstraintSystem &cs, AbstractFunctionDecl *
12011193
argLabel = context.getIdentifier(argLabelToken.getText());
12021194
}
12031195

1196+
auto *paramDecl = paramList->get(i);
1197+
if (!paramDecl->hasAttachedPropertyWrapper() && !argLabel.hasDollarPrefix()) {
1198+
adjustedParamTypes.push_back(paramTypes[i]);
1199+
continue;
1200+
}
1201+
12041202
auto *wrappedType = cs.createTypeVariable(cs.getConstraintLocator(locator), 0);
12051203
auto paramType = paramTypes[i].getParameterType();
12061204
auto paramLabel = paramTypes[i].getLabel();
@@ -1209,7 +1207,8 @@ unwrapPropertyWrapperParameterTypes(ConstraintSystem &cs, AbstractFunctionDecl *
12091207
ConstraintKind::Equal, locator);
12101208
}
12111209

1212-
return FunctionType::get(adjustedParamTypes, functionType->getResult());
1210+
return FunctionType::get(adjustedParamTypes, functionType->getResult(),
1211+
functionType->getExtInfo());
12131212
}
12141213

12151214
std::pair<Type, Type>

test/Sema/property_wrapper_parameter_invalid.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,13 @@ struct S {
7373
// expected-error@+1 {{property wrapper attribute on parameter not yet supported on subscript}}
7474
subscript(@Wrapper position: Int) -> Int { 0 }
7575
}
76+
77+
func testInvalidArgLabel() {
78+
func noWrappers(argLabel: Int) {}
79+
80+
// expected-error@+1 {{cannot use property wrapper projection argument; parameter does not have an attached property wrapper}}
81+
let ref = noWrappers($argLabel:)
82+
83+
// expected-error@+1 {{cannot use property wrapper projection argument; parameter does not have an attached property wrapper}}
84+
noWrappers($argLabel: 10)
85+
}

0 commit comments

Comments
 (0)