From 697dfbae96b7900a6d072337cb36f359cfa8bcc8 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 5 Aug 2022 11:24:17 -0700 Subject: [PATCH] [TypeChecker] Enable result builder AST transform by default --- include/swift/Basic/Features.def | 2 +- lib/Frontend/CompilerInvocation.cpp | 2 + test/Constraints/result_builder_diags.swift | 45 +++++++---- test/Constraints/result_builder_one_way.swift | 80 ------------------- test/IDE/complete_in_result_builder.swift | 4 +- test/Sema/type_eraser.swift | 2 +- .../Sema/regex_builder_already_imported.swift | 9 +-- .../IDE/issues_fixed/issue-57041.swift | 4 +- .../Sema/SwiftUI/issue-56479.swift | 1 - .../Sema/SwiftUI/issue-56591.swift | 5 +- .../Sema/SwiftUI/rdar75367157.swift | 2 +- .../Sema/SwiftUI/rdar88256059.swift | 3 +- .../rdar50869732.swift | 4 +- .../issue-57241.swift | 6 +- 14 files changed, 53 insertions(+), 116 deletions(-) delete mode 100644 test/Constraints/result_builder_one_way.swift diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index e0b2e8d7879..cc97186927d 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -84,6 +84,7 @@ LANGUAGE_FEATURE(BuiltinCopy, 0, "Builtin.copy()", true) LANGUAGE_FEATURE(BuiltinStackAlloc, 0, "Builtin.stackAlloc", true) LANGUAGE_FEATURE(BuiltinTaskRunInline, 0, "Builtin.taskRunInline", true) LANGUAGE_FEATURE(BuiltinUnprotectedAddressOf, 0, "Builtin.unprotectedAddressOf", true) +LANGUAGE_FEATURE(ResultBuilderASTTransform, 0, "result builders as AST transform", true) SUPPRESSIBLE_LANGUAGE_FEATURE(SpecializeAttributeWithAvailability, 0, "@_specialize attribute with availability", true) LANGUAGE_FEATURE(BuiltinAssumeAlignment, 0, "Builtin.assumeAlignment", true) SUPPRESSIBLE_LANGUAGE_FEATURE(UnsafeInheritExecutor, 0, "@_unsafeInheritExecutor", true) @@ -104,7 +105,6 @@ EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false) EXPERIMENTAL_FEATURE(MoveOnly, false) EXPERIMENTAL_FEATURE(OneWayClosureParameters, false) EXPERIMENTAL_FEATURE(TypeWitnessSystemInference, false) -EXPERIMENTAL_FEATURE(ResultBuilderASTTransform, true) EXPERIMENTAL_FEATURE(LayoutPrespecialization, false) EXPERIMENTAL_FEATURE(ModuleInterfaceExportAs, true) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index e07c122e1b7..68c7f65d663 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -708,6 +708,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, if (Args.hasArg(OPT_enable_experimental_opaque_type_erasure)) Opts.Features.insert(Feature::OpaqueTypeErasure); + Opts.Features.insert(Feature::ResultBuilderASTTransform); + Opts.EnableAppExtensionRestrictions |= Args.hasArg(OPT_enable_app_extension); Opts.EnableSwift3ObjCInference = diff --git a/test/Constraints/result_builder_diags.swift b/test/Constraints/result_builder_diags.swift index 6d25264fbe3..d229b973e8d 100644 --- a/test/Constraints/result_builder_diags.swift +++ b/test/Constraints/result_builder_diags.swift @@ -78,7 +78,7 @@ struct TupleBuilderWithoutIf { // expected-note 3{{struct 'TupleBuilderWithoutIf static func buildDo(_ value: T) -> T { return value } } -func tuplify(_ cond: Bool, @TupleBuilder body: (Bool) -> T) { // expected-note {{in call to function 'tuplify(_:body:)'}} +func tuplify(_ cond: Bool, @TupleBuilder body: (Bool) -> T) { print(body(cond)) } @@ -194,7 +194,7 @@ struct TupleP : P { @resultBuilder struct Builder { - static func buildBlock(_ stmt1: S0, _ stmt2: S1) // expected-note {{required by static method 'buildBlock' where 'S1' = 'Label<_>.Type'}} + static func buildBlock(_ stmt1: S0, _ stmt2: S1) -> TupleP<(S0, S1)> where S0: P, S1: P { return TupleP((stmt1, stmt2)) } @@ -216,7 +216,7 @@ struct Label : P where L : P { // expected-note 2 {{'L' declared as parameter } func test_51167632() -> some P { - AnyP(G { // expected-error {{type 'Label<_>.Type' cannot conform to 'P'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}} + AnyP(G { Text("hello") Label // expected-error {{generic parameter 'L' could not be inferred}} // expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{10-10=<<#L: P#>>}} @@ -509,7 +509,7 @@ enum E3 { } func testCaseMutabilityMismatches(e: E3) { - tuplify(true) { c in // expected-error {{generic parameter 'T' could not be inferred}} + tuplify(true) { c in "testSwitch" switch e { case .a(let x, var y), @@ -527,12 +527,13 @@ func testCaseMutabilityMismatches(e: E3) { // Check for type equivalence among different case variables with the same name. func testCaseVarTypes(e: E3) { - // FIXME: Terrible diagnostic - tuplify(true) { c in // expected-error{{type of expression is ambiguous without more context}} + tuplify(true) { c in "testSwitch" switch e { case .a(let x, let y), .c(let x, let y): + // expected-error@-1 {{pattern variable bound to type 'String', expected type 'Int'}} + // expected-error@-2 {{pattern variable bound to type 'Int', expected type 'String'}} x y + "a" } @@ -659,6 +660,8 @@ struct MyView { } @TupleBuilder var invalidCaseWithoutDot: some P { + // expected-error@-1 {{return type of property 'invalidCaseWithoutDot' requires that 'Either' conform to 'P'}} + // expected-note@-2 {{opaque return type declared here}} switch Optional.some(1) { case none: 42 // expected-error {{cannot find 'none' in scope}} case .some(let x): @@ -666,7 +669,7 @@ struct MyView { } } - @TupleBuilder var invalidConversion: Int { // expected-error {{cannot convert value of type 'String' to specified type 'Int'}} + @TupleBuilder var invalidConversion: Int { // expected-error {{cannot convert return expression of type 'String' to return type 'Int'}} "" } } @@ -684,7 +687,7 @@ do { } struct TuplifiedStructWithInvalidClosure { - var condition: Bool + var condition: Bool? @TupleBuilder var unknownParameter: some Any { if let cond = condition { @@ -697,7 +700,7 @@ struct TuplifiedStructWithInvalidClosure { } @TupleBuilder var unknownResult: some Any { - if let cond = condition { + if let _ = condition { let _ = { () -> UnknownType in // expected-error {{cannot find type 'UnknownType' in scope}} } 42 @@ -707,7 +710,7 @@ struct TuplifiedStructWithInvalidClosure { } @TupleBuilder var multipleLevelsDeep: some Any { - if let cond = condition { + if let _ = condition { switch MyError.boom { case .boom: let _ = { () -> UnknownType in // expected-error {{cannot find type 'UnknownType' in scope}} @@ -721,7 +724,7 @@ struct TuplifiedStructWithInvalidClosure { } @TupleBuilder var errorsDiagnosedByParser: some Any { - if let cond = condition { + if let _ = condition { tuplify { _ in self. // expected-error {{expected member name following '.'}} } @@ -759,9 +762,10 @@ func test_rdar65667992() { var entry: E @Builder var body: S { - switch entry { // expected-error {{type 'E' has no member 'unset'}} + switch entry { case .set(_, _): S() - case .unset(_): S() // expected-error {{'_' can only appear in a pattern or on the left side of an assignment}} + case .unset(_): S() // expected-error {{type 'E' has no member 'unset'}} + // expected-error@-1 {{'_' can only appear in a pattern or on the left side of an assignment}} default: S() } } @@ -796,7 +800,9 @@ func test_missing_member_in_optional_context() { if let prop = test?.prop { // expected-error {{value of type 'Test' has no member 'prop'}} 0 } + } + tuplify(true) { c in if let method = test?.method() { // expected-error {{value of type 'Test' has no member 'method'}} 1 } @@ -850,10 +856,10 @@ func test_invalid_result_is_diagnosed() { } } - struct S {} // expected-note {{arguments to generic parameter 'T' ('Int' and 'String') are expected to be equal}} + struct S {} @MyBuilder - func test() -> S { // expected-error {{cannot convert result builder result type 'S' to return type 'S}} + func test() -> S { // expected-error {{conflicting arguments to generic parameter 'T1' ('S' vs. 'S')}} S() } } @@ -887,6 +893,15 @@ func test_associated_values_dont_block_solver_when_unresolved() { // expected-note@-1 {{chain the optional using '?' to access member 'kind' only for non-'nil' base values}} // expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} + switch v.kind { + case .a(_): "a" + case .b: "b" + } + } + + @Builder var switchError: String { + let v = container.prop!.kind + switch v.kind { // expected-error {{value of type 'Value.Kind' has no member 'kind'}} case .a(_): "a" case .b: "b" diff --git a/test/Constraints/result_builder_one_way.swift b/test/Constraints/result_builder_one_way.swift deleted file mode 100644 index 4764e220929..00000000000 --- a/test/Constraints/result_builder_one_way.swift +++ /dev/null @@ -1,80 +0,0 @@ -// RUN: %target-typecheck-verify-swift -// RUN: %target-typecheck-verify-swift -debug-constraints > %t.log 2>&1 -// RUN: %FileCheck %s < %t.log - -enum Either { - case first(T) - case second(U) -} - -@resultBuilder -struct TupleBuilder { - static func buildBlock(_ t1: T1) -> T1 { - return t1 - } - - static func buildBlock(_ t1: T1, _ t2: T2) -> (T1, T2) { - return (t1, t2) - } - - static func buildBlock(_ t1: T1, _ t2: T2, _ t3: T3) - -> (T1, T2, T3) { - return (t1, t2, t3) - } - - static func buildBlock(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4) - -> (T1, T2, T3, T4) { - return (t1, t2, t3, t4) - } - - static func buildBlock( - _ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5 - ) -> (T1, T2, T3, T4, T5) { - return (t1, t2, t3, t4, t5) - } - - static func buildDo(_ value: T) -> T { return value } - static func buildIf(_ value: T?) -> T? { return value } - - static func buildEither(first value: T) -> Either { - return .first(value) - } - static func buildEither(second value: U) -> Either { - return .second(value) - } -} - -func tuplify(_ collection: C, @TupleBuilder body: (C.Element) -> T) -> T { - return body(collection.first!) -} - -// CHECK: ---Connected components--- -// CHECK-NEXT: 1: $T10 depends on 0 -// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T82 $T83 depends on 3 -// CHECK-NEXT: 3: $T12 $T17 $T28 $T43 $T55 $T57 $T58 $T59 $T60 $T61 $T63 $T64 $T65 $T66 $T67 $T68 $T70 $T71 $T73 $T74 $T75 $T76 $T77 $T78 $T79 $T80 $T81 depends on 2, 4, 5, 7, 10 -// CHECK-NEXT: 10: $T49 $T51 $T52 $T53 $T54 depends on 9 -// CHECK-NEXT: 9: $T44 $T45 $T46 $T47 $T48 -// CHECK-NEXT: 7: $T31 $T35 $T37 $T38 $T39 $T40 $T41 $T42 depends on 6, 8 -// CHECK-NEXT: 8: $T32 $T33 $T34 -// CHECK-NEXT: 6: $T30 -// CHECK-NEXT: 5: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 -// CHECK-NEXT: 4: $T15 $T16 -// CHECK-NEXT: 2: $T11 -let names = ["Alice", "Bob", "Charlie"] -let b = true -var number = 17 -print( - tuplify(names) { name in - 17 - number - "Hello, \(name)" - tuplify(["a", "b"]) { value in - value.first! - } - if b { - 2.71828 - ["if", "stmt"] - } else { - [1, 2, 3, 17] - } - }) diff --git a/test/IDE/complete_in_result_builder.swift b/test/IDE/complete_in_result_builder.swift index cf72094da00..9eb88ccd602 100644 --- a/test/IDE/complete_in_result_builder.swift +++ b/test/IDE/complete_in_result_builder.swift @@ -36,7 +36,7 @@ func testGlobalLookup() { @TupleBuilder var x1 { #^GLOBAL_LOOKUP^# // GLOBAL_LOOKUP: Begin completions - // GLOBAL_LOOKUP: Decl[GlobalVar]/CurrModule/TypeRelation[Convertible]: MyConstantString[#String#]; + // GLOBAL_LOOKUP: Decl[GlobalVar]/CurrModule/TypeRelation[Convertible]: MyConstantString[#String#]; name=MyConstantString // GLOBAL_LOOKUP: End completions } @@ -81,6 +81,8 @@ func testStaticMemberLookup() { @TupleBuilder var x1 { StringFactory.#^COMPLETE_STATIC_MEMBER^# // COMPLETE_STATIC_MEMBER: Begin completions + // COMPLETE_STATIC_MEMBER: Keyword[self]/CurrNominal: self[#StringFactory.Type#]; name=self + // COMPLETE_STATIC_MEMBER: Keyword/CurrNominal: Type[#StringFactory.Type#]; name=Type // COMPLETE_STATIC_MEMBER: Decl[StaticMethod]/CurrNominal/TypeRelation[Convertible]: makeString({#x: String#})[#String#]; // COMPLETE_STATIC_MEMBER: End completions } diff --git a/test/Sema/type_eraser.swift b/test/Sema/type_eraser.swift index 7dee74c1462..7c786c254c0 100644 --- a/test/Sema/type_eraser.swift +++ b/test/Sema/type_eraser.swift @@ -86,7 +86,7 @@ class TestResultBuilder { // CHECK: closure_expr type='() -> ConcreteP' takesBuilder { // CHECK: return_stmt - // CHECK-NEXT: load_expr implicit type='ConcreteP' + // CHECK-NEXT: call_expr implicit type='ConcreteP' ConcreteP() } } diff --git a/test/StringProcessing/Sema/regex_builder_already_imported.swift b/test/StringProcessing/Sema/regex_builder_already_imported.swift index 83f9d3de552..bd200d784d5 100644 --- a/test/StringProcessing/Sema/regex_builder_already_imported.swift +++ b/test/StringProcessing/Sema/regex_builder_already_imported.swift @@ -3,14 +3,11 @@ import RegexBuilder extension Regex where Output == Substring { - init(_ x: String) {} // expected-note {{'init(_:)' declared here}} + init(_ x: String) {} } func foo() { - // FIXME: This diagnostic could probably be better, it's not clear we should - // be resolving to init(_ x: String) vs the result builder API and diagnosing - // the fact that Int isn't a RegexComponent. - _ = Regex { // expected-error {{trailing closure passed to parameter of type 'String' that does not accept a closure}} - 0 + _ = Regex { + 0 // expected-error {{static method 'buildExpression' requires that 'Int' conform to 'RegexComponent'}} } } diff --git a/validation-test/IDE/issues_fixed/issue-57041.swift b/validation-test/IDE/issues_fixed/issue-57041.swift index 730a9d3fc8b..40c9c3f04de 100644 --- a/validation-test/IDE/issues_fixed/issue-57041.swift +++ b/validation-test/IDE/issues_fixed/issue-57041.swift @@ -72,6 +72,6 @@ struct SplitView: View2 { } // COMPLETE: Begin completions -// COMPLETE-DAG: Decl[InstanceMethod]/Super: frame()[#Never#]; name=frame() -// COMPLETE-DAG: Decl[InstanceMethod]/Super: frame({#width: Int?#}, {#height: Int?#})[#Never#]; name=frame(width:height:) +// COMPLETE-DAG: Decl[InstanceMethod]/Super/TypeRelation[Convertible]: frame()[#Never#]; name=frame() +// COMPLETE-DAG: Decl[InstanceMethod]/Super/TypeRelation[Convertible]: frame({#width: Int?#}, {#height: Int?#})[#Never#]; name=frame(width:height:) // COMPLETE: End completions diff --git a/validation-test/Sema/SwiftUI/issue-56479.swift b/validation-test/Sema/SwiftUI/issue-56479.swift index ea37ca7b539..8d90d92d785 100644 --- a/validation-test/Sema/SwiftUI/issue-56479.swift +++ b/validation-test/Sema/SwiftUI/issue-56479.swift @@ -16,7 +16,6 @@ struct ContentView: View { DatePicker("Enter a date", selection: $date, displayedComponents: .date, in: Date()) // expected-error@-1 {{argument 'in' must precede argument 'displayedComponents'}} {{78-90=}} {{52-52=in: Date(), }} DatePicker("Enter a date", selection: $date, displayedComponents: .date, in: Date() ... Date().addingTimeInterval(100)) - // expected-error@-1 {{argument 'in' must precede argument 'displayedComponents'}} {{78-125=}} {{52-52=in: Date() ... Date().addingTimeInterval(100), }} } } } diff --git a/validation-test/Sema/SwiftUI/issue-56591.swift b/validation-test/Sema/SwiftUI/issue-56591.swift index e815789ec88..f60f950d57e 100644 --- a/validation-test/Sema/SwiftUI/issue-56591.swift +++ b/validation-test/Sema/SwiftUI/issue-56591.swift @@ -9,10 +9,13 @@ import SwiftUI struct Experiment: View { var body: some View { - HStack { // expected-error {{generic parameter 'Content' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}emacs + HStack { Slider(value: <#T##Binding#>, in: <#T##ClosedRange#>, label: <#T##() -> _#>) // expected-error 3 {{editor placeholder in source file}} // expected-error@-1 {{type 'any BinaryFloatingPoint' cannot conform to 'Comparable'}} // expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}} + // expected-error@-3 {{type 'any BinaryFloatingPoint' cannot conform to 'BinaryFloatingPoint'}} + // expected-note@-4 {{only concrete types such as structs, enums and classes can conform to protocols}} + // expected-note@-5 {{required by initializer 'init(value:in:label:onEditingChanged:)' where 'V' = 'any BinaryFloatingPoint'}} } } } diff --git a/validation-test/Sema/SwiftUI/rdar75367157.swift b/validation-test/Sema/SwiftUI/rdar75367157.swift index fccc09935c4..bbd729a5c10 100644 --- a/validation-test/Sema/SwiftUI/rdar75367157.swift +++ b/validation-test/Sema/SwiftUI/rdar75367157.swift @@ -22,7 +22,7 @@ struct S : View { EmptyView() } - if (check(self.test)) { // expected-error {{cannot convert value of type 'E' to expected argument type 'String'}} {{26-26=.rawValue}} + if (check(self.test)) { Spacer() } } diff --git a/validation-test/Sema/SwiftUI/rdar88256059.swift b/validation-test/Sema/SwiftUI/rdar88256059.swift index 5324f86cf24..e3c9fe34d84 100644 --- a/validation-test/Sema/SwiftUI/rdar88256059.swift +++ b/validation-test/Sema/SwiftUI/rdar88256059.swift @@ -9,7 +9,8 @@ struct MyView: View { var body: some View { Table(self.data) { - // expected-error@-1 {{cannot infer return type of empty closure}} {{23-23=<#result#>}} + // expected-error@-1 {{missing argument for parameter #1 in call}} + // expected-error@-2 {{cannot infer return type of empty closure}} {{23-23=<#result#>}} } } } diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar50869732.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar50869732.swift index ca99694a28d..753849a9fdb 100644 --- a/validation-test/Sema/type_checker_crashers_fixed/rdar50869732.swift +++ b/validation-test/Sema/type_checker_crashers_fixed/rdar50869732.swift @@ -10,7 +10,7 @@ struct Generic { @resultBuilder struct Builder { - static func buildBlock(_ c0: C0, _ c1: C1) // expected-note 2 {{where 'C0' = 'Empty'}} expected-note {{where 'C1' = 'Test>'}} + static func buildBlock(_ c0: C0, _ c1: C1) // expected-note {{where 'C0' = 'Empty'}} // expected-note@-1 {{'buildBlock' declared here}} -> Generic<(C0, C1)> where C0 : P, C1 : P { return Generic((c0, c1)) @@ -30,8 +30,6 @@ struct Test where T : P { // expected-note {{where 'T' = 'Generic<(Empty, _)> } let x = G { - // expected-error@-1 {{static method 'buildBlock' requires that 'Empty' conform to 'P'}} - // expected-error@-2 {{static method 'buildBlock' requires that 'Test>' conform to 'P'}} Empty() Test { Empty() } // expected-error@-1 {{static method 'buildBlock' requires that 'Empty' conform to 'P'}} diff --git a/validation-test/compiler_crashers_2_fixed/issue-57241.swift b/validation-test/compiler_crashers_2_fixed/issue-57241.swift index 0812d6a3333..57352f672d4 100644 --- a/validation-test/compiler_crashers_2_fixed/issue-57241.swift +++ b/validation-test/compiler_crashers_2_fixed/issue-57241.swift @@ -7,9 +7,9 @@ struct S { private func f() {} func test() { - // expected-error@+1 {{static method 'buildBlock' requires that 'ForEach<[String], ()>' conform to 'View'}} ForEach(data) { group in - ForEach(group) { month in + ForEach(group) { month in // expected-error {{type '()' cannot conform to 'View'}} + // expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}} self.f() } } @@ -21,7 +21,7 @@ struct Wrapper {} protocol View {} @resultBuilder struct Builder { - // expected-note@+1 {{where 'Content' = 'ForEach<[String], ()>'}} + // expected-note@+1 {{required by static method 'buildBlock' where 'Content' = '()'}} static func buildBlock(_ content: Content) -> Content { fatalError() } }