-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[5.9][interop] do not import functions whose return type is not imported #65105
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3048,13 +3048,16 @@ namespace { | |
|
||
if (auto recordType = dyn_cast<clang::RecordType>( | ||
decl->getReturnType().getCanonicalType())) { | ||
Impl.addImportDiagnostic( | ||
decl, Diagnostic(diag::reference_passed_by_value, | ||
Impl.SwiftContext.AllocateCopy( | ||
recordType->getDecl()->getNameAsString()), | ||
"the return"), | ||
decl->getLocation()); | ||
return recordHasReferenceSemantics(recordType->getDecl()); | ||
if (recordHasReferenceSemantics(recordType->getDecl())) { | ||
Impl.addImportDiagnostic( | ||
decl, | ||
Diagnostic(diag::reference_passed_by_value, | ||
Impl.SwiftContext.AllocateCopy( | ||
recordType->getDecl()->getNameAsString()), | ||
"the return"), | ||
decl->getLocation()); | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
|
@@ -3391,6 +3394,14 @@ namespace { | |
func->setAccess(AccessLevel::Public); | ||
} | ||
|
||
if (!isa<clang::CXXConstructorDecl>(decl) && !importedType) { | ||
if (!Impl.importFunctionReturnType(decl, result->getDeclContext())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We intentionally don't eagerly import some class template specializations. These really need to be lazily evaluated to respect C++ semantics. You are allowed to have a completely broken class template specialization, as long as the method is never called. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are currently handling this logic on line 3304/3307: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To elaborate on the first comment, this is the case I'm talking about, where we may violate C++ "semantics" if we try to do this too eagerly:
In other words, we cannot import |
||
Impl.addImportDiagnostic( | ||
decl, Diagnostic(diag::unsupported_return_type, decl), | ||
decl->getSourceRange().getBegin()); | ||
return nullptr; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just for the sake of completeness, I'd like to mention that Objective-C and C will also hit this codepath, so there's a (hopefully very small?) chance of behavior change there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the important (and oh so terrible) condition here is
If that condition is true, then we'll already apply the behavior of this patch by returning a null There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here's an example:
|
||
} | ||
} | ||
result->setIsObjC(false); | ||
result->setIsDynamic(false); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// RUN: rm -rf %t | ||
// RUN: split-file %s %t | ||
// RUN: %target-swift-ide-test -print-module -module-to-print=CxxModule -I %t/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s | ||
|
||
// RUN: %target-swift-frontend -typecheck -verify -I %t/Inputs -enable-experimental-cxx-interop %t/test.swift | ||
|
||
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs -enable-experimental-cxx-interop %t/test.swift 2>&1 | %FileCheck --check-prefix=NOTE %s | ||
|
||
|
||
//--- Inputs/module.modulemap | ||
module CxxTypes { | ||
header "types.h" | ||
requires cplusplus | ||
} | ||
|
||
module CxxModule { | ||
header "header.h" | ||
requires cplusplus | ||
} | ||
|
||
//--- Inputs/types.h | ||
|
||
template<class T> | ||
class TemplateInTypesModule { | ||
public: | ||
T x, y; | ||
}; | ||
|
||
//--- Inputs/header.h | ||
|
||
#pragma clang module import CxxTypes | ||
|
||
class Struct { | ||
public: | ||
int x, y; | ||
|
||
TemplateInTypesModule<int> returnsClassInTypesModules() const; | ||
|
||
void takesClassInTypesModules(TemplateInTypesModule<int>) const; | ||
void takesClassInTypesModulesRef(const TemplateInTypesModule<int> &) const; | ||
}; | ||
|
||
// CHECK: struct Struct { | ||
// CHECK-NEXT: init() | ||
// CHECK-NEXT: init(x: Int32, y: Int32) | ||
// CHECK-NEXT: var x: Int32 | ||
// CHECK-NEXT: var y: Int32 | ||
// CHECK-NEXT: } | ||
|
||
// CHECK-NOT: funcWithClass | ||
|
||
TemplateInTypesModule<int> funcWithClassInTypesModules(); | ||
void funcWithClassInTypesModulesParam(TemplateInTypesModule<int>); | ||
void funcWithClassInTypesModulesParamRef(const TemplateInTypesModule<int> &); | ||
|
||
//--- test.swift | ||
|
||
import CxxModule | ||
|
||
func test() { | ||
funcWithClassInTypesModules() // expected-error {{cannot find 'funcWithClassInTypesModules' in scope}} | ||
Struct().returnsClassInTypesModules() // expected-error {{value of type 'Struct' has no member 'returnsClassInTypesModules'}} | ||
} | ||
|
||
// NOTE: note: C++ function 'funcWithClassInTypesModules' is unavailable: return type is unavailable in Swift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like
!importedType
should be a sufficient condition here. Why try importing it twice?