Skip to content
Open
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
7 changes: 7 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -7862,6 +7862,13 @@ ERROR(atomics_ordering_must_be_constant, none,
"ordering argument must be a static method or property of %0",
(Identifier))

//------------------------------------------------------------------------------
// MARK: SwiftUI
//------------------------------------------------------------------------------

WARNING(swiftui_arg_must_be_integer_literal, none,
"argument must be an integer literal", ())

//------------------------------------------------------------------------------
// MARK: access notes
//------------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/SemanticAttrs.def
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ SEMANTICS_ATTR(OSLOG_REQUIRES_CONSTANT_ARGUMENTS, "oslog.requires_constant_argum
SEMANTICS_ATTR(OSLOG_LOG_WITH_LEVEL, "oslog.log_with_level")
SEMANTICS_ATTR(ATOMICS_REQUIRES_CONSTANT_ORDERINGS, "atomics.requires_constant_orderings")

SEMANTICS_ATTR(SWIFT_UI_REQUIRES_CONSTANT_RANGE, "swiftui.requires_constant_range")

SEMANTICS_ATTR(TYPE_CHECKER_OPEN_EXISTENTIAL, "typechecker._openExistential(_:do:)")
SEMANTICS_ATTR(TYPE_CHECKER_TYPE, "typechecker.type(of:)")
SEMANTICS_ATTR(TYPE_CHECKER_WITHOUT_ACTUALLY_ESCAPING, "typechecker.withoutActuallyEscaping(_:do:)")
Expand Down
8 changes: 8 additions & 0 deletions lib/Sema/ConstantnessSemaDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ static bool isParamRequiredToBeConstant(AbstractFunctionDecl *funcDecl, ParamDec
nominal = paramType->getNominalOrBoundGenericNominal();
return !nominal || !isOSLogDynamicObject(nominal);
}
if (hasSemanticsAttr(funcDecl, semantics::SWIFT_UI_REQUIRES_CONSTANT_RANGE))
return param->getParameterName().str() == "data";
if (!hasSemanticsAttr(funcDecl,
semantics::ATOMICS_REQUIRES_CONSTANT_ORDERINGS))
return false;
Expand Down Expand Up @@ -245,6 +247,12 @@ static void diagnoseError(Expr *errorExpr, const ASTContext &astContext,
return;
}

if (hasSemanticsAttr(funcDecl,
semantics::SWIFT_UI_REQUIRES_CONSTANT_RANGE)) {
diags.diagnose(errorLoc, diag::swiftui_arg_must_be_integer_literal);
return;
}

// Diagnose os_log specific errors here.

// Diagnose primitive stdlib types.
Expand Down
34 changes: 34 additions & 0 deletions test/Sema/diag_constantness_check_swift_ui.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// RUN: %target-typecheck-verify-swift

// Replicating the SwiftUI framework `ForEach` from the SDK
public struct ForEach<Data, ID, Content> where Data : Swift.RandomAccessCollection, ID: Swift.Hashable {
public var data: Data
public var content: (Data.Element) -> Content
}

public protocol View {}
public struct AView: View {}

extension ForEach where Content : View {
public init(_ data: Data, id: Swift.KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content) {
self.data = data
self.content = content
}
}

extension ForEach where Data == Swift.Range<Swift.Int>, ID == Swift.Int, Content : View {
@_semantics("swiftui.requires_constant_range") public init(_ data: Swift.Range<Swift.Int>, content: @escaping (Swift.Int) -> Content)
}


func testSwiftUIForEachInvalid() {
let notReallyConstant = 10
_ = ForEach(0..<notReallyConstant) { _ in AView() }
// expected-warning@-1 {{argument must be an integer literal}}
}

func testSwiftUIForEachValid() {
_ = ForEach(0..<10) { _ in AView() }
let notReallyConstant = 10
_ = ForEach(0..<notReallyConstant, id: \.self) { _ in AView() }
}