Skip to content

AST: Try harder to preserve type sugar in AbstractGenericSignatureRequest #33619

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,7 @@ class SpecializeAttr : public DeclAttribute {

TrailingWhereClause *getTrailingWhereClause() const;

GenericSignature getSpecializedSgnature() const {
GenericSignature getSpecializedSignature() const {
return specializedSignature;
}

Expand Down
7 changes: 0 additions & 7 deletions include/swift/AST/GenericEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
std::pair<Type, ProtocolConformanceRef>
mapConformanceRefIntoContext(Type conformingType,
ProtocolConformanceRef conformance) const;

/// Get the sugared form of a generic parameter type.
GenericTypeParamType *getSugaredType(GenericTypeParamType *type) const;

/// Get the sugared form of a type by substituting any
/// generic parameter types by their sugared form.
Type getSugaredType(Type type) const;

SubstitutionMap getForwardingSubstitutionMap() const;

Expand Down
9 changes: 8 additions & 1 deletion include/swift/AST/GenericSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,11 +397,18 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
/// <t_0_0, t_0_1, t_1_0>
/// then this will return 0 for t_0_0, 1 for t_0_1, and 2 for t_1_0.
unsigned getGenericParamOrdinal(GenericTypeParamType *param) const;

/// Get a substitution map that maps all of the generic signature's
/// generic parameters to themselves.
SubstitutionMap getIdentitySubstitutionMap() const;

/// Get the sugared form of a generic parameter type.
GenericTypeParamType *getSugaredType(GenericTypeParamType *type) const;

/// Get the sugared form of a type by substituting any
/// generic parameter types by their sugared form.
Type getSugaredType(Type type) const;

/// Whether this generic signature involves a type variable.
bool hasTypeVariable() const;

Expand Down
6 changes: 3 additions & 3 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

namespace swift {
class ASTPrinter;
class GenericEnvironment;
class GenericSignatureImpl;
class CanType;
class Decl;
class Pattern;
Expand Down Expand Up @@ -423,8 +423,8 @@ struct PrintOptions {
/// Replaces the name of private and internal properties of types with '_'.
bool OmitNameOfInaccessibleProperties = false;

/// Print dependent types as references into this generic environment.
GenericEnvironment *GenericEnv = nullptr;
/// Use this signature to re-sugar dependent types.
const GenericSignatureImpl *GenericSig = nullptr;

/// Print types with alternative names from their canonical names.
llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr;
Expand Down
20 changes: 10 additions & 10 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
Expand Down Expand Up @@ -2488,14 +2488,14 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
Printer << " = ";
// FIXME: An inferred associated type witness type alias may reference
// an opaque type, but OpaqueTypeArchetypes are always canonicalized
// so lose type sugar for generic params. Bind the generic environment so
// we can map params back into the generic environment and print them
// so lose type sugar for generic params. Bind the generic signature so
// we can map params back into the generic signature and print them
// correctly.
//
// Remove this when we have a way to represent non-canonical archetypes
// preserving sugar.
llvm::SaveAndRestore<GenericEnvironment*> setGenericEnv(Options.GenericEnv,
decl->getGenericEnvironment());
llvm::SaveAndRestore<const GenericSignatureImpl *> setGenericSig(
Options.GenericSig, decl->getGenericSignature().getPointer());
printTypeLoc(TypeLoc(decl->getUnderlyingTypeRepr(), Ty));
printDeclGenericRequirements(decl);
}
Expand Down Expand Up @@ -4319,7 +4319,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
Optional<TypePrinter> subBuffer;
PrintOptions subOptions = Options;
if (auto substitutions = T->getPatternSubstitutions()) {
subOptions.GenericEnv = nullptr;
subOptions.GenericSig = nullptr;
subBuffer.emplace(Printer, subOptions);
sub = &*subBuffer;

Expand Down Expand Up @@ -4411,7 +4411,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
// A box layout has its own independent generic environment. Don't try
// to print it with the environment's generic params.
PrintOptions subOptions = Options;
subOptions.GenericEnv = nullptr;
subOptions.GenericSig = nullptr;
TypePrinter sub(Printer, subOptions);

// Capture list used here to ensure we don't print anything using `this`
Expand Down Expand Up @@ -4594,10 +4594,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}
}

// When printing SIL types, use a generic environment to map them from
// When printing SIL types, use a generic signature to map them from
// canonical types to sugared types.
if (Options.GenericEnv)
T = Options.GenericEnv->getSugaredType(T);
if (Options.GenericSig)
T = Options.GenericSig->getSugaredType(T);
}

auto Name = T->getName();
Expand Down
55 changes: 8 additions & 47 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,32 +589,11 @@ static void printDifferentiableAttrArguments(
if (!isLeadingClause)
stream << ' ';
stream << "where ";
std::function<Type(Type)> getInterfaceType;
if (!original || !original->getGenericEnvironment()) {
getInterfaceType = [](Type Ty) -> Type { return Ty; };
} else {
// Use GenericEnvironment to produce user-friendly
// names instead of something like 't_0_0'.
auto *genericEnv = original->getGenericEnvironment();
assert(genericEnv);
getInterfaceType = [=](Type Ty) -> Type {
return genericEnv->getSugaredType(Ty);
};
}
interleave(requirementsToPrint, [&](Requirement req) {
if (const auto &originalGenSig = original->getGenericSignature())
if (originalGenSig->isRequirementSatisfied(req))
return;
auto FirstTy = getInterfaceType(req.getFirstType());
if (req.getKind() != RequirementKind::Layout) {
auto SecondTy = getInterfaceType(req.getSecondType());
Requirement ReqWithDecls(req.getKind(), FirstTy, SecondTy);
ReqWithDecls.print(stream, Options);
} else {
Requirement ReqWithDecls(req.getKind(), FirstTy,
req.getLayoutConstraint());
ReqWithDecls.print(stream, Options);
}
req.print(stream, Options);
}, [&] {
stream << ", ";
});
Expand Down Expand Up @@ -928,25 +907,16 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
Printer << "kind: " << kind << ", ";
SmallVector<Requirement, 4> requirementsScratch;
ArrayRef<Requirement> requirements;
if (auto sig = attr->getSpecializedSgnature())
if (auto sig = attr->getSpecializedSignature())
requirements = sig->getRequirements();

std::function<Type(Type)> GetInterfaceType;
auto *FnDecl = dyn_cast_or_null<AbstractFunctionDecl>(D);
if (!FnDecl || !FnDecl->getGenericEnvironment())
GetInterfaceType = [](Type Ty) -> Type { return Ty; };
else {
// Use GenericEnvironment to produce user-friendly
// names instead of something like t_0_0.
auto *GenericEnv = FnDecl->getGenericEnvironment();
assert(GenericEnv);
GetInterfaceType = [=](Type Ty) -> Type {
return GenericEnv->getSugaredType(Ty);
};

if (auto sig = attr->getSpecializedSgnature()) {
if (FnDecl && FnDecl->getGenericSignature()) {
auto genericSig = FnDecl->getGenericSignature();

if (auto sig = attr->getSpecializedSignature()) {
requirementsScratch = sig->requirementsNotSatisfiedBy(
GenericEnv->getGenericSignature());
genericSig);
requirements = requirementsScratch;
}
}
Expand All @@ -957,16 +927,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,

interleave(requirements,
[&](Requirement req) {
auto FirstTy = GetInterfaceType(req.getFirstType());
if (req.getKind() != RequirementKind::Layout) {
auto SecondTy = GetInterfaceType(req.getSecondType());
Requirement ReqWithDecls(req.getKind(), FirstTy, SecondTy);
ReqWithDecls.print(Printer, Options);
} else {
Requirement ReqWithDecls(req.getKind(), FirstTy,
req.getLayoutConstraint());
ReqWithDecls.print(Printer, Options);
}
req.print(Printer, Options);
},
[&] { Printer << ", "; });

Expand Down
21 changes: 0 additions & 21 deletions lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,27 +171,6 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
return result;
}

GenericTypeParamType *GenericEnvironment::getSugaredType(
GenericTypeParamType *type) const {
for (auto *sugaredType : getGenericParams())
if (sugaredType->isEqual(type))
return sugaredType;

llvm_unreachable("missing generic parameter");
}

Type GenericEnvironment::getSugaredType(Type type) const {
if (!type->hasTypeParameter())
return type;

return type.transform([this](Type Ty) -> Type {
if (auto GP = dyn_cast<GenericTypeParamType>(Ty.getPointer())) {
return Type(getSugaredType(GP));
}
return Ty;
});
}

SubstitutionMap GenericEnvironment::getForwardingSubstitutionMap() const {
auto genericSig = getGenericSignature();
return SubstitutionMap::get(genericSig,
Expand Down
21 changes: 19 additions & 2 deletions lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1037,10 +1037,27 @@ SubstitutionMap GenericSignatureImpl::getIdentitySubstitutionMap() const {
MakeAbstractConformanceForGenericType());
}

GenericTypeParamType *GenericSignatureImpl::getSugaredType(
GenericTypeParamType *type) const {
unsigned ordinal = getGenericParamOrdinal(type);
return getGenericParams()[ordinal];
}

Type GenericSignatureImpl::getSugaredType(Type type) const {
if (!type->hasTypeParameter())
return type;

return type.transform([this](Type Ty) -> Type {
if (auto GP = dyn_cast<GenericTypeParamType>(Ty.getPointer())) {
return Type(getSugaredType(GP));
}
return Ty;
});
}

unsigned GenericSignatureImpl::getGenericParamOrdinal(
GenericTypeParamType *param) const {
return GenericParamKey(param->getDepth(), param->getIndex())
.findIndexIn(getGenericParams());
return GenericParamKey(param).findIndexIn(getGenericParams());
}

bool GenericSignatureImpl::hasTypeVariable() const {
Expand Down
13 changes: 4 additions & 9 deletions lib/AST/GenericSignatureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7430,13 +7430,11 @@ AbstractGenericSignatureRequest::evaluate(
if (baseSignature)
canBaseSignature = baseSignature->getCanonicalSignature();

llvm::SmallDenseMap<GenericTypeParamType *, Type> mappedTypeParameters;
SmallVector<GenericTypeParamType *, 2> canAddedParameters;
canAddedParameters.reserve(addedParameters.size());
for (auto gp : addedParameters) {
auto canGP = gp->getCanonicalType()->castTo<GenericTypeParamType>();
canAddedParameters.push_back(canGP);
mappedTypeParameters[canGP] = Type(gp);
}

SmallVector<Requirement, 2> canAddedRequirements;
Expand All @@ -7453,10 +7451,8 @@ AbstractGenericSignatureRequest::evaluate(
if (!canSignatureResult || !*canSignatureResult)
return GenericSignature();

// Substitute in the original generic parameters to form a more-sugared
// result closer to what the original request wanted. Note that this
// loses sugar on concrete types, but for abstract signatures that
// shouldn't matter.
// Substitute in the original generic parameters to form the sugared
// result the original request wanted.
auto canSignature = *canSignatureResult;
SmallVector<GenericTypeParamType *, 2> resugaredParameters;
resugaredParameters.reserve(canSignature->getGenericParams().size());
Expand All @@ -7474,9 +7470,8 @@ AbstractGenericSignatureRequest::evaluate(
auto resugaredReq = req.subst(
[&](SubstitutableType *type) {
if (auto gp = dyn_cast<GenericTypeParamType>(type)) {
auto knownGP = mappedTypeParameters.find(gp);
if (knownGP != mappedTypeParameters.end())
return knownGP->second;
unsigned ordinal = canSignature->getGenericParamOrdinal(gp);
return Type(resugaredParameters[ordinal]);
}
return Type(type);
},
Expand Down
2 changes: 1 addition & 1 deletion lib/PrintAsObjC/DeclAndTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1909,7 +1909,7 @@ class DeclAndTypePrinter::Implementation
assert(extension->getGenericSignature().getCanonicalSignature() ==
extendedClass->getGenericSignature().getCanonicalSignature() &&
"constrained extensions or custom generic parameters?");
type = extendedClass->getGenericEnvironment()->getSugaredType(type);
type = extendedClass->getGenericSignature()->getSugaredType(type);
decl = type->getDecl();
}

Expand Down
2 changes: 1 addition & 1 deletion lib/SIL/IR/SILFunctionBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void SILFunctionBuilder::addFunctionAttributes(
? SILSpecializeAttr::SpecializationKind::Full
: SILSpecializeAttr::SpecializationKind::Partial;
F->addSpecializeAttr(
SILSpecializeAttr::create(M, SA->getSpecializedSgnature(),
SILSpecializeAttr::create(M, SA->getSpecializedSignature(),
SA->isExported(), kind));
}

Expand Down
Loading