Skip to content

Commit 0e56809

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. rdar://158401346
1 parent bc88160 commit 0e56809

File tree

7 files changed

+106
-36
lines changed

7 files changed

+106
-36
lines changed

include/swift/ClangImporter/ClangModule.h

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

144+
// Strips the inline namespaces from inner until we reach outer or a
145+
// non-inline namespace. Returns the stripped nominal type or null when
146+
// something unexpected happened during stripping.
147+
NominalType *stripInlineNamespaces(NominalType *outer, NominalType *inner);
144148
}
145149

146150
#endif

lib/ClangImporter/ClangImporter.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3433,7 +3433,7 @@ class DarwinLegacyFilterDeclConsumer : public swift::VisibleDeclConsumer {
34333433
/// Translate a MacroDefinition to a ClangNode, either a ModuleMacro for
34343434
/// a definition imported from a module or a MacroInfo for a macro defined
34353435
/// locally.
3436-
ClangNode getClangNodeForMacroDefinition(clang::MacroDefinition &M) {
3436+
static ClangNode getClangNodeForMacroDefinition(clang::MacroDefinition &M) {
34373437
if (!M.getModuleMacros().empty())
34383438
return ClangNode(M.getModuleMacros().back()->getMacroInfo());
34393439
if (auto *MD = M.getLocalDirective())
@@ -9044,3 +9044,18 @@ swift::importer::getCxxRefConventionWithAttrs(const clang::Decl *decl) {
90449044

90459045
return std::nullopt;
90469046
}
9047+
9048+
NominalType *swift::stripInlineNamespaces(NominalType *outer,
9049+
NominalType *inner) {
9050+
if (!outer || !inner || inner == outer)
9051+
return nullptr;
9052+
auto CDInner = inner->getDecl()->getClangDecl();
9053+
while (inner && isa_and_nonnull<clang::NamespaceDecl>(CDInner) &&
9054+
cast<clang::NamespaceDecl>(CDInner)->isInline() &&
9055+
inner->getCanonicalType() != outer->getCanonicalType()) {
9056+
CDInner = cast<clang::Decl>(CDInner->getDeclContext());
9057+
inner = dyn_cast<NominalType>(inner->getParent().getPointer());
9058+
}
9059+
9060+
return inner;
9061+
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10610,7 +10610,7 @@ ClangImporter::Implementation::importDeclContextOf(
1061010610
// Treat friend decls like top-level decls.
1061110611
if (functionDecl->getFriendObjectKind()) {
1061210612
// Find the top-level decl context.
10613-
while (isa<clang::NamedDecl>(dc))
10613+
while (!dc->isFileContext())
1061410614
dc = dc->getParent();
1061510615
}
1061610616

lib/SILGen/SILGenExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1495,7 +1495,7 @@ RValue RValueEmitter::visitDerivedToBaseExpr(DerivedToBaseExpr *E,
14951495
RValue RValueEmitter::visitMetatypeConversionExpr(MetatypeConversionExpr *E,
14961496
SGFContext C) {
14971497
SILValue metaBase =
1498-
SGF.emitRValueAsSingleValue(E->getSubExpr()).getUnmanagedValue();
1498+
SGF.emitRValueAsSingleValue(E->getSubExpr()).getUnmanagedValue();
14991499

15001500
// Metatype conversion casts in the AST might not be reflected as
15011501
// such in the SIL type system, for example, a cast from DynamicSelf.Type

lib/Sema/TypeOfReference.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,20 @@
2222
#include "TypeCheckType.h"
2323
#include "TypeChecker.h"
2424
#include "swift/AST/ConformanceLookup.h"
25-
#include "swift/AST/GenericEnvironment.h"
2625
#include "swift/AST/Effects.h"
26+
#include "swift/AST/GenericEnvironment.h"
2727
#include "swift/AST/MacroDefinition.h"
2828
#include "swift/AST/ParameterList.h"
2929
#include "swift/AST/ProtocolConformance.h"
30+
#include "swift/AST/Type.h"
3031
#include "swift/AST/TypeTransform.h"
31-
#include "swift/Sema/ConstraintSystem.h"
32-
#include "swift/Sema/PreparedOverload.h"
32+
#include "swift/AST/Types.h"
3333
#include "swift/Basic/Assertions.h"
34-
#include "swift/Basic/Statistic.h"
3534
#include "swift/Basic/Defer.h"
35+
#include "swift/Basic/Statistic.h"
36+
#include "swift/ClangImporter/ClangModule.h"
37+
#include "swift/Sema/ConstraintSystem.h"
38+
#include "swift/Sema/PreparedOverload.h"
3639

3740
using namespace swift;
3841
using namespace constraints;
@@ -1646,11 +1649,12 @@ static void addSelfConstraint(ConstraintSystem &cs, Type objectTy, Type selfTy,
16461649
PreparedOverloadBuilder *preparedOverload) {
16471650
assert(!selfTy->is<ProtocolType>());
16481651

1649-
// Otherwise, use a subtype constraint for classes to cope with inheritance.
1652+
// Otherwise, use a subtype constraint for classes to cope with
1653+
// inheritance.
16501654
if (selfTy->getClassOrBoundGenericClass()) {
16511655
cs.addConstraint(ConstraintKind::Subtype, objectTy, selfTy,
1652-
cs.getConstraintLocator(locator), /*isFavored=*/false,
1653-
preparedOverload);
1656+
cs.getConstraintLocator(locator),
1657+
/*isFavored=*/false, preparedOverload);
16541658
return;
16551659
}
16561660

@@ -1950,6 +1954,29 @@ ConstraintSystem::getTypeOfMemberReferencePre(
19501954
value, /*isCurriedInstanceReference*/ !hasAppliedSelf, functionRefInfo);
19511955
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);
19521956

1957+
// Adjust for C++ inline namespaces.
1958+
if (const auto *FT = openedType->getAs<FunctionType>()) {
1959+
auto openedParams = FT->getParams();
1960+
assert(openedParams.size() == 1);
1961+
auto param = openedParams.front();
1962+
1963+
Type selfObjTy = param.getPlainType();
1964+
bool wasMetaType = false;
1965+
if (param.getPlainType()->is<MetatypeType>()) {
1966+
selfObjTy = param.getPlainType()->getMetatypeInstanceType();
1967+
wasMetaType = true;
1968+
}
1969+
if (auto *objectTyNominal = baseObjTy->getAs<NominalType>()) {
1970+
if (auto *selfTyNominal = selfObjTy->getAs<NominalType>())
1971+
if (auto newSelfTy =
1972+
swift::stripInlineNamespaces(objectTyNominal, selfTyNominal))
1973+
openedType = FunctionType::get(
1974+
param.withType(wasMetaType ? Type(MetatypeType::get(newSelfTy))
1975+
: Type(newSelfTy)),
1976+
FT->getResult(), FT->getExtInfo());
1977+
}
1978+
}
1979+
19531980
Type baseOpenedTy = baseObjTy;
19541981

19551982
// If we are looking at a member of an existential, open the existential.

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

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: %target-swift-frontend -c -verify -verify-ignore-unknown -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop -verify
4+
5+
//--- Inputs/module.modulemap
6+
module namespaces {
7+
header "test.h"
8+
requires cplusplus
9+
}
10+
//--- Inputs/test.h
11+
namespace Parent {
12+
inline namespace InlineChild {
13+
inline namespace InlineChild2 {
14+
void functionInInlineChild2();
15+
int GlobalVariableInInlineChild2;
16+
struct GlobalTypeInInlineChild2 {};
17+
} // namespace InlineChild2
18+
void functionInInlineChild();
19+
int GlobalVariableInInlineChild;
20+
struct GlobalTypeInInlineChild {};
21+
namespace Child {
22+
void functionInInlineChildsNonInlineNamespace();
23+
} // namespace Child
24+
} // namespace InlineChild
25+
} // namespace Parent
26+
27+
//--- test.swift
28+
29+
import namespaces;
30+
31+
func test() {
32+
Parent.functionInInlineChild()
33+
Parent.GlobalVariableInInlineChild = 1
34+
Parent.functionInInlineChild2()
35+
Parent.GlobalVariableInInlineChild2 = 2
36+
Parent.InlineChild.functionInInlineChild()
37+
Parent.InlineChild.GlobalVariableInInlineChild = 3
38+
Parent.InlineChild.functionInInlineChild2()
39+
Parent.InlineChild.GlobalVariableInInlineChild2 = 4
40+
Parent.InlineChild.InlineChild2.functionInInlineChild2()
41+
Parent.InlineChild.InlineChild2.GlobalVariableInInlineChild2 = 5
42+
// FIXME: fix the below case.
43+
Parent.Child.functionInInlineChildsNonInlineNamespace() // expected-error {{failed to produce diagnostic for expression}}
44+
Parent.InlineChild.Child.functionInInlineChildsNonInlineNamespace()
45+
}
46+
47+
func testTypes(x: Parent.GlobalTypeInInlineChild, y: Parent.GlobalTypeInInlineChild2,
48+
x2: Parent.InlineChild.GlobalTypeInInlineChild,
49+
y2: Parent.InlineChild.GlobalTypeInInlineChild2,
50+
y3: Parent.InlineChild.InlineChild2.GlobalTypeInInlineChild2) {}

0 commit comments

Comments
 (0)