Skip to content

Commit de9eca0

Browse files
committed
- tmp
1 parent 36e4bd0 commit de9eca0

File tree

9 files changed

+76
-55
lines changed

9 files changed

+76
-55
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ let mandatoryPerformanceOptimizations = ModulePass(name: "mandatory-performance-
4545
}
4646

4747
optimizeFunctionsTopDown(using: &worklist, moduleContext)
48+
49+
if moduleContext.options.enableEmbeddedSwift {
50+
checkVTablesForGenericFunctions(moduleContext)
51+
}
4852
}
4953

5054
private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist,
@@ -265,21 +269,38 @@ private func specializeWitnessTables(for initExRef: InitExistentialRefInst, _ co
265269
let conformingType = initExRef.instance.type
266270
assert(conformingType.isClass)
267271

268-
for conformance in initExRef.conformances {
269-
if conformance.isConcrete,
270-
conformance.isSpecialized,
271-
context.lookupWitnessTable(for: conformance) == nil
272-
{
273-
let wt = specializeWitnessTable(forConformance: conformance, context)
274-
for entry in wt.entries where entry.kind == .method {
275-
if let method = entry.methodFunction,
276-
// A new witness table can still contain a generic function if the method couldn't be specialized for
277-
// some reason and an error has been printed. Exclude generic functions to not run into an assert later.
278-
!method.isGeneric
279-
{
280-
worklist.pushIfNotVisited(method)
281-
}
272+
for conformance in initExRef.conformances where conformance.isConcrete {
273+
let origWitnessTable = context.lookupWitnessTable(for: conformance)
274+
if conformance.isSpecialized {
275+
if origWitnessTable == nil {
276+
let wt = specializeWitnessTable(forConformance: conformance, errorLocation: initExRef.location, context)
277+
worklist.addWitnessMethods(of: wt)
282278
}
279+
} else if let origWitnessTable {
280+
checkForGenericMethods(in: origWitnessTable, errorLocation: initExRef.location, context)
281+
}
282+
}
283+
}
284+
285+
private func checkForGenericMethods(in witnessTable: WitnessTable,
286+
errorLocation: Location,
287+
_ context: ModulePassContext)
288+
{
289+
for entry in witnessTable.entries where entry.kind == .method {
290+
if let method = entry.methodFunction,
291+
method.isGeneric
292+
{
293+
context.diagnosticEngine.diagnose(errorLocation.sourceLoc, .cannot_specialize_witness_method,
294+
entry.methodRequirement)
295+
return
296+
}
297+
}
298+
}
299+
300+
private func checkVTablesForGenericFunctions(_ context: ModulePassContext) {
301+
for vTable in context.vTables where !vTable.class.isGenericAtAnyLevel {
302+
for entry in vTable.entries where entry.implementation.isGeneric {
303+
context.diagnosticEngine.diagnose(entry.methodDecl.location.sourceLoc, .non_final_generic_class_function)
283304
}
284305
}
285306
}
@@ -489,6 +510,18 @@ fileprivate struct FunctionWorklist {
489510
}
490511
}
491512

513+
mutating func addWitnessMethods(of witnessTable: WitnessTable) {
514+
for entry in witnessTable.entries where entry.kind == .method {
515+
if let method = entry.methodFunction,
516+
// A new witness table can still contain a generic function if the method couldn't be specialized for
517+
// some reason and an error has been printed. Exclude generic functions to not run into an assert later.
518+
!method.isGeneric
519+
{
520+
pushIfNotVisited(method)
521+
}
522+
}
523+
}
524+
492525
mutating func pushIfNotVisited(_ element: Function) {
493526
if pushedFunctions.insert(element).inserted {
494527
functions.append(element)

SwiftCompilerSources/Sources/Optimizer/Utilities/DiagnosticEngine.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ extension Type: DiagnosticArgument {
3535
fn(bridged.asDiagnosticArgument())
3636
}
3737
}
38+
extension DeclRef: DiagnosticArgument {
39+
public func _withBridgedDiagnosticArgument(_ fn: (BridgedDiagnosticArgument) -> Void) {
40+
fn(bridged.asDiagnosticArgument())
41+
}
42+
}
3843

3944
public struct DiagnosticFixIt {
4045
public let start: SourceLoc

SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func specializeVTablesOfSuperclasses(_ moduleContext: ModulePassContext) {
7777
}
7878

7979
func specializeWitnessTable(forConformance conformance: ProtocolConformance,
80+
errorLocation: Location,
8081
_ context: ModulePassContext) -> WitnessTable
8182
{
8283
let genericConformance = conformance.genericConformance
@@ -88,10 +89,16 @@ func specializeWitnessTable(forConformance conformance: ProtocolConformance,
8889
let newEntries = witnessTable.entries.map { origEntry in
8990
switch origEntry.kind {
9091
case .method:
92+
guard let origMethod = origEntry.methodFunction else {
93+
return origEntry
94+
}
9195
let methodDecl = origEntry.methodRequirement
92-
guard let specializedMethod = context.specialize(function: origEntry.methodFunction!,
93-
for: conformance.specializedSubstitutions) else {
94-
context.diagnosticEngine.diagnose(methodDecl.location.sourceLoc, .cannot_specialize_witness_method)
96+
let methodSubs = conformance.specializedSubstitutions.getMethodSubstitutions(for: origMethod)
97+
98+
guard !methodSubs.conformances.contains(where: {!$0.isValid}),
99+
let specializedMethod = context.specialize(function: origMethod, for: methodSubs) else
100+
{
101+
context.diagnosticEngine.diagnose(errorLocation.sourceLoc, .cannot_specialize_witness_method, methodDecl)
95102
return origEntry
96103
}
97104
return WitnessTable.Entry(methodRequirement: methodDecl, methodFunction: specializedMethod)

SwiftCompilerSources/Sources/SIL/Declarations.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public struct NominalTypeDecl : Equatable, Hashable {
6060
}
6161

6262
public struct DeclRef {
63-
let bridged: BridgedDeclRef
63+
public let bridged: BridgedDeclRef
6464

6565
public var location: Location { Location(bridged: bridged.getLocation()) }
6666
}

include/swift/AST/DiagnosticsSIL.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ ERROR(global_must_be_compile_time_const,none,
378378
ERROR(non_final_generic_class_function,none,
379379
"classes cannot have non-final generic fuctions in embedded Swift", ())
380380
ERROR(cannot_specialize_witness_method,none,
381-
"generic method cannot be used in existential type", ())
381+
"an existential type cannot contain a generic method %0 in embedded Swift", (DeclName))
382382
ERROR(cannot_specialize_class,none,
383383
"cannot specialize %0 because class definition is not available (make sure to build with -wmo)", (Type))
384384
ERROR(embedded_swift_existential_type,none,

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,8 +1264,8 @@ struct BridgedDeclRef {
12641264
return *reinterpret_cast<const swift::SILDeclRef *>(&storage);
12651265
}
12661266
#endif
1267-
12681267
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedLocation getLocation() const;
1268+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDiagnosticArgument asDiagnosticArgument() const;
12691269
};
12701270

12711271
struct BridgedVTableEntry {

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,10 @@ BridgedLocation BridgedDeclRef::getLocation() const {
16601660
return swift::SILDebugLocation(unbridged().getDecl(), nullptr);
16611661
}
16621662

1663+
BridgedDiagnosticArgument BridgedDeclRef::asDiagnosticArgument() const {
1664+
return swift::DiagnosticArgument(unbridged().getDecl()->getName());
1665+
}
1666+
16631667
//===----------------------------------------------------------------------===//
16641668
// BridgedVTable
16651669
//===----------------------------------------------------------------------===//

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -914,36 +914,8 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
914914
for (SILFunction *function : constructorsAndDestructors) {
915915
diagnoser.visitFunctionEmbeddedSwift(function);
916916
}
917-
918-
checkVTables();
919917
}
920918
}
921-
922-
void checkVTables() {
923-
for (SILVTable *vtable : getModule()->getVTables()) {
924-
if (vtable->getClass()->isGenericContext())
925-
continue;
926-
927-
for (SILVTableEntry &entry : vtable->getMutableEntries()) {
928-
SILFunction *method = entry.getImplementation();
929-
if (!method->getLoweredFunctionType()->isPolymorphic())
930-
continue;
931-
932-
ValueDecl *decl = entry.getMethod().getDecl();
933-
getModule()->getASTContext().Diags.diagnose(
934-
decl->getLoc(), diag::non_final_generic_class_function);
935-
936-
if (decl->getLoc().isInvalid()) {
937-
auto demangledName = Demangle::demangleSymbolAsString(
938-
method->getName(),
939-
Demangle::DemangleOptions::SimplifiedUIDemangleOptions());
940-
llvm::errs() << "in function " << demangledName << "\n";
941-
llvm::errs() << "in class " << vtable->getClass()->getName() << "\n";
942-
}
943-
}
944-
}
945-
}
946-
947919
};
948920

949921
} // end anonymous namespace

test/embedded/classes-non-final-method-no-stdlib.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33
// REQUIRES: swift_in_compiler
44

55
public class MyClass {
6-
public func foo<T>(t: T) { } // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
7-
public func bar() { }
6+
func foo<T>(t: T) { } // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
7+
func bar() { }
88
}
99

10-
public final class C2<Element> {
10+
final class C2<Element> {
1111
// TODO: this shouldn't be a problem because the class is final
12-
public init<T>(x: T) { } // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
12+
init<T>(x: T) { } // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
1313
}
1414

15-
public struct S {}
15+
struct S {}
1616

17-
public func testit2() -> C2<S> {
17+
func testit2() -> C2<S> {
1818
return C2(x: S())
1919
}
2020

2121
open class C3<X> {
2222
public func foo<T>(t: T) {} // expected-error {{classes cannot have non-final generic fuctions in embedded Swift}}
2323
}
2424

25-
public func testit3() -> C3<S> {
25+
func testit3() -> C3<S> {
2626
return C3<S>()
2727
}
2828

0 commit comments

Comments
 (0)