Skip to content

SIL type lowering support for closures that capture pack element archetypes #73393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
4 changes: 3 additions & 1 deletion include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1276,8 +1276,10 @@ class SILFunction
GenericEnvironment *getGenericEnvironment() const {
return GenericEnv;
}
void setGenericEnvironment(GenericEnvironment *env) {
void setGenericEnvironment(GenericEnvironment *env,
SubstitutionMap forwardingSubs=SubstitutionMap()) {
GenericEnv = env;
ForwardingSubMap = forwardingSubs;
}

/// Retrieve the generic signature from the generic environment of this
Expand Down
34 changes: 32 additions & 2 deletions include/swift/SIL/TypeLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,28 @@ struct FunctionTypeInfo {
CanSILFunctionType ExpectedLoweredType;
};

/// Return type of getGenericSignatureWithCapturedEnvironments().
struct GenericSignatureWithCapturedEnvironments {
GenericSignature baseGenericSig;
GenericSignature genericSig;
ArrayRef<GenericEnvironment *> capturedEnvs;

explicit GenericSignatureWithCapturedEnvironments() {}

explicit GenericSignatureWithCapturedEnvironments(
GenericSignature baseGenericSig)
: baseGenericSig(baseGenericSig),
genericSig(baseGenericSig) {}

GenericSignatureWithCapturedEnvironments(
GenericSignature baseGenericSig,
GenericSignature genericSig,
ArrayRef<GenericEnvironment *> capturedEnvs)
: baseGenericSig(baseGenericSig),
genericSig(genericSig),
capturedEnvs(capturedEnvs) {}
};

/// TypeConverter - helper class for creating and managing TypeLowerings.
class TypeConverter {
friend class TypeLowering;
Expand Down Expand Up @@ -1047,12 +1069,20 @@ class TypeConverter {
const SILConstantInfo &getConstantInfo(TypeExpansionContext context,
SILDeclRef constant);

/// Get the generic environment for a constant.
GenericSignature getConstantGenericSignature(SILDeclRef constant);
/// Get the generic signature for a constant.
GenericSignatureWithCapturedEnvironments
getGenericSignatureWithCapturedEnvironments(SILDeclRef constant);

/// Get the generic environment for a constant.
GenericEnvironment *getConstantGenericEnvironment(SILDeclRef constant);

/// Get the generic environment for SILGen to use. The substitution map
/// sends the generic parameters of the function's interface type into
/// archetypes, which will either be primary archetypes from this
/// environment, or local archetypes captured by this function.
std::pair<GenericEnvironment *, SubstitutionMap>
getForwardingSubstitutionsForLowering(SILDeclRef constant);

/// Returns the SIL type of a constant reference.
SILType getConstantType(TypeExpansionContext context, SILDeclRef constant) {
return getConstantInfo(context, constant).getSILType();
Expand Down
27 changes: 21 additions & 6 deletions lib/AST/RequirementMachine/GenericSignatureQueries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ Type RequirementMachine::getReducedType(

// Get a type (concrete or dependent) for U.
auto prefixType = [&]() -> Type {
if (prefix.empty())
return Type();

verify(prefix);

auto *props = Map.lookUpProperties(prefix);
Expand Down Expand Up @@ -461,13 +464,25 @@ Type RequirementMachine::getReducedType(

// If U is not concrete, we have an invalid member type of a dependent
// type, which is not valid in this generic signature. Give up.
if (prefixType->isTypeParameter()) {
llvm::errs() << "Invalid type parameter in getReducedType()\n";
llvm::errs() << "Original type: " << type << "\n";
llvm::errs() << "Simplified term: " << term << "\n";
llvm::errs() << "Longest valid prefix: " << prefix << "\n";
llvm::errs() << "Prefix type: " << prefixType << "\n";
if (prefix.empty() || prefixType->isTypeParameter()) {
llvm::errs() << "\n";
llvm::errs() << "getReducedType() was called\n";
llvm::errs() << " with " << Sig << ",\n";
llvm::errs() << " and " << type << ".\n\n";
llvm::errs() << "This type contains the type parameter " << t << ".\n\n";
if (prefix.empty()) {
llvm::errs() << "This type parameter contains the generic parameter "
<< Type(t->getRootGenericParam()) << ".\n\n";
llvm::errs() << "This generic parameter is not part of the given "
<< "generic signature.\n\n";
} else {
llvm::errs() << "This type parameter's reduced term is " << term << ".\n\n";
llvm::errs() << "This is not a valid term, because " << prefix << " does not "
<< "have a member type named " << term[prefix.size()] << ".\n\n";
}
llvm::errs() << "This usually indicates the caller passed the wrong type or "
<< "generic signature to getReducedType().\n\n";

dump(llvm::errs());
abort();
}
Expand Down
43 changes: 28 additions & 15 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1934,11 +1934,7 @@ void updateResultTypeForForeignInfo(
llvm_unreachable("unhandled kind");
}

/// Lower any/all capture context parameters.
///
/// *NOTE* Currently default arg generators can not capture anything.
/// If we ever add that ability, it will be a different capture list
/// from the function to which the argument is attached.
/// Captured values become SIL function parameters in this function.
static void
lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
CanGenericSignature genericSig,
Expand All @@ -1962,28 +1958,38 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
// signature from the AST for that.
auto origGenericSig = function.getAnyFunctionRef()->getGenericSignature();
auto loweredCaptures = TC.getLoweredLocalCaptures(function);
auto capturedEnvs = loweredCaptures.getGenericEnvironments();
auto *isolatedParam = loweredCaptures.getIsolatedParamCapture();

auto mapTypeOutOfContext = [&](Type t) -> CanType {
LLVM_DEBUG(llvm::dbgs() << "-- capture with contextual type " << t << "\n");

t = t.subst(MapLocalArchetypesOutOfContext(origGenericSig, capturedEnvs),
MakeAbstractConformanceForGenericType(),
SubstFlags::PreservePackExpansionLevel);

LLVM_DEBUG(llvm::dbgs() << "-- maps to " << t->getCanonicalType() << "\n");
return t->getCanonicalType();
};

for (auto capture : loweredCaptures.getCaptures()) {
if (capture.isDynamicSelfMetadata()) {
ParameterConvention convention = ParameterConvention::Direct_Unowned;
auto dynamicSelfInterfaceType =
loweredCaptures.getDynamicSelfType()->mapTypeOutOfContext();
mapTypeOutOfContext(loweredCaptures.getDynamicSelfType());

auto selfMetatype = MetatypeType::get(dynamicSelfInterfaceType,
MetatypeRepresentation::Thick);
auto selfMetatype = CanMetatypeType::get(dynamicSelfInterfaceType,
MetatypeRepresentation::Thick);

auto canSelfMetatype = selfMetatype->getReducedType(origGenericSig);
SILParameterInfo param(canSelfMetatype, convention);
SILParameterInfo param(selfMetatype, convention);
inputs.push_back(param);

continue;
}

if (capture.isOpaqueValue()) {
OpaqueValueExpr *opaqueValue = capture.getOpaqueValue();
auto canType = opaqueValue->getType()->mapTypeOutOfContext()
->getReducedType(origGenericSig);
auto canType = mapTypeOutOfContext(opaqueValue->getType());
auto &loweredTL =
TC.getTypeLowering(AbstractionPattern(genericSig, canType),
canType, expansion);
Expand All @@ -2001,9 +2007,16 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
continue;
}

auto *varDecl = capture.getDecl();
auto type = varDecl->getInterfaceType();
auto canType = type->getReducedType(origGenericSig);
auto *varDecl = cast<VarDecl>(capture.getDecl());

auto type = varDecl->getTypeInContext();
assert(!type->hasLocalArchetype() ||
(genericSig && origGenericSig &&
!genericSig->isEqual(origGenericSig)));
type = mapTypeOutOfContext(type);

auto canType = type->getReducedType(
genericSig ? genericSig : origGenericSig);

auto options = SILParameterInfo::Options();
if (isolatedParam == varDecl) {
Expand Down
Loading