Skip to content

Commit c982953

Browse files
committed
[Archetype builder] Simplify handling of typealiases in protocols.
PotentialArchetype::getNestedType() was effectively reimplementing a simplified form of mapTypeOutOfContext(), missing some cases in the process. Just use mapTypeOutOfContext() and resolveArchetype(). While here, stop re-implementing the addSameType* operations; just call them directly. With these changes, we no longer need the "typealias in protocol is too complex" diagnostic. Eliminates another use of getSelfTypeInContext().
1 parent 18aa710 commit c982953

File tree

7 files changed

+32
-79
lines changed

7 files changed

+32
-79
lines changed

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/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();

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}}

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)