Skip to content

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

Merged
merged 16 commits into from
Mar 1, 2022
Merged

Eng/pr getters setters #40842

merged 16 commits into from
Mar 1, 2022

Conversation

bro4all
Copy link
Contributor

@bro4all bro4all commented Jan 13, 2022

In this patch, we add the ability to import struct getters/setters

example:

struct X {
    int getX() const {}
    void setX(int) {}
};

// will be:
var Object = X()
Object.x = 1

@bro4all bro4all force-pushed the eng/PR-getters-setters branch from 2c99890 to 4c36d52 Compare January 13, 2022 17:14
@bro4all bro4all requested a review from zoecarver January 13, 2022 17:14
@bro4all
Copy link
Contributor Author

bro4all commented Jan 13, 2022

@swift-ci please smoke test.

Copy link
Contributor

@zoecarver zoecarver left a 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.

Comment on lines 106 to 110
Expr *createSelfExpr(AccessorDecl *accessorDecl);
DeclRefExpr *createParamRefExpr(AccessorDecl *accessorDecl, unsigned index);
CallExpr * createAccessorImplCallExpr(FuncDecl *accessorImpl,
Expr *selfExpr,
DeclRefExpr *keyRefExpr = nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these forward declarations.

@@ -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;
Copy link
Contributor

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.

Copy link
Contributor

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.

@@ -3577,7 +3587,9 @@ namespace {
if (auto structResult = dyn_cast<StructDecl>(result))
structResult->setIsCxxNonTrivial(
!cxxRecordDecl->isTriviallyCopyable());

for (auto &getterAndSetter : Impl.GetterSetterMap){
Copy link
Contributor

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.

@@ -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));
Copy link
Contributor

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.




Decl *VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) {
Copy link
Contributor

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.

@@ -7568,7 +7741,14 @@ createAccessorImplCallExpr(FuncDecl *accessorImpl,
accessorImplDotCallExpr->setType(accessorImpl->getMethodInterfaceType());
accessorImplDotCallExpr->setThrows(false);

auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {keyRefExpr});
ArgumentList *argList;
if (keyRefExpr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove.

@@ -7568,7 +7741,14 @@ createAccessorImplCallExpr(FuncDecl *accessorImpl,
accessorImplDotCallExpr->setType(accessorImpl->getMethodInterfaceType());
accessorImplDotCallExpr->setThrows(false);

auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {keyRefExpr});
ArgumentList *argList;
Copy link
Contributor

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.

@@ -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
Copy link
Contributor

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.

@zoecarver zoecarver added the c++ interop Feature: Interoperability with C++ label Jan 14, 2022
@zoecarver
Copy link
Contributor

zoecarver commented Jan 14, 2022

I'd specifically like to see some tests that check for the following cases:

void getX();
void get();
int getX();
int get();
int getfoo();
int getFOO();
int GetFoo();
int Getter();

And

void setX();
void set();
int setX(int);
void setX(int, int);
void set(int);
...

And at least one test when we have a setter but no getter.

Copy link
Contributor

@egorzhdan egorzhdan left a 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.

@bro4all
Copy link
Contributor Author

bro4all commented Jan 16, 2022

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).

@bro4all
Copy link
Contributor Author

bro4all commented Jan 16, 2022

It would be nice to still be able to call the getters or setters explicitly

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.

@@ -3577,7 +3587,9 @@ namespace {
if (auto structResult = dyn_cast<StructDecl>(result))
structResult->setIsCxxNonTrivial(
!cxxRecordDecl->isTriviallyCopyable());

for (auto &getterAndSetter : Impl.GetterSetterMap){
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These VarDecls will be added to every record.

@bro4all bro4all force-pushed the eng/PR-getters-setters branch from 4c36d52 to b8b9478 Compare January 28, 2022 07:45
@bro4all
Copy link
Contributor Author

bro4all commented Feb 10, 2022

@swift-ci please smoke test

@bro4all bro4all force-pushed the eng/PR-getters-setters branch from 28c3a07 to fa5ca21 Compare February 10, 2022 17:37
@bro4all
Copy link
Contributor Author

bro4all commented Feb 10, 2022

@swift-ci please smoke test

@hyp
Copy link
Contributor

hyp commented Feb 11, 2022

@swift-ci please smoke test

@bro4all bro4all force-pushed the eng/PR-getters-setters branch from fa5ca21 to 6ae41ad Compare February 15, 2022 21:27
@bro4all bro4all force-pushed the eng/PR-getters-setters branch from 6ae41ad to 659d4d5 Compare February 15, 2022 21:37
@bro4all
Copy link
Contributor Author

bro4all commented Feb 16, 2022

@swift-ci please smoke test

@bro4all bro4all requested a review from egorzhdan February 17, 2022 18:49
@@ -3507,6 +3571,9 @@ namespace {
continue;
}

if(nd->getDeclName().isIdentifier())
Copy link
Contributor

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);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: new line.

setterDecl->setSelfAccessKind(SelfAccessKind::Mutating);
result->setIsSetterMutating(true);
} else {
setterDecl->setSelfAccessKind(SelfAccessKind::NonMutating);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation.

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?

Comment on lines 9187 to 9205
// 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"));
}
}
Copy link
Contributor

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)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space

return Kind::getter;
}

rdar://89453187 (Add subscripts clarification to CXXMethod Bridging to clean up importDecl)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment.

Comment on lines 25 to 27
// this should be handled as snake case. See: rdar://89453010
// case. In the future we could
// import these too, though.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
// 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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VoidSetterNoName

Comment on lines 9 to 23
struct VoidGetterNoName {
void set();
};

struct IllegalIntReturnSetter {
int setX(int);
};

struct TwoParameterSetter {
void setX(int, int);
};

struct NoNameSetter {
void set(int);
};
Copy link
Contributor

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 {
Copy link
Contributor

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rdar://89453187 (Add subscripts clarification to CXXMethod Bridging to clean up importDecl)
// TODO: classify subscripts here (rdar://89453187).

@zoecarver
Copy link
Contributor

It's worrying to see any tests passing... this shouldn't compile.

@zoecarver
Copy link
Contributor

@egorzhdan want to take another look over this?

@zoecarver
Copy link
Contributor

@swift-ci please test.

Comment on lines 11 to 22
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
Copy link
Contributor

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?

@zoecarver
Copy link
Contributor

@swift-ci please test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants