Skip to content

Commit 73552d0

Browse files
committed
Emit reflection metadata for noncopyable fields more often
When emitting reflection metadata for fields that have noncopyable type with deployment targets that predate support for noncopyable types, we introduce some indirection to make sure that these fields are only visible to reflection clients (e.g., mirrors) when running on a sufficiently-new Swift runtime. However, this indirection has the downside that out-of-process clients (such as LLDB) can no longer reflect the fields. Tweak the heuristic to only introduce the indirection if the field is *guaranteed* to have noncopyable type. If it somehow could be copyable, e.g., based on the properties of its generic arguments, then still emit the normal metadata. This eliminates regressions when existing generic types like Optional become conditionally Copyable (based on their Wrapped functions).
1 parent 1a84094 commit 73552d0

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,28 @@ getTypeRefImpl(IRGenModule &IGM,
411411
// signal from future runtimes whether they support noncopyable types before
412412
// exposing their metadata to them.
413413
Type contextualTy = type;
414-
if (sig)
414+
if (sig) {
415415
contextualTy = sig.getGenericEnvironment()->mapTypeIntoContext(type);
416+
}
416417

418+
bool isAlwaysNoncopyable = false;
417419
if (contextualTy->isNoncopyable()) {
420+
// If the contextual type has any archetypes in it, it's plausible that
421+
// we could end up with a copyable type in some instances. Look for those.
422+
if (contextualTy->hasArchetype()) {
423+
// If this is a nominal type, check whether it can ever be copyable.
424+
if (auto nominal = contextualTy->getAnyNominal()) {
425+
if (!nominal->canBeCopyable())
426+
isAlwaysNoncopyable = true;
427+
} else {
428+
// Assume that we could end up with a copyable type somehow.
429+
}
430+
} else {
431+
isAlwaysNoncopyable = true;
432+
}
433+
}
434+
435+
if (isAlwaysNoncopyable) {
418436
IGM.IRGen.noteUseOfTypeMetadata(type);
419437
return getTypeRefByFunction(IGM, sig, type);
420438
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-ir -o - %s -module-name test \
3+
// RUN: -enable-experimental-feature NoncopyableGenerics \
4+
// RUN: -enable-experimental-feature NonescapableTypes \
5+
// RUN: -parse-as-library \
6+
// RUN: -enable-library-evolution \
7+
// RUN: > %t/test.irgen
8+
9+
// RUN: %FileCheck %s < %t/test.irgen
10+
11+
@frozen
12+
public enum ConditionallyCopyable<Wrapped: ~Copyable>: ~Copyable {
13+
case none
14+
case some(Wrapped)
15+
}
16+
17+
extension ConditionallyCopyable: Copyable where Wrapped: Copyable { }
18+
19+
@frozen
20+
public enum NeverCopyable<Wrapped: ~Copyable>: ~Copyable {
21+
case none
22+
case some(Wrapped)
23+
}
24+
25+
@frozen
26+
public struct NonCopyable: ~Copyable { }
27+
28+
// CHECK: @"$s4test1CCMF" =
29+
// CHECK-SAME: @"symbolic _____yxG 4test21ConditionallyCopyableOAARiczrlE"
30+
// CHECK-SAME: @"get_type_metadata Riczl4test21ConditionallyCopyableOyAA03NonC0VG.3"
31+
// CHECK-SAME: @"symbolic _____yxG 4test21ConditionallyCopyableOAARiczrlE"
32+
// CHECK-SAME: @"get_type_metadata Riczl4test21ConditionallyCopyableOyAA03NonC0VG.3"
33+
public class C<T: ~Copyable> {
34+
var ccT: ConditionallyCopyable<T> = .none
35+
var ccNC: ConditionallyCopyable<NonCopyable> = .none
36+
var ncT: ConditionallyCopyable<T> = .none
37+
var ncNC: ConditionallyCopyable<NonCopyable> = .none
38+
}

0 commit comments

Comments
 (0)