Skip to content

Commit f555bfe

Browse files
committed
[Property Wrappers] Add new contextual type purposes for property wrappers
to produce better diagnostics when there's a 'wrappedValue' type mismatch.
1 parent 2386374 commit f555bfe

File tree

8 files changed

+35
-3
lines changed

8 files changed

+35
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5010,6 +5010,12 @@ NOTE(property_wrapper_direct_init,none,
50105010
ERROR(property_wrapper_incompatible_property, none,
50115011
"property type %0 does not match that of the 'wrappedValue' property of "
50125012
"its wrapper type %1", (Type, Type))
5013+
ERROR(wrapped_value_mismatch, none,
5014+
"property type %0 does not match 'wrappedValue' type %1",
5015+
(Type, Type))
5016+
ERROR(composed_property_wrapper_mismatch, none,
5017+
"composed wrapper type %0 does not match former 'wrappedValue' type %1",
5018+
(Type, Type))
50135019

50145020
ERROR(property_wrapper_type_access,none,
50155021
"%select{%select{variable|constant}0|property}1 "

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8039,6 +8039,8 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
80398039
case swift::CTP_AssignSource:
80408040
case swift::CTP_SubscriptAssignSource:
80418041
case swift::CTP_Condition:
8042+
case swift::CTP_WrappedProperty:
8043+
case swift::CTP_ComposedPropertyWrapper:
80428044
case swift::CTP_CannotFail:
80438045
result.setExpr(rewrittenExpr);
80448046
break;

lib/Sema/CSDiagnostics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,10 @@ Optional<Diag<Type, Type>> GenericArgumentsMismatchFailure::getDiagnosticFor(
613613
return diag::cannot_convert_subscript_assign;
614614
case CTP_Condition:
615615
return diag::cannot_convert_condition_value;
616+
case CTP_WrappedProperty:
617+
return diag::wrapped_value_mismatch;
618+
case CTP_ComposedPropertyWrapper:
619+
return diag::composed_property_wrapper_mismatch;
616620

617621
case CTP_ThrowStmt:
618622
case CTP_ForEachStmt:
@@ -2206,6 +2210,8 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) {
22062210
case CTP_ThrowStmt:
22072211
case CTP_ForEachStmt:
22082212
case CTP_YieldByReference:
2213+
case CTP_WrappedProperty:
2214+
case CTP_ComposedPropertyWrapper:
22092215
return None;
22102216

22112217
case CTP_EnumCaseRawValue:
@@ -2904,6 +2910,11 @@ ContextualFailure::getDiagnosticFor(ContextualTypePurpose context,
29042910
case CTP_Condition:
29052911
return diag::cannot_convert_condition_value;
29062912

2913+
case CTP_WrappedProperty:
2914+
return diag::wrapped_value_mismatch;
2915+
case CTP_ComposedPropertyWrapper:
2916+
return diag::composed_property_wrapper_mismatch;
2917+
29072918
case CTP_ThrowStmt:
29082919
case CTP_ForEachStmt:
29092920
case CTP_Unused:

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3893,8 +3893,10 @@ static Type generateWrappedPropertyTypeConstraints(
38933893
auto *locator =
38943894
cs.getConstraintLocator(typeRepr, LocatorPathElt::ContextualType());
38953895
wrapperType = cs.openUnboundGenericTypes(rawWrapperType, locator);
3896-
cs.addConstraint(ConstraintKind::Equal, wrappedValueType, wrapperType,
3896+
cs.addConstraint(ConstraintKind::Equal, wrapperType, wrappedValueType,
38973897
locator);
3898+
cs.setContextualType(typeRepr, TypeLoc::withoutLoc(wrappedValueType),
3899+
CTP_ComposedPropertyWrapper);
38983900
}
38993901

39003902
wrappedValueType = wrapperType->getTypeOfMember(
@@ -4184,6 +4186,8 @@ bool ConstraintSystem::generateConstraints(
41844186

41854187
addConstraint(ConstraintKind::Equal, propertyType, wrappedValueType,
41864188
getConstraintLocator(wrappedVar, LocatorPathElt::ContextualType()));
4189+
setContextualType(wrappedVar, TypeLoc::withoutLoc(wrappedValueType),
4190+
CTP_WrappedProperty);
41874191
return false;
41884192
}
41894193
}

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10156,6 +10156,8 @@ void ConstraintSystem::addContextualConversionConstraint(
1015610156
case CTP_CoerceOperand:
1015710157
case CTP_SubscriptAssignSource:
1015810158
case CTP_ForEachStmt:
10159+
case CTP_WrappedProperty:
10160+
case CTP_ComposedPropertyWrapper:
1015910161
break;
1016010162
}
1016110163

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4752,6 +4752,8 @@ bool SolutionApplicationTarget::contextualTypeIsOnlyAHint() const {
47524752
case CTP_AssignSource:
47534753
case CTP_SubscriptAssignSource:
47544754
case CTP_Condition:
4755+
case CTP_WrappedProperty:
4756+
case CTP_ComposedPropertyWrapper:
47554757
case CTP_CannotFail:
47564758
return false;
47574759
}

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ enum ContextualTypePurpose {
144144
///< `if`, `for`, `while` etc.
145145
CTP_ForEachStmt, ///< "expression/sequence" associated with 'for-in' loop
146146
///< is expected to conform to 'Sequence' protocol.
147+
CTP_WrappedProperty, ///< Property type expected to match 'wrappedValue' type
148+
CTP_ComposedPropertyWrapper, ///< Composed wrapper type expected to match
149+
///< former 'wrappedValue' type
147150

148151
CTP_CannotFail, ///< Conversion can never fail. abort() if it does.
149152
};

test/decl/var/property_wrappers.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,9 @@ struct TestFunction {
347347
@Function var f: (Int) -> Float?
348348

349349
// FIXME: This diagnostic should be more specific
350-
@Function var f2: (Int) -> Float // expected-error{{generic parameter 'U' could not be inferred}}
351-
// expected-note@-1 {{explicitly specify}}
350+
@Function var f2: (Int) -> Float // expected-error {{property type '(Int) -> Float' does not match 'wrappedValue' type '(Int) -> U?'}}
351+
// expected-error@-1 {{generic parameter 'U' could not be inferred}}
352+
// expected-note@-2 {{explicitly specify}}
352353

353354
func test() {
354355
let _: Int = _f // expected-error{{cannot convert value of type 'Function<Int, Float>' to specified type 'Int'}}
@@ -1051,6 +1052,7 @@ struct TestComposition {
10511052
@WrapperD<WrapperC, Int, String> @WrapperC var p4: Int?
10521053
@WrapperD<WrapperC, Int, String> @WrapperE var p5: Int // expected-error{{generic parameter 'Value' could not be inferred}}
10531054
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}}
1055+
// expected-error@-2 {{composed wrapper type 'WrapperE<Int>' does not match former 'wrappedValue' type 'WrapperC<Value>'}}
10541056

10551057
func triggerErrors(d: Double) { // expected-note 6 {{mark method 'mutating' to make 'self' mutable}} {{2-2=mutating }}
10561058
p1 = d // expected-error{{cannot assign value of type 'Double' to type 'Int'}} {{8-8=Int(}} {{9-9=)}}

0 commit comments

Comments
 (0)