Skip to content

Commit

Permalink
[SE-0404] Rebase fixes and better handling of generic superclasses wi…
Browse files Browse the repository at this point in the history
…th inferred params
  • Loading branch information
karwa committed Oct 6, 2023
1 parent 7b68919 commit f3a4558
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 40 deletions.
6 changes: 6 additions & 0 deletions lib/AST/DeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ DeclContext *DeclContext::getParentForLookup() const {
// outer types.
return getModuleScopeContext();
}
if (isa<ProtocolDecl>(this) && getParent()->isGenericContext()) {
// Protocols in generic contexts must not look in to their parents,
// as the parents may contain types with inferred implicit
// generic parameters not present in the protocol's generic signature.
return getModuleScopeContext();
}
if (isa<NominalTypeDecl>(this)) {
// If we are inside a nominal type that is inside a protocol,
// skip the protocol.
Expand Down
49 changes: 20 additions & 29 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2674,30 +2674,30 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
NTD->diagnose(diag::tuple_extension_nested_type, NTD);
return;
}
}

// We don't support protocols nested in generic contexts.
// This includes protocols nested in other protocols.
if (isa<ProtocolDecl>(NTD) && NTD->getParent()->isGenericContext()) {
if (auto *OuterPD = NTD->getParent()->getSelfProtocolDecl())
NTD->diagnose(diag::unsupported_nested_protocol_in_protocol, NTD,
OuterPD);
else
NTD->diagnose(diag::unsupported_nested_protocol_in_generic, NTD);
// We don't support protocols nested in generic contexts.
// This includes protocols nested in other protocols.
if (isa<ProtocolDecl>(NTD) && DC->isGenericContext()) {
if (auto *OuterPD = DC->getSelfProtocolDecl())
NTD->diagnose(diag::unsupported_nested_protocol_in_protocol, NTD,
OuterPD);
else
NTD->diagnose(diag::unsupported_nested_protocol_in_generic, NTD);

NTD->setInvalid();
return;
}
NTD->setInvalid();
return;
}

// We don't support nested types in protocols.
if (auto proto = dyn_cast<ProtocolDecl>(parentDecl)) {
if (DC->getExtendedProtocolDecl()) {
NTD->diagnose(diag::unsupported_type_nested_in_protocol_extension, NTD,
proto);
} else {
NTD->diagnose(diag::unsupported_type_nested_in_protocol, NTD, proto);
// We don't support nested types in protocols.
if (auto proto = dyn_cast<ProtocolDecl>(parentDecl)) {
if (DC->getExtendedProtocolDecl()) {
NTD->diagnose(diag::unsupported_type_nested_in_protocol_extension, NTD,
proto);
} else {
NTD->diagnose(diag::unsupported_type_nested_in_protocol, NTD, proto);
}
NTD->setInvalid();
}
NTD->setInvalid();
}

// We don't support nested types in generic functions yet.
Expand Down Expand Up @@ -3189,15 +3189,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
if (!PD->getPrimaryAssociatedTypeNames().empty())
(void) PD->getPrimaryAssociatedTypes();

// We cannot compute the requirement signature of a protocol
// in a generic context, because superclass constraints
// may include implicitly inferred generic arguments that are
// not part of the protocol's generic signature.
if (PD->getParent()->isGenericContext()) {
assert(PD->isInvalid());
return;
}

// Explicitly compute the requirement signature to detect errors.
// Do this before visiting members, to avoid a request cycle if
// a member references another declaration whose generic signature
Expand Down
25 changes: 14 additions & 11 deletions test/decl/nested/protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,15 @@ struct OuterGeneric<D> {
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested in a generic context}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ t: D)
func flop(_ t: D) // expected-error {{cannot find type 'D' in scope}}
}
}

class OuterGenericClass<T> {
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested in a generic context}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ t: T)
func flop(_ t: T) // expected-error {{cannot find type 'T' in scope}}
}
}

Expand All @@ -180,7 +180,7 @@ protocol OuterProtocol {
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested in protocol 'OuterProtocol'}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ h: Hen)
func flop(_ h: Hen) // expected-error {{cannot find type 'Hen' in scope}}
}
}

Expand All @@ -195,37 +195,40 @@ struct ConformsToOuterProtocol : OuterProtocol {

extension OuterProtocol {
func f() {
protocol Invalid_0 {} // expected-error{{protocol 'Invalid_0' cannot be nested in a generic context}}
protocol Invalid_0 {} // expected-error{{type 'Invalid_0' cannot be nested in generic function 'f()'}}

struct SomeType { // expected-error{{type 'SomeType' cannot be nested in generic function 'f()'}}
protocol Invalid_1 {} // expected-error{{protocol 'Invalid_1' cannot be nested in a generic context}}
}
}
func g<T>(_: T) {
protocol Invalid_2 {} // expected-error{{protocol 'Invalid_2' cannot be nested in a generic context}}
protocol Invalid_2 {} // expected-error{{type 'Invalid_2' cannot be nested in generic function 'g'}}
}
}

// 'InnerProtocol' does not inherit the generic parameters of
// 'OtherGenericClass', so the occurrence of 'OtherGenericClass'
// in 'InnerProtocol' is not "in context" with implicitly
// inferred generic arguments <T, U>.
class OtherGenericClass<T, U> {
class OtherGenericClass<T, U> { // expected-note {{generic type 'OtherGenericClass' declared here}}
protocol InnerProtocol : OtherGenericClass { }
// expected-error@-1{{protocol 'InnerProtocol' cannot be nested in a generic context}}
// expected-error@-1 {{protocol 'InnerProtocol' cannot be nested in a generic context}}
// expected-error@-2 {{reference to generic type 'OtherGenericClass' requires arguments in <...>}}
}

protocol InferredGenericTest {
associatedtype A
}
extension OtherGenericClass {
protocol P: InferredGenericTest where Self.A == T {} // expected-error {{protocol 'P' cannot be nested in a generic context}}
protocol P: InferredGenericTest where Self.A == T {}
// expected-error@-1 {{protocol 'P' cannot be nested in a generic context}}
// expected-error@-2 {{cannot find type 'T' in scope}}
}

// A nested protocol does not satisfy an associated type requirement.

protocol HasAssoc {
associatedtype A // expected-note {{protocol requires nested type 'A'; do you want to add it?}}
associatedtype A // expected-note {{protocol requires nested type 'A'; add nested type 'A' for conformance}}
}
struct ConformsToHasAssoc: HasAssoc { // expected-error {{type 'ConformsToHasAssoc' does not conform to protocol 'HasAssoc'}}
protocol A {}
Expand Down Expand Up @@ -257,12 +260,12 @@ func testLookup<T: OuterForUFI.Inner>(_ x: T) {
// Protocols cannot be nested inside of generic functions.

func invalidProtocolInGeneric<T>(_: T) {
protocol Test {} // expected-error{{protocol 'Test' cannot be nested in a generic context}}
protocol Test {} // expected-error{{type 'Test' cannot be nested in generic function 'invalidProtocolInGeneric'}}
}

struct NestedInGenericMethod<T> {
func someMethod() {
protocol AnotherTest {} // expected-error{{protocol 'AnotherTest' cannot be nested in a generic context}}
protocol AnotherTest {} // expected-error{{type 'AnotherTest' cannot be nested in generic function 'someMethod()'}}
}
}

Expand Down

0 comments on commit f3a4558

Please sign in to comment.