Skip to content

Commit 6334c34

Browse files
Merge pull request swiftlang#32906 from ravikandhadai/SwiftUIPreviewFix
[Sema][os_log] Allow wrapping os_log strings within constant evaluable functions.
2 parents 58a84ea + 49b0984 commit 6334c34

File tree

3 files changed

+84
-8
lines changed

3 files changed

+84
-8
lines changed

lib/Sema/ConstantnessSemaDiagnostics.cpp

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

91+
/// Return true iff the \p decl is annotated with oslog.message.init semantics
92+
/// attribute.
93+
static bool isOSLogMessageInitializer(ValueDecl *decl) {
94+
return hasSemanticsAttr(decl, semantics::OSLOG_MESSAGE_INIT_STRING_LITERAL) ||
95+
hasSemanticsAttr(decl, semantics::OSLOG_MESSAGE_INIT_INTERPOLATION);
96+
}
97+
9198
/// Check whether \p expr is a compile-time constant. It must either be a
9299
/// literal_expr, which does not include array and dictionary literal, or a
93100
/// closure expression, which is considered a compile-time constant of a
@@ -158,12 +165,6 @@ static Expr *checkConstantness(Expr *expr) {
158165
if (!isa<ApplyExpr>(expr))
159166
return expr;
160167

161-
if (NominalTypeDecl *nominal =
162-
expr->getType()->getNominalOrBoundGenericNominal()) {
163-
if (nominal->getName() == nominal->getASTContext().Id_OSLogMessage)
164-
return expr;
165-
}
166-
167168
ApplyExpr *apply = cast<ApplyExpr>(expr);
168169
ValueDecl *calledValue = apply->getCalledValue();
169170
if (!calledValue)
@@ -175,10 +176,18 @@ static Expr *checkConstantness(Expr *expr) {
175176
continue;
176177
}
177178

179+
AbstractFunctionDecl *callee = dyn_cast<AbstractFunctionDecl>(calledValue);
180+
if (!callee)
181+
return expr;
182+
183+
// If this is an application of OSLogMessage initializer, fail the check
184+
// as this type must be created from string interpolations.
185+
if (isOSLogMessageInitializer(callee))
186+
return expr;
187+
178188
// If this is a constant_evaluable function, check whether the arguments are
179189
// constants.
180-
AbstractFunctionDecl *callee = dyn_cast<AbstractFunctionDecl>(calledValue);
181-
if (!callee || !hasConstantEvaluableAttr(callee))
190+
if (!hasConstantEvaluableAttr(callee))
182191
return expr;
183192
expressionsToCheck.push_back(apply->getArg());
184193
}

test/SILOptimizer/OSLogMandatoryOptTest.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,41 @@ extension TestProtocolSelfTypeCapture {
585585
}
586586
}
587587

588+
// Test that SwiftUI's preview transformations work with the logging APIs.
589+
590+
// A function similar to the one used by SwiftUI preview to wrap string
591+
// literals.
592+
@_semantics("constant_evaluable")
593+
@_transparent
594+
public func __designTimeStringStub(
595+
_ key: String,
596+
fallback: OSLogMessage
597+
) -> OSLogMessage {
598+
fallback
599+
}
600+
601+
// CHECK-LABEL: @${{.*}}testSwiftUIPreviewWrappingyy
602+
func testSwiftUIPreviewWrapping() {
603+
_osLogTestHelper(__designTimeStringStub("key", fallback: "percent: %"))
604+
// CHECK: string_literal utf8 "percent: %%"
605+
// CHECK-NOT: OSLogMessage
606+
// CHECK-NOT: OSLogInterpolation
607+
// CHECK-LABEL: end sil function '${{.*}}testSwiftUIPreviewWrappingyy
608+
}
609+
610+
611+
func functionTakingClosure(_ x: () -> Void) { }
612+
613+
func testWrappingWithinClosures(x: Int) {
614+
functionTakingClosure {
615+
_osLogTestHelper(
616+
__designTimeStringStub(
617+
"key",
618+
fallback: "escaping of percent: %"))
619+
// CHECK-LABEL: @${{.*}}testWrappingWithinClosures1xySi_tFyyXEfU_
620+
// CHECK: string_literal utf8 "escaping of percent: %%"
621+
// CHECK-NOT: OSLogMessage
622+
// CHECK-NOT: OSLogInterpolation
623+
// CHECK-LABEL: end sil function '${{.*}}testWrappingWithinClosures1xySi_tFyyXEfU_
624+
}
625+
}

test/Sema/diag_constantness_check_os_log.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,32 @@ func testNonConstantLogObjectLevel(
156156
osLogWithLevel(level, log: log, message)
157157
// expected-error@-1 {{argument must be a string interpolation}}
158158
}
159+
160+
// Test that log messages can be wrapped in constant_evaluable functions.
161+
162+
// A function similar to the one used by SwiftUI preview to wrap string
163+
// literals.
164+
@_semantics("constant_evaluable")
165+
public func __designTimeStringStub(
166+
_ key: String,
167+
fallback: OSLogMessage
168+
) -> OSLogMessage {
169+
fallback
170+
}
171+
172+
func testSwiftUIPreviewWrapping() {
173+
// This should not produce any diagnostics.
174+
_osLogTestHelper(__designTimeStringStub("key", fallback: "A literal message"))
175+
}
176+
177+
public func nonConstantFunction(
178+
_ key: String,
179+
fallback: OSLogMessage
180+
) -> OSLogMessage {
181+
fallback
182+
}
183+
184+
func testLogMessageWrappingDiagnostics() {
185+
_osLogTestHelper(nonConstantFunction("key", fallback: "A literal message"))
186+
// expected-error@-1{{argument must be a string interpolation}}
187+
}

0 commit comments

Comments
 (0)