Skip to content

Commit 6828a12

Browse files
committed
Sema: Remove unnecessary circularity breaks
1 parent 044204a commit 6828a12

File tree

12 files changed

+35
-81
lines changed

12 files changed

+35
-81
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,7 @@ class UnderlyingTypeRequest :
12091209
bool isCached() const { return true; }
12101210
Optional<Type> getCachedResult() const;
12111211
void cacheResult(Type value) const;
1212+
void diagnoseCycle(DiagnosticEngine &diags) const;
12121213
};
12131214

12141215
class OperatorPrecedenceGroupRequest

lib/AST/TypeCheckRequests.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "swift/AST/ASTContext.h"
1313
#include "swift/AST/Decl.h"
1414
#include "swift/AST/DiagnosticsCommon.h"
15+
#include "swift/AST/DiagnosticsSema.h"
1516
#include "swift/AST/Module.h"
1617
#include "swift/AST/NameLookup.h"
1718
#include "swift/AST/PropertyWrappers.h"
@@ -855,6 +856,13 @@ void UnderlyingTypeRequest::cacheResult(Type value) const {
855856
typeAlias->UnderlyingTy.setType(value);
856857
}
857858

859+
void UnderlyingTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
860+
auto aliasDecl = std::get<0>(getStorage());
861+
diags.diagnose(aliasDecl, diag::recursive_decl_reference,
862+
aliasDecl->getDescriptiveKind(),
863+
aliasDecl->getName());
864+
}
865+
858866
//----------------------------------------------------------------------------//
859867
// EnumRawValuesRequest computation.
860868
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckDecl.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3901,23 +3901,17 @@ void TypeChecker::validateDecl(ValueDecl *D) {
39013901
case DeclKind::AssociatedType: {
39023902
auto assocType = cast<AssociatedTypeDecl>(D);
39033903

3904-
DeclValidationRAII IBV(assocType);
3905-
3906-
// Finally, set the interface type.
3907-
if (!assocType->hasInterfaceType())
3908-
assocType->computeType();
3904+
assocType->computeType();
3905+
assocType->setValidationToChecked();
39093906

39103907
break;
39113908
}
39123909

39133910
case DeclKind::TypeAlias: {
39143911
auto typeAlias = cast<TypeAliasDecl>(D);
39153912

3916-
DeclValidationRAII IBV(typeAlias);
3917-
3918-
// Finally, set the interface type.
3919-
if (!typeAlias->hasInterfaceType())
3920-
typeAlias->computeType();
3913+
typeAlias->computeType();
3914+
typeAlias->setValidationToChecked();
39213915

39223916
break;
39233917
}
@@ -3953,8 +3947,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
39533947

39543948
case DeclKind::Protocol: {
39553949
auto proto = cast<ProtocolDecl>(D);
3956-
if (!proto->hasInterfaceType())
3957-
proto->computeType();
3950+
proto->computeType();
39583951
proto->setValidationToChecked();
39593952

39603953
break;

lib/Sema/TypeCheckType.cpp

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -214,22 +214,16 @@ Type TypeResolution::resolveDependentMemberType(
214214
ref->setValue(singleType, nullptr);
215215
}
216216

217+
auto *concrete = ref->getBoundDecl();
218+
217219
// If the nested type has been resolved to an associated type, use it.
218-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(ref->getBoundDecl())) {
220+
if (auto assocType = dyn_cast<AssociatedTypeDecl>(concrete)) {
219221
return DependentMemberType::get(baseTy, assocType);
220222
}
221223

222224
// Otherwise, the nested type comes from a concrete type,
223225
// or it's a typealias declared in protocol or protocol extension.
224226
// Substitute the base type into it.
225-
auto concrete = ref->getBoundDecl();
226-
if (!concrete->getInterfaceType()) {
227-
ctx.Diags.diagnose(ref->getIdLoc(), diag::recursive_decl_reference,
228-
concrete->getDescriptiveKind(), concrete->getName());
229-
concrete->diagnose(diag::kind_declared_here,
230-
DescriptiveDeclKind::Type);
231-
return ErrorType::get(ctx);
232-
}
233227

234228
// Make sure that base type didn't get replaced along the way.
235229
assert(baseTy->isTypeParameter());
@@ -713,16 +707,6 @@ Type TypeChecker::applyGenericArguments(Type type,
713707
}
714708
}
715709

716-
// Cannot extend a bound generic type.
717-
if (options.is(TypeResolverContext::ExtensionBinding)) {
718-
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
719-
diags.diagnose(loc, diag::extension_specialization,
720-
genericDecl->getName())
721-
.highlight(generic->getSourceRange());
722-
}
723-
return ErrorType::get(ctx);
724-
}
725-
726710
// FIXME: More principled handling of circularity.
727711
if (!genericDecl->getGenericSignature()) {
728712
diags.diagnose(loc, diag::recursive_decl_reference,
@@ -934,33 +918,6 @@ static Type resolveTypeDecl(TypeDecl *typeDecl, SourceLoc loc,
934918
DeclContext *foundDC, TypeResolution resolution,
935919
GenericIdentTypeRepr *generic,
936920
TypeResolutionOptions options) {
937-
auto fromDC = resolution.getDeclContext();
938-
assert(fromDC && "No declaration context for type resolution?");
939-
940-
ASTContext &ctx = typeDecl->getASTContext();
941-
auto &diags = ctx.Diags;
942-
943-
// Hack: Don't validate nested typealiases if we only need the structural
944-
// type.
945-
auto prevalidatingAlias = [](TypeDecl *typeDecl, TypeResolution res) {
946-
return isa<TypeAliasDecl>(typeDecl)
947-
&& !typeDecl->hasInterfaceType()
948-
&& typeDecl->getDeclContext()->isTypeContext()
949-
&& res.getStage() == TypeResolutionStage::Structural;
950-
};
951-
952-
// Don't validate nominal type declarations during extension binding.
953-
if ((!options.is(TypeResolverContext::ExtensionBinding) ||
954-
!isa<NominalTypeDecl>(typeDecl)) &&
955-
!prevalidatingAlias(typeDecl, resolution)) {
956-
// If we were not able to validate recursively, bail out.
957-
if (!typeDecl->getInterfaceType()) {
958-
diags.diagnose(loc, diag::recursive_decl_reference,
959-
typeDecl->getDescriptiveKind(), typeDecl->getName());
960-
typeDecl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type);
961-
return ErrorType::get(ctx);
962-
}
963-
}
964921

965922
// Resolve the type declaration to a specific type. How this occurs
966923
// depends on the current context and where the type was found.
@@ -971,11 +928,13 @@ static Type resolveTypeDecl(TypeDecl *typeDecl, SourceLoc loc,
971928
!options.is(TypeResolverContext::TypeAliasDecl) &&
972929
!options.contains(TypeResolutionFlags::AllowUnboundGenerics)) {
973930
diagnoseUnboundGenericType(type, loc);
974-
return ErrorType::get(ctx);
931+
return ErrorType::get(typeDecl->getASTContext());
975932
}
976933

977934
if (type->hasError() && foundDC &&
978935
(isa<AssociatedTypeDecl>(typeDecl) || isa<TypeAliasDecl>(typeDecl))) {
936+
auto fromDC = resolution.getDeclContext();
937+
assert(fromDC && "No declaration context for type resolution?");
979938
maybeDiagnoseBadConformanceRef(fromDC, foundDC->getDeclaredInterfaceType(),
980939
loc, typeDecl);
981940
}
@@ -3477,8 +3436,6 @@ class UnsupportedProtocolVisitor
34773436
T->setInvalid();
34783437
}
34793438
} else if (auto *alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl())) {
3480-
if (!alias->hasInterfaceType())
3481-
return;
34823439
auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType());
34833440
type.findIf([&](Type type) -> bool {
34843441
if (T->isInvalid())
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %target-typecheck-verify-swift
22

3-
typealias A = B // expected-note{{type declared here}}
4-
typealias C = D
5-
typealias D = (A, Int) // expected-error{{type alias 'A' references itself}}
6-
typealias B = C
3+
typealias A = B // expected-error {{type alias 'A' references itself}}
4+
typealias C = D // expected-note {{through reference here}}
5+
typealias D = (A, Int) // expected-note {{through reference here}}
6+
typealias B = C // expected-note {{through reference here}}

test/Sema/circular_decl_checking.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class X {
6666
struct SomeStruct<A> {
6767
typealias A = A // this is OK now -- the underlying type is the generic parameter 'A'
6868
typealias B = B // expected-error {{type alias 'B' references itself}}
69-
// expected-note@-1 {{type declared here}}
7069
}
7170

7271
// <rdar://problem/27680407> Infinite recursion when using fully-qualified associatedtype name that has not been defined with typealias

test/Sema/diag_typealias.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@
33
struct S {}
44

55
typealias S = S // expected-error {{type alias 'S' references itself}}
6-
// expected-note@-1{{type declared here}}

test/decl/enum/Inputs/objc_enum_multi_file_helper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
func useEnum(_ x: TheEnum) {
22
switch x {
3-
case A:
3+
case .A:
44
print("a!")
55
default:
66
break

test/decl/enum/objc_enum_multi_file.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -typecheck -D NO_RAW_TYPE 2>&1 | %FileCheck -check-prefix=NO_RAW_TYPE %s
2-
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -typecheck -D BAD_RAW_TYPE 2>&1 | %FileCheck -check-prefix=BAD_RAW_TYPE %s
3-
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -typecheck -D NON_INT_RAW_TYPE 2>&1 | %FileCheck -check-prefix=NON_INT_RAW_TYPE %s
4-
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -typecheck -D NO_CASES 2>&1 | %FileCheck -check-prefix=NO_CASES %s
5-
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -typecheck -D DUPLICATE_CASES 2>&1 | %FileCheck -check-prefix=DUPLICATE_CASES %s
1+
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NO_RAW_TYPE 2>&1 | %FileCheck -check-prefix=NO_RAW_TYPE %s
2+
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D BAD_RAW_TYPE 2>&1 | %FileCheck -check-prefix=BAD_RAW_TYPE %s
3+
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NON_INT_RAW_TYPE 2>&1 | %FileCheck -check-prefix=NON_INT_RAW_TYPE %s
4+
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NO_CASES 2>&1 | %FileCheck -check-prefix=NO_CASES %s
5+
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D DUPLICATE_CASES 2>&1 | %FileCheck -check-prefix=DUPLICATE_CASES %s
66
// Note that the *other* file is the primary file in this test!
77

88
#if NO_RAW_TYPE

test/decl/init/basic_init.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ class C {
1111
}
1212

1313
typealias t = t // expected-error {{type alias 't' references itself}}
14-
// expected-note@-1{{type declared here}}
1514

1615
extension Foo {
1716
convenience init() {} // expected-error{{invalid redeclaration of synthesized 'init()'}}

0 commit comments

Comments
 (0)