Skip to content

SILGen: Emit move-only bases for lvalues in a borrow scope. #65302

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 1 commit into from
Apr 20, 2023

Conversation

jckarter
Copy link
Contributor

Normally, if we project from a mutable class ivar or global variable, we'll load a copy in a tight access scope and then project from the copy, in order to minimize the potential for exclusivity violations while working with classes and copyable values. However, this is undesirable when a value is move-only, since copying is not allowed; borrowing the value in place is the expected and only possible behavior. rdar://105794506

Normally, if we project from a mutable class ivar or global variable, we'll
load a copy in a tight access scope and then project from the copy, in order to
minimize the potential for exclusivity violations while working with classes and
copyable values. However, this is undesirable when a value is move-only, since
copying is not allowed; borrowing the value in place is the expected and only possible
behavior. rdar://105794506
@jckarter jckarter requested review from kavon and gottesmm April 19, 2023 21:54
@jckarter
Copy link
Contributor Author

@swift-ci Please test

Copy link
Member

@kavon kavon left a comment

Choose a reason for hiding this comment

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

Nice fix overall 👍🏼

Comment on lines +2814 to +2817
// If the base is a load of a noncopyable type (or, eventually, when we have
// a `borrow x` operator, the operator is used on the base here), we want to
// apply the lvalue within a formal access to the original value instead of
// an actual loaded copy.
Copy link
Member

@kavon kavon Apr 20, 2023

Choose a reason for hiding this comment

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

So we do have the expression form _borrow x behind -enable-experimental-move-only, so it's worth checking if this also works for that too. This:

struct X: ~Copyable {
  var something: Int { return 1 }
}

func f() -> Int {
  var x = X()
  return (_borrow x).something
}

gives an AST like this:

(member_ref_expr ...
  (paren_expr ...
    (load_expr implicit type='X' ...
      (borrow_expr type='@lvalue X' ...
        (declref_expr type='@lvalue X' ... )))))

It doesn't appear that SILGenLValue has a visitor for a BorrowExpr yet, so this might crash now (haven' tried your branch yet).

Comment on lines +15 to +17
// error: 'self.val' has consuming use that cannot
// be eliminated due to a tight exclusivity scope
return val.empty // note: consuming use here
Copy link
Member

Choose a reason for hiding this comment

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

maybe we can remove these comments now that it's working

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.

2 participants