MiscDiagnostics.cpp (swift-swift-5.8-RELEASE) | : | MiscDiagnostics.cpp (swift-swift-5.8.1-RELEASE) | ||
---|---|---|---|---|
skipping to change at line 113 | skipping to change at line 113 | |||
/// - KeyPath expressions cannot refer to effectful properties / subscripts | /// - KeyPath expressions cannot refer to effectful properties / subscripts | |||
/// - Move expressions must have a declref expr subvalue. | /// - Move expressions must have a declref expr subvalue. | |||
/// | /// | |||
static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, | static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, | |||
bool isExprStmt) { | bool isExprStmt) { | |||
class DiagnoseWalker : public BaseDiagnosticWalker { | class DiagnoseWalker : public BaseDiagnosticWalker { | |||
SmallPtrSet<Expr*, 4> AlreadyDiagnosedMetatypes; | SmallPtrSet<Expr*, 4> AlreadyDiagnosedMetatypes; | |||
SmallPtrSet<DeclRefExpr*, 4> AlreadyDiagnosedBitCasts; | SmallPtrSet<DeclRefExpr*, 4> AlreadyDiagnosedBitCasts; | |||
bool IsExprStmt; | bool IsExprStmt; | |||
bool HasReachedSemanticsProvidingExpr; | ||||
ASTContext &Ctx; | ASTContext &Ctx; | |||
const DeclContext *DC; | const DeclContext *DC; | |||
public: | public: | |||
DiagnoseWalker(const DeclContext *DC, bool isExprStmt) | DiagnoseWalker(const DeclContext *DC, bool isExprStmt) | |||
: IsExprStmt(isExprStmt), HasReachedSemanticsProvidingExpr(false), | : IsExprStmt(isExprStmt), Ctx(DC->getASTContext()), DC(DC) {} | |||
Ctx(DC->getASTContext()), DC(DC) {} | ||||
PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override { | PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override { | |||
return Action::SkipChildren(P); | return Action::SkipChildren(P); | |||
} | } | |||
PreWalkAction walkToTypeReprPre(TypeRepr *T) override { | PreWalkAction walkToTypeReprPre(TypeRepr *T) override { | |||
return Action::Continue(); | return Action::Continue(); | |||
} | } | |||
bool shouldWalkCaptureInitializerExpressions() override { return true; } | bool shouldWalkCaptureInitializerExpressions() override { return true; } | |||
bool shouldWalkIntoTapExpression() override { return false; } | bool shouldWalkIntoTapExpression() override { return false; } | |||
PreWalkResult<Expr *> walkToExprPre(Expr *E) override { | PreWalkResult<Expr *> walkToExprPre(Expr *E) override { | |||
if (auto collection = dyn_cast<CollectionExpr>(E)) { | ||||
if (collection->isTypeDefaulted()) { | ||||
// Diagnose type defaulted collection literals in subexpressions as | ||||
// warnings to preserve source compatibility. | ||||
diagnoseTypeDefaultedCollectionExpr( | ||||
collection, Ctx, | ||||
/*downgradeToWarning=*/HasReachedSemanticsProvidingExpr); | ||||
} | ||||
} | ||||
// See through implicit conversions of the expression. We want to be able | // See through implicit conversions of the expression. We want to be able | |||
// to associate the parent of this expression with the ultimate callee. | // to associate the parent of this expression with the ultimate callee. | |||
auto Base = E; | auto Base = E; | |||
while (auto Conv = dyn_cast<ImplicitConversionExpr>(Base)) | while (auto Conv = dyn_cast<ImplicitConversionExpr>(Base)) | |||
Base = Conv->getSubExpr(); | Base = Conv->getSubExpr(); | |||
if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) { | if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) { | |||
// Verify metatype uses. | // Verify metatype uses. | |||
if (isa<TypeDecl>(DRE->getDecl())) { | if (isa<TypeDecl>(DRE->getDecl())) { | |||
if (isa<ModuleDecl>(DRE->getDecl())) | if (isa<ModuleDecl>(DRE->getDecl())) | |||
skipping to change at line 348 | skipping to change at line 336 | |||
if (auto cast = dyn_cast<CheckedCastExpr>(E)) { | if (auto cast = dyn_cast<CheckedCastExpr>(E)) { | |||
checkCheckedCastExpr(cast); | checkCheckedCastExpr(cast); | |||
} | } | |||
// Diagnose move expression uses where the sub expression is not a declref | // Diagnose move expression uses where the sub expression is not a declref | |||
// expr. | // expr. | |||
if (auto *moveExpr = dyn_cast<MoveExpr>(E)) { | if (auto *moveExpr = dyn_cast<MoveExpr>(E)) { | |||
checkMoveExpr(moveExpr); | checkMoveExpr(moveExpr); | |||
} | } | |||
if (!HasReachedSemanticsProvidingExpr && | ||||
E == E->getSemanticsProvidingExpr()) { | ||||
HasReachedSemanticsProvidingExpr = true; | ||||
} | ||||
return Action::Continue(E); | return Action::Continue(E); | |||
} | } | |||
PostWalkResult<Expr *> walkToExprPost(Expr *E) override { | PostWalkResult<Expr *> walkToExprPost(Expr *E) override { | |||
return Action::Continue(E); | return Action::Continue(E); | |||
} | } | |||
/// Visit each component of the keypath and emit a diagnostic if they | /// Visit each component of the keypath and emit a diagnostic if they | |||
/// refer to a member that has effects. | /// refer to a member that has effects. | |||
void checkForEffectfulKeyPath(KeyPathExpr *keyPath) { | void checkForEffectfulKeyPath(KeyPathExpr *keyPath) { | |||
skipping to change at line 475 | skipping to change at line 458 | |||
// NSObject.removeObserver(_:forKeyPath:context:) | // NSObject.removeObserver(_:forKeyPath:context:) | |||
if (uncurryLevel == 1 && argIndex == 2) { | if (uncurryLevel == 1 && argIndex == 2) { | |||
return decl->getName().isCompoundName("removeObserver", | return decl->getName().isCompoundName("removeObserver", | |||
{ "", "forKeyPath", "context" }); | { "", "forKeyPath", "context" }); | |||
} | } | |||
return false; | return false; | |||
} | } | |||
/// Diagnose a collection literal with a defaulted type such as \c [Any]. | /// We have a collection literal with a defaulted type, e.g. of [Any]. Emit | |||
static void diagnoseTypeDefaultedCollectionExpr(CollectionExpr *c, | /// an error if it was inferred to this type in an invalid context, which is | |||
ASTContext &ctx, | /// one in which the parent expression is not itself a collection literal. | |||
bool downgradeToWarning) { | void checkTypeDefaultedCollectionExpr(CollectionExpr *c) { | |||
// Produce a diagnostic with a fixit to add the defaulted type as an | // If the parent is a non-expression, or is not itself a literal, then | |||
// explicit annotation. | // produce an error with a fixit to add the type as an explicit | |||
auto &diags = ctx.Diags; | // annotation. | |||
if (c->getNumElements() == 0) | ||||
if (c->getNumElements() == 0) { | Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_empty) | |||
InFlightDiagnostic inFlight = | .highlight(c->getSourceRange()); | |||
diags.diagnose(c->getLoc(), diag::collection_literal_empty); | else { | |||
inFlight.highlight(c->getSourceRange()); | ||||
if (downgradeToWarning) { | ||||
inFlight.limitBehavior(DiagnosticBehavior::Warning); | ||||
} | ||||
} else { | ||||
assert(c->getType()->hasTypeRepr() && | assert(c->getType()->hasTypeRepr() && | |||
"a defaulted type should always be printable"); | "a defaulted type should always be printable"); | |||
InFlightDiagnostic inFlight = diags.diagnose( | Ctx.Diags | |||
c->getLoc(), diag::collection_literal_heterogeneous, c->getType()); | .diagnose(c->getLoc(), diag::collection_literal_heterogeneous, | |||
inFlight.highlight(c->getSourceRange()); | c->getType()) | |||
inFlight.fixItInsertAfter(c->getEndLoc(), | .highlight(c->getSourceRange()) | |||
" as " + c->getType()->getString()); | .fixItInsertAfter(c->getEndLoc(), | |||
" as " + c->getType()->getString()); | ||||
if (downgradeToWarning) { | ||||
inFlight.limitBehavior(DiagnosticBehavior::Warning); | ||||
} | ||||
} | } | |||
} | } | |||
void checkMagicIdentifierMismatch(ConcreteDeclRef callee, | void checkMagicIdentifierMismatch(ConcreteDeclRef callee, | |||
unsigned uncurryLevel, | unsigned uncurryLevel, | |||
unsigned argIndex, | unsigned argIndex, | |||
Expr *arg) { | Expr *arg) { | |||
// We only care about args in the arg list. | // We only care about args in the arg list. | |||
if (uncurryLevel != (callee.getDecl()->hasCurriedSelf() ? 1 : 0)) | if (uncurryLevel != (callee.getDecl()->hasCurriedSelf() ? 1 : 0)) | |||
return; | return; | |||
skipping to change at line 1376 | skipping to change at line 1350 | |||
.highlight(lhs->getSourceRange()) | .highlight(lhs->getSourceRange()) | |||
.highlight(rhs->getSourceRange()); | .highlight(rhs->getSourceRange()); | |||
return; | return; | |||
} | } | |||
} | } | |||
} | } | |||
}; | }; | |||
DiagnoseWalker Walker(DC, isExprStmt); | DiagnoseWalker Walker(DC, isExprStmt); | |||
const_cast<Expr *>(E)->walk(Walker); | const_cast<Expr *>(E)->walk(Walker); | |||
// Diagnose uses of collection literals with defaulted types at the top | ||||
// level. | ||||
if (auto collection = | ||||
dyn_cast<CollectionExpr>(E->getSemanticsProvidingExpr())) { | ||||
if (collection->isTypeDefaulted()) { | ||||
Walker.checkTypeDefaultedCollectionExpr( | ||||
const_cast<CollectionExpr *>(collection)); | ||||
} | ||||
} | ||||
} | } | |||
/// Diagnose recursive use of properties within their own accessors | /// Diagnose recursive use of properties within their own accessors | |||
static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) { | static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) { | |||
auto fn = dyn_cast<AccessorDecl>(DC); | auto fn = dyn_cast<AccessorDecl>(DC); | |||
if (!fn) | if (!fn) | |||
return; | return; | |||
auto var = dyn_cast<VarDecl>(fn->getStorage()); | auto var = dyn_cast<VarDecl>(fn->getStorage()); | |||
if (!var) // Ignore subscripts | if (!var) // Ignore subscripts | |||
End of changes. 7 change blocks. | ||||
44 lines changed or deleted | 28 lines changed or added |