Skip to content

Commit ffcae60

Browse files
author
Gabor Horvath
committed
[cxx-interop] Support calling functions in inline namespaces
The overload resolution generated a constraint that tried to bind outer.inline_inner to outer. This constraint failed. This PR attempts to recognize this scenario and make the constraint succeed, inserting a MetatypeConversionExpr that is later ignored by SILGen. rdar://158401346
1 parent a868d92 commit ffcae60

File tree

6 files changed

+52
-2
lines changed

6 files changed

+52
-2
lines changed

include/swift/ClangImporter/ClangModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ class ClangModuleUnit final : public LoadedFile {
141141
}
142142
};
143143

144+
bool isInlineNamespaceInside(const NominalType *outer,
145+
const NominalType *inner);
144146
}
145147

146148
#endif

lib/AST/ASTVerifier.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
#include "swift/AST/Stmt.h"
3939
#include "swift/AST/TypeCheckRequests.h"
4040
#include "swift/AST/TypeRepr.h"
41+
#include "swift/AST/Types.h"
4142
#include "swift/Basic/Assertions.h"
4243
#include "swift/Basic/SourceManager.h"
44+
#include "swift/ClangImporter/ClangModule.h"
4345
#include "swift/Subsystems.h"
4446
#include "llvm/ADT/SmallBitVector.h"
4547
#include "llvm/ADT/SmallString.h"
@@ -3606,6 +3608,10 @@ class Verifier : public ASTWalker {
36063608
const char *what) {
36073609
if (srcTy->isEqual(destTy)) return;
36083610

3611+
if (isInlineNamespaceInside(srcTy->getAs<NominalType>(),
3612+
destTy->getAs<NominalType>()))
3613+
return;
3614+
36093615
if (auto srcMetatype = srcTy->getAs<AnyMetatypeType>()) {
36103616
if (auto destMetatype = destTy->getAs<AnyMetatypeType>()) {
36113617
return checkTrivialSubtype(E,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8870,3 +8870,20 @@ swift::importer::getCxxRefConventionWithAttrs(const clang::Decl *decl) {
88708870

88718871
return std::nullopt;
88728872
}
8873+
8874+
bool swift::isInlineNamespaceInside(const NominalType *outer,
8875+
const NominalType *inner) {
8876+
if (!outer || !inner)
8877+
return false;
8878+
auto CDOuter = outer->getDecl()->getClangDecl();
8879+
if (!isa_and_nonnull<clang::NamespaceDecl>(CDOuter))
8880+
return false;
8881+
8882+
auto CDInner = inner->getDecl()->getClangDecl();
8883+
while (isa_and_nonnull<clang::NamespaceDecl>(CDInner) &&
8884+
cast<clang::NamespaceDecl>(CDInner)->isInline()) {
8885+
CDInner = cast<clang::Decl>(CDInner->getDeclContext());
8886+
}
8887+
8888+
return CDInner->getCanonicalDecl() == CDOuter->getCanonicalDecl();
8889+
}

lib/SILGen/SILGenExpr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "swift/Basic/Defer.h"
4747
#include "swift/Basic/SourceManager.h"
4848
#include "swift/Basic/type_traits.h"
49+
#include "swift/ClangImporter/ClangModule.h"
4950
#include "swift/SIL/Consumption.h"
5051
#include "swift/SIL/DynamicCasts.h"
5152
#include "swift/SIL/SILArgument.h"
@@ -1503,6 +1504,18 @@ RValue RValueEmitter::visitMetatypeConversionExpr(MetatypeConversionExpr *E,
15031504
SILValue metaBase =
15041505
SGF.emitRValueAsSingleValue(E->getSubExpr()).getUnmanagedValue();
15051506

1507+
if (isInlineNamespaceInside(E->getSubExpr()
1508+
->getType()
1509+
->getAs<AnyMetatypeType>()
1510+
->getInstanceType()
1511+
->getAs<NominalType>(),
1512+
E->getType()
1513+
->getAs<AnyMetatypeType>()
1514+
->getInstanceType()
1515+
->getAs<NominalType>()))
1516+
return RValue(SGF, E,
1517+
ManagedValue::forObjectRValueWithoutOwnership(metaBase));
1518+
15061519
// Metatype conversion casts in the AST might not be reflected as
15071520
// such in the SIL type system, for example, a cast from DynamicSelf.Type
15081521
// directly to its own Self.Type.

lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@
3838
#include "swift/Basic/StringExtras.h"
3939
#include "swift/ClangImporter/ClangModule.h"
4040
#include "swift/Sema/CSFix.h"
41+
#include "swift/Sema/Constraint.h"
4142
#include "swift/Sema/ConstraintSystem.h"
4243
#include "swift/Sema/IDETypeChecking.h"
4344
#include "swift/Sema/PreparedOverload.h"
45+
#include "clang/AST/Decl.h"
4446
#include "llvm/ADT/SetVector.h"
47+
#include "llvm/Support/Casting.h"
4548
#include "llvm/Support/Compiler.h"
4649

4750
using namespace swift;
@@ -7570,6 +7573,15 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
75707573
case TypeKind::Class: {
75717574
auto nominal1 = cast<NominalType>(desugar1);
75727575
auto nominal2 = cast<NominalType>(desugar2);
7576+
7577+
if (isa<EnumType>(nominal1) && kind == ConstraintKind::Bind) {
7578+
// Check for C++ inline namespaces
7579+
if (isInlineNamespaceInside(nominal1, nominal2)) {
7580+
nominal2 = nominal1;
7581+
type2 = type1;
7582+
}
7583+
}
7584+
75737585
if (nominal1->getDecl() == nominal2->getDecl())
75747586
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
75757587

test/Interop/Cxx/namespace/inline-namespace-function-call-broken.swift renamed to test/Interop/Cxx/namespace/inline-namespace-function-call.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t
22
// RUN: split-file %s %t
3-
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unknown -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop
3+
// RUN: %target-swift-frontend -verify -verify-ignore-unknown -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop
44

55
//--- Inputs/module.modulemap
66
module namespaces {
@@ -22,5 +22,5 @@ import namespaces;
2222

2323
// Swift's typechecker currently doesn't allow calling a function from inline namespace when it's referenced through the parent namespace.
2424
func test() {
25-
Parent.functionInInlineChild() // expected-error {{type of expression is ambiguous without a type annotation}}
25+
Parent.functionInInlineChild()
2626
}

0 commit comments

Comments
 (0)