/// Build a map from generic parameter -> source of its metadata at runtime. /// /// If the callee that we are partially applying to create a box/closure /// isn't generic, then the map is empty. MetadataSourceMap getMetadataSourceMap() { MetadataSourceMap SourceMap; if (!OrigCalleeType->isPolymorphic()) return SourceMap; // Any generic parameters that are not fulfilled are passed in via the // bindings. Structural types are decomposed, so emit the contents of // the bindings structure directly. auto &Bindings = Layout.getBindings(); for (unsigned i = 0; i < Bindings.size(); ++i) { // Skip protocol requirements (FIXME: for now?) if (Bindings[i].Protocol != nullptr) continue; auto Source = SourceBuilder.createClosureBinding(i); auto BindingType = Caller.mapTypeOutOfContext(Bindings[i].TypeParameter); SourceMap.push_back({BindingType->getCanonicalType(), Source}); } PolymorphicConvention Convention(IGM, OrigCalleeType); using SourceKind = PolymorphicConvention::SourceKind; // Check if any requirements were fulfilled by metadata stored inside a // captured value. auto GenericSig = OrigCalleeType->getGenericSignature(); auto SubstMap = GenericSig->getSubstitutionMap(Subs); auto Generics = GenericSig->getGenericParams(); for (auto GenericParam : Generics) { auto GenericParamType = GenericParam->getCanonicalType(); auto Fulfillment = Convention.getFulfillmentForTypeMetadata(GenericParamType); if (Fulfillment != nullptr) { auto ConventionSource = Convention.getSource(Fulfillment->SourceIndex); if (ConventionSource.getKind() == SourceKind::SelfMetadata || ConventionSource.getKind() == SourceKind::SelfWitnessTable) { // Handled as part of bindings continue; } // The metadata might be reached via a non-trivial path (eg, // dereferencing an isa pointer or a generic argument). Record // the path. We assume captured values map 1-1 with function // parameters. auto Root = ConventionSource.getMetadataSource(SourceBuilder); auto Src = Fulfillment->Path.getMetadataSource(SourceBuilder, Root); auto SubstType = Caller.mapTypeOutOfContext(SubstMap[GenericParam]); SourceMap.push_back({SubstType->getCanonicalType(), Src}); } } return SourceMap; }
/// Build a map from generic parameter -> source of its metadata at runtime. /// /// If the callee that we are partially applying to create a box/closure /// isn't generic, then the map is empty. MetadataSourceMap getMetadataSourceMap() { MetadataSourceMap SourceMap; // Generic parameters of pseudogeneric functions do not have // runtime metadata. if (!OrigCalleeType->isPolymorphic() || OrigCalleeType->isPseudogeneric()) return SourceMap; // Any generic parameters that are not fulfilled are passed in via the // bindings. Structural types are decomposed, so emit the contents of // the bindings structure directly. auto &Bindings = Layout.getBindings(); for (unsigned i = 0; i < Bindings.size(); ++i) { // Skip protocol requirements (FIXME: for now?) if (Bindings[i].Protocol != nullptr) continue; auto Source = SourceBuilder.createClosureBinding(i); auto BindingType = Bindings[i].TypeParameter; auto InterfaceType = BindingType->mapTypeOutOfContext(); SourceMap.push_back({InterfaceType->getCanonicalType(), Source}); } // Check if any requirements were fulfilled by metadata stored inside a // captured value. enumerateGenericParamFulfillments(IGM, OrigCalleeType, [&](CanType GenericParam, const irgen::MetadataSource &Source, const MetadataPath &Path) { const reflection::MetadataSource *Root; switch (Source.getKind()) { case irgen::MetadataSource::Kind::SelfMetadata: case irgen::MetadataSource::Kind::SelfWitnessTable: // Handled as part of bindings return; case irgen::MetadataSource::Kind::GenericLValueMetadata: // FIXME? return; case irgen::MetadataSource::Kind::ClassPointer: Root = SourceBuilder.createReferenceCapture(Source.getParamIndex()); break; case irgen::MetadataSource::Kind::Metadata: Root = SourceBuilder.createMetadataCapture(Source.getParamIndex()); break; } // The metadata might be reached via a non-trivial path (eg, // dereferencing an isa pointer or a generic argument). Record // the path. We assume captured values map 1-1 with function // parameters. auto Src = Path.getMetadataSource(SourceBuilder, Root); auto SubstType = GenericParam.subst(Subs); auto InterfaceType = SubstType->mapTypeOutOfContext(); SourceMap.push_back({InterfaceType->getCanonicalType(), Src}); }); return SourceMap; }