Skip to content

[PlaygroundTransform] Disable logging ~Copyable types as they can’t be passed to the generic logging function #71293

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

Conversation

dbukowski
Copy link
Contributor

@dbukowski dbukowski commented Jan 31, 2024

Summary

Xcode Playgrounds cannot execute code with ~Copyable types, as the Playground Transform tries to pass them to the generic logging function, which is not supported yet. These changes disable logging them altogether for now, which can be reverted once generics start supporting move-only types. Another approach would be to introduce a placeholder log, which could be recognized by the clients in order to inform the user about the reason for the missing logs.

Changes

  • Add a new function in Playground Transform shouldLogType(Type) to check the isNoncopyable flag and use it in all paths that can lead to creating a playground log.
  • Add unit tests verifying that the move-only types are omitted by the Playground Transform in various scenarios.

rdar://115035973

@dbukowski dbukowski requested review from jckarter and cwakamo January 31, 2024 23:34
@dbukowski dbukowski self-assigned this Jan 31, 2024
@dbukowski
Copy link
Contributor Author

@swift-ci please test windows platform

@dbukowski
Copy link
Contributor Author

@swift-ci please smoke test

@dbukowski dbukowski force-pushed the eng/dbukowski/disable-logging-moveonly-types-in-playground-transform branch from ad61364 to af5f647 Compare February 1, 2024 21:40
@dbukowski
Copy link
Contributor Author

@swift-ci please test windows platform

@dbukowski
Copy link
Contributor Author

@swift-ci please smoke test

@dbukowski
Copy link
Contributor Author

@swift-ci please test windows platform

@dbukowski dbukowski requested a review from abertelrud February 8, 2024 21:04
@@ -786,6 +799,14 @@ class Instrumenter : InstrumenterBase {
return std::make_pair(PBD, VD);
}

bool shouldLogType(Type Ty) {
Copy link
Contributor

@xedin xedin Feb 15, 2024

Choose a reason for hiding this comment

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

Maybe generalize this over ASTNode instead i.e. shouldLog(ASTNode) so that you can cast to ValueDecl * internally to get its interface type?

bool shouldLog(ASTNode node) {
  if (auto *VD = node.dyn_cast<ValueDecl *>())
    return VD->hasInterfaceType() ? !VD->getInterfaceType()->isNoncopyable() : true;
  if (auto *E = node.dyn_cast<Expr *>())
    return !E->getType()->isNoncopyable();
  return true;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried this change and the CI is failing with:

/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: error: implicit instantiation of undefined template 'llvm::FirstIndexOfType<swift::ValueDecl *>'
    : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
                                         ^
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: note: in instantiation of template class 'llvm::FirstIndexOfType<swift::ValueDecl *, swift::CaseLabelItem *>' requested here
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: note: in instantiation of template class 'llvm::FirstIndexOfType<swift::ValueDecl *, swift::StmtConditionElement *, swift::CaseLabelItem *>' requested here
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: note: in instantiation of template class 'llvm::FirstIndexOfType<swift::ValueDecl *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>' requested here
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: note: in instantiation of template class 'llvm::FirstIndexOfType<swift::ValueDecl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>' requested here
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: note: in instantiation of template class 'llvm::FirstIndexOfType<swift::ValueDecl *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>' requested here
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/STLExtras.h:172:42: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/PointerUnion.h:230:30: note: in instantiation of template class 'llvm::FirstIndexOfType<swift::ValueDecl *, swift::Expr *, swift::Stmt *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>' requested here
    return F.Val.getInt() == FirstIndexOfType<To, PTs...>::value;
                             ^
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/ADT/PointerUnion.h:248:27: note: in instantiation of function template specialization 'llvm::CastInfoPointerUnionImpl<swift::Expr *, swift::Stmt *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>::isPossible<swift::ValueDecl *>' requested here
    return Impl::template isPossible<To>(f);
                          ^
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/Support/Casting.h:311:19: note: in instantiation of member function 'llvm::CastInfo<swift::ValueDecl *, llvm::PointerUnion<swift::Expr *, swift::Stmt *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>>::isPossible' requested here
    if (!Derived::isPossible(f))
                  ^
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/llvm-project/llvm/include/llvm/Support/Casting.h:406:23: note: in instantiation of member function 'llvm::DefaultDoCastIfPossible<swift::ValueDecl *, llvm::PointerUnion<swift::Expr *, swift::Stmt *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>, llvm::CastInfo<swift::ValueDecl *, llvm::PointerUnion<swift::Expr *, swift::Stmt *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>>>::doCastIfPossible' requested here
    return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f));
                      ^
/Users/ec2-user/jenkins/workspace/swift-PR-macos-smoke-test/branch-main/swift/lib/Sema/PlaygroundTransform.cpp:803:25: note: in instantiation of function template specialization 'llvm::PointerUnion<swift::Expr *, swift::Stmt *, swift::Decl *, swift::Pattern *, swift::TypeRepr *, swift::StmtConditionElement *, swift::CaseLabelItem *>::dyn_cast<swift::ValueDecl *>' requested here
    if (auto *VD = node.dyn_cast<ValueDecl *>())

Copy link
Contributor

Choose a reason for hiding this comment

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

ah, it's union with a Decl * so you need to do dyn_cast_or_null<ValueDecl>(node.dyn_cast<Decl *>())

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks Pavel, CI is green with this change now. Does the rest of the code look reasonable to you?

@dbukowski
Copy link
Contributor Author

@swift-ci please smoke test

@dbukowski dbukowski force-pushed the eng/dbukowski/disable-logging-moveonly-types-in-playground-transform branch from 03e769e to 4d6284d Compare February 22, 2024 02:00
@dbukowski
Copy link
Contributor Author

@swift-ci please smoke test

@dbukowski
Copy link
Contributor Author

@swift-ci please test windows platform

1 similar comment
@dbukowski
Copy link
Contributor Author

@swift-ci please test windows platform

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

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

Looks good with one small note I left inline. Do you want to do the same for ~Escapable?

@@ -686,6 +694,11 @@ class Instrumenter : InstrumenterBase {
} else if (auto *MRE = dyn_cast<MemberRefExpr>(*RE)) {
Expr *B = MRE->getBase();
ConcreteDeclRef M = MRE->getMember();
VarDecl *VD = cast<VarDecl>(M.getDecl());
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 think you need to do this, can pass M.getDecl() to shouldLog directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, thanks! Removed.

@dbukowski dbukowski force-pushed the eng/dbukowski/disable-logging-moveonly-types-in-playground-transform branch from 4d6284d to e0cbc62 Compare February 22, 2024 23:25
@dbukowski
Copy link
Contributor Author

@swift-ci please smoke test

@dbukowski
Copy link
Contributor Author

Do you want to do the same for ~Escapable?

Oh, we should definitely do that. I can address that in a separate PR.

@xedin
Copy link
Contributor

xedin commented Feb 22, 2024

Sounds good to me!

@dbukowski
Copy link
Contributor Author

@swift-ci please smoke test

1 similar comment
@xedin
Copy link
Contributor

xedin commented Feb 23, 2024

@swift-ci please smoke test

Copy link
Contributor

@abertelrud abertelrud left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks @dbukowski!

@dbukowski dbukowski merged commit a16372e into main Feb 23, 2024
@dbukowski dbukowski deleted the eng/dbukowski/disable-logging-moveonly-types-in-playground-transform branch February 23, 2024 21:27
Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

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

Please test with -enable-experimental-feature NoncopyableGenerics

@@ -786,6 +799,14 @@ class Instrumenter : InstrumenterBase {
return std::make_pair(PBD, VD);
}

bool shouldLogType(Type Ty) {
// Don't try to log ~Copyable types, as we can't pass them to the generic logging functions yet.
if (Ty->isNoncopyable()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You can’t pass interface types to isNoncopyable(), it will assert once the noncopyable generics flag is on.

@@ -686,6 +694,11 @@ class Instrumenter : InstrumenterBase {
} else if (auto *MRE = dyn_cast<MemberRefExpr>(*RE)) {
Expr *B = MRE->getBase();
ConcreteDeclRef M = MRE->getMember();
VarDecl *VD = cast<VarDecl>(M.getDecl());

if (!shouldLogType(VD->getInterfaceType())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Use VD->getTypeInContext()

@@ -658,6 +658,10 @@ class Instrumenter : InstrumenterBase {
// after or instead of the expression they're looking at. Only call this
// if the variable has an initializer.
Added<Stmt *> logVarDecl(VarDecl *VD) {
if (!shouldLogType(VD->getInterfaceType())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

VD-getTypeInContext()

@@ -674,6 +678,10 @@ class Instrumenter : InstrumenterBase {
if (auto *DRE = dyn_cast<DeclRefExpr>(*RE)) {
VarDecl *VD = cast<VarDecl>(DRE->getDecl());

if (!shouldLogType(VD->getInterfaceType())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

VD->getTypeInContext()

bool shouldLog(ASTNode node) {
// Don't try to log ~Copyable types, as we can't pass them to the generic logging functions yet.
if (auto *VD = dyn_cast_or_null<ValueDecl>(node.dyn_cast<Decl *>()))
return VD->hasInterfaceType() ? !VD->getInterfaceType()->isNoncopyable() : true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Don’t call hasInterfaceType(), it doesn’t do what you think it does (it means “have I computed the type yet” not “this has a type”)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks Slava! Based on your comments, it sounds like shouldLog should look something like this:

bool shouldLog(ASTNode node) {
    // Don't try to log ~Copyable types, as we can't pass them to the generic logging functions yet.
    if (auto *VD = dyn_cast_or_null<ValueDecl>(node.dyn_cast<Decl *>()))
      return !VD->getTypeInContext()->isNoncopyable();
    if (auto *E = node.dyn_cast<Expr *>())
      return !E->getType()->isNoncopyable();
    return true;
  }

Does that look reasonable? Unfortunately, I have already merged this PR, so I would open a new one with the necessary changes (after testing with -enable-experimental-feature NoncopyableGenerics as you suggested).

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes that looks good, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants