Skip to content

Commit 53bcf9f

Browse files
committed
[Sema] TypeWrappers: Implement @typeWrapperIgnored checking
1 parent 116dea2 commit 53bcf9f

File tree

4 files changed

+66
-5
lines changed

4 files changed

+66
-5
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,12 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
385385
if (var->isImplicit())
386386
continue;
387387

388-
// Computed properties are not included.
389-
if (!var->hasStorage())
388+
// Computed properties are not included, except in cases
389+
// where property has a property wrapper and `@typeWrapperIgnored`
390+
// attribute.
391+
if (!var->hasStorage() &&
392+
!(var->hasAttachedPropertyWrapper() &&
393+
var->getAttrs().hasAttribute<TypeWrapperIgnoredAttr>()))
390394
continue;
391395

392396
// If this is a memberwise initializeable property include

lib/Sema/TypeCheckTypeWrapper.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator,
315315
if (property->isStatic() || property->isLet())
316316
return false;
317317

318+
// If this property has `@typeWrapperIgnored` attribute
319+
// it should not be managed by a type wrapper.
320+
if (property->getAttrs().hasAttribute<TypeWrapperIgnoredAttr>())
321+
return false;
322+
318323
// `lazy` properties are not wrapped.
319324
if (property->getAttrs().hasAttribute<LazyAttr>() ||
320325
property->isLazyStorageProperty())
@@ -337,9 +342,13 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator,
337342
// This is the only thing that wrapper needs to handle because
338343
// all access to the wrapped variable and it's projection
339344
// is routed through it.
340-
if (property->getOriginalWrappedProperty(
341-
PropertyWrapperSynthesizedPropertyKind::Backing))
342-
return true;
345+
if (auto *wrappedProperty = property->getOriginalWrappedProperty(
346+
PropertyWrapperSynthesizedPropertyKind::Backing)) {
347+
// If wrapped property is ignored - its backing storage is
348+
// ignored as well.
349+
return !wrappedProperty->getAttrs()
350+
.hasAttribute<TypeWrapperIgnoredAttr>();
351+
}
343352
}
344353

345354
// Don't wrap any compiler synthesized properties except to

test/Interpreter/Inputs/type_wrapper_defs.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,10 @@ public class ClassWithDesignatedInit {
146146
$_storage = .init(memberwise: $Storage(a: 42, _b: PropWrapperWithoutInit(value: b)))
147147
}
148148
}
149+
150+
@Wrapper
151+
public class PersonWithIgnoredAge {
152+
public var name: String
153+
@typeWrapperIgnored public var age: Int = 0
154+
@typeWrapperIgnored @PropWrapper public var manufacturer: String?
155+
}

test/Interpreter/type_wrappers.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,44 @@ do {
408408
// CHECK: in getter
409409
// CHECK-NEXT: [42]
410410
}
411+
412+
do {
413+
var arthur = PersonWithIgnoredAge(name: "Arthur Dent", age: 30)
414+
// CHECK: Wrapper.init($Storage(name: "Arthur Dent"))
415+
416+
print(arthur.name)
417+
// CHECK: in getter
418+
// CHECK-NEXT: Arthur Dent
419+
420+
print(arthur.age)
421+
// CHECK-NOT: in getter
422+
// CHECK-NEXT: 30
423+
424+
print(arthur.manufacturer)
425+
// CHECK-NOT: in getter
426+
// CHECK-NEXT: nil
427+
428+
arthur.age = 32
429+
// CHECK-NOT: in setter
430+
431+
var marvin = PersonWithIgnoredAge(name: "Marvin The Paranoid Android", manufacturer: "Sirius Cybernetics Corporation")
432+
// CHECK: Wrapper.init($Storage(name: "Marvin The Paranoid Android"))
433+
434+
print(marvin.name)
435+
// CHECK: in getter
436+
// CHECK-NEXT: Marvin The Paranoid Android
437+
438+
print(marvin.age)
439+
// CHECK-NOT: in getter
440+
// CHECK-NEXT: 0
441+
442+
print(marvin.manufacturer)
443+
// CHECK-NOT: in getter
444+
// CHECK-NEXT: Sirius Cybernetics Corporation
445+
446+
marvin.age = 1000
447+
// CHECK-NOT: in setter
448+
449+
marvin.manufacturer = nil
450+
// CHECK-NOT: in setter
451+
}

0 commit comments

Comments
 (0)