Skip to content
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
3 changes: 3 additions & 0 deletions lib/SIL/IR/SILSymbolVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ class SILSymbolVisitorImpl : public ASTVisitor<SILSymbolVisitorImpl> {
rootConformance->forEachValueWitness([&](ValueDecl *valueReq,
Witness witness) {
auto witnessDecl = witness.getDecl();
if (!witnessDecl)
return;

if (isa<AbstractFunctionDecl>(valueReq)) {
addSymbolIfNecessary(valueReq, witnessDecl);
} else if (auto *storage = dyn_cast<AbstractStorageDecl>(valueReq)) {
Expand Down
12 changes: 8 additions & 4 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1665,8 +1665,6 @@ void Serializer::writeLocalNormalProtocolConformance(

PrettyStackTraceConformance trace("serializing", conformance);

// The conformance must be complete, or we can't serialize it.
assert(conformance->isComplete() || allowCompilerErrors());
assert(ConformancesToSerialize.hasRef(conformance));

auto protocol = conformance->getProtocol();
Expand All @@ -1688,7 +1686,7 @@ void Serializer::writeLocalNormalProtocolConformance(
data.push_back(addDeclRef(typeDecl, /*allowTypeAliasXRef*/true));
++numTypeWitnesses;
return false;
});
}, /*useResolver=*/true);

conformance->forEachValueWitness([&](ValueDecl *req, Witness witness) {
PrettyStackTraceDecl traceValueWitness(
Expand Down Expand Up @@ -1717,7 +1715,7 @@ void Serializer::writeLocalNormalProtocolConformance(

data.push_back(addSubstitutionMapRef(subs));
data.push_back(witness.getEnterIsolation().has_value() ? 1 : 0);
});
}, /*useResolver=*/true);

unsigned abbrCode
= DeclTypeAbbrCodes[NormalProtocolConformanceLayout::Code];
Expand Down Expand Up @@ -3261,8 +3259,14 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
size_t addConformances(const IterableDeclContext *declContext,
ConformanceLookupKind lookupKind,
SmallVectorImpl<TypeID> &data) {
// We don't expect to be serializing conformances for skipped decls.
assert(!S.shouldSkipDecl(declContext->getDecl()));

size_t count = 0;
for (auto conformance : declContext->getLocalConformances(lookupKind)) {
if (S.shouldSkipDecl(conformance->getProtocol()))
continue;

data.push_back(S.addConformanceRef(conformance));
count++;
}
Expand Down
39 changes: 35 additions & 4 deletions test/Inputs/lazy_typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public func publicFuncWithOpaqueReturnType() -> some PublicProto { // expected-n
// MARK: - Nominal types

public protocol PublicProto {
func req() -> Int
func req() -> Int // expected-note 2 {{protocol requires function 'req()' with type '() -> Int'; add a stub for conformance}}
}

protocol InternalProto {
// FIXME: Serialization causes typechecking of protocols regardless of access level
// func req() -> DoesNotExist
func goodReq() -> Int // expected-note {{protocol requires function 'goodReq()' with type '() -> Int'; add a stub for conformance}}
func badReq() -> DoesNotExist // expected-error {{cannot find type 'DoesNotExist' in scope}}
}

public struct PublicStruct {
Expand Down Expand Up @@ -114,6 +114,37 @@ public class PublicClass {
class InternalClass: DoesNotExist { // expected-error {{cannot find type 'DoesNotExist' in scope}}
init(x: DoesNotExist) {} // expected-error {{cannot find type 'DoesNotExist' in scope}}
}

// MARK: - Conformances

public struct PublicStructConformingToPublicProto: PublicProto {
public init() {}
public func req() -> Int {
return true // expected-error {{cannot convert return expression of type 'Bool' to return type 'Int'}}
}
}

public class PublicClassConformingToPublicProto: PublicProto {
public init() {}
public func req() -> Int {
return true // expected-error {{cannot convert return expression of type 'Bool' to return type 'Int'}}
}
}

extension String: PublicProto {
public func req() -> Int {
return true // expected-error {{cannot convert return expression of type 'Bool' to return type 'Int'}}
}
}

struct InternalStructConformingToPublicProto: PublicProto { // expected-error {{type 'InternalStructConformingToPublicProto' does not conform to protocol 'PublicProto'}}
}

extension InternalStruct: PublicProto { // expected-error {{type 'InternalStruct' does not conform to protocol 'PublicProto'}}
}

struct InternalStructConformingToInternalProto: InternalProto { // expected-error {{type 'InternalStructConformingToInternalProto' does not conform to protocol 'InternalProto'}}
}

// FIXME: Test enums
// FIXME: Test conformances
// FIXME: Test global vars
8 changes: 8 additions & 0 deletions test/Inputs/lazy_typecheck_client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@ func testPublicClass() {
_ = c.publicMethod()
PublicClass.publicClassMethod()
}

func testConformances() {
let _: [any PublicProto] = [
PublicStructConformingToPublicProto(),
PublicClassConformingToPublicProto(),
"string",
]
}
14 changes: 12 additions & 2 deletions test/ModuleInterface/lazy-typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,26 @@
// CHECK: public protocol PublicProto {
// CHECK: func req() -> Swift.Int
// CHECK: }

// CHECK: public struct PublicStruct {
// CHECK: public init(x: Swift.Int)
// CHECK: public func publicMethod() -> Swift.Int
// CHECK: public static func publicStaticMethod()
// CHECK: }

// CHECK: public class PublicClass {
// CHECK: public init(x: Swift.Int)
// CHECK: public func publicMethod() -> Swift.Int
// CHECK: public class func publicClassMethod()
// CHECK: deinit
// CHECK: }
// CHECK: public struct PublicStructConformingToPublicProto : PublicProto {
// CHECK: public init()
// CHECK: public func req() -> Swift.Int
// CHECK: }
// CHECK: public class PublicClassConformingToPublicProto : PublicProto {
// CHECK: public init()
// CHECK: public func req() -> Swift.Int
// CHECK: deinit
// CHECK: }
// CHECK: extension Swift.String : PublicProto {
// CHECK: public func req() -> Swift.Int
// CHECK: }
10 changes: 10 additions & 0 deletions test/TBD/lazy-typecheck-bad-conformance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck -experimental-lazy-typecheck -emit-tbd -emit-tbd-path %t/lazy.tbd %s -enable-library-evolution -parse-as-library

public protocol P {
func req()
}

// FIXME: This malformed conformance should probably be diagnosed.
public struct S: P {
}
29 changes: 27 additions & 2 deletions test/TBD/lazy-typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,30 @@ compatibility-version: 0
swift-abi-version: 7
exports:
- targets: [ arm64-macos ]
symbols: [ '_$s14lazy_typecheck10publicFuncSiyF', '_$s14lazy_typecheck11PublicClassC06publicD6MethodyyFZTj',
symbols: [ '_$s14lazy_typecheck023PublicClassConformingToC5ProtoC3reqSiyFTj',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoC3reqSiyFTq',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCAA0cG0AAMc',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCAA0cG0AAWP',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCACycfC',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCACycfCTj',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCACycfCTq',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCACycfc',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCMa',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCMm',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCMn',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCMo',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCMu',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCN',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCfD',
'_$s14lazy_typecheck023PublicClassConformingToC5ProtoCfd',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoV3reqSiyF',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoVAA0cG0AAMc',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoVAA0cG0AAWP',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoVACycfC',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoVMa',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoVMn',
'_$s14lazy_typecheck024PublicStructConformingToC5ProtoVN',
'_$s14lazy_typecheck10publicFuncSiyF', '_$s14lazy_typecheck11PublicClassC06publicD6MethodyyFZTj',
'_$s14lazy_typecheck11PublicClassC06publicD6MethodyyFZTq',
'_$s14lazy_typecheck11PublicClassC12publicMethodSiyFTj', '_$s14lazy_typecheck11PublicClassC12publicMethodSiyFTq',
'_$s14lazy_typecheck11PublicClassC1xACSi_tcfC', '_$s14lazy_typecheck11PublicClassC1xACSi_tcfCTj',
Expand All @@ -35,5 +58,7 @@ exports:
'_$s14lazy_typecheck13inlinableFuncSiyF', '_$s14lazy_typecheck24publicFuncWithDefaultArgyS2iF',
'_$s14lazy_typecheck30publicFuncWithOpaqueReturnTypeQryF',
'_$s14lazy_typecheck30publicFuncWithOpaqueReturnTypeQryFQOMQ',
'_$s14lazy_typecheck32constrainedGenericPublicFunctionyyxAA0E5ProtoRzlF' ]
'_$s14lazy_typecheck32constrainedGenericPublicFunctionyyxAA0E5ProtoRzlF',
'_$sSS14lazy_typecheck11PublicProtoAAMc', '_$sSS14lazy_typecheck11PublicProtoAAWP',
'_$sSS14lazy_typecheckE3reqSiyF' ]
...