diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index bbc6763b8db..ff70f4549de 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5010,6 +5010,12 @@ NOTE(property_wrapper_direct_init,none, ERROR(property_wrapper_incompatible_property, none, "property type %0 does not match that of the 'wrappedValue' property of " "its wrapper type %1", (Type, Type)) +ERROR(wrapped_value_mismatch, none, + "property type %0 does not match 'wrappedValue' type %1", + (Type, Type)) +ERROR(composed_property_wrapper_mismatch, none, + "composed wrapper type %0 does not match former 'wrappedValue' type %1", + (Type, Type)) ERROR(property_wrapper_type_access,none, "%select{%select{variable|constant}0|property}1 " diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 06ba2023760..36ee5f7a6c5 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -8039,6 +8039,8 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { case swift::CTP_AssignSource: case swift::CTP_SubscriptAssignSource: case swift::CTP_Condition: + case swift::CTP_WrappedProperty: + case swift::CTP_ComposedPropertyWrapper: case swift::CTP_CannotFail: result.setExpr(rewrittenExpr); break; diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index d1c928b356f..155b863e82c 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -613,6 +613,10 @@ Optional> GenericArgumentsMismatchFailure::getDiagnosticFor( return diag::cannot_convert_subscript_assign; case CTP_Condition: return diag::cannot_convert_condition_value; + case CTP_WrappedProperty: + return diag::wrapped_value_mismatch; + case CTP_ComposedPropertyWrapper: + return diag::composed_property_wrapper_mismatch; case CTP_ThrowStmt: case CTP_ForEachStmt: @@ -2206,6 +2210,8 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) { case CTP_ThrowStmt: case CTP_ForEachStmt: case CTP_YieldByReference: + case CTP_WrappedProperty: + case CTP_ComposedPropertyWrapper: return None; case CTP_EnumCaseRawValue: @@ -2904,6 +2910,11 @@ ContextualFailure::getDiagnosticFor(ContextualTypePurpose context, case CTP_Condition: return diag::cannot_convert_condition_value; + case CTP_WrappedProperty: + return diag::wrapped_value_mismatch; + case CTP_ComposedPropertyWrapper: + return diag::composed_property_wrapper_mismatch; + case CTP_ThrowStmt: case CTP_ForEachStmt: case CTP_Unused: diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 2752a003095..f449a5d4213 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -3893,8 +3893,10 @@ static Type generateWrappedPropertyTypeConstraints( auto *locator = cs.getConstraintLocator(typeRepr, LocatorPathElt::ContextualType()); wrapperType = cs.openUnboundGenericTypes(rawWrapperType, locator); - cs.addConstraint(ConstraintKind::Equal, wrappedValueType, wrapperType, + cs.addConstraint(ConstraintKind::Equal, wrapperType, wrappedValueType, locator); + cs.setContextualType(typeRepr, TypeLoc::withoutLoc(wrappedValueType), + CTP_ComposedPropertyWrapper); } wrappedValueType = wrapperType->getTypeOfMember( @@ -4184,6 +4186,8 @@ bool ConstraintSystem::generateConstraints( addConstraint(ConstraintKind::Equal, propertyType, wrappedValueType, getConstraintLocator(wrappedVar, LocatorPathElt::ContextualType())); + setContextualType(wrappedVar, TypeLoc::withoutLoc(wrappedValueType), + CTP_WrappedProperty); return false; } } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 6341a41ea72..2bf03eae13e 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -10156,6 +10156,8 @@ void ConstraintSystem::addContextualConversionConstraint( case CTP_CoerceOperand: case CTP_SubscriptAssignSource: case CTP_ForEachStmt: + case CTP_WrappedProperty: + case CTP_ComposedPropertyWrapper: break; } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 27ed7adf658..9d27ee0a6ce 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -4752,6 +4752,8 @@ bool SolutionApplicationTarget::contextualTypeIsOnlyAHint() const { case CTP_AssignSource: case CTP_SubscriptAssignSource: case CTP_Condition: + case CTP_WrappedProperty: + case CTP_ComposedPropertyWrapper: case CTP_CannotFail: return false; } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index f4c1c6ca61c..bb5afff9d12 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -144,6 +144,9 @@ enum ContextualTypePurpose { ///< `if`, `for`, `while` etc. CTP_ForEachStmt, ///< "expression/sequence" associated with 'for-in' loop ///< is expected to conform to 'Sequence' protocol. + CTP_WrappedProperty, ///< Property type expected to match 'wrappedValue' type + CTP_ComposedPropertyWrapper, ///< Composed wrapper type expected to match + ///< former 'wrappedValue' type CTP_CannotFail, ///< Conversion can never fail. abort() if it does. }; diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 090c4dcefef..18bf7666bd2 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -347,8 +347,9 @@ struct TestFunction { @Function var f: (Int) -> Float? // FIXME: This diagnostic should be more specific - @Function var f2: (Int) -> Float // expected-error{{generic parameter 'U' could not be inferred}} - // expected-note@-1 {{explicitly specify}} + @Function var f2: (Int) -> Float // expected-error {{property type '(Int) -> Float' does not match 'wrappedValue' type '(Int) -> U?'}} + // expected-error@-1 {{generic parameter 'U' could not be inferred}} + // expected-note@-2 {{explicitly specify}} func test() { let _: Int = _f // expected-error{{cannot convert value of type 'Function' to specified type 'Int'}} @@ -1051,6 +1052,7 @@ struct TestComposition { @WrapperD @WrapperC var p4: Int? @WrapperD @WrapperE var p5: Int // expected-error{{generic parameter 'Value' could not be inferred}} // expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} + // expected-error@-2 {{composed wrapper type 'WrapperE' does not match former 'wrappedValue' type 'WrapperC'}} func triggerErrors(d: Double) { // expected-note 6 {{mark method 'mutating' to make 'self' mutable}} {{2-2=mutating }} p1 = d // expected-error{{cannot assign value of type 'Double' to type 'Int'}} {{8-8=Int(}} {{9-9=)}}