Skip to content

Commit

Permalink
Sema: More consistent logic for non-requirement protocol members
Browse files Browse the repository at this point in the history
  • Loading branch information
slavapestov committed Dec 21, 2016
1 parent 3f7a72e commit 978941f
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 23 deletions.
11 changes: 2 additions & 9 deletions lib/Sema/TypeCheckNameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ namespace {
}

// Dig out the witness.
ValueDecl *witness;
ValueDecl *witness = nullptr;
auto concrete = conformance->getConcrete();
if (auto assocType = dyn_cast<AssociatedTypeDecl>(found)) {
// If we're validating the protocol recursively, bail out.
Expand All @@ -159,14 +159,7 @@ namespace {

witness = concrete->getTypeWitnessSubstAndDecl(assocType, &TC)
.second;
} else if (isa<TypeAliasDecl>(found)) {
// No witness for typealiases. This means typealiases in
// protocols cannot be found if PerformConformanceCheck
// is on.
//
// FIXME: Fix this.
return;
} else {
} else if (TC.isRequirement(found)) {
witness = concrete->getWitness(found, &TC).getDecl();
}

Expand Down
26 changes: 13 additions & 13 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3969,17 +3969,6 @@ void ConformanceChecker::resolveSingleTypeWitness(
}
}

// Not all protocol members are requirements.
static bool isRequirement(ValueDecl *requirement) {
if (auto *FD = dyn_cast<FuncDecl>(requirement))
if (FD->isAccessor())
return false;
if (isa<TypeAliasDecl>(requirement) ||
isa<NominalTypeDecl>(requirement))
return false;
return true;
}

void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
assert(!isa<AssociatedTypeDecl>(requirement) && "Not a value witness");
assert(!Conformance->hasWitness(requirement) && "Already resolved");
Expand All @@ -3998,7 +3987,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
return;
}

if (!isRequirement(requirement))
if (!TC.isRequirement(requirement))
return;

// Resolve all associated types before trying to resolve this witness.
Expand Down Expand Up @@ -4147,7 +4136,7 @@ void ConformanceChecker::checkConformance() {
continue;

// Type aliases don't have requirements themselves.
if (!isRequirement(requirement))
if (!TC.isRequirement(requirement))
continue;

/// Local function to finalize the witness.
Expand Down Expand Up @@ -5564,6 +5553,17 @@ void DefaultWitnessChecker::recordWitness(
storage);
}

// Not all protocol members are requirements.
bool TypeChecker::isRequirement(ValueDecl *requirement) {
if (auto *FD = dyn_cast<FuncDecl>(requirement))
if (FD->isAccessor())
return false;
if (isa<TypeAliasDecl>(requirement) ||
isa<NominalTypeDecl>(requirement))
return false;
return true;
}

void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
DefaultWitnessChecker checker(*this, proto);

Expand Down
3 changes: 3 additions & 0 deletions lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,9 @@ class TypeChecker final : public LazyResolver {
/// Introduce the accessors for a 'lazy' variable.
void introduceLazyVarAccessors(VarDecl *var) override;

// Not all protocol members are requirements.
bool isRequirement(ValueDecl *requirement);

/// Infer default value witnesses for all requirements in the given protocol.
void inferDefaultWitnesses(ProtocolDecl *proto);

Expand Down
8 changes: 8 additions & 0 deletions test/decl/nested/protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,20 @@ class OuterGenericClass<T> {
protocol OuterProtocol {
associatedtype Hen
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested inside another declaration}}
// expected-note@-1 {{did you mean 'InnerProtocol'?}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ h: Hen)
}
}

struct ConformsToOuterProtocol : OuterProtocol {
typealias Hen = Int

func f() { let _ = InnerProtocol.self }
// expected-error@-1 {{use of unresolved identifier 'InnerProtocol'}}
}

protocol Racoon {
associatedtype Stripes
class Claw<T> { // expected-error{{type 'Claw' cannot be nested in protocol 'Racoon'}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

// RUN: not --crash %target-swift-frontend %s -emit-ir
// RUN: not %target-swift-frontend %s -emit-ir
// REQUIRES: asserts
class d:A{var f{{_=A{}}}}protocol A{protocol A

0 comments on commit 978941f

Please sign in to comment.