Skip to content

Commit 23e7451

Browse files
authored
Merge pull request swiftlang#6038 from DougGregor/archetypebuilder-typealias
2 parents ebb103c + 633b63b commit 23e7451

16 files changed

+69
-107
lines changed

include/swift/AST/DeclContext.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,13 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
320320
/// \brief Retrieve the innermost archetypes of this context or any
321321
/// of its parents.
322322
GenericEnvironment *getGenericEnvironmentOfContext() const;
323-
323+
324+
/// Map an interface type to a contextual type within this context.
325+
Type mapTypeIntoContext(Type type) const;
326+
327+
/// Map a type within this context to an interface type.
328+
Type mapTypeOutOfContext(Type type) const;
329+
324330
/// Returns this or the first local parent context, or nullptr if it is not
325331
/// contained in one.
326332
DeclContext *getLocalContext();

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,9 +564,6 @@ ERROR(invalid_member_type_suggest,none,
564564
ERROR(invalid_member_reference,none,
565565
"%0 %1 is not a member type of %2",
566566
(DescriptiveDeclKind, Identifier, Type))
567-
ERROR(invalid_member_type_alias,none,
568-
"typealias %0 is too complex to be used as a generic constraint; "
569-
"use an associatedtype instead", (Identifier))
570567
ERROR(ambiguous_member_type,none,
571568
"ambiguous type name %0 in %1", (Identifier, Type))
572569
ERROR(no_module_type,none,

lib/AST/ArchetypeBuilder.cpp

Lines changed: 13 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -426,51 +426,18 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
426426

427427
auto type = alias->getUnderlyingType();
428428
SmallVector<Identifier, 4> identifiers;
429-
430-
if (auto archetype = type->getAs<ArchetypeType>()) {
431-
auto containingProtocol = dyn_cast<ProtocolDecl>(alias->getParent());
432-
if (!containingProtocol) continue;
433-
434-
// Go up archetype parents until we find our containing protocol.
435-
while (archetype->getParent()) {
436-
identifiers.push_back(archetype->getName());
437-
archetype = archetype->getParent();
438-
}
439-
if (!archetype->isEqual(containingProtocol->getSelfTypeInContext()))
440-
continue;
441-
} else if (auto dependent = type->getAs<DependentMemberType>()) {
442-
do {
443-
identifiers.push_back(dependent->getName());
444-
dependent = dependent->getBase()->getAs<DependentMemberType>();
445-
} while (dependent);
429+
430+
// Map the type out of its context.
431+
if (auto genericEnv = alias->getGenericEnvironmentOfContext()) {
432+
type = genericEnv->mapTypeOutOfContext(alias->getModuleContext(),
433+
type);
446434
}
447-
448-
if (identifiers.size()) {
449-
// Go down our PAs until we find the referenced PA.
450-
auto existingPA = this;
451-
while (identifiers.size()) {
452-
auto identifier = identifiers.back();
453-
// If we end up looking for ourselves, don't recurse.
454-
if (existingPA == this && identifier == nestedName) {
455-
existingPA = pa;
456-
} else {
457-
existingPA = existingPA->getNestedType(identifier, builder);
458-
existingPA = existingPA->getRepresentative();
459-
}
460-
identifiers.pop_back();
461-
}
462-
if (pa != existingPA) {
463-
pa->Representative = existingPA;
464-
pa->Representative->EquivalenceClass.push_back(pa);
465-
pa->SameTypeSource = redundantSource;
466-
}
467-
} else if (type->hasArchetype()) {
468-
// This is a complex type involving other associatedtypes, we'll fail
469-
// to resolve and get a special diagnosis in finalize.
470-
continue;
435+
436+
if (auto existingPA = builder.resolveArchetype(type)) {
437+
builder.addSameTypeRequirementBetweenArchetypes(pa, existingPA,
438+
redundantSource);
471439
} else {
472-
pa->ConcreteType = type;
473-
pa->SameTypeSource = redundantSource;
440+
builder.addSameTypeRequirementToConcrete(pa, type, redundantSource);
474441
}
475442
} else
476443
continue;
@@ -488,17 +455,8 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
488455
// case we want to make sure the associatedtype is frontmost to
489456
// generate generics/witness lists correctly, and the alias
490457
// will be unused/useless for generic constraining anyway.
491-
for (auto existing : nested) {
492-
existing->Representative = pa;
493-
existing->Representative->EquivalenceClass.push_back(existing);
494-
existing->SameTypeSource = redundantSource;
495-
}
496458
nested.insert(nested.begin(), pa);
497-
NestedTypes[nestedName] = nested;
498459
} else {
499-
pa->Representative = existing->getRepresentative();
500-
pa->Representative->EquivalenceClass.push_back(pa);
501-
pa->SameTypeSource = redundantSource;
502460
nested.push_back(pa);
503461
}
504462
} else
@@ -1847,25 +1805,10 @@ ArchetypeBuilder::finalize(SourceLoc loc, bool allowConcreteGenericParams) {
18471805
visitPotentialArchetypes([&](PotentialArchetype *pa) {
18481806
// We only care about nested types that haven't been resolved.
18491807
if (pa->getParent() == nullptr || pa->getResolvedAssociatedType() ||
1808+
pa->getTypeAliasDecl() ||
18501809
/* FIXME: Should be able to handle this earlier */pa->getSuperclass())
18511810
return;
18521811

1853-
// If a typealias with this name exists in one of the parent protocols,
1854-
// give a special diagnosis.
1855-
auto parentConformances = pa->getParent()->getConformsTo();
1856-
for (auto &conforms : parentConformances) {
1857-
for (auto member : conforms.first->getMembers()) {
1858-
auto typealias = dyn_cast<TypeAliasDecl>(member);
1859-
if (!typealias || typealias->getName() != pa->getName())
1860-
continue;
1861-
1862-
Context.Diags.diagnose(loc, diag::invalid_member_type_alias,
1863-
pa->getName());
1864-
pa->setInvalid();
1865-
return;
1866-
}
1867-
}
1868-
18691812
// Try to typo correct to a nested type name.
18701813
Identifier correction = typoCorrectNestedType(pa);
18711814
if (correction.empty()) {
@@ -2202,7 +2145,8 @@ GenericEnvironment *ArchetypeBuilder::getGenericEnvironment(
22022145
/*allowUnresolved=*/false);
22032146
auto repInContext = genericEnv->mapTypeIntoContext(&getModule(), repDepTy);
22042147
assert((inContext->isEqual(repInContext) ||
2205-
(inContext->hasError() && repInContext->hasError())) &&
2148+
inContext->hasError() ||
2149+
repInContext->hasError()) &&
22062150
"Potential archetype mapping differs from representative!");
22072151
});
22082152
}

lib/AST/DeclContext.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,20 @@ GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const {
301301
}
302302
}
303303

304+
Type DeclContext::mapTypeIntoContext(Type type) const {
305+
if (auto genericEnv = getGenericEnvironmentOfContext())
306+
return genericEnv->mapTypeIntoContext(getParentModule(), type);
307+
308+
return type;
309+
}
310+
311+
Type DeclContext::mapTypeOutOfContext(Type type) const {
312+
if (auto genericEnv = getGenericEnvironmentOfContext())
313+
return genericEnv->mapTypeOutOfContext(getParentModule(), type);
314+
315+
return type;
316+
}
317+
304318
DeclContext *DeclContext::getLocalContext() {
305319
if (isLocalContext())
306320
return this;

lib/SILGen/SILGenApply.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,6 @@ replaceSelfTypeForDynamicLookup(ASTContext &ctx,
8686
ctx);
8787
}
8888

89-
static Type getExistentialArchetype(SILValue existential) {
90-
CanType ty = existential->getType().getSwiftRValueType();
91-
if (ty->is<ArchetypeType>())
92-
return ty;
93-
return cast<ProtocolType>(ty)->getDecl()->getSelfTypeInContext();
94-
}
95-
9689
/// Retrieve the type to use for a method found via dynamic lookup.
9790
static CanSILFunctionType getDynamicMethodLoweredType(SILGenFunction &gen,
9891
SILValue proto,
@@ -103,7 +96,8 @@ static CanSILFunctionType getDynamicMethodLoweredType(SILGenFunction &gen,
10396
// Determine the opaque 'self' parameter type.
10497
CanType selfTy;
10598
if (methodName.getDecl()->isInstanceMember()) {
106-
selfTy = getExistentialArchetype(proto)->getCanonicalType();
99+
selfTy = proto->getType().getSwiftRValueType();
100+
assert(selfTy->is<ArchetypeType>() && "Dynamic lookup needs an archetype");
107101
} else {
108102
selfTy = proto->getType().getSwiftType();
109103
}

lib/SILGen/SILGenMaterializeForSet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ struct MaterializeForSetEmitter {
201201
ArrayRef<Substitution> witnessSubs) {
202202
auto *dc = witness->getDeclContext();
203203
Type selfInterfaceType = dc->getSelfInterfaceType();
204-
Type selfType = dc->getSelfTypeInContext();
204+
Type selfType = witness->computeSelfType()->getRValueInstanceType();
205205

206206
SILDeclRef constant(witness);
207207
auto constantInfo = SGM.Types.getConstantInfo(constant);

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,13 +1331,7 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD,
13311331
// Borrow the parameters from the requirement declaration.
13321332
SmallVector<ParameterList *, 2> ParamLists;
13331333
if (DC->isTypeContext()) {
1334-
auto self = new (Context) ParamDecl(/*let*/ true, SourceLoc(), SourceLoc(),
1335-
Identifier(), SourceLoc(),
1336-
Context.Id_self,
1337-
DC->getSelfTypeInContext(), DC);
1338-
self->setInterfaceType(DC->getSelfInterfaceType());
1339-
self->setImplicit();
1340-
1334+
auto self = ParamDecl::createSelf(SourceLoc(), DC);
13411335
ParamLists.push_back(ParameterList::create(Context, SourceLoc(),
13421336
self, SourceLoc()));
13431337
ParamLists.back()->get(0)->setImplicit();
@@ -1795,8 +1789,8 @@ void swift::maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC) {
17951789
Type behaviorSelf;
17961790
Type behaviorInterfaceSelf;
17971791
if (dc->isTypeContext()) {
1798-
behaviorSelf = dc->getSelfTypeInContext();
17991792
behaviorInterfaceSelf = dc->getSelfInterfaceType();
1793+
behaviorSelf = dc->mapTypeIntoContext(behaviorInterfaceSelf);
18001794
assert(behaviorSelf && "type context doesn't have self type?!");
18011795
if (var->isStatic())
18021796
behaviorSelf = MetatypeType::get(behaviorSelf);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4616,14 +4616,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
46164616
if (!selfNominal) return;
46174617

46184618
// Check the parameters for a reference to 'Self'.
4619+
auto genericEnv = FD->getGenericEnvironment();
46194620
bool isProtocol = isa<ProtocolDecl>(selfNominal);
46204621
for (auto param : *FD->getParameterList(1)) {
46214622
auto paramType = param->getType();
46224623
if (!paramType) break;
46234624

46244625
// Look through 'inout'.
46254626
paramType = paramType->getInOutObjectType();
4626-
4627+
if (genericEnv) {
4628+
paramType = genericEnv->mapTypeOutOfContext(FD->getModuleContext(),
4629+
paramType);
4630+
}
46274631
// Look through a metatype reference, if there is one.
46284632
if (auto metatypeType = paramType->getAs<AnyMetatypeType>())
46294633
paramType = metatypeType->getInstanceType();
@@ -4636,11 +4640,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
46364640
if (auto genericParam = paramType->getAs<GenericTypeParamType>())
46374641
if (genericParam->isEqual(DC->getSelfInterfaceType()))
46384642
return;
4639-
4640-
// ... or the 'Self' archetype?
4641-
if (auto archetype = paramType->getAs<ArchetypeType>())
4642-
if (archetype->isEqual(DC->getSelfTypeInContext()))
4643-
return;
46444643
}
46454644
}
46464645

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,12 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
232232
// If the nested type comes from a type alias, use either the alias's
233233
// concrete type, or resolve its components down to another dependent member.
234234
if (auto alias = nestedPA->getTypeAliasDecl()) {
235-
return TC.substMemberTypeWithBase(DC->getParentModule(), alias,
236-
baseTy);
235+
Type result = TC.substMemberTypeWithBase(DC->getParentModule(), alias,
236+
baseTy);
237+
238+
// FIXME: Introduce a SubstitutedType so availability checking can use it.
239+
// This is a horrible hack.
240+
return SubstitutedType::get(alias->getAliasType(), result, TC.Context);
237241
}
238242

239243
Identifier name = ref->getIdentifier();

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2392,7 +2392,7 @@ static void diagnoseNoWitness(ValueDecl *Requirement, Type RequirementType,
23922392
Options.AccessibilityFilter = Accessibility::Private;
23932393
Options.PrintAccessibility = false;
23942394
Options.FunctionBody = [](const ValueDecl *VD) { return "<#code#>"; };
2395-
Options.setBaseType(Adopter->getSelfTypeInContext());
2395+
Options.setBaseType(Conformance->getType());
23962396
Options.CurrentModule = Adopter->getParentModule();
23972397
if (!Adopter->isExtensionContext()) {
23982398
// Create a variable declaration instead of a computed property in

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
942942
// while the 'Self' type is more than just a reference to a TypeDecl.
943943

944944
return DynamicSelfType::get(
945-
func->getDeclContext()->getSelfTypeInContext(),
945+
func->computeSelfType()->getRValueInstanceType(),
946946
TC.Context);
947947
}
948948

test/decl/typealias/protocol.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ protocol P2 {
110110
associatedtype B
111111
}
112112

113-
func go3<T : P1, U : P2>(_ x: T) -> U where T.F == U.B { // expected-error {{typealias 'F' is too complex to be used as a generic constraint; use an associatedtype instead}} expected-error {{'F' is not a member type of 'T'}}
113+
func go3<T : P1, U : P2>(_ x: T) -> U where T.F == U.B {
114114
}
115115

116116
// Specific diagnosis for things that look like Swift 2.x typealiases
@@ -179,3 +179,12 @@ struct S7 : P7 {
179179
_ = Y.self
180180
}
181181
}
182+
183+
protocol P8 {
184+
associatedtype B
185+
186+
@available(*, unavailable, renamed: "B")
187+
typealias A = B // expected-note{{'A' has been explicitly marked unavailable here}}
188+
}
189+
190+
func testP8<T: P8>(_: T) where T.A == Int { } // expected-error{{'A' has been renamed to 'B'}}{{34-35=B}}

test/stdlib/Renames.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func _Collection() {
5959
}
6060

6161
func _Collection<C : Collection>(c: C) {
62-
func fn<T : Collection, U>(_: T, _: U) where T.Generator == U {} // expected-error {{'T' does not have a member type named 'Generator'; did you mean 'Iterator'?}} {{50-59=Iterator}} {{none}}
62+
func fn<T : Collection, U>(_: T, _: U) where T.Generator == U {} // expected-error {{'Generator' has been renamed to 'Iterator'}} {{50-59=Iterator}} {{none}}
6363
_ = c.generate() // expected-error {{'generate()' has been renamed to 'makeIterator()'}} {{9-17=makeIterator}} {{none}}
6464
_ = c.underestimateCount() // expected-error {{'underestimateCount()' has been replaced by 'underestimatedCount'}} {{9-27=underestimatedCount}} {{27-29=}} {{none}}
6565
_ = c.split(1) { _ in return true} // expected-error {{split(maxSplits:omittingEmptySubsequences:whereSeparator:) instead}} {{none}}

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,8 +1260,10 @@ resolveCursorFromUSR(SwiftLangSupport &Lang, StringRef InputFile, StringRef USR,
12601260
} else if (auto *VD = dyn_cast<ValueDecl>(D)) {
12611261
auto *DC = VD->getDeclContext();
12621262
Type selfTy;
1263-
if (DC->isTypeContext())
1264-
selfTy = DC->getSelfTypeInContext();
1263+
if (DC->isTypeContext()) {
1264+
selfTy = DC->getSelfInterfaceType();
1265+
selfTy = VD->getInnermostDeclContext()->mapTypeIntoContext(selfTy);
1266+
}
12651267
bool Failed =
12661268
passCursorInfoForDecl(VD, MainModule, selfTy, Type(),
12671269
/*isRef=*/false, BufferID, Lang, CompInvok,

validation-test/compiler_crashers/28448-dist-nested-type-should-have-matched-associated-type-failed.swift renamed to validation-test/compiler_crashers_fixed/28448-dist-nested-type-should-have-matched-associated-type-failed.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
9-
// REQUIRES: asserts
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
extension A{func c:f.c:typealias e:A{}}protocol A{typealias f{}typealias e

validation-test/compiler_crashers/28468-segfault-0xd09050-0xd08dfd-0xbe9d76-0xbeb154.swift renamed to validation-test/compiler_crashers_fixed/28468-segfault-0xd09050-0xd08dfd-0xbe9d76-0xbeb154.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
protocol A{typealias B>typealias B<a>:a}extension A

0 commit comments

Comments
 (0)