Skip to content

Assorted bug fixes [5.1] #23754

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/swift/AST/ASTWalker.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ class ASTWalker {
/// However, ASTWalker does not walk into LazyInitializerExprs on its own.
virtual bool shouldWalkIntoLazyInitializers() { return true; }

/// This method configures whether the walker should visit the body of a
/// non-single expression closure.
///
/// For work that is performed for every top-level expression, this should
/// be overridden to return false, to avoid duplicating work or visiting
/// bodies of closures that have not yet been type checked.
virtual bool shouldWalkIntoNonSingleExpressionClosure() { return true; }

/// walkToParameterListPre - This method is called when first visiting a
/// ParameterList, before walking into its parameters. If it returns false,
/// the subtree is skipped.
Expand Down
8 changes: 2 additions & 6 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2273,14 +2273,10 @@ ERROR(duplicate_inheritance,none,
"duplicate inheritance from %0", (Type))
WARNING(duplicate_anyobject_class_inheritance,none,
"redundant inheritance from 'AnyObject' and Swift 3 'class' keyword", ())
ERROR(objc_protocol_with_superclass,none,
"protocol %0 is '@objc' and cannot have a superclass constraint", (Identifier))
ERROR(inheritance_from_protocol_with_superclass,none,
"inheritance from class-constrained protocol composition type %0", (Type))
ERROR(multiple_inheritance,none,
"multiple inheritance from classes %0 and %1", (Type, Type))
ERROR(non_class_inheritance,none,
"non-class type %0 cannot inherit from class %1", (Type, Type))
ERROR(extension_class_inheritance,none,
"extension of type %0 cannot inherit from class %1", (Type, Type))
ERROR(inheritance_from_non_protocol_or_class,none,
"inheritance from non-protocol, non-class type %0", (Type))
ERROR(inheritance_from_non_protocol,none,
Expand Down
8 changes: 4 additions & 4 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1595,10 +1595,10 @@ void ASTMangler::appendContext(const DeclContext *ctx) {
return appendEntity(eed);
}

case DeclContextKind::SubscriptDecl:
// FIXME: We may need to do something here if subscripts contain any symbols
// exposed with linkage names, or if/when they get generic parameters.
return appendContext(ctx->getParent());
case DeclContextKind::SubscriptDecl: {
auto sd = cast<SubscriptDecl>(ctx);
return appendEntity(sd);
}

case DeclContextKind::Initializer:
switch (cast<Initializer>(ctx)->getInitializerKind()) {
Expand Down
9 changes: 7 additions & 2 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
return nullptr;
}

if (!Walker.shouldWalkIntoNonSingleExpressionClosure())
return expr;

// Handle other closures.
if (BraceStmt *body = cast_or_null<BraceStmt>(doIt(expr->getBody()))) {
expr->setBody(body, false);
Expand Down Expand Up @@ -1071,12 +1074,14 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
if (auto oldSubExpr = E->getSubExpr()) {
if (auto subExpr = doIt(oldSubExpr)) {
E->setSubExpr(subExpr);
}
else {
} else {
return nullptr;
}
}

if (!Walker.shouldWalkIntoNonSingleExpressionClosure())
return E;

if (auto oldBody = E->getBody()) {
if (auto body = doIt(oldBody)) {
E->setBody(dyn_cast<BraceStmt>(body));
Expand Down
3 changes: 2 additions & 1 deletion lib/IRGen/GenProto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,8 @@ class AccessorConformanceInfo : public ConformanceInfo {
llvm::Value *getTable(IRGenFunction &IGF,
llvm::Value **typeMetadataCache) const override {
// If we're looking up a dependent type, we can't cache the result.
if (Conformance->getType()->hasArchetype()) {
if (Conformance->getType()->hasArchetype() ||
Conformance->getType()->hasDynamicSelfType()) {
return emitWitnessTableAccessorCall(IGF, Conformance,
typeMetadataCache);
}
Expand Down
4 changes: 1 addition & 3 deletions lib/SILGen/SILGenConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
if (!field->isStatic() && field->isLet() &&
field->getParentInitializer()) {
#ifndef NDEBUG
auto fieldTy = decl->getDeclContext()->mapTypeIntoContext(
field->getInterfaceType());
assert(fieldTy->isEqual(field->getParentInitializer()->getType())
assert(field->getType()->isEqual(field->getParentInitializer()->getType())
&& "Checked by sema");
#endif

Expand Down
25 changes: 15 additions & 10 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
bool walkToDeclPre(Decl *D) override { return false; }
bool walkToTypeReprPre(TypeRepr *T) override { return true; }

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
// See through implicit conversions of the expression. We want to be able
// to associate the parent of this expression with the ultimate callee.
Expand Down Expand Up @@ -1408,6 +1410,8 @@ static void diagRecursivePropertyAccess(TypeChecker &TC, const Expr *E,
cast<VarDecl>(DRE->getDecl())->isSelfParameter();
}

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
Expr *subExpr;
bool isStore = false;
Expand Down Expand Up @@ -1556,11 +1560,10 @@ static void diagnoseImplicitSelfUseInClosure(TypeChecker &TC, const Expr *E,
return false;
}

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
if (!CE->hasSingleExpressionBody())
return { false, E };

// If this is a potentially-escaping closure expression, start looking
// for references to self if we aren't already.
if (isClosureRequiringSelfQualification(CE))
Expand Down Expand Up @@ -2387,7 +2390,7 @@ class VarDeclUsageChecker : public ASTWalker {
// other things going on in the initializer expressions.
return true;
}

/// The heavy lifting happens when visiting expressions.
std::pair<bool, Expr *> walkToExprPre(Expr *E) override;

Expand Down Expand Up @@ -2772,8 +2775,6 @@ void VarDeclUsageChecker::markStoredOrInOutExpr(Expr *E, unsigned Flags) {
E->walk(*this);
}



/// The heavy lifting happens when visiting expressions.
std::pair<bool, Expr *> VarDeclUsageChecker::walkToExprPre(Expr *E) {
// Sema leaves some subexpressions null, which seems really unfortunate. It
Expand Down Expand Up @@ -3020,6 +3021,8 @@ static void checkStmtConditionTrailingClosure(TypeChecker &TC, const Expr *E) {
public:
DiagnoseWalker(TypeChecker &tc) : TC(tc) { }

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
// Dig into implicit expression.
if (E->isImplicit()) return { true, E };
Expand Down Expand Up @@ -3151,6 +3154,8 @@ class ObjCSelectorWalker : public ASTWalker {
ObjCSelectorWalker(TypeChecker &tc, const DeclContext *dc, Type selectorTy)
: TC(tc), DC(dc), SelectorTy(selectorTy) { }

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
auto *stringLiteral = dyn_cast<StringLiteralExpr>(expr);
bool fromStringLiteral = false;
Expand Down Expand Up @@ -3827,14 +3832,12 @@ static void diagnoseUnintendedOptionalBehavior(TypeChecker &TC, const Expr *E,
}
}

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
if (!E || isa<ErrorExpr>(E) || !E->getType())
return { false, E };

if (auto *CE = dyn_cast<AbstractClosureExpr>(E))
if (!CE->hasSingleExpressionBody())
return { false, E };

if (IgnoredExprs.count(E))
return { true, E };

Expand Down Expand Up @@ -3901,6 +3904,8 @@ static void diagnoseDeprecatedWritableKeyPath(TypeChecker &TC, const Expr *E,
}
}

bool shouldWalkIntoNonSingleExpressionClosure() override { return false; }

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
if (!E || isa<ErrorExpr>(E) || !E->getType())
return {false, E};
Expand Down
117 changes: 43 additions & 74 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ static void validateAttributes(TypeChecker &TC, Decl *D);
/// file.
static void checkInheritanceClause(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> declUnion) {
TypeResolutionOptions options = None;
DeclContext *DC;
MutableArrayRef<TypeLoc> inheritedClause;
ExtensionDecl *ext = nullptr;
Expand All @@ -224,7 +223,6 @@ static void checkInheritanceClause(
if ((ext = declUnion.dyn_cast<ExtensionDecl *>())) {
decl = ext;
DC = ext;
options |= TypeResolutionFlags::AllowUnavailableProtocol;

inheritedClause = ext->getInherited();

Expand All @@ -243,14 +241,17 @@ static void checkInheritanceClause(
decl = typeDecl;
if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
DC = nominal;
options |= TypeResolutionFlags::AllowUnavailableProtocol;
} else {
DC = typeDecl->getDeclContext();
}

inheritedClause = typeDecl->getInherited();
}

bool canHaveSuperclass = (isa<ClassDecl>(decl) ||
(isa<ProtocolDecl>(decl) &&
!cast<ProtocolDecl>(decl)->isObjC()));

ASTContext &ctx = decl->getASTContext();
auto &diags = ctx.Diags;

Expand All @@ -259,13 +260,6 @@ static void checkInheritanceClause(
if (ext)
return ext->getSourceRange().End;

if (auto genericTypeDecl = dyn_cast<GenericTypeDecl>(typeDecl)) {
if (auto genericParams = genericTypeDecl->getGenericParams())
return genericParams->getSourceRange().End;

return genericTypeDecl->getNameLoc();
}

return typeDecl->getNameLoc();
};

Expand Down Expand Up @@ -316,6 +310,12 @@ static void checkInheritanceClause(
if (!inheritedTy || inheritedTy->hasError())
continue;

// For generic parameters and associated types, the GSB checks constraints;
// however, we still want to fire off the requests to produce diagnostics
// in some circular validation cases.
if (isa<AbstractTypeParamDecl>(decl))
continue;

// Check whether we inherited from 'AnyObject' twice.
// Other redundant-inheritance scenarios are checked below, the
// GenericSignatureBuilder (for protocol inheritance) or the
Expand Down Expand Up @@ -351,41 +351,36 @@ static void checkInheritanceClause(
if (inheritedTy->isExistentialType()) {
auto layout = inheritedTy->getExistentialLayout();

// @objc protocols cannot have superclass constraints.
if (layout.explicitSuperclass) {
if (auto *protoDecl = dyn_cast<ProtocolDecl>(decl)) {
if (protoDecl->isObjC()) {
protoDecl->diagnose(diag::objc_protocol_with_superclass,
protoDecl->getName());
continue;
}
}
}
// Inheritance from protocol compositions that do not contain classes
// or AnyObject is always OK.
if (!layout.hasExplicitAnyObject &&
!layout.explicitSuperclass)
continue;

// Protocols, generic parameters and associated types can inherit
// from subclass existentials, which are "exploded" into their
// corresponding requirements.
//
// Extensions, structs and enums can only inherit from protocol
// compositions that do not contain AnyObject or class members.
if (isa<ProtocolDecl>(decl) ||
isa<AbstractTypeParamDecl>(decl) ||
(!layout.hasExplicitAnyObject &&
!layout.explicitSuperclass)) {
// Protocols can inherit from AnyObject.
if (layout.hasExplicitAnyObject &&
isa<ProtocolDecl>(decl))
continue;
}

// Classes can inherit from subclass existentials as long as they
// do not contain an explicit AnyObject member.
if (isa<ClassDecl>(decl) &&
!layout.hasExplicitAnyObject) {
// Superclass inheritance is handled below.
inheritedTy = layout.explicitSuperclass;
if (!inheritedTy)
// Class-constrained protocol compositions are not allowed except in
// special cases.
if (layout.explicitSuperclass) {
if (!canHaveSuperclass) {
decl->diagnose(diag::inheritance_from_protocol_with_superclass,
inheritedTy);
continue;
}

// Classes can inherit from protocol compositions that contain a
// superclass, but not AnyObject.
if (isa<ClassDecl>(decl) &&
!layout.hasExplicitAnyObject) {
// Superclass inheritance is handled below.
inheritedTy = layout.explicitSuperclass;
}
}
}

// If this is an enum inheritance clause, check for a raw type.
if (isa<EnumDecl>(decl)) {
// Check if we already had a raw type.
Expand Down Expand Up @@ -445,29 +440,6 @@ static void checkInheritanceClause(
continue;
}

// @objc protocols cannot have superclass constraints.
if (auto *protoDecl = dyn_cast<ProtocolDecl>(decl)) {
if (protoDecl->isObjC()) {
protoDecl->diagnose(diag::objc_protocol_with_superclass,
protoDecl->getName());
continue;
}
}

// If the declaration we're looking at doesn't allow a superclass,
// complain.
if (isa<StructDecl>(decl) || isa<ExtensionDecl>(decl)) {
decl->diagnose(isa<ExtensionDecl>(decl)
? diag::extension_class_inheritance
: diag::non_class_inheritance,
isa<ExtensionDecl>(decl)
? cast<ExtensionDecl>(decl)->getDeclaredInterfaceType()
: cast<TypeDecl>(decl)->getDeclaredInterfaceType(),
inheritedTy)
.highlight(inherited.getSourceRange());
continue;
}

// If this is not the first entry in the inheritance clause, complain.
if (isa<ClassDecl>(decl) && i > 0) {
auto removeRange = getRemovalRange(i);
Expand All @@ -480,21 +452,18 @@ static void checkInheritanceClause(
// Fall through to record the superclass.
}

// Record the superclass.
superclassTy = inheritedTy;
superclassRange = inherited.getSourceRange();
continue;
if (canHaveSuperclass) {
// Record the superclass.
superclassTy = inheritedTy;
superclassRange = inherited.getSourceRange();
continue;
}
}

// The GenericSignatureBuilder diagnoses problems with generic type
// parameters.
if (isa<GenericTypeParamDecl>(decl))
continue;

// We can't inherit from a non-class, non-protocol type.
decl->diagnose((isa<StructDecl>(decl) || isa<ExtensionDecl>(decl))
? diag::inheritance_from_non_protocol
: diag::inheritance_from_non_protocol_or_class,
decl->diagnose(canHaveSuperclass
? diag::inheritance_from_non_protocol_or_class
: diag::inheritance_from_non_protocol,
inheritedTy);
// FIXME: Note pointing to the declaration 'inheritedTy' references?
}
Expand Down
Loading