mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -479,6 +479,10 @@ public:
|
||||
/// asked.
|
||||
virtual Optional<NullablePtr<DeclContext>> computeSelfDCForParent() const;
|
||||
|
||||
/// Returns the context that should be used when a nested scope (e.g. a
|
||||
/// closure) captures self explicitly.
|
||||
virtual NullablePtr<DeclContext> capturedSelfDC() const;
|
||||
|
||||
protected:
|
||||
/// Find either locals or members (no scope has both)
|
||||
/// \param history The scopes visited since the start of lookup (including
|
||||
@@ -692,6 +696,15 @@ public:
|
||||
/// to compute the selfDC from the history.
|
||||
static NullablePtr<DeclContext>
|
||||
computeSelfDC(ArrayRef<const ASTScopeImpl *> history);
|
||||
|
||||
/// If we find a lookup result that requires the dynamic implict self value,
|
||||
/// we need to check the nested scopes to see if any closures explicitly
|
||||
/// captured \c self. In that case, the appropriate selfDC is that of the
|
||||
/// innermost closure which captures a \c self value from one of this type's
|
||||
/// methods.
|
||||
static NullablePtr<DeclContext>
|
||||
checkNestedScopesForSelfCapture(ArrayRef<const ASTScopeImpl *> history,
|
||||
size_t start);
|
||||
};
|
||||
|
||||
/// Behavior specific to representing the trailing where clause of a
|
||||
@@ -1449,6 +1462,13 @@ public:
|
||||
std::string getClassName() const override;
|
||||
SourceRange
|
||||
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
|
||||
|
||||
/// Since explicit captures of \c self by closures enable the use of implicit
|
||||
/// \c self, we need to make sure that the appropriate \c self is used as the
|
||||
/// base decl for these uses (otherwise, the capture would be marked as
|
||||
/// unused. \c ClosureParametersScope::capturedSelfDC() checks if we have such
|
||||
/// a capture of self.
|
||||
NullablePtr<DeclContext> capturedSelfDC() const override;
|
||||
|
||||
protected:
|
||||
ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
|
||||
|
||||
@@ -334,12 +334,15 @@ protected:
|
||||
IsStatic : 1
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1,
|
||||
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1+1,
|
||||
/// Encodes whether this is a 'let' binding.
|
||||
Introducer : 1,
|
||||
|
||||
/// Whether this declaration was an element of a capture list.
|
||||
IsCaptureList : 1,
|
||||
|
||||
/// Whether this declaration captures the 'self' param under the same name.
|
||||
IsSelfParamCapture : 1,
|
||||
|
||||
/// Whether this vardecl has an initial value bound to it in a way
|
||||
/// that isn't represented in the AST with an initializer in the pattern
|
||||
@@ -5029,6 +5032,12 @@ public:
|
||||
|
||||
/// Is this an element in a capture list?
|
||||
bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }
|
||||
|
||||
/// Is this a capture of the self param?
|
||||
bool isSelfParamCapture() const { return Bits.VarDecl.IsSelfParamCapture; }
|
||||
void setIsSelfParamCapture(bool IsSelfParamCapture = true) {
|
||||
Bits.VarDecl.IsSelfParamCapture = IsSelfParamCapture;
|
||||
}
|
||||
|
||||
/// Return true if this vardecl has an initial value bound to it in a way
|
||||
/// that isn't represented in the AST with an initializer in the pattern
|
||||
|
||||
@@ -3244,11 +3244,20 @@ ERROR(self_assignment_var,none,
|
||||
ERROR(self_assignment_prop,none,
|
||||
"assigning a property to itself", ())
|
||||
ERROR(property_use_in_closure_without_explicit_self,none,
|
||||
"reference to property %0 in closure requires explicit 'self.' to make"
|
||||
" capture semantics explicit", (Identifier))
|
||||
"reference to property %0 in closure requires explicit use of 'self' to"
|
||||
" make capture semantics explicit", (Identifier))
|
||||
ERROR(method_call_in_closure_without_explicit_self,none,
|
||||
"call to method %0 in closure requires explicit 'self.' to make"
|
||||
"call to method %0 in closure requires explicit use of 'self' to make"
|
||||
" capture semantics explicit", (Identifier))
|
||||
NOTE(note_capture_self_explicitly,none,
|
||||
"capture 'self' explicitly to enable implicit 'self' in this closure", ())
|
||||
NOTE(note_reference_self_explicitly,none,
|
||||
"reference 'self.' explicitly", ())
|
||||
NOTE(note_other_self_capture,none,
|
||||
"variable other than 'self' captured here under the name 'self' does not "
|
||||
"enable implicit 'self'", ())
|
||||
NOTE(note_self_captured_weakly,none,
|
||||
"weak capture of 'self' here does not enable implicit 'self'", ())
|
||||
ERROR(implicit_use_of_self_in_closure,none,
|
||||
"implicit use of 'self' in closure; use 'self.' to make"
|
||||
" capture semantics explicit", ())
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace swift {
|
||||
class EnumElementDecl;
|
||||
class CallExpr;
|
||||
class KeyPathExpr;
|
||||
class CaptureListExpr;
|
||||
|
||||
enum class ExprKind : uint8_t {
|
||||
#define EXPR(Id, Parent) Id,
|
||||
@@ -3582,6 +3583,18 @@ public:
|
||||
/// \endcode
|
||||
class ClosureExpr : public AbstractClosureExpr {
|
||||
|
||||
/// The range of the brackets of the capture list, if present.
|
||||
SourceRange BracketRange;
|
||||
|
||||
/// The (possibly null) VarDecl captured by this closure with the literal name
|
||||
/// "self". In order to recover this information at the time of name lookup,
|
||||
/// we must be able to access it from the associated DeclContext.
|
||||
/// Because the DeclContext inside a closure is the closure itself (and not
|
||||
/// the CaptureListExpr which would normally maintain this sort of
|
||||
/// information about captured variables), we need to have some way to access
|
||||
/// this information directly on the ClosureExpr.
|
||||
VarDecl *CapturedSelfDecl;
|
||||
|
||||
/// The location of the "throws", if present.
|
||||
SourceLoc ThrowsLoc;
|
||||
|
||||
@@ -3598,16 +3611,16 @@ class ClosureExpr : public AbstractClosureExpr {
|
||||
/// The body of the closure, along with a bit indicating whether it
|
||||
/// was originally just a single expression.
|
||||
llvm::PointerIntPair<BraceStmt *, 1, bool> Body;
|
||||
|
||||
public:
|
||||
ClosureExpr(ParameterList *params, SourceLoc throwsLoc, SourceLoc arrowLoc,
|
||||
ClosureExpr(SourceRange bracketRange, VarDecl *capturedSelfDecl,
|
||||
ParameterList *params, SourceLoc throwsLoc, SourceLoc arrowLoc,
|
||||
SourceLoc inLoc, TypeLoc explicitResultType,
|
||||
unsigned discriminator, DeclContext *parent)
|
||||
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
|
||||
discriminator, parent),
|
||||
BracketRange(bracketRange), CapturedSelfDecl(capturedSelfDecl),
|
||||
ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
|
||||
ExplicitResultType(explicitResultType),
|
||||
Body(nullptr) {
|
||||
ExplicitResultType(explicitResultType), Body(nullptr) {
|
||||
setParameterList(params);
|
||||
Bits.ClosureExpr.HasAnonymousClosureVars = false;
|
||||
}
|
||||
@@ -3639,6 +3652,8 @@ public:
|
||||
/// explicitly-specified result type.
|
||||
bool hasExplicitResultType() const { return ArrowLoc.isValid(); }
|
||||
|
||||
/// Retrieve the range of the \c '[' and \c ']' that enclose the capture list.
|
||||
SourceRange getBracketRange() const { return BracketRange; }
|
||||
|
||||
/// Retrieve the location of the \c '->' for closures with an
|
||||
/// explicit result type.
|
||||
@@ -3704,6 +3719,14 @@ public:
|
||||
/// Is this a completely empty closure?
|
||||
bool hasEmptyBody() const;
|
||||
|
||||
/// VarDecl captured by this closure under the literal name \c self , if any.
|
||||
VarDecl *getCapturedSelfDecl() const { return CapturedSelfDecl; }
|
||||
|
||||
/// Whether this closure captures the \c self param in its body in such a
|
||||
/// way that implicit \c self is enabled within its body (i.e. \c self is
|
||||
/// captured non-weakly).
|
||||
bool capturesSelfEnablingImplictSelf() const;
|
||||
|
||||
static bool classof(const Expr *E) {
|
||||
return E->getKind() == ExprKind::Closure;
|
||||
}
|
||||
@@ -3778,6 +3801,8 @@ struct CaptureListEntry {
|
||||
CaptureListEntry(VarDecl *Var, PatternBindingDecl *Init)
|
||||
: Var(Var), Init(Init) {
|
||||
}
|
||||
|
||||
bool isSimpleSelfCapture() const;
|
||||
};
|
||||
|
||||
/// CaptureListExpr - This expression represents the capture list on an explicit
|
||||
|
||||
@@ -70,13 +70,15 @@ private:
|
||||
/// When finding \c bar() from the function body of \c foo(), \c BaseDC is
|
||||
/// the method \c foo().
|
||||
///
|
||||
/// \c BaseDC will be the method if \c self is needed for the lookup,
|
||||
/// and will be the type if not.
|
||||
/// In other words: If \c baseDC is a method, it means you found an instance
|
||||
/// member and you should add an implicit 'self.' (Each method has its own
|
||||
/// implicit self decl.) There's one other kind of non-method context that
|
||||
/// has a 'self.' -- a lazy property initializer, which unlike a non-lazy
|
||||
/// property can reference \c self) Hence: \code
|
||||
/// \c BaseDC will be the type if \c self is not needed for the lookup. If
|
||||
/// \c self is needed, \c baseDC will be either the method or a closure
|
||||
/// which explicitly captured \c self.
|
||||
/// In other words: If \c baseDC is a method or a closure, it means you
|
||||
/// found an instance member and you should add an implicit 'self.' (Each
|
||||
/// method has its own implicit self decl.) There's one other kind of
|
||||
/// non-method, non-closure context that has a 'self.' -- a lazy property
|
||||
/// initializer, which unlike a non-lazy property can reference \c self.
|
||||
/// \code
|
||||
/// class Outer {
|
||||
/// static func s()
|
||||
/// func i()
|
||||
|
||||
@@ -293,7 +293,17 @@ public:
|
||||
/// resides.
|
||||
///
|
||||
/// \param Loc The source location of the beginning of a token.
|
||||
static Token getTokenAtLocation(const SourceManager &SM, SourceLoc Loc);
|
||||
///
|
||||
/// \param CRM How comments should be treated by the lexer. Default is to
|
||||
/// return the comments as tokens. This is needed in situations where
|
||||
/// detecting the next semantically meaningful token is required, such as
|
||||
/// the 'implicit self' diagnostic determining whether a capture list is
|
||||
/// empty (i.e., the opening bracket is immediately followed by a closing
|
||||
/// bracket, possibly with comments in between) in order to insert the
|
||||
/// appropriate fix-it.
|
||||
static Token getTokenAtLocation(
|
||||
const SourceManager &SM, SourceLoc Loc,
|
||||
CommentRetentionMode CRM = CommentRetentionMode::ReturnAsTokens);
|
||||
|
||||
|
||||
/// Retrieve the source location that points just past the
|
||||
|
||||
@@ -1514,6 +1514,8 @@ public:
|
||||
/// identifier (',' identifier)* func-signature-result? 'in'
|
||||
/// \endverbatim
|
||||
///
|
||||
/// \param bracketRange The range of the brackets enclosing a capture list, if
|
||||
/// present. Needed to offer fix-its for inserting 'self' into a capture list.
|
||||
/// \param captureList The entries in the capture list.
|
||||
/// \param params The parsed parameter list, or null if none was provided.
|
||||
/// \param arrowLoc The location of the arrow, if present.
|
||||
@@ -1522,12 +1524,14 @@ public:
|
||||
///
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
bool parseClosureSignatureIfPresent(
|
||||
SmallVectorImpl<CaptureListEntry> &captureList,
|
||||
ParameterList *¶ms,
|
||||
SourceLoc &throwsLoc,
|
||||
SourceLoc &arrowLoc,
|
||||
TypeRepr *&explicitResultType,
|
||||
SourceLoc &inLoc);
|
||||
SourceRange &bracketRange,
|
||||
SmallVectorImpl<CaptureListEntry> &captureList,
|
||||
VarDecl *&capturedSelfParamDecl,
|
||||
ParameterList *¶ms,
|
||||
SourceLoc &throwsLoc,
|
||||
SourceLoc &arrowLoc,
|
||||
TypeRepr *&explicitResultType,
|
||||
SourceLoc &inLoc);
|
||||
|
||||
Expr *parseExprAnonClosureArg();
|
||||
ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok,
|
||||
|
||||
Reference in New Issue
Block a user