Skip to content

Commit bf51b9a

Browse files
authored
Merge pull request #1508 from swiftwasm/maxd/fix-5.3-lit
Pass `subst_target_sil_opt_mock_sdk_after` in lit.cfg 5.3 branch
2 parents 2e8eeb8 + aa71d4a commit bf51b9a

23 files changed

+443
-32
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5056,6 +5056,10 @@ NOTE(function_builder_infer_add_return, none,
50565056
NOTE(function_builder_infer_pick_specific, none,
50575057
"apply function builder %0 (inferred from %select{protocol|dynamic replacement of}1 %2)",
50585058
(Type, unsigned, DeclName))
5059+
WARNING(function_builder_missing_limited_availability, none,
5060+
"function builder %0 does not implement `buildLimitedAvailability`; "
5061+
"this code may crash on earlier versions of the OS",
5062+
(Type))
50595063

50605064
//------------------------------------------------------------------------------
50615065
// MARK: Tuple Shuffle Diagnostics

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ IDENTIFIER(buildEither)
3737
IDENTIFIER(buildExpression)
3838
IDENTIFIER(buildFinalResult)
3939
IDENTIFIER(buildIf)
40+
IDENTIFIER(buildLimitedAvailability)
4041
IDENTIFIER(buildOptional)
4142
IDENTIFIER(callAsFunction)
4243
IDENTIFIER(Change)

lib/AST/Decl.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,14 +1326,28 @@ bool ExtensionDecl::isConstrainedExtension() const {
13261326
bool ExtensionDecl::isEquivalentToExtendedContext() const {
13271327
auto decl = getExtendedNominal();
13281328
bool extendDeclFromSameModule = false;
1329-
if (!decl->getAlternateModuleName().empty()) {
1330-
// if the extended type was defined in the same module with the extension,
1331-
// we should consider them as the same module to preserve ABI stability.
1332-
extendDeclFromSameModule = decl->getAlternateModuleName() ==
1333-
getParentModule()->getNameStr();
1329+
auto extensionAlterName = getAlternateModuleName();
1330+
auto typeAlterName = decl->getAlternateModuleName();
1331+
1332+
if (!extensionAlterName.empty()) {
1333+
if (!typeAlterName.empty()) {
1334+
// Case I: type and extension are both moved from somewhere else
1335+
extendDeclFromSameModule = typeAlterName == extensionAlterName;
1336+
} else {
1337+
// Case II: extension alone was moved from somewhere else
1338+
extendDeclFromSameModule = extensionAlterName ==
1339+
decl->getParentModule()->getNameStr();
1340+
}
13341341
} else {
1335-
extendDeclFromSameModule = decl->getParentModule() == getParentModule();
1342+
if (!typeAlterName.empty()) {
1343+
// Case III: extended type alone was moved from somewhere else
1344+
extendDeclFromSameModule = typeAlterName == getParentModule()->getNameStr();
1345+
} else {
1346+
// Case IV: neither of type and extension was moved from somewhere else
1347+
extendDeclFromSameModule = getParentModule() == decl->getParentModule();
1348+
}
13361349
}
1350+
13371351
return extendDeclFromSameModule
13381352
&& !isConstrainedExtension()
13391353
&& !getDeclaredInterfaceType()->isExistentialType();

lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,6 @@ bool FunctionSignatureTransform::run(bool hasCaller) {
641641
TransformDescriptor.hasOnlyDirectInModuleCallers;
642642
SILFunction *F = TransformDescriptor.OriginalFunction;
643643

644-
645644
// If we are asked to assume a caller for testing purposes, set the flag.
646645
hasCaller |= FSOOptimizeIfNotCalled;
647646

@@ -651,6 +650,16 @@ bool FunctionSignatureTransform::run(bool hasCaller) {
651650
return false;
652651
}
653652

653+
// Bail if we have a pseudo-generic function. We do not handle these today. If
654+
// we let it through here we crash when attempting to compute the optimized
655+
// function type.
656+
//
657+
// TODO: Add support for this.
658+
if (F->getLoweredFunctionType()->isPseudogeneric()) {
659+
LLVM_DEBUG(llvm::dbgs() << " function is pseudo-generic -> abort\n");
660+
return false;
661+
}
662+
654663
// Run OwnedToGuaranteed optimization.
655664
if (OwnedToGuaranteedAnalyze()) {
656665
Changed = true;

lib/Sema/BuilderTransform.cpp

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "MiscDiagnostics.h"
2020
#include "SolutionResult.h"
2121
#include "TypeChecker.h"
22+
#include "TypeCheckAvailability.h"
2223
#include "swift/AST/ASTVisitor.h"
2324
#include "swift/AST/ASTWalker.h"
2425
#include "swift/AST/NameLookup.h"
@@ -38,6 +39,24 @@ using namespace constraints;
3839

3940
namespace {
4041

42+
/// Find the first #available condition within the statement condition,
43+
/// or return NULL if there isn't one.
44+
const StmtConditionElement *findAvailabilityCondition(StmtCondition stmtCond) {
45+
for (const auto &cond : stmtCond) {
46+
switch (cond.getKind()) {
47+
case StmtConditionElement::CK_Boolean:
48+
case StmtConditionElement::CK_PatternBinding:
49+
continue;
50+
51+
case StmtConditionElement::CK_Availability:
52+
return &cond;
53+
break;
54+
}
55+
}
56+
57+
return nullptr;
58+
}
59+
4160
/// Visitor to classify the contents of the given closure.
4261
class BuilderClosureVisitor
4362
: private StmtVisitor<BuilderClosureVisitor, VarDecl *> {
@@ -502,10 +521,20 @@ class BuilderClosureVisitor
502521
if (!cs || !thenVar || (elseChainVar && !*elseChainVar))
503522
return nullptr;
504523

524+
// If there is a #available in the condition, the 'then' will need to
525+
// be wrapped in a call to buildAvailabilityErasure(_:), if available.
526+
Expr *thenVarRefExpr = buildVarRef(
527+
thenVar, ifStmt->getThenStmt()->getEndLoc());
528+
if (findAvailabilityCondition(ifStmt->getCond()) &&
529+
builderSupports(ctx.Id_buildLimitedAvailability)) {
530+
thenVarRefExpr = buildCallIfWanted(
531+
ifStmt->getThenStmt()->getEndLoc(), ctx.Id_buildLimitedAvailability,
532+
{ thenVarRefExpr }, { Identifier() });
533+
}
534+
505535
// Prepare the `then` operand by wrapping it to produce a chain result.
506536
Expr *thenExpr = buildWrappedChainPayload(
507-
buildVarRef(thenVar, ifStmt->getThenStmt()->getEndLoc()),
508-
payloadIndex, numPayloads, isOptional);
537+
thenVarRefExpr, payloadIndex, numPayloads, isOptional);
509538

510539
// Prepare the `else operand:
511540
Expr *elseExpr;
@@ -1054,6 +1083,35 @@ class BuilderClosureRewriter
10541083
capturedThen.first, {capturedThen.second.front()}));
10551084
ifStmt->setThenStmt(newThen);
10561085

1086+
// Look for a #available condition. If there is one, we need to check
1087+
// that the resulting type of the "then" does refer to any types that
1088+
// are unavailable in the enclosing context.
1089+
//
1090+
// Note that this is for staging in support for
1091+
if (auto availabilityCond = findAvailabilityCondition(ifStmt->getCond())) {
1092+
SourceLoc loc = availabilityCond->getStartLoc();
1093+
Type thenBodyType = solution.simplifyType(
1094+
solution.getType(target.captured.second[0]));
1095+
thenBodyType.findIf([&](Type type) {
1096+
auto nominal = type->getAnyNominal();
1097+
if (!nominal)
1098+
return false;
1099+
1100+
if (auto reason = TypeChecker::checkDeclarationAvailability(
1101+
nominal, loc, dc)) {
1102+
// Note that the problem is with the function builder, not the body.
1103+
// This is for staging only. We want to disable #available in
1104+
// function builders that don't support this operation.
1105+
ctx.Diags.diagnose(
1106+
loc, diag::function_builder_missing_limited_availability,
1107+
builderTransform.builderType);
1108+
return true;
1109+
}
1110+
1111+
return false;
1112+
});
1113+
}
1114+
10571115
if (auto elseBraceStmt =
10581116
dyn_cast_or_null<BraceStmt>(ifStmt->getElseStmt())) {
10591117
// Translate the "else" branch when it's a stmt-brace.

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3037,6 +3037,9 @@ namespace {
30373037
typeContext->getDeclaredInterfaceType());
30383038
auto superclassTy = selfTy->getSuperclass();
30393039

3040+
if (!superclassTy)
3041+
return Type();
3042+
30403043
if (selfDecl->getInterfaceType()->is<MetatypeType>())
30413044
superclassTy = MetatypeType::get(superclassTy);
30423045

lib/Sema/ConstantnessSemaDiagnostics.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ static bool hasConstantEvaluableAttr(ValueDecl *decl) {
9292
return hasSemanticsAttr(decl, semantics::CONSTANT_EVALUABLE);
9393
}
9494

95+
/// Return true iff the \p decl is annotated with oslog.message.init semantics
96+
/// attribute.
97+
static bool isOSLogMessageInitializer(ValueDecl *decl) {
98+
return hasSemanticsAttr(decl, semantics::OSLOG_MESSAGE_INIT_STRING_LITERAL) ||
99+
hasSemanticsAttr(decl, semantics::OSLOG_MESSAGE_INIT_INTERPOLATION);
100+
}
101+
95102
/// Check whether \p expr is a compile-time constant. It must either be a
96103
/// literal_expr, which does not include array and dictionary literal, or a
97104
/// closure expression, which is considered a compile-time constant of a
@@ -162,12 +169,6 @@ static Expr *checkConstantness(Expr *expr) {
162169
if (!isa<ApplyExpr>(expr))
163170
return expr;
164171

165-
if (NominalTypeDecl *nominal =
166-
expr->getType()->getNominalOrBoundGenericNominal()) {
167-
if (nominal->getName() == nominal->getASTContext().Id_OSLogMessage)
168-
return expr;
169-
}
170-
171172
ApplyExpr *apply = cast<ApplyExpr>(expr);
172173
ValueDecl *calledValue = apply->getCalledValue();
173174
if (!calledValue)
@@ -179,10 +180,18 @@ static Expr *checkConstantness(Expr *expr) {
179180
continue;
180181
}
181182

183+
AbstractFunctionDecl *callee = dyn_cast<AbstractFunctionDecl>(calledValue);
184+
if (!callee)
185+
return expr;
186+
187+
// If this is an application of OSLogMessage initializer, fail the check
188+
// as this type must be created from string interpolations.
189+
if (isOSLogMessageInitializer(callee))
190+
return expr;
191+
182192
// If this is a constant_evaluable function, check whether the arguments are
183193
// constants.
184-
AbstractFunctionDecl *callee = dyn_cast<AbstractFunctionDecl>(calledValue);
185-
if (!callee || !hasConstantEvaluableAttr(callee))
194+
if (!hasConstantEvaluableAttr(callee))
186195
return expr;
187196
expressionsToCheck.push_back(apply->getArg());
188197
}

lib/Sema/ConstraintSystem.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,13 +1206,15 @@ struct DynamicCallableMethods {
12061206
/// Describes the target to which a constraint system's solution can be
12071207
/// applied.
12081208
class SolutionApplicationTarget {
1209+
public:
12091210
enum class Kind {
12101211
expression,
12111212
function,
12121213
stmtCondition,
12131214
caseLabelItem,
12141215
} kind;
12151216

1217+
private:
12161218
union {
12171219
struct {
12181220
/// The expression being type-checked.
@@ -1418,6 +1420,12 @@ class SolutionApplicationTarget {
14181420
/// For a pattern initialization target, retrieve the contextual pattern.
14191421
ContextualPattern getContextualPattern() const;
14201422

1423+
/// Whether this target is for a for-in statement.
1424+
bool isForEachStmt() const {
1425+
return kind == Kind::expression &&
1426+
getExprContextualTypePurpose() == CTP_ForEachStmt;
1427+
}
1428+
14211429
/// Whether this is an initialization for an Optional.Some pattern.
14221430
bool isOptionalSomePatternInit() const {
14231431
return kind == Kind::expression &&
@@ -1466,14 +1474,12 @@ class SolutionApplicationTarget {
14661474
}
14671475

14681476
const ForEachStmtInfo &getForEachStmtInfo() const {
1469-
assert(kind == Kind::expression);
1470-
assert(expression.contextualPurpose == CTP_ForEachStmt);
1477+
assert(isForEachStmt());
14711478
return expression.forEachStmt;
14721479
}
14731480

14741481
ForEachStmtInfo &getForEachStmtInfo() {
1475-
assert(kind == Kind::expression);
1476-
assert(expression.contextualPurpose == CTP_ForEachStmt);
1482+
assert(isForEachStmt());
14771483
return expression.forEachStmt;
14781484
}
14791485

@@ -5284,6 +5290,11 @@ bool isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl);
52845290
/// statements that could produce non-void result.
52855291
bool hasExplicitResult(ClosureExpr *closure);
52865292

5293+
/// Emit diagnostics for syntactic restrictions within a given solution
5294+
/// application target.
5295+
void performSyntacticDiagnosticsForTarget(
5296+
const SolutionApplicationTarget &target, bool isExprStmt);
5297+
52875298
} // end namespace constraints
52885299

52895300
template<typename ...Args>

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,31 @@ bool GenericRequirementsCheckListener::diagnoseUnsatisfiedRequirement(
20082008
return false;
20092009
}
20102010

2011+
void constraints::performSyntacticDiagnosticsForTarget(
2012+
const SolutionApplicationTarget &target, bool isExprStmt) {
2013+
auto *dc = target.getDeclContext();
2014+
switch (target.kind) {
2015+
case SolutionApplicationTarget::Kind::expression: {
2016+
// First emit diagnostics for the main expression.
2017+
performSyntacticExprDiagnostics(target.getAsExpr(), dc, isExprStmt);
2018+
2019+
// If this is a for-in statement, we also need to check the where clause if
2020+
// present.
2021+
if (target.isForEachStmt()) {
2022+
if (auto *whereExpr = target.getForEachStmtInfo().whereExpr)
2023+
performSyntacticExprDiagnostics(whereExpr, dc, /*isExprStmt*/ false);
2024+
}
2025+
return;
2026+
}
2027+
case SolutionApplicationTarget::Kind::function:
2028+
case SolutionApplicationTarget::Kind::stmtCondition:
2029+
case SolutionApplicationTarget::Kind::caseLabelItem:
2030+
// Nothing to do for these.
2031+
return;
2032+
}
2033+
llvm_unreachable("Unhandled case in switch!");
2034+
}
2035+
20112036
#pragma mark High-level entry points
20122037
Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
20132038
TypeLoc convertType,
@@ -2122,7 +2147,7 @@ TypeChecker::typeCheckExpression(
21222147
// expression now.
21232148
if (!cs.shouldSuppressDiagnostics()) {
21242149
bool isExprStmt = options.contains(TypeCheckExprFlags::IsExprStmt);
2125-
performSyntacticExprDiagnostics(result, dc, isExprStmt);
2150+
performSyntacticDiagnosticsForTarget(*resultTarget, isExprStmt);
21262151
}
21272152

21282153
resultTarget->setExpr(result);

stdlib/public/Reflection/TypeRef.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -728,11 +728,15 @@ bool TypeRef::isConcreteAfterSubstitutions(
728728

729729
unsigned NominalTypeTrait::getDepth() const {
730730
if (auto P = Parent) {
731-
if (auto *Nominal = dyn_cast<NominalTypeRef>(P))
732-
return 1 + Nominal->getDepth();
733-
return 1 + cast<BoundGenericTypeRef>(P)->getDepth();
731+
switch (P->getKind()) {
732+
case TypeRefKind::Nominal:
733+
return 1 + cast<NominalTypeRef>(P)->getDepth();
734+
case TypeRefKind::BoundGeneric:
735+
return 1 + cast<BoundGenericTypeRef>(P)->getDepth();
736+
default:
737+
break;
738+
}
734739
}
735-
736740
return 0;
737741
}
738742

0 commit comments

Comments
 (0)