Skip to content

[PrintAsObjC] Use of imported generics require the full definition. #5518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
23 changes: 11 additions & 12 deletions lib/PrintAsObjC/PrintAsObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1537,7 +1537,7 @@ class ReferencedTypeFinder : private TypeVisitor<ReferencedTypeFinder> {

ModuleDecl &M;
llvm::function_ref<void(ReferencedTypeFinder &, const TypeDecl *)> Callback;
bool IsWithinConstrainedObjCGeneric = false;
bool NeedsDefinition = false;

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

void visitBoundGenericType(BoundGenericType *boundGeneric) {
auto *decl = boundGeneric->getDecl();

NeedsDefinition = true;
Callback(*this, decl);
NeedsDefinition = false;

bool isObjCGeneric = decl->hasClangNode();
auto *sig = decl->getGenericSignature();

for_each(boundGeneric->getGenericArgs(),
sig->getInnermostGenericParams(),
[&](Type argTy, GenericTypeParamType *paramTy) {
if (isObjCGeneric && isConstrained(M, sig, paramTy))
IsWithinConstrainedObjCGeneric = true;
NeedsDefinition = true;
visit(argTy);
IsWithinConstrainedObjCGeneric = false;
NeedsDefinition = false;
});

// Ignore the base type; that either can't be exposed to Objective-C or
// was an Objective-C type to begin with. Every bound generic Swift type we
// care about gets mapped to a particular construct in Objective-C.
// (For example, Optional<NSFoo> is mapped to NSFoo *.)
}

public:
using TypeVisitor::visit;

bool isWithinConstrainedObjCGeneric() const {
return IsWithinConstrainedObjCGeneric;
bool needsDefinition() const {
return NeedsDefinition;
}

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

if (finder.isWithinConstrainedObjCGeneric() &&
isa<NominalTypeDecl>(TD)) {
if (finder.needsDefinition() && isa<NominalTypeDecl>(TD)) {
// We can delay individual members of classes; do so if necessary.
if (isa<ClassDecl>(container)) {
if (!tryRequire(TD)) {
Expand Down
6 changes: 6 additions & 0 deletions test/PrintAsObjC/Inputs/custom-modules/SingleGenericClass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This file is meant to be included with modules turned off, compiled against
// the fake clang-importer-sdk.
#import <Foundation.h>

@interface SingleImportedObjCGeneric<A> : NSObject
@end
5 changes: 5 additions & 0 deletions test/PrintAsObjC/Inputs/custom-modules/module.map
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ module Base {
}
}

module SingleGenericClass {
header "SingleGenericClass.h"
export *
}

module OverrideBase [system] {
header "override.h"
export *
Expand Down
15 changes: 10 additions & 5 deletions test/PrintAsObjC/classes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
// FIXME: END -enable-source-import hackaround


// 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
// 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
// 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
// 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
// RUN: %FileCheck %s < %t/classes.h
// RUN: %FileCheck --check-prefix=NEGATIVE %s < %t/classes.h
// RUN: %check-in-clang %t/classes.h
// RUN: not %check-in-clang -fno-modules -Qunused-arguments %t/classes.h
// RUN: %check-in-clang -fno-modules -Qunused-arguments %t/classes.h -include Foundation.h -include CoreFoundation.h -include objc_generics.h
// RUN: %check-in-clang -I %S/Inputs/custom-modules/ %t/classes.h
// RUN: not %check-in-clang -I %S/Inputs/custom-modules/ -fno-modules -Qunused-arguments %t/classes.h
// 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

// CHECK-NOT: AppKit;
// CHECK-NOT: Properties;
Expand All @@ -28,12 +28,14 @@
// CHECK-NEXT: @import CoreGraphics;
// CHECK-NEXT: @import CoreFoundation;
// CHECK-NEXT: @import objc_generics;
// CHECK-NEXT: @import SingleGenericClass;
// CHECK-NOT: AppKit;
// CHECK-NOT: Swift;
import Foundation
import objc_generics
import AppKit // only used in implementations
import CoreFoundation
import SingleGenericClass

// CHECK-LABEL: @interface A1{{$}}
// CHECK-NEXT: init
Expand Down Expand Up @@ -715,6 +717,9 @@ public class NonObjCClass { }
typealias Dipper = Spoon
// CHECK: - (FungibleContainer<FungibleObject> * _Nonnull)fungibleContainerWithAliases:(FungibleContainer<Spoon *> * _Nullable)x;
@objc func fungibleContainerWithAliases(_ x: FungibleContainer<Dipper>?) -> FungibleContainer<FungibleObject> { fatalError("") }

// CHECK: - (void)referenceSingleGenericClass:(SingleImportedObjCGeneric<id> * _Nullable)_;
func referenceSingleGenericClass(_: SingleImportedObjCGeneric<AnyObject>?) {}
}
// CHECK: @end

1 change: 1 addition & 0 deletions test/PrintAsObjC/lit.local.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ config.substitutions.insert(0, ('%check-in-clang',
'%%clang -fsyntax-only -x objective-c-header -fobjc-arc -fmodules '
'-fmodules-validate-system-headers '
'-Weverything -Werror -Wno-unused-macros -Wno-incomplete-module '
'-Wno-auto-import '
'-I %%clang-include-dir '
'-isysroot %r/Inputs/clang-importer-sdk' % config.test_source_root) )