Skip to content

Commit 38e48ac

Browse files
committed
TypeWitnessSystem: Disable by default
1 parent b83137c commit 38e48ac

File tree

8 files changed

+1009
-331
lines changed

8 files changed

+1009
-331
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ namespace swift {
352352
/// Enable variadic generics.
353353
bool EnableExperimentalVariadicGenerics = false;
354354

355+
/// Enable experimental associated type inference using type witness
356+
/// systems.
357+
bool EnableExperimentalAssociatedTypeInference = false;
358+
355359
/// Disable the implicit import of the _Concurrency module.
356360
bool DisableImplicitConcurrencyModuleImport =
357361
!SWIFT_IMPLICIT_CONCURRENCY_IMPORT;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,10 @@ def enable_experimental_variadic_generics :
556556
Flag<["-"], "enable-experimental-variadic-generics">,
557557
HelpText<"Enable experimental support for variadic generic types">;
558558

559+
def enable_experimental_associated_type_inference :
560+
Flag<["-"], "enable-experimental-associated-type-inference">,
561+
HelpText<"Enable experimental associated type inference via type witness systems">;
562+
559563
def disable_availability_checking : Flag<["-"],
560564
"disable-availability-checking">,
561565
HelpText<"Disable checking for potentially unavailable APIs">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
459459
Opts.EnableExperimentalVariadicGenerics |=
460460
Args.hasArg(OPT_enable_experimental_variadic_generics);
461461

462+
Opts.EnableExperimentalAssociatedTypeInference |=
463+
Args.hasArg(OPT_enable_experimental_associated_type_inference);
464+
462465
Opts.EnableExperimentalMoveOnly |=
463466
Args.hasArg(OPT_enable_experimental_move_only);
464467

lib/Sema/TypeCheckProtocol.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ class TypeWitnessSystem final {
945945
struct TypeWitnessCandidate final {
946946
/// The defaulted associated type declaration correlating with this
947947
/// candidate, if present.
948-
const AssociatedTypeDecl *DefaultedAssocType;
948+
AssociatedTypeDecl *DefaultedAssocType;
949949

950950
/// The equivalence class of this candidate.
951951
EquivalenceClass *EquivClass;
@@ -973,7 +973,7 @@ class TypeWitnessSystem final {
973973

974974
/// Get the defaulted associated type relating to the resolved type witness
975975
/// for the associated type with the given name, if present.
976-
const AssociatedTypeDecl *getDefaultedAssocType(Identifier name) const;
976+
AssociatedTypeDecl *getDefaultedAssocType(Identifier name) const;
977977

978978
/// Record a type witness for the given associated type name.
979979
///
@@ -987,8 +987,7 @@ class TypeWitnessSystem final {
987987
/// defines the given default type.
988988
///
989989
/// \note This need not lead to the resolution of a type witness.
990-
void addDefaultTypeWitness(Type type,
991-
const AssociatedTypeDecl *defaultedAssocType);
990+
void addDefaultTypeWitness(Type type, AssociatedTypeDecl *defaultedAssocType);
992991

993992
/// Record the given same-type requirement, if regarded of interest to
994993
/// the system.

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,26 +1201,56 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
12011201
return nullptr;
12021202
}
12031203

1204-
TypeWitnessSystem system(unresolvedAssocTypes);
1205-
collectAbstractTypeWitnesses(system, unresolvedAssocTypes);
1204+
// Attempt to compute abstract type witnesses for associated types that could
1205+
// not resolve otherwise.
1206+
llvm::SmallVector<AbstractTypeWitness, 2> abstractTypeWitnesses;
12061207

1207-
if (ctx.LangOpts.DumpTypeWitnessSystems) {
1208-
system.dump(llvm::dbgs(), conformance);
1209-
}
1208+
if (ctx.LangOpts.EnableExperimentalAssociatedTypeInference) {
1209+
TypeWitnessSystem system(unresolvedAssocTypes);
1210+
collectAbstractTypeWitnesses(system, unresolvedAssocTypes);
12101211

1211-
// If we couldn't resolve an associated type, bail out.
1212-
for (auto *assocType : unresolvedAssocTypes) {
1213-
if (!system.hasResolvedTypeWitness(assocType->getName())) {
1214-
return assocType;
1212+
if (ctx.LangOpts.DumpTypeWitnessSystems) {
1213+
system.dump(llvm::dbgs(), conformance);
12151214
}
1216-
}
12171215

1218-
// Record the tentative type witnesses to make them available during
1219-
// substitutions.
1220-
for (auto *assocType : unresolvedAssocTypes) {
1221-
typeWitnesses.insert(
1222-
assocType,
1223-
{system.getResolvedTypeWitness(assocType->getName()), reqDepth});
1216+
// If we couldn't resolve an associated type, bail out.
1217+
for (auto *assocType : unresolvedAssocTypes) {
1218+
if (!system.hasResolvedTypeWitness(assocType->getName())) {
1219+
return assocType;
1220+
}
1221+
}
1222+
1223+
// Record the tentative type witnesses to make them available during
1224+
// substitutions.
1225+
for (auto *assocType : unresolvedAssocTypes) {
1226+
auto resolvedTy = system.getResolvedTypeWitness(assocType->getName());
1227+
1228+
typeWitnesses.insert(assocType, {resolvedTy, reqDepth});
1229+
1230+
if (auto *defaultedAssocType =
1231+
system.getDefaultedAssocType(assocType->getName())) {
1232+
abstractTypeWitnesses.emplace_back(assocType, resolvedTy,
1233+
defaultedAssocType);
1234+
} else {
1235+
abstractTypeWitnesses.emplace_back(assocType, resolvedTy);
1236+
}
1237+
}
1238+
} else {
1239+
for (auto *const assocType : unresolvedAssocTypes) {
1240+
// Try to compute the type without the aid of a specific potential
1241+
// witness.
1242+
if (const auto &typeWitness = computeAbstractTypeWitness(assocType)) {
1243+
// Record the type witness immediately to make it available
1244+
// for substitutions into other tentative type witnesses.
1245+
typeWitnesses.insert(assocType, {typeWitness->getType(), reqDepth});
1246+
1247+
abstractTypeWitnesses.push_back(std::move(typeWitness.getValue()));
1248+
continue;
1249+
}
1250+
1251+
// The solution is incomplete.
1252+
return assocType;
1253+
}
12241254
}
12251255

12261256
// Check each abstract type witness against the generic requirements on the
@@ -1237,8 +1267,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
12371267
// associatedtype B: Sequence = Never
12381268
// }
12391269
const auto substOptions = getSubstOptionsWithCurrentTypeWitnesses();
1240-
for (auto *const assocType : unresolvedAssocTypes) {
1241-
Type type = system.getResolvedTypeWitness(assocType->getName());
1270+
for (const auto &witness : abstractTypeWitnesses) {
1271+
auto *const assocType = witness.getAssocType();
1272+
Type type = witness.getType();
1273+
12421274
// Replace type parameters with other known or tentative type witnesses.
12431275
if (type->hasTypeParameter()) {
12441276
// FIXME: We should find a better way to detect and reason about these
@@ -1250,7 +1282,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
12501282
std::function<Type(Type)> substCurrentTypeWitnesses;
12511283
substCurrentTypeWitnesses = [&](Type ty) -> Type {
12521284
if (auto *gp = ty->getAs<GenericTypeParamType>()) {
1253-
if (isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
1285+
// FIXME: 'computeFixedTypeWitness' uses 'getCanonicalTypeInContext',
1286+
// so if a generic parameter is canonical here, it's 'Self'.
1287+
if (gp->isCanonical() ||
1288+
isa<ProtocolDecl>(gp->getDecl()->getDeclContext()->getAsDecl())) {
12541289
return adoptee;
12551290
}
12561291

@@ -1355,8 +1390,7 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
13551390
checkTypeWitness(type, assocType, conformance, substOptions)) {
13561391
// We failed to satisfy a requirement. If this is a default type
13571392
// witness failure and we haven't seen one already, write it down.
1358-
auto *defaultedAssocType =
1359-
system.getDefaultedAssocType(assocType->getName());
1393+
auto *defaultedAssocType = witness.getDefaultedAssocType();
13601394
if (defaultedAssocType && !failedDefaultedAssocType &&
13611395
!failed.isError()) {
13621396
failedDefaultedAssocType = defaultedAssocType;
@@ -2260,7 +2294,7 @@ Type TypeWitnessSystem::getResolvedTypeWitness(Identifier name) const {
22602294
return Type();
22612295
}
22622296

2263-
const AssociatedTypeDecl *
2297+
AssociatedTypeDecl *
22642298
TypeWitnessSystem::getDefaultedAssocType(Identifier name) const {
22652299
assert(this->TypeWitnesses.count(name));
22662300

@@ -2341,7 +2375,7 @@ void TypeWitnessSystem::addTypeWitness(Identifier name, Type type) {
23412375
}
23422376

23432377
void TypeWitnessSystem::addDefaultTypeWitness(
2344-
Type type, const AssociatedTypeDecl *defaultedAssocType) {
2378+
Type type, AssociatedTypeDecl *defaultedAssocType) {
23452379
const auto name = defaultedAssocType->getName();
23462380
assert(this->TypeWitnesses.count(name));
23472381

0 commit comments

Comments
 (0)