Skip to content

Commit c0ad612

Browse files
Merge pull request #71335 from nate-chandler/bitwise-copyable/sil-token
[BitwiseCopyable] Permit SILTokenType's nonconformance.
2 parents c89f63f + c148e11 commit c0ad612

File tree

3 files changed

+82
-45
lines changed

3 files changed

+82
-45
lines changed

lib/SIL/IR/TypeLowering.cpp

Lines changed: 63 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,6 +2793,17 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
27932793
}
27942794

27952795
namespace swift::test {
2796+
static FunctionTest PrintASTTypeLowering(
2797+
"print_ast_type_lowering", [](auto &function, auto &arguments, auto &test) {
2798+
auto value = arguments.takeValue();
2799+
auto silTy = value->getType();
2800+
auto canTy = silTy.getRawASTType();
2801+
auto *ty = canTy.getPointer();
2802+
function.getModule()
2803+
.Types.getTypeLowering(AbstractionPattern(ty), ty, function)
2804+
.print(llvm::outs());
2805+
});
2806+
27962807
// Arguments:
27972808
// - value: whose type will be printed
27982809
// Dumps:
@@ -3028,67 +3039,78 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30283039
auto conformance = M.checkConformance(substType, bitwiseCopyableProtocol);
30293040

30303041
if (lowering.isTrivial() && !conformance) {
3031-
// A trivial type can only lack a conformance if one of its leaves is a
3032-
// public type that doesn't conform.
3042+
// A trivial type can lack a conformance in a few cases:
3043+
// (1) containing or being a resilient type
3044+
// (2) containing or being a generic type which doesn't conform
3045+
// unconditionally but in this particular instantiation is trivial
3046+
// (3) being a special type that's not worth forming a conformance for
3047+
// - ModuleType
3048+
// - SILTokenType
3049+
// (4) being an unowned(unsafe) reference to a class/class-bound existential
3050+
// NOTE: ReferenceStorageType(C) does not conform HOWEVER the presence
3051+
// of an unowned(unsafe) field within an aggregate DOES NOT allow
3052+
// the aggregate to lack conformance. In other words, this must
3053+
// conform:
3054+
// struct S {
3055+
// unowned(unsafe) var o: AnyObject
3056+
// }
30333057
bool hasNoNonconformingNode = visitAggregateLeaves(
30343058
origType, substType, forExpansion,
3035-
/*isLeaf=*/
3059+
/*isLeafAggregate=*/
30363060
[&](auto ty, auto origTy, auto *field, auto index) -> bool {
3037-
// The field's type is an aggregate. Treat it as a leaf if it is
3038-
// public.
30393061
auto *nominal = ty.getAnyNominal();
3040-
// Non-nominal types are public iff their components are; visit the
3041-
// components.
3062+
// Non-nominal aggregates must not be responsible for non-conformance;
3063+
// walk into them.
30423064
if (!nominal)
30433065
return false;
30443066

3045-
// Nominals with generic parameters must be explicitly conformed to
3046-
// BitwiseCopyable.
3047-
auto *generic = ty.getAnyGeneric();
3048-
if (generic && generic->isGenericContext()) {
3067+
// Nominals with fields that are generic may not conform
3068+
// unconditionally (the only kind automatically derived currently)
3069+
// and so may lack a conformance (case (2)).
3070+
if (nominal->isGenericContext()) {
30493071
return true;
30503072
}
30513073

3052-
return nominal
3053-
->getFormalAccessScope(/*useDC=*/nullptr,
3054-
/*treatUsableFromInlineAsPublic=*/true)
3055-
.isPublic();
3074+
// Resilient trivial types may not conform (case (1)).
3075+
return nominal->isResilient();
30563076
},
30573077
/*visit=*/
30583078
[&](auto ty, auto origTy, auto *field, auto index) -> bool {
30593079
// Return false to indicate seeing a leaf which justifies the type
30603080
// being trivial but not conforming to BitwiseCopyable.
30613081

3082+
auto isTopLevel = !field;
3083+
30623084
// A BitwiseCopyable conformer appearing within its layout doesn't
30633085
// explain why substType doesn't itself conform.
30643086
if (M.checkConformance(ty, bitwiseCopyableProtocol))
30653087
return true;
30663088

3067-
// ModuleTypes are trivial but don't warrant being given a conformance
3068-
// to BitwiseCopyable.
3069-
if (auto mt = dyn_cast<ModuleType>(ty)) {
3070-
// If one were to appear within a type, its lack of conformance
3071-
// wouldn't result in the type's failure to conform. Conversely, if
3072-
// substType itself is the ModuleType, it is trivial and
3073-
// non-conformant; return false to indicate its the leaf which
3074-
// justifies substType being non-conformant.
3075-
return field;
3089+
// ModuleTypes are trivial but don't warrant being given a
3090+
// conformance to BitwiseCopyable (case (3)).
3091+
if (isa<ModuleType, SILTokenType>(ty)) {
3092+
// These types should never appear within aggregates.
3093+
assert(isTopLevel && "aggregate containing marker type!?");
3094+
// If they did, though, they would not justify the aggregate's
3095+
// non-conformance.
3096+
// top-level -> justified to be trivial and non-conformant -> false
3097+
// leaf -> must not be responsible for non-conformance -> true
3098+
return !isTopLevel;
30763099
}
30773100

3078-
// Given a non-bitwise-copyable C, unowned(unsafe) C is still
3079-
// BitwiseCopyable.
3101+
// ReferenceStorageTypes with unmanaged ownership do not themselves
3102+
// conform (case (4)).
30803103
auto rst = dyn_cast<ReferenceStorageType>(ty);
30813104
if (rst && rst->getOwnership() == ReferenceOwnership::Unmanaged) {
3082-
// If a ReferenceStorageType appears as a component of an aggregate,
3083-
// that shouldn't stop the aggregate from being BitwiseCopyable. If
3084-
// the whole type is the ReferenceStorageType, however, it does not
3085-
// conform.
3086-
return field;
3105+
// top-level -> justified to be trivial and non-conformant -> false
3106+
// leaf -> must not be responsible for non-conformance -> true
3107+
return !isTopLevel;
30873108
}
30883109

30893110
auto *nominal = ty.getAnyNominal();
30903111

3091-
// Non-nominal types are trivial iff conforming.
3112+
// Non-nominal types (besides case (3) handled above) are trivial iff
3113+
// conforming.
30923114
if (!nominal) {
30933115
llvm::errs()
30943116
<< "Non-nominal type without conformance to _BitwiseCopyable:\n"
@@ -3099,20 +3121,14 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30993121
return true;
31003122
}
31013123

3102-
/// A non-conforming generic nominal type justifies substType not
3103-
/// conforming.
3104-
auto *generic = ty.getAnyGeneric();
3105-
if (generic && generic->isGenericContext()) {
3124+
// A generic type may be trivial when instantiated with particular
3125+
// types but lack a conformance (case (3)).
3126+
if (nominal->isGenericContext()) {
31063127
return false;
31073128
}
31083129

3109-
// The field is trivial and the whole type is nonconforming. That's
3110-
// legal iff the type is public.
3111-
return !nominal
3112-
->getFormalAccessScope(
3113-
/*useDC=*/nullptr,
3114-
/*treatUsableFromInlineAsPublic=*/true)
3115-
.isPublic();
3130+
// Resilient trivial types may not conform (case (1)).
3131+
return !nominal->isResilient();
31163132
});
31173133
if (hasNoNonconformingNode) {
31183134
llvm::errs() << "Trivial type without a BitwiseCopyable conformance!?:\n"
@@ -3123,8 +3139,8 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
31233139
}
31243140

31253141
if (!lowering.isTrivial() && conformance) {
3126-
// A non-trivial type can only conform if at least one of its leaves is a
3127-
// type parameter that conforms.
3142+
// A non-trivial type can have a conformance in one case:
3143+
// (1) contains a conforming archetype
31283144
bool hasNoConformingArchetypeNode = visitAggregateLeaves(
31293145
origType, substType, forExpansion,
31303146
/*isLeaf=*/
@@ -3139,6 +3155,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
31393155
"leaf of non-trivial BitwiseCopyable type that doesn't "
31403156
"conform to BitwiseCopyable!?");
31413157

3158+
// An archetype may conform but be non-trivial (case (2)).
31423159
if (origTy.isTypeParameter())
31433160
return false;
31443161

@@ -3148,6 +3165,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
31483165
llvm::errs() << "Non-trivial type with _BitwiseCopyable conformance!?:\n"
31493166
<< substType << "\n";
31503167
conformance.print(llvm::errs());
3168+
llvm::errs() << "\n";
31513169
assert(false);
31523170
}
31533171
}

test/SIL/type_lowering_unit.sil

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,14 @@ entry(%instance : $*GE<T>):
9494
%retval = tuple ()
9595
return %retval : $()
9696
}
97+
98+
// CHECK-LABEL: begin {{.*}} token: print_ast_type_lowering with: %instance
99+
// CHECK: isTrivial: true
100+
// CHECK-LABEL: end {{.*}} token: print_ast_type_lowering with: %instance
101+
sil @token : $@convention(thin) (@in Builtin.RawPointer) -> () {
102+
entry(%addr : $*Builtin.RawPointer):
103+
%ptr = address_to_pointer %addr : $*Builtin.RawPointer to $Builtin.RawPointer
104+
%instance = builtin "once"(%ptr : $Builtin.RawPointer, undef : $()) : $Builtin.SILToken
105+
specify_test "print_ast_type_lowering %instance"
106+
return undef : $()
107+
}

test/SILGen/bitwise_copyable.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,11 @@ enum Context<T> {
3939
}
4040

4141
func doit() -> Context<Int>.Here { .init(t: 0) }
42+
43+
public enum E {
44+
case a
45+
}
46+
47+
func take<T : _BitwiseCopyable>(_ t: T) {}
48+
49+
func pass(_ e: E) { take(e) }

0 commit comments

Comments
 (0)