@@ -264,6 +264,54 @@ getTypeRefByFunction(IRGenModule &IGM,
264264 ? genericEnv->mapTypeIntoContext (t)->getCanonicalType ()
265265 : t;
266266
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+
267315 bindFromGenericRequirementsBuffer (
268316 IGF, requirements,
269317 Address (bindingsBufPtr, IGM.Int8Ty , IGM.getPointerAlignment ()),
@@ -276,6 +324,7 @@ getTypeRefByFunction(IRGenModule &IGM,
276324 auto ret = IGF.emitTypeMetadataRef (substT);
277325 IGF.Builder .CreateRet (ret);
278326 }
327+ done_building_function:
279328 // Form the mangled name with its relative reference.
280329 auto S = B.beginStruct ();
281330 S.setPacked (true );
@@ -315,6 +364,21 @@ getTypeRefImpl(IRGenModule &IGM,
315364 case MangledTypeRefRole::FlatUnique:
316365 useFlatUnique = true ;
317366 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;
318382
319383 case MangledTypeRefRole::DefaultAssociatedTypeWitness:
320384 case MangledTypeRefRole::Metadata:
@@ -724,14 +788,14 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
724788 if (type->isForeignReferenceType ()) {
725789 auto opaqueType = type->getASTContext ().getOpaquePointerType ();
726790 // 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
728792 // runtime metadata is available.
729- addTypeRef (opaqueType, genericSig, MangledTypeRefRole::Metadata );
793+ addTypeRef (opaqueType, genericSig, MangledTypeRefRole::FieldMetadata );
730794 } else {
731795 // 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
733797 // runtime metadata is available.
734- addTypeRef (type, genericSig, MangledTypeRefRole::Metadata );
798+ addTypeRef (type, genericSig, MangledTypeRefRole::FieldMetadata );
735799 }
736800 }
737801
0 commit comments