From 5e815b9728d0387758bc4c9c4aea0d81167ca364 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 12 Dec 2025 17:42:38 -0800 Subject: [PATCH] [DeclChecker] Skip contextualization of initializers associated with property wrapped variables Fixes a double-contextualization that results in an assert because properties with property wrappers have the same initializer in two places - original property (which becomes computed) and backing storage property - that's where the initializer is copied. Contextualization of the fully type-checked initializer should happen as part of backing storage property processing by the declaration checker. Resolves: rdar://163562182 --- lib/Sema/TypeCheckDeclPrimary.cpp | 9 +++++ .../rdar163562182.swift | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 validation-test/Sema/type_checker_crashers_fixed/rdar163562182.swift diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 9e02c74db944f..3bcab4796669b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2706,6 +2706,15 @@ class DeclChecker : public DeclVisitor { if (!PBD->isInitialized(i)) continue; + if (PBD->isInitializerSubsumed(i)) { + auto *var = PBD->getSingleVar(); + // The initializer of a property wrapped variable gets transferred + // the synthesized backing storage property, let have it contextualized + // there. + if (var && var->hasAttachedPropertyWrapper()) + continue; + } + if (!PBD->isInitializerChecked(i)) { TypeCheckExprOptions options; diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar163562182.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar163562182.swift new file mode 100644 index 0000000000000..9c79f5419e208 --- /dev/null +++ b/validation-test/Sema/type_checker_crashers_fixed/rdar163562182.swift @@ -0,0 +1,34 @@ +// RUN: %target-typecheck-verify-swift + +enum CustomError: Error { +} + +struct ValidationError: Error { +} + +func parseOption(_: String) throws -> Int { + 42 +} + +@propertyWrapper +public struct Option { + public var wrappedValue: Value + + public init( + wrappedValue: Value, + transform: @Sendable @escaping (String) throws -> Value + ) { + self.wrappedValue = wrappedValue + } +} + +struct Test { + @Option(transform: { + do { + return try parseOption($0) + } catch let error as CustomError { + throw ValidationError() + } + }) + var prop: Int = 0 +}