Skip to content

Sema: Fix request cycle involving protocol typealiases in preparation for RequirementMachine support #41332

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
merged 3 commits into from
Feb 11, 2022
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
1 change: 1 addition & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ class StructuralTypeRequest :
public:
// Caching.
bool isCached() const { return true; }
void diagnoseCycle(DiagnosticEngine &diags) const;
};

/// Request the fragile function kind for the context.
Expand Down
7 changes: 3 additions & 4 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1468,10 +1468,9 @@ CanType TypeBase::computeCanonicalType() {
// If we haven't set a depth for this generic parameter, try to do so.
// FIXME: This is a dreadful hack.
if (gpDecl->getDepth() == GenericTypeParamDecl::InvalidDepth) {
if (auto decl =
gpDecl->getDeclContext()->getInnermostDeclarationDeclContext())
if (auto valueDecl = decl->getAsGenericContext())
(void)valueDecl->getGenericSignature();
auto *dc = gpDecl->getDeclContext();
auto *gpList = dc->getAsDecl()->getAsGenericContext()->getGenericParams();
gpList->setDepth(dc->getGenericContextDepth());
}

assert(gpDecl->getDepth() != GenericTypeParamDecl::InvalidDepth &&
Expand Down
11 changes: 11 additions & 0 deletions lib/AST/TypeCheckRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,17 @@ void UnderlyingTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
aliasDecl->getName());
}

//----------------------------------------------------------------------------//
// StructuralTypeRequest computation.
//----------------------------------------------------------------------------//

void StructuralTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
auto aliasDecl = std::get<0>(getStorage());
diags.diagnose(aliasDecl, diag::recursive_decl_reference,
aliasDecl->getDescriptiveKind(),
aliasDecl->getName());
}

//----------------------------------------------------------------------------//
// EnumRawValuesRequest computation.
//----------------------------------------------------------------------------//
Expand Down
18 changes: 9 additions & 9 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,9 +827,6 @@ Type TypeResolution::applyUnboundGenericArguments(
genericArgs.size() >= decl->getGenericParams()->size() - 1)) &&
"invalid arguments, use applyGenericArguments for diagnostic emitting");

auto genericSig = decl->getGenericSignature();
assert(!genericSig.isNull());

TypeSubstitutionMap subs;

// Get the interface type for the declaration. We will be substituting
Expand All @@ -855,6 +852,7 @@ Type TypeResolution::applyUnboundGenericArguments(
if (!resultType->hasTypeParameter())
return resultType;

auto genericSig = decl->getGenericSignature();
auto parentSig = decl->getDeclContext()->getGenericSignatureOfContext();
for (auto gp : parentSig.getGenericParams())
subs[gp->getCanonicalType()->castTo<GenericTypeParamType>()] =
Expand All @@ -864,18 +862,18 @@ Type TypeResolution::applyUnboundGenericArguments(
}

skipRequirementsCheck |= parentTy->hasTypeVariable();
} else if (auto genericSig =
} else if (auto parentSig =
decl->getDeclContext()->getGenericSignatureOfContext()) {
for (auto gp : genericSig.getGenericParams()) {
for (auto gp : parentSig.getGenericParams()) {
subs[gp->getCanonicalType()->castTo<GenericTypeParamType>()] = gp;
}
}

// Realize the types of the generic arguments and add them to the
// substitution map.
auto innerParams = genericSig.getInnermostGenericParams();
for (unsigned i = 0; i < innerParams.size(); ++i) {
auto origTy = innerParams[i];
auto innerParams = decl->getGenericParams()->getParams();
for (unsigned i : indices(innerParams)) {
auto origTy = innerParams[i]->getDeclaredInterfaceType();
auto origGP = origTy->getCanonicalType()->castTo<GenericTypeParamType>();

if (!origGP->isTypeSequence()) {
Expand All @@ -894,7 +892,8 @@ Type TypeResolution::applyUnboundGenericArguments(
// types we can bind to this type sequence parameter.
unsigned tail;
for (tail = 1; tail <= innerParams.size(); ++tail) {
auto tailTy = innerParams[innerParams.size() - tail];
auto tailTy = innerParams[innerParams.size() - tail]
->getDeclaredInterfaceType();
auto tailGP = tailTy->getCanonicalType()->castTo<GenericTypeParamType>();
if (tailGP->isTypeSequence()) {
assert(tailGP->isEqual(origGP) &&
Expand Down Expand Up @@ -943,6 +942,7 @@ Type TypeResolution::applyUnboundGenericArguments(
if (noteLoc.isInvalid())
noteLoc = loc;

auto genericSig = decl->getGenericSignature();
auto result = TypeChecker::checkGenericArguments(
module, loc, noteLoc,
UnboundGenericType::get(decl, parentTy, getASTContext()),
Expand Down
4 changes: 1 addition & 3 deletions test/Generics/generic_types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,7 @@ class Top {}
class Bottom<T : Bottom<Top>> {}
// expected-error@-1 {{'Bottom' requires that 'Top' inherit from 'Bottom<Top>'}}
// expected-note@-2 {{requirement specified as 'T' : 'Bottom<Top>' [with T = Top]}}
// expected-error@-3 4{{generic class 'Bottom' has self-referential generic requirements}}
// expected-note@-4 {{while resolving type 'Bottom<Top>'}}
// expected-note@-5 {{through reference here}}
// expected-error@-3 3{{generic class 'Bottom' has self-referential generic requirements}}

// Invalid inheritance clause

Expand Down
6 changes: 2 additions & 4 deletions test/decl/protocol/req/recursion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ public protocol P {
}

public struct S<A: P> where A.T == S<A> {
// expected-error@-1 4{{generic struct 'S' has self-referential generic requirements}}
// expected-note@-2 {{while resolving type 'S<A>'}}
// expected-error@-1 3{{generic struct 'S' has self-referential generic requirements}}
func f(a: A.T) {
g(a: id(t: a)) // `a` has error type which is diagnosed as circular reference
_ = A.T.self
Expand All @@ -71,8 +70,7 @@ protocol PI {
}

struct SI<A: PI> : I where A : I, A.T == SI<A> {
// expected-error@-1 4{{generic struct 'SI' has self-referential generic requirements}}
// expected-note@-2 {{while resolving type 'SI<A>'}}
// expected-error@-1 3{{generic struct 'SI' has self-referential generic requirements}}
func ggg<T : I>(t: T.Type) -> T {
return T()
}
Expand Down
2 changes: 1 addition & 1 deletion validation-test/compiler_crashers_2_fixed/sr-10612.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not %target-swift-frontend -typecheck %s
// RUN: %target-swift-frontend -typecheck %s

protocol P1: class {
associatedtype P1P1: P1
Expand Down