SubstitutionMap GenericSignature::getSubstitutionMap(SubstitutionList subs) const { SubstitutionMap result(const_cast<GenericSignature *>(this)); enumeratePairedRequirements( [&](Type depTy, ArrayRef<Requirement> reqts) -> bool { auto sub = subs.front(); subs = subs.slice(1); auto canTy = depTy->getCanonicalType(); if (auto paramTy = dyn_cast<GenericTypeParamType>(canTy)) result.addSubstitution(paramTy, sub.getReplacement()); auto conformances = sub.getConformances(); assert(reqts.size() == conformances.size()); for (unsigned i = 0, e = conformances.size(); i < e; i++) { assert(reqts[i].getSecondType()->getAnyNominal() == conformances[i].getRequirement()); result.addConformance(canTy, conformances[i]); } return false; }); assert(subs.empty() && "did not use all substitutions?!"); result.verify(); return result; }
SubstitutionMap GenericEnvironment:: getSubstitutionMap(SubstitutionList subs) const { SubstitutionMap result; for (auto depTy : getGenericSignature()->getAllDependentTypes()) { // Map the interface type to a context type. auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this), MakeAbstractConformanceForGenericType()); auto sub = subs.front(); subs = subs.slice(1); // Record the replacement type and its conformances. if (auto *archetype = contextTy->getAs<ArchetypeType>()) { result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement()); for (auto conformance : sub.getConformances()) result.addConformance(CanType(archetype), conformance); continue; } // FIXME: getAllDependentTypes() includes generic type parameters that // have been made concrete. assert(contextTy->hasError() || depTy->is<GenericTypeParamType>()); } assert(subs.empty() && "did not use all substitutions?!"); populateParentMap(result); return result; }
static SubstitutionMap getSubstitutionsForProtocolConformance(ProtocolConformanceRef CRef) { auto C = CRef.getConcrete(); // Walk down to the base NormalProtocolConformance. SubstitutionList Subs; const ProtocolConformance *ParentC = C; while (!isa<NormalProtocolConformance>(ParentC)) { switch (ParentC->getKind()) { case ProtocolConformanceKind::Normal: llvm_unreachable("should have exited the loop?!"); case ProtocolConformanceKind::Inherited: ParentC = cast<InheritedProtocolConformance>(ParentC) ->getInheritedConformance(); break; case ProtocolConformanceKind::Specialized: { auto SC = cast<SpecializedProtocolConformance>(ParentC); ParentC = SC->getGenericConformance(); assert(Subs.empty() && "multiple conformance specializations?!"); Subs = SC->getGenericSubstitutions(); break; } } } const NormalProtocolConformance *NormalC = cast<NormalProtocolConformance>(ParentC); // If the normal conformance is for a generic type, and we didn't hit a // specialized conformance, collect the substitutions from the generic type. // FIXME: The AST should do this for us. if (!NormalC->getType()->isSpecialized()) return SubstitutionMap(); if (Subs.empty()) { auto *DC = NormalC->getDeclContext(); return NormalC->getType() ->getContextSubstitutionMap(DC->getParentModule(), DC); } return NormalC->getGenericSignature()->getSubstitutionMap(Subs); }
static ManagedValue emitBuiltinCastBitPatternFromBridgeObject( SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1 && "cast should have one argument"); assert(subs.empty() && "cast should not have subs"); SILType wordType = SILType::getBuiltinWordType(SGF.getASTContext()); SILValue result = SGF.B.createBridgeObjectToWord(loc, args[0].getValue(), wordType); return ManagedValue::forUnmanaged(result); }
ManagedValue SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, CanType expectedType, SubstitutionList subs) { auto closure = *constant.getAnyFunctionRef(); auto captureInfo = closure.getCaptureInfo(); auto loweredCaptureInfo = SGM.Types.getLoweredLocalCaptures(closure); auto hasCaptures = SGM.Types.hasLoweredLocalCaptures(closure); assert(((constant.uncurryLevel == 1 && hasCaptures) || (constant.uncurryLevel == 0 && !hasCaptures)) && "curried local functions not yet supported"); auto constantInfo = getConstantInfo(constant); SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo); SILType functionTy = functionRef->getType(); // Apply substitutions. auto pft = constantInfo.SILFnType; auto *dc = closure.getAsDeclContext()->getParent(); if (dc->isLocalContext() && !loweredCaptureInfo.hasGenericParamCaptures()) { // If the lowered function type is not polymorphic but we were given // substitutions, we have a closure in a generic context which does not // capture generic parameters. Just drop the substitutions. subs = { }; } else if (closure.getAbstractClosureExpr()) { // If we have a closure expression in generic context, Sema won't give // us substitutions, so we just use the forwarding substitutions from // context. subs = getForwardingSubstitutions(); } bool wasSpecialized = false; if (!subs.empty()) { auto specialized = pft->substGenericArgs(F.getModule(), subs); functionTy = SILType::getPrimitiveObjectType(specialized); wasSpecialized = true; } // If we're in top-level code, we don't need to physically capture script // globals, but we still need to mark them as escaping so that DI can flag // uninitialized uses. if (this == SGM.TopLevelSGF) { SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals( loc, captureInfo); } if (!hasCaptures && !wasSpecialized) { auto result = ManagedValue::forUnmanaged(functionRef); return emitOrigToSubstValue(loc, result, AbstractionPattern(expectedType), expectedType); } SmallVector<ManagedValue, 4> capturedArgs; emitCaptures(loc, closure, CaptureEmission::PartialApplication, capturedArgs); // The partial application takes ownership of the context parameters. SmallVector<SILValue, 4> forwardedArgs; for (auto capture : capturedArgs) forwardedArgs.push_back(capture.forward(*this)); SILType closureTy = SILGenBuilder::getPartialApplyResultType(functionRef->getType(), capturedArgs.size(), SGM.M, subs, ParameterConvention::Direct_Owned); auto toClosure = B.createPartialApply(loc, functionRef, functionTy, subs, forwardedArgs, closureTy); auto result = emitManagedRValueWithCleanup(toClosure); // Get the lowered AST types: // - the original type auto origLoweredFormalType = AbstractionPattern(constantInfo.LoweredInterfaceType); if (hasCaptures) { // Get the unlowered formal type of the constant, stripping off // the first level of function application, which applies captures. origLoweredFormalType = AbstractionPattern(constantInfo.FormalInterfaceType) .getFunctionResultType(); // Lower it, being careful to use the right generic signature. origLoweredFormalType = AbstractionPattern( origLoweredFormalType.getGenericSignature(), SGM.Types.getLoweredASTFunctionType( cast<FunctionType>(origLoweredFormalType.getType()), 0, constant)); } // - the substituted type auto substFormalType = cast<FunctionType>(expectedType); auto substLoweredFormalType = SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant); // Generalize if necessary. result = emitOrigToSubstValue(loc, result, origLoweredFormalType, substLoweredFormalType); return result; }