-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Eng/pr getters setters #40842
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
Eng/pr getters setters #40842
Conversation
2c99890
to
4c36d52
Compare
@swift-ci please smoke test. |
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.
Hey Omar! This patch looks great! I'm super excited to start importing these methods more ergonomically!
Don't be overwhelmed by the comments, the logic actually looks pretty good, so most of these are just nits. Please add some test cases as well.
Also, I think we may need a forum post for this patch at some point. But we can probably get to that later.
lib/ClangImporter/ImportDecl.cpp
Outdated
Expr *createSelfExpr(AccessorDecl *accessorDecl); | ||
DeclRefExpr *createParamRefExpr(AccessorDecl *accessorDecl, unsigned index); | ||
CallExpr * createAccessorImplCallExpr(FuncDecl *accessorImpl, | ||
Expr *selfExpr, | ||
DeclRefExpr *keyRefExpr = nullptr); |
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.
Remove these forward declarations.
lib/ClangImporter/ImporterImpl.h
Outdated
@@ -499,7 +499,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation | |||
/// Keep track of subscript declarations based on getter/setter | |||
/// pairs. | |||
llvm::DenseMap<std::pair<FuncDecl *, FuncDecl *>, SubscriptDecl *> Subscripts; | |||
|
|||
llvm::DenseMap<Identifier, std::tuple<VarDecl *, AccessorDecl *, AccessorDecl *>> GetterSetterMap; |
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.
Please add a comment to this like the one for Subscripts
.
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.
Also, I wonder if there's a better way to hold the values than a tuple.
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -3577,7 +3587,9 @@ namespace { | |||
if (auto structResult = dyn_cast<StructDecl>(result)) | |||
structResult->setIsCxxNonTrivial( | |||
!cxxRecordDecl->isTriviallyCopyable()); | |||
|
|||
for (auto &getterAndSetter : Impl.GetterSetterMap){ |
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.
This should be called computedProperties
or something.
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -3577,7 +3587,9 @@ namespace { | |||
if (auto structResult = dyn_cast<StructDecl>(result)) | |||
structResult->setIsCxxNonTrivial( | |||
!cxxRecordDecl->isTriviallyCopyable()); | |||
|
|||
for (auto &getterAndSetter : Impl.GetterSetterMap){ | |||
result->addMember(get<0>(getterAndSetter.second)); |
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.
If we can't get rid of the tuple, please add a comment explaining that this is the vardecl/property itself.
lib/ClangImporter/ImportDecl.cpp
Outdated
|
||
|
||
|
||
Decl *VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) { |
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.
I think you can clean up and refactor this whole function.
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -7568,7 +7741,14 @@ createAccessorImplCallExpr(FuncDecl *accessorImpl, | |||
accessorImplDotCallExpr->setType(accessorImpl->getMethodInterfaceType()); | |||
accessorImplDotCallExpr->setThrows(false); | |||
|
|||
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {keyRefExpr}); | |||
ArgumentList *argList; | |||
if (keyRefExpr) { |
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.
Remove.
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -7568,7 +7741,14 @@ createAccessorImplCallExpr(FuncDecl *accessorImpl, | |||
accessorImplDotCallExpr->setType(accessorImpl->getMethodInterfaceType()); | |||
accessorImplDotCallExpr->setThrows(false); | |||
|
|||
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {keyRefExpr}); | |||
ArgumentList *argList; |
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.
Nit: please initialize this to nullptr
.
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -8930,6 +9110,18 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl, | |||
Result = importDecl(UnderlyingDecl, version); | |||
SkippedOverTypedef = true; | |||
} | |||
// TODO extend Swift classes to it's equivalents from it's ClanDecled attributes |
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.
I don't understand this TODO.
I'd specifically like to see some tests that check for the following cases:
And
And at least one test when we have a setter but no getter. |
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.
This looks great! Other than what Zoe already mentioned, I have a few ideas for test cases:
int& getInt() const;
void setInt(int);
// I don't know if these should be transformed into a computed property, I think, for now we should just make sure it doesn't crash :)
int& getInt2() const;
void setInt2(int*);
// Same as above.
void settings(int);
void setUp(int);
// These should not be transformed into a computed property.
int getOrCreateSomething() const;
// This would probably be transformed into something awkward (`var orCreateSomething: Int`), and I think it's fine.
// It would be nice to still be able to call the getters or setters explicitly
// (in this case, `let x = object.getOrCreateSomething()` instead of `let x = object.orCreateSomething`)
// I think it's worth having a test for this.
Another test case: make sure that it doesn't matter which order getters/setters are defined in (i.e., you can define the setter first). |
Yes, I think we should always continue to import the original method. Maybe we want to add a deprecation, though. I think this happens for some Objective-C enums. Maybe something for the forums to decide. |
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -3577,7 +3587,9 @@ namespace { | |||
if (auto structResult = dyn_cast<StructDecl>(result)) | |||
structResult->setIsCxxNonTrivial( | |||
!cxxRecordDecl->isTriviallyCopyable()); | |||
|
|||
for (auto &getterAndSetter : Impl.GetterSetterMap){ |
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.
These VarDecl
s will be added to every record.
4c36d52
to
b8b9478
Compare
@swift-ci please smoke test |
28c3a07
to
fa5ca21
Compare
@swift-ci please smoke test |
@swift-ci please smoke test |
fa5ca21
to
6ae41ad
Compare
6ae41ad
to
659d4d5
Compare
@swift-ci please smoke test |
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -3507,6 +3571,9 @@ namespace { | |||
continue; | |||
} | |||
|
|||
if(nd->getDeclName().isIdentifier()) |
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.
nit: space
@@ -4308,9 +4404,53 @@ namespace { | |||
|
|||
recordObjCOverride(result); | |||
} |
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.
Nit: new line.
lib/ClangImporter/ImportDecl.cpp
Outdated
setterDecl->setSelfAccessKind(SelfAccessKind::Mutating); | ||
result->setIsSetterMutating(true); | ||
} else { | ||
setterDecl->setSelfAccessKind(SelfAccessKind::NonMutating); |
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.
nit: indentation.
lib/ClangImporter/ImportDecl.cpp
Outdated
@@ -9027,6 +9184,25 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl, | |||
Result = importDecl(UnderlyingDecl, version); | |||
SkippedOverTypedef = true; | |||
} | |||
// TODO extend Swift classes to it's equivalents from it's ClanDecled |
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.
What does this mean?
lib/ClangImporter/ImportDecl.cpp
Outdated
// TODO extend Swift classes to it's equivalents from it's ClanDecled | ||
// attributes | ||
|
||
if (isa<clang::FunctionDecl>(ClangDecl)) { | ||
if (ClangDecl->getDeclName().isIdentifier() && | ||
ClangDecl->getName().startswith_insensitive("get") && | ||
ClangDecl->getName().lower() != "getter") { | ||
const_cast<clang::NamedDecl *>(ClangDecl)->addAttr( | ||
clang::SwiftAttrAttr::CreateImplicit(ClangDecl->getASTContext(), | ||
"import_as_getter")); | ||
} | ||
if (ClangDecl->getDeclName().isIdentifier() && | ||
ClangDecl->getName().startswith_insensitive("set") && | ||
ClangDecl->getName().lower() != "setter") { | ||
const_cast<clang::NamedDecl *>(ClangDecl)->addAttr( | ||
clang::SwiftAttrAttr::CreateImplicit(ClangDecl->getASTContext(), | ||
"import_as_setter")); | ||
} | ||
} |
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.
This can all be removed.
expectEqual(a.foo, 42) | ||
a.foo = 32 | ||
expectEqual(a.foo, 32) | ||
|
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.
Space
test/Interop/Cxx/ergonomics/implicit-computed-properties-module-interface.swift
Show resolved
Hide resolved
return Kind::getter; | ||
} | ||
|
||
rdar://89453187 (Add subscripts clarification to CXXMethod Bridging to clean up importDecl) |
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.
Comment.
// this should be handled as snake case. See: rdar://89453010 | ||
// case. In the future we could | ||
// import these too, though. |
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.
Nit:
// this should be handled as snake case. See: rdar://89453010 | |
// case. In the future we could | |
// import these too, though. | |
// TODO: this should be handle snake case too (rdar://89453010). |
void setX(int); | ||
}; | ||
|
||
struct VoidGetterNoName { |
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.
VoidSetterNoName
struct VoidGetterNoName { | ||
void set(); | ||
}; | ||
|
||
struct IllegalIntReturnSetter { | ||
int setX(int); | ||
}; | ||
|
||
struct TwoParameterSetter { | ||
void setX(int, int); | ||
}; | ||
|
||
struct NoNameSetter { | ||
void set(int); | ||
}; |
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.
These all need correct getters. Otherwise they're all testing the same thing.
int setFOO(int v) const {} | ||
mutable int value = 42; | ||
int getFOO() const { return value; } | ||
void setFOO(int v) const {value = v ;} | ||
}; | ||
|
||
struct LongNameMix { |
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.
LongNameMix doesn't really make sense here. This shows the need for two different tests:
struct UpperCaseMix {
int getFoo() const;
void SetFoo(int);
}
And:
struct UpperCaseGetterSetter {
...
}
return Kind::getter; | ||
} | ||
|
||
rdar://89453187 (Add subscripts clarification to CXXMethod Bridging to clean up importDecl) |
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.
rdar://89453187 (Add subscripts clarification to CXXMethod Bridging to clean up importDecl) | |
// TODO: classify subscripts here (rdar://89453187). |
It's worrying to see any tests passing... this shouldn't compile. |
@egorzhdan want to take another look over this? |
@swift-ci please test. |
//===----------------------------------------------------------------------===// | ||
// | ||
// This file implements IR generation for value witnesses in Swift. | ||
// | ||
// Value witnesses are (predominantly) functions that implement the basic | ||
// operations for copying and destroying values. | ||
// | ||
// In the comments throughout this file, three type names are used: | ||
// 'B' is the type of a fixed-size buffer | ||
// 'T' is the type which implements a protocol | ||
// | ||
//===----------------------------------------------------------------------===// |
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.
Sorry can you delete this or change it?
@swift-ci please test. |
In this patch, we add the ability to import struct getters/setters
example: