Skip to content

Commit 7add05f

Browse files
authored
[PrintAsObjC] Use of imported generics require the full definition. (#5518)
I'm not sure why this didn't occur to me in 8282160: of course if you see a generic type with arguments, you need to see the @interface for that type in order to supply the arguments. Maybe I was thinking the generated interface would automatically import anything the module itself imports, but that hasn't ever been true. rdar://problem/28738008
1 parent c587c69 commit 7add05f

File tree

5 files changed

+33
-17
lines changed

5 files changed

+33
-17
lines changed

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ class ReferencedTypeFinder : private TypeVisitor<ReferencedTypeFinder> {
15371537

15381538
ModuleDecl &M;
15391539
llvm::function_ref<void(ReferencedTypeFinder &, const TypeDecl *)> Callback;
1540-
bool IsWithinConstrainedObjCGeneric = false;
1540+
bool NeedsDefinition = false;
15411541

15421542
ReferencedTypeFinder(ModuleDecl &mod, decltype(Callback) callback)
15431543
: M(mod), Callback(callback) {}
@@ -1637,29 +1637,29 @@ class ReferencedTypeFinder : private TypeVisitor<ReferencedTypeFinder> {
16371637

16381638
void visitBoundGenericType(BoundGenericType *boundGeneric) {
16391639
auto *decl = boundGeneric->getDecl();
1640+
1641+
NeedsDefinition = true;
1642+
Callback(*this, decl);
1643+
NeedsDefinition = false;
1644+
16401645
bool isObjCGeneric = decl->hasClangNode();
16411646
auto *sig = decl->getGenericSignature();
16421647

16431648
for_each(boundGeneric->getGenericArgs(),
16441649
sig->getInnermostGenericParams(),
16451650
[&](Type argTy, GenericTypeParamType *paramTy) {
16461651
if (isObjCGeneric && isConstrained(M, sig, paramTy))
1647-
IsWithinConstrainedObjCGeneric = true;
1652+
NeedsDefinition = true;
16481653
visit(argTy);
1649-
IsWithinConstrainedObjCGeneric = false;
1654+
NeedsDefinition = false;
16501655
});
1651-
1652-
// Ignore the base type; that either can't be exposed to Objective-C or
1653-
// was an Objective-C type to begin with. Every bound generic Swift type we
1654-
// care about gets mapped to a particular construct in Objective-C.
1655-
// (For example, Optional<NSFoo> is mapped to NSFoo *.)
16561656
}
16571657

16581658
public:
16591659
using TypeVisitor::visit;
16601660

1661-
bool isWithinConstrainedObjCGeneric() const {
1662-
return IsWithinConstrainedObjCGeneric;
1661+
bool needsDefinition() const {
1662+
return NeedsDefinition;
16631663
}
16641664

16651665
static void walk(ModuleDecl &mod, Type ty, decltype(Callback) callback) {
@@ -1851,8 +1851,7 @@ class ModuleWriter {
18511851
if (TD == container)
18521852
return;
18531853

1854-
if (finder.isWithinConstrainedObjCGeneric() &&
1855-
isa<NominalTypeDecl>(TD)) {
1854+
if (finder.needsDefinition() && isa<NominalTypeDecl>(TD)) {
18561855
// We can delay individual members of classes; do so if necessary.
18571856
if (isa<ClassDecl>(container)) {
18581857
if (!tryRequire(TD)) {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// This file is meant to be included with modules turned off, compiled against
2+
// the fake clang-importer-sdk.
3+
#import <Foundation.h>
4+
5+
@interface SingleImportedObjCGeneric<A> : NSObject
6+
@end

test/PrintAsObjC/Inputs/custom-modules/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ module Base {
1919
}
2020
}
2121

22+
module SingleGenericClass {
23+
header "SingleGenericClass.h"
24+
export *
25+
}
26+
2227
module OverrideBase [system] {
2328
header "override.h"
2429
export *

test/PrintAsObjC/classes.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
// FIXME: END -enable-source-import hackaround
1414

1515

16-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -o %t %s -disable-objc-attr-requires-foundation-module
17-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -parse-as-library %t/classes.swiftmodule -parse -emit-objc-header-path %t/classes.h -import-objc-header %S/../Inputs/empty.h -disable-objc-attr-requires-foundation-module
16+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -I %S/Inputs/custom-modules -o %t %s -disable-objc-attr-requires-foundation-module
17+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -parse-as-library %t/classes.swiftmodule -parse -I %S/Inputs/custom-modules -emit-objc-header-path %t/classes.h -import-objc-header %S/../Inputs/empty.h -disable-objc-attr-requires-foundation-module
1818
// RUN: %FileCheck %s < %t/classes.h
1919
// RUN: %FileCheck --check-prefix=NEGATIVE %s < %t/classes.h
20-
// RUN: %check-in-clang %t/classes.h
21-
// RUN: not %check-in-clang -fno-modules -Qunused-arguments %t/classes.h
22-
// RUN: %check-in-clang -fno-modules -Qunused-arguments %t/classes.h -include Foundation.h -include CoreFoundation.h -include objc_generics.h
20+
// RUN: %check-in-clang -I %S/Inputs/custom-modules/ %t/classes.h
21+
// RUN: not %check-in-clang -I %S/Inputs/custom-modules/ -fno-modules -Qunused-arguments %t/classes.h
22+
// RUN: %check-in-clang -I %S/Inputs/custom-modules/ -fno-modules -Qunused-arguments %t/classes.h -include Foundation.h -include CoreFoundation.h -include objc_generics.h -include SingleGenericClass.h
2323

2424
// CHECK-NOT: AppKit;
2525
// CHECK-NOT: Properties;
@@ -28,12 +28,14 @@
2828
// CHECK-NEXT: @import CoreGraphics;
2929
// CHECK-NEXT: @import CoreFoundation;
3030
// CHECK-NEXT: @import objc_generics;
31+
// CHECK-NEXT: @import SingleGenericClass;
3132
// CHECK-NOT: AppKit;
3233
// CHECK-NOT: Swift;
3334
import Foundation
3435
import objc_generics
3536
import AppKit // only used in implementations
3637
import CoreFoundation
38+
import SingleGenericClass
3739

3840
// CHECK-LABEL: @interface A1{{$}}
3941
// CHECK-NEXT: init
@@ -715,6 +717,9 @@ public class NonObjCClass { }
715717
typealias Dipper = Spoon
716718
// CHECK: - (FungibleContainer<FungibleObject> * _Nonnull)fungibleContainerWithAliases:(FungibleContainer<Spoon *> * _Nullable)x;
717719
@objc func fungibleContainerWithAliases(_ x: FungibleContainer<Dipper>?) -> FungibleContainer<FungibleObject> { fatalError("") }
720+
721+
// CHECK: - (void)referenceSingleGenericClass:(SingleImportedObjCGeneric<id> * _Nullable)_;
722+
func referenceSingleGenericClass(_: SingleImportedObjCGeneric<AnyObject>?) {}
718723
}
719724
// CHECK: @end
720725

test/PrintAsObjC/lit.local.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ config.substitutions.insert(0, ('%check-in-clang',
55
'%%clang -fsyntax-only -x objective-c-header -fobjc-arc -fmodules '
66
'-fmodules-validate-system-headers '
77
'-Weverything -Werror -Wno-unused-macros -Wno-incomplete-module '
8+
'-Wno-auto-import '
89
'-I %%clang-include-dir '
910
'-isysroot %r/Inputs/clang-importer-sdk' % config.test_source_root) )

0 commit comments

Comments
 (0)