@@ -264,6 +264,54 @@ getTypeRefByFunction(IRGenModule &IGM,
264
264
? genericEnv->mapTypeIntoContext (t)->getCanonicalType ()
265
265
: t;
266
266
267
+ // If a type is noncopyable, lie about the resolved type unless the
268
+ // runtime is sufficiently aware of noncopyable types.
269
+ if (substT->isPureMoveOnly ()) {
270
+ // Darwin-based platforms have ABI stability, and we want binaries
271
+ // that use noncopyable types nongenerically today to be forward
272
+ // compatible with a future OS runtime that supports noncopyable
273
+ // generics. On other platforms, a new Swift compiler and runtime
274
+ // require recompilation anyway, so this dance is unnecessary, and
275
+ // for now, we can unconditionally lie.
276
+ bool useForwardCompatibility =
277
+ IGM.Context .LangOpts .Target .isOSDarwin ();
278
+
279
+ llvm::Instruction *br = nullptr ;
280
+ llvm::BasicBlock *supportedBB = nullptr ;
281
+ if (useForwardCompatibility) {
282
+ auto runtimeSupportsNoncopyableTypesSymbol
283
+ = IGM.Module .getOrInsertGlobal (" swift_runtimeSupportsNoncopyableTypes" ,
284
+ IGM.Int8Ty );
285
+ cast<llvm::GlobalVariable>(runtimeSupportsNoncopyableTypesSymbol)
286
+ ->setLinkage (llvm::GlobalValue::ExternalWeakLinkage);
287
+
288
+ auto runtimeSupportsNoncopyableTypes
289
+ = IGF.Builder .CreateIsNotNull (runtimeSupportsNoncopyableTypesSymbol,
290
+ " supports.noncopyable" );
291
+ supportedBB = IGF.createBasicBlock (" does.support.noncopyable" );
292
+ auto unsupportedBB = IGF.createBasicBlock (" does.not.support.noncopyable" );
293
+ br = IGF.Builder .CreateCondBr (runtimeSupportsNoncopyableTypes,
294
+ supportedBB,
295
+ unsupportedBB);
296
+
297
+ IGF.Builder .emitBlock (unsupportedBB);
298
+ }
299
+
300
+ // If the runtime does not yet support noncopyable types, lie that the
301
+ // field is an empty tuple, so the runtime doesn't try to do anything
302
+ // with the actual value.
303
+ auto phonyRet = IGF.emitTypeMetadataRef (IGM.Context .TheEmptyTupleType );
304
+ IGF.Builder .CreateRet (phonyRet);
305
+
306
+ if (!useForwardCompatibility) {
307
+ goto done_building_function;
308
+ }
309
+
310
+ // Emit the type metadata normally otherwise.
311
+ IGF.Builder .SetInsertPoint (br);
312
+ IGF.Builder .emitBlock (supportedBB);
313
+ }
314
+
267
315
bindFromGenericRequirementsBuffer (
268
316
IGF, requirements,
269
317
Address (bindingsBufPtr, IGM.Int8Ty , IGM.getPointerAlignment ()),
@@ -276,6 +324,7 @@ getTypeRefByFunction(IRGenModule &IGM,
276
324
auto ret = IGF.emitTypeMetadataRef (substT);
277
325
IGF.Builder .CreateRet (ret);
278
326
}
327
+ done_building_function:
279
328
// Form the mangled name with its relative reference.
280
329
auto S = B.beginStruct ();
281
330
S.setPacked (true );
@@ -315,6 +364,21 @@ getTypeRefImpl(IRGenModule &IGM,
315
364
case MangledTypeRefRole::FlatUnique:
316
365
useFlatUnique = true ;
317
366
break ;
367
+
368
+ case MangledTypeRefRole::FieldMetadata:
369
+ // We want to keep fields of noncopyable type from being exposed to
370
+ // in-process runtime reflection libraries in older Swift runtimes, since
371
+ // they more than likely assume they can copy field values, and the language
372
+ // support for noncopyable types as dynamic or generic types isn't yet
373
+ // implemented as of the writing of this comment. If the type is
374
+ // noncopyable, use a function to emit the type ref which will look for a
375
+ // signal from future runtimes whether they support noncopyable types before
376
+ // exposing their metadata to them.
377
+ if (type->isPureMoveOnly ()) {
378
+ IGM.IRGen .noteUseOfTypeMetadata (type);
379
+ return getTypeRefByFunction (IGM, sig, type);
380
+ }
381
+ LLVM_FALLTHROUGH;
318
382
319
383
case MangledTypeRefRole::DefaultAssociatedTypeWitness:
320
384
case MangledTypeRefRole::Metadata:
@@ -724,14 +788,14 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
724
788
if (type->isForeignReferenceType ()) {
725
789
auto opaqueType = type->getASTContext ().getOpaquePointerType ();
726
790
// The standard library's Mirror demangles metadata from field
727
- // descriptors, so use MangledTypeRefRole::Metadata to ensure
791
+ // descriptors, so use MangledTypeRefRole::FieldMetadata to ensure
728
792
// runtime metadata is available.
729
- addTypeRef (opaqueType, genericSig, MangledTypeRefRole::Metadata );
793
+ addTypeRef (opaqueType, genericSig, MangledTypeRefRole::FieldMetadata );
730
794
} else {
731
795
// The standard library's Mirror demangles metadata from field
732
- // descriptors, so use MangledTypeRefRole::Metadata to ensure
796
+ // descriptors, so use MangledTypeRefRole::FieldMetadata to ensure
733
797
// runtime metadata is available.
734
- addTypeRef (type, genericSig, MangledTypeRefRole::Metadata );
798
+ addTypeRef (type, genericSig, MangledTypeRefRole::FieldMetadata );
735
799
}
736
800
}
737
801
0 commit comments