diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 93ca008b25c25..d2144d14d3383 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -724,7 +724,7 @@ namespace swift { /// Enable experimental support for type inference through multi-statement /// closures. - bool EnableMultiStatementClosureInference = false; + bool EnableMultiStatementClosureInference = true; /// Enable experimental support for generic parameter inference in /// parameter positions from associated default expressions. diff --git a/include/swift/Sema/ConstraintLocator.h b/include/swift/Sema/ConstraintLocator.h index d5996d53aea09..5c9adad004409 100644 --- a/include/swift/Sema/ConstraintLocator.h +++ b/include/swift/Sema/ConstraintLocator.h @@ -1058,6 +1058,19 @@ class LocatorPathElt::ClosureBodyElement final } }; +class LocatorPathElt::PatternBindingElement final + : public StoredIntegerElement<1> { +public: + PatternBindingElement(unsigned index) + : StoredIntegerElement(ConstraintLocator::PatternBindingElement, index) {} + + unsigned getIndex() const { return getValue(); } + + static bool classof(const LocatorPathElt *elt) { + return elt->getKind() == ConstraintLocator::PatternBindingElement; + } +}; + namespace details { template class PathElement { diff --git a/include/swift/Sema/ConstraintLocatorPathElts.def b/include/swift/Sema/ConstraintLocatorPathElts.def index 35c819d0035d8..0d9d8b4f5ceaa 100644 --- a/include/swift/Sema/ConstraintLocatorPathElts.def +++ b/include/swift/Sema/ConstraintLocatorPathElts.def @@ -232,6 +232,9 @@ SIMPLE_LOCATOR_PATH_ELT(ImplicitDynamicMemberSubscript) /// The element of the closure body e.g. statement, declaration, or expression. CUSTOM_LOCATOR_PATH_ELT(ClosureBodyElement) +/// The element of the pattern binding declaration. +CUSTOM_LOCATOR_PATH_ELT(PatternBindingElement) + #undef LOCATOR_PATH_ELT #undef CUSTOM_LOCATOR_PATH_ELT #undef SIMPLE_LOCATOR_PATH_ELT diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index c94a9f0b614a3..13bee8a11518a 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -483,12 +483,81 @@ class ClosureConstraintGenerator }); } + void visitPatternBinding(PatternBindingDecl *patternBinding, + SmallVectorImpl &patterns) { + auto *baseLoc = cs.getConstraintLocator( + locator, LocatorPathElt::ClosureBodyElement(patternBinding)); + + for (unsigned index : range(patternBinding->getNumPatternEntries())) { + auto *pattern = TypeChecker::resolvePattern( + patternBinding->getPattern(index), patternBinding->getDeclContext(), + /*isStmtCondition=*/true); + + if (!pattern) { + hadError = true; + return; + } + + // Reset binding to point to the resolved pattern. This is required + // before calling `forPatternBindingDecl`. + patternBinding->setPattern(index, pattern, + patternBinding->getInitContext(index)); + + patterns.push_back(makeElement( + patternBinding, + cs.getConstraintLocator( + baseLoc, LocatorPathElt::PatternBindingElement(index)))); + } + } + + void visitPatternBindingElement(PatternBindingDecl *patternBinding) { + assert(locator->isLastElement()); + + auto index = + locator->castLastElementTo() + .getIndex(); + + auto contextualPattern = + ContextualPattern::forPatternBindingDecl(patternBinding, index); + Type patternType = TypeChecker::typeCheckPattern(contextualPattern); + + // Fail early if pattern couldn't be type-checked. + if (!patternType || patternType->hasError()) { + hadError = true; + return; + } + + auto *pattern = patternBinding->getPattern(index); + auto *init = patternBinding->getInit(index); + + if (!init && patternBinding->isDefaultInitializable(index) && + pattern->hasStorage()) { + init = TypeChecker::buildDefaultInitializer(patternType); + } + + auto target = init ? SolutionApplicationTarget::forInitialization( + init, patternBinding->getDeclContext(), + patternType, patternBinding, index, + /*bindPatternVarsOneWay=*/false) + : SolutionApplicationTarget::forUninitializedVar( + patternBinding, index, patternType); + + if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) { + hadError = true; + return; + } + + // Keep track of this binding entry. + cs.setSolutionApplicationTarget({patternBinding, index}, target); + } + void visitDecl(Decl *decl) { if (isSupportedMultiStatementClosure()) { if (auto patternBinding = dyn_cast(decl)) { - SolutionApplicationTarget target(patternBinding); - if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) - hadError = true; + if (locator->isLastElement()) + visitPatternBindingElement(patternBinding); + else + llvm_unreachable("cannot visit pattern binding directly"); return; } } @@ -788,6 +857,13 @@ class ClosureConstraintGenerator element.is() && (!ctx.LangOpts.Playground && !ctx.LangOpts.DebuggerSupport); + if (auto *decl = element.dyn_cast()) { + if (auto *PDB = dyn_cast(decl)) { + visitPatternBinding(PDB, elements); + continue; + } + } + elements.push_back(makeElement( element, cs.getConstraintLocator( @@ -1600,6 +1676,17 @@ void ConjunctionElement::findReferencedVariables( TypeVariableRefFinder refFinder(cs, locator->getAnchor(), typeVars); + if (auto *patternBinding = + dyn_cast_or_null(element.dyn_cast())) { + if (auto patternBindingElt = + locator + ->getLastElementAs()) { + if (auto *init = patternBinding->getInit(patternBindingElt->getIndex())) + init->walk(refFinder); + return; + } + } + if (element.is() || element.is() || element.is() || element.isStmt(StmtKind::Return)) element.walk(refFinder); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 9d292b284a53b..6249f3bff491c 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2299,9 +2299,71 @@ namespace { locator); } - // If we have a type to ascribe to the variable, do so now. - if (oneWayVarType) + // Ascribe a type to the declaration so it's always available to + // constraint system. + if (oneWayVarType) { CS.setType(var, oneWayVarType); + } else if (externalPatternType) { + // If there is an externally imposed type, that's what the + // declaration is going to be bound to. + CS.setType(var, externalPatternType); + } else { + // Otherwise, let's use the type of the pattern. The type + // of the declaration has to be r-value, so let's add an + // equality constraint if pattern type has any type variables + // that are allowed to be l-value. + bool foundLValueVars = false; + + // Note that it wouldn't be always correct to allocate a single type + // variable, that disallows l-value types, to use as a declaration + // type because equality constraint would drop TVO_CanBindToLValue + // from the right-hand side (which is not the case for `OneWayEqual`) + // e.g.: + // + // sturct S { var x, y: Int } + // + // func test(s: S) { + // let (x, y) = (s.x, s.y) + // } + // + // Single type variable approach results in the following constraint: + // `$T_x_y = ($T_s_x, $T_s_y)` where both `$T_s_x` and `$T_s_y` have + // to allow l-value, but `$T_x_y` does not. Early simplication of `=` + // constraint (due to right-hand side being a "concrete" tuple type) + // would drop l-value option from `$T_s_x` and `$T_s_y` which leads to + // a failure during member lookup because `x` and `y` are both + // `@lvalue Int`. To avoid that, declaration type would mimic pattern + // type with all l-value options stripped, so the equality constraint + // becomes `($T_x, $_T_y) = ($T_s_x, $T_s_y)` which doesn't result in + // stripping of l-value flag from the right-hand side since + // simplification can only happen when either side is resolved. + auto declTy = varType.transform([&](Type type) -> Type { + if (auto *typeVar = type->getAs()) { + if (typeVar->getImpl().canBindToLValue()) { + foundLValueVars = true; + + // Drop l-value from the options but preserve the rest. + auto options = typeVar->getImpl().getRawOptions(); + options &= ~TVO_CanBindToLValue; + + return CS.createTypeVariable(typeVar->getImpl().getLocator(), + options); + } + } + return type; + }); + + // If pattern types allows l-value types, let's create an + // equality constraint between r-value only declaration type + // and l-value pattern type that would take care of looking + // through l-values when necessary. + if (foundLValueVars) { + CS.addConstraint(ConstraintKind::Equal, declTy, varType, + CS.getConstraintLocator(locator)); + } + + CS.setType(var, declTy); + } return setType(varType); } diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index 1001ab23be28e..1dcef91a86354 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -388,8 +388,21 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const { } if (Kind == ConstraintKind::ClosureBodyElement) { - Out << "closure body element "; - getClosureElement().dump(Out); + auto *locator = getLocator(); + auto element = getClosureElement(); + + if (auto patternBindingElt = + locator + ->getLastElementAs()) { + auto *patternBinding = cast(element.get()); + Out << "pattern binding element @ "; + Out << patternBindingElt->getIndex() << " : "; + patternBinding->getPattern(patternBindingElt->getIndex())->dump(Out); + } else { + Out << "closure body element "; + getClosureElement().dump(Out); + } + return; } diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index 215cee2c1da58..c5d8de2184214 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -96,6 +96,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const { case ConstraintLocator::ClosureBodyElement: case ConstraintLocator::PackType: case ConstraintLocator::PackElement: + case ConstraintLocator::PatternBindingElement: return 0; case ConstraintLocator::FunctionArgument: @@ -578,6 +579,14 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const { out << "pack element #" << llvm::utostr(packElt.getIndex()); break; } + + case PatternBindingElement: { + auto patternBindingElt = + elt.castTo(); + out << "pattern binding element #" + << llvm::utostr(patternBindingElt.getIndex()); + break; + } } } out << ']'; diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index 42616c02e36bc..cb4a32e5aa3e4 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -252,7 +252,7 @@ struct CC {} func callCC(_ f: (CC) -> U) -> () {} func typeCheckMultiStmtClosureCrash() { - callCC { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{none}} + callCC { _ = $0 return 1 } @@ -312,9 +312,8 @@ func testAcceptNothingToInt(ac1: @autoclosure () -> Int) { struct Thing { init?() {} } -// This throws a compiler error -let things = Thing().map { thing in // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{34-34=-> <#Result#> }} - // Commenting out this makes it compile + +let things = Thing().map { thing in _ = thing return thing } @@ -322,14 +321,14 @@ let things = Thing().map { thing in // expected-error {{cannot infer return typ // QoI: [Closure return type inference] Swift cannot find members for the result of inlined lambdas with branches func r21675896(file : String) { - let x: String = { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{20-20= () -> <#Result#> in }} + let x: String = { if true { return "foo" } else { return file } - }().pathExtension + }().pathExtension // expected-error {{value of type 'String' has no member 'pathExtension'}} } @@ -360,7 +359,7 @@ func someGeneric19997471(_ x: T) { // Swift fails to compile: [0].map() { _ in let r = (1,2).0; return r } -[0].map { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{5-5=-> <#Result#> }} +let _ = [0].map { _ in let r = (1,2).0 return r @@ -408,7 +407,7 @@ func r20789423() { print(p.f(p)()) // expected-error {{cannot convert value of type 'C' to expected argument type 'Int'}} // expected-error@-1:11 {{cannot call value of non-function type '()'}} - let _f = { (v: Int) in // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{23-23=-> <#Result#> }} + let _f = { (v: Int) in print("a") return "hi" } @@ -1127,7 +1126,7 @@ func rdar76058892() { func experiment(arr: [S]?) { test { // expected-error {{contextual closure type '() -> String' expects 0 arguments, but 1 was used in closure body}} if let arr = arr { - arr.map($0.test) // expected-note {{anonymous closure parameter '$0' is used here}} + arr.map($0.test) // expected-note {{anonymous closure parameter '$0' is used here}} // expected-error {{generic parameter 'T' could not be inferred}} } } } diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index 6b7aa27c3f2f7..2ebd3e52c8a1d 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -148,7 +148,7 @@ func ***~(_: Int, _: String) { } i ***~ i // expected-error{{cannot convert value of type 'Int' to expected argument type 'String'}} @available(*, unavailable, message: "call the 'map()' method on the sequence") -public func myMap( +public func myMap( // expected-note {{'myMap' has been explicitly marked unavailable here}} _ source: C, _ transform: (C.Iterator.Element) -> T ) -> [T] { fatalError("unavailable function can't be called") @@ -161,7 +161,7 @@ public func myMap(_ x: T?, _ f: (T) -> U) -> U? { // func rdar20142523() { - myMap(0..<10, { x in // expected-error{{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{21-21=-> <#Result#> }} {{educational-notes=complex-closure-inference}} + _ = myMap(0..<10, { x in // expected-error {{'myMap' is unavailable: call the 'map()' method on the sequence}} () return x }) diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift index 61e58d891c9b5..5dda70ee0d26b 100644 --- a/test/Constraints/members.swift +++ b/test/Constraints/members.swift @@ -595,10 +595,10 @@ func rdar50679161() { func foo() { _ = { () -> Void in + // Missing `.self` or `init` is not diagnosed here because there are errors in + // `if let` statement and `MiscDiagnostics` only run if the body is completely valid. var foo = S - // expected-error@-1 {{expected member name or constructor call after type name}} - // expected-note@-2 {{add arguments after the type to construct a value of the type}} - // expected-note@-3 {{use '.self' to reference the type object}} + if let v = Int?(1) { var _ = Q( a: v + foo.w, @@ -610,6 +610,14 @@ func rdar50679161() { ) } } + + _ = { () -> Void in + var foo = S + // expected-error@-1 {{expected member name or constructor call after type name}} + // expected-note@-2 {{add arguments after the type to construct a value of the type}} + // expected-note@-3 {{use '.self' to reference the type object}} + print(foo) + } } } diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift index 40577ded3e629..0dd5c677991e2 100644 --- a/test/Constraints/patterns.swift +++ b/test/Constraints/patterns.swift @@ -230,14 +230,14 @@ func good(_ a: A) -> Int { } func bad(_ a: A) { - a.map { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{none}} + let _ = a.map { let _: EE = $0 return 1 } } func ugly(_ a: A) { - a.map { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{none}} + let _ = a.map { switch $0 { case .A: return 1 diff --git a/test/Constraints/rdar46544601.swift b/test/Constraints/rdar46544601.swift index e633bda722ee2..28e5882d6772e 100644 --- a/test/Constraints/rdar46544601.swift +++ b/test/Constraints/rdar46544601.swift @@ -26,6 +26,6 @@ func crash(_ p: P, payload: [UInt8]) throws { p.foo(arr: arr, data: []).and(result: (id, arr)) }.then { args0 in let (parentID, args1) = args0 - p.bar(root: parentID, from: p).and(args1) + p.bar(root: parentID, from: p).and(result: args1) }.whenFailure { _ in } } diff --git a/test/Constraints/rdar65320500.swift b/test/Constraints/rdar65320500.swift index 25b08ac7aad5e..2d9dc9f9311a4 100644 --- a/test/Constraints/rdar65320500.swift +++ b/test/Constraints/rdar65320500.swift @@ -31,13 +31,13 @@ test_builder { test_builder { test(doesntExist()) // expected-error {{cannot find 'doesntExist' in scope}} - if let result = doesntExist() { + if let result = doesntExist() { // expected-error {{cannot find 'doesntExist' in scope}} } - if bar = test(42) {} + if bar = test(42) {} // expected-error {{cannot find 'bar' in scope}} - let foo = bar() + let foo = bar() // expected-error {{cannot find 'bar' in scope}} - switch (doesntExist()) { + switch (doesntExist()) { // expected-error {{cannot find 'doesntExist' in scope}} } } diff --git a/test/Constraints/result_builder_diags.swift b/test/Constraints/result_builder_diags.swift index ce189a976d472..8f91ff8294032 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) { +func tuplify(_ cond: Bool, @TupleBuilder body: (Bool) -> T) { // expected-note {{in call to function 'tuplify(_:body:)'}} print(body(cond)) } @@ -307,21 +307,6 @@ struct MyTuplifiedStruct { } } -func test_invalid_return_type_in_body() { - tuplify(true) { _ -> (Void, Int) in - tuplify(false) { condition in - if condition { - return 42 // expected-error {{cannot use explicit 'return' statement in the body of result builder 'TupleBuilder'}} - // expected-note@-1 {{remove 'return' statements to apply the result builder}} {{9-16=}} - } else { - 1 - } - } - - 42 - } -} - // Check that we're performing syntactic use diagnostics. func acceptMetatype(_: T.Type) -> Bool { true } @@ -481,7 +466,7 @@ struct TestConstraintGenerationErrors { func buildTupleClosure() { tuplify(true) { _ in let a = nothing // expected-error {{cannot find 'nothing' in scope}} - String(nothing) + String(nothing) // expected-error {{cannot find 'nothing' in scope}} } } } @@ -522,7 +507,7 @@ enum E3 { } func testCaseMutabilityMismatches(e: E3) { - tuplify(true) { c in + tuplify(true) { c in // expected-error {{generic parameter 'T' could not be inferred}} "testSwitch" switch e { case .a(let x, var y), diff --git a/test/Constraints/tuple.swift b/test/Constraints/tuple.swift index d89ee2b5d1251..5c2965e6b4b2b 100644 --- a/test/Constraints/tuple.swift +++ b/test/Constraints/tuple.swift @@ -218,14 +218,14 @@ extension r25271859 { func map(f: (T) -> U) -> r25271859 { } - func andThen(f: (T) -> r25271859) { // expected-note {{in call to function 'andThen(f:)'}} + func andThen(f: (T) -> r25271859) { } } func f(a : r25271859<(Float, Int)>) { - a.map { $0.0 } // expected-error {{generic parameter 'U' could not be inferred}} (This is related to how solver is setup with multiple statements) + a.map { $0.0 } .andThen { _ in - print("hello") // comment this out and it runs, leave any form of print in and it doesn't + print("hello") return r25271859() } } diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift index ec14a257c96aa..a568be0bc5206 100644 --- a/test/Constraints/tuple_arguments.swift +++ b/test/Constraints/tuple_arguments.swift @@ -1407,25 +1407,41 @@ func processArrayOfFunctions(f1: [((Bool, Bool)) -> ()], } f2.forEach { block in - // expected-note@-1 2{{'block' declared here}} + // expected-note@-1 {{'block' declared here}} block(p) // expected-error {{parameter 'block' expects 2 separate arguments}} + } + + f2.forEach { block in + // expected-note@-1 {{'block' declared here}} block((c, c)) // expected-error {{parameter 'block' expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{11-12=}} {{16-17=}} block(c, c) } + f2.forEach { block in + block(c, c) + } + f2.forEach { (block: ((Bool, Bool)) -> ()) in // expected-error@-1 {{cannot convert value of type '(((Bool, Bool)) -> ()) -> Void' to expected argument type '(@escaping (Bool, Bool) -> ()) throws -> Void'}} block(p) block((c, c)) - block(c, c) + block(c, c) // expected-error {{parameter 'block' expects a single parameter of type '(Bool, Bool)'}} } f2.forEach { (block: (Bool, Bool) -> ()) in - // expected-note@-1 2{{'block' declared here}} + // expected-note@-1 {{'block' declared here}} block(p) // expected-error {{parameter 'block' expects 2 separate arguments}} + } + + f2.forEach { (block: (Bool, Bool) -> ()) in + // expected-note@-1 {{'block' declared here}} block((c, c)) // expected-error {{parameter 'block' expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{11-12=}} {{16-17=}} block(c, c) } + + f2.forEach { (block: (Bool, Bool) -> ()) in + block(c, c) + } } // expected-error@+1 {{cannot create a single-element tuple with an element label}} diff --git a/test/Constraints/without_actually_escaping.swift b/test/Constraints/without_actually_escaping.swift index 12752c08e8c2e..d6ce858c24801 100644 --- a/test/Constraints/without_actually_escaping.swift +++ b/test/Constraints/without_actually_escaping.swift @@ -10,7 +10,7 @@ func escapeX(_ xx: (Int) -> Int, _ value: Int) { // expected-note* {{non-escapin withoutActuallyEscaping(xx) { escapableXX in x = xx // expected-error{{non-escaping parameter}} x = escapableXX - x = xx // expected-error{{non-escaping parameter}} + x = xx _ = x(value) _ = xx(value) diff --git a/test/Sema/diag_ambiguous_overloads.swift b/test/Sema/diag_ambiguous_overloads.swift index 1aa56b1b0bece..e351f3885d935 100644 --- a/test/Sema/diag_ambiguous_overloads.swift +++ b/test/Sema/diag_ambiguous_overloads.swift @@ -132,15 +132,13 @@ func SR12689(_ u: UnsafeBufferPointer) {} let array : [UInt16] = [1, 2] array.withUnsafeBufferPointer { - SR12689(UnsafeRawPointer($0).bindMemory(to: UInt16.self, capacity: 1)) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafeBufferPointer'}} - // expected-error@-1 {{no exact matches in call to initializer}} - // expected-note@-2 {{candidate expects value of type 'UnsafeRawPointer' for parameter #1}} - // expected-note@-3 {{candidate expects value of type 'UnsafeMutableRawPointer' for parameter #1}} - - UnsafeRawPointer($0) as UnsafeBufferPointer // expected-error {{cannot convert value of type 'UnsafeRawPointer' to type 'UnsafeBufferPointer' in coercion}} - // expected-error@-1 {{no exact matches in call to initializer}} - // expected-note@-2 {{found candidate with type '(UnsafeRawPointer) -> UnsafeRawPointer'}} - // expected-note@-3 {{found candidate with type '(UnsafeMutableRawPointer) -> UnsafeRawPointer'}} + _ = SR12689(UnsafeRawPointer($0).bindMemory(to: UInt16.self, capacity: 1)) // expected-error {{cannot convert value of type 'UnsafePointer' to expected argument type 'UnsafeBufferPointer'}} + // expected-error@-1 {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawPointer'}} +} + +array.withUnsafeBufferPointer { + _ = UnsafeRawPointer($0) as UnsafeBufferPointer // expected-error {{cannot convert value of type 'UnsafeRawPointer' to type 'UnsafeBufferPointer' in coercion}} + // expected-error@-1 {{cannot convert value of type 'UnsafeBufferPointer' to expected argument type 'UnsafeMutableRawPointer'}} } func SR12689_1(_ u: Int) -> String { "" } // expected-note {{found this candidate}} expected-note {{candidate expects value of type 'Int' for parameter #1 (got 'Double')}} diff --git a/test/diagnostics/pretty-printed-diagnostics.swift b/test/diagnostics/pretty-printed-diagnostics.swift index b110ecfa45c23..6ff1e65045cd1 100644 --- a/test/diagnostics/pretty-printed-diagnostics.swift +++ b/test/diagnostics/pretty-printed-diagnostics.swift @@ -124,13 +124,6 @@ foo(b: // CHECK: | ^ note: Remove '=' to make 'x' a computed property [remove '= ' and replace 'let' with 'var'] // CHECK: [[#LINE+1]] | } -// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:9 -// CHECK: [[#LINE-1]] | -// CHECK: [[#LINE]] | let x = { () -> Result in -// CHECK: | +++++++++++++++++ -// CHECK: | ^ error: cannot infer return type for closure with multiple statements; add explicit type to disambiguate -// CHECK: [[#LINE+1]] | let y = 1 - // CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:8 // CHECK: [[#LINE-1]] | // CHECK: [[#LINE]] | struct B: Decodable { @@ -149,12 +142,6 @@ foo(b: // CHECK: | ^ error: argument 'a' must precede argument 'b' [remove ', a: 2' and insert 'a: 2, '] // CHECK: [[#LINE+1]] | -// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:20 -// CHECK: [[#LINE-1]] | -// CHECK: [[#LINE]] | let 👍👍👍 = { -// CHECK: | --> error: cannot infer return type for closure with multiple statements; add explicit type to disambiguate [insert ' () -> <#Result#> in '] -// CHECK: [[#LINE+1]] | let y = 1 - // CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:5 // CHECK: [[#LINE-2]] | // Multi-line fix-its // CHECK: [[#LINE-1]] | foo(a: 2, b: 1, diff --git a/test/expr/closure/anonymous.swift b/test/expr/closure/anonymous.swift index 3a9caf47f7537..e5de36e8d2412 100644 --- a/test/expr/closure/anonymous.swift +++ b/test/expr/closure/anonymous.swift @@ -29,11 +29,7 @@ func variadic() { takesVariadicGeneric({takesIntArray($0)}) - // FIXME: Problem here is related to multi-statement closure body not being type-checked together with - // enclosing context. We could have inferred `$0` to be `[Int]` if `let` was a part of constraint system. takesVariadicGeneric({let _: [Int] = $0}) - // expected-error@-1 {{unable to infer type of a closure parameter '$0' in the current context}} - takesVariadicIntInt({_ = $0; takesIntArray($1)}) takesVariadicIntInt({_ = $0; let _: [Int] = $1}) } diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index 49508cc7a8fd2..0c2c821665539 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -115,11 +115,11 @@ func t() { func f0(_ a: Any) -> Int { return 1 } assert(f0(1) == 1) - +// TODO(diagnostics): Bad diagnostic - should be `circular reference` var selfRef = { selfRef() } -// expected-note@-1 2{{through reference here}} -// expected-error@-2 {{circular reference}} +// expected-error@-1 {{unable to infer closure type in the current context}} +// TODO: should be an error `circular reference` but it's diagnosed via overlapped requests var nestedSelfRef = { var recursive = { nestedSelfRef() } // expected-warning@-1 {{variable 'recursive' was never mutated; consider changing to 'let' constant}} @@ -140,12 +140,11 @@ func anonymousClosureArgsInClosureWithArgs() { var a3 = { (z: Int) in $0 } // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'z'?}} {{26-28=z}} var a4 = { (z: [Int], w: [Int]) in f($0.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'z'?}} {{7-9=z}} expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} - f($1.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'w'?}} {{7-9=w}} expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} + f($1.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'w'?}} {{7-9=w}} } var a5 = { (_: [Int], w: [Int]) in f($0.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments}} f($1.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'w'?}} {{7-9=w}} - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'String'}} } } @@ -403,7 +402,7 @@ Void(0) // expected-error{{argument passed to call that takes no arguments}} _ = {0} // "multi-statement closures require an explicit return type" should be an error not a note -let samples = { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }} +let samples = { if (i > 10) { return true } else { return false } }() @@ -485,8 +484,8 @@ func lvalueCapture(c: GenericClass) { } // Don't expose @lvalue-ness in diagnostics. -let closure = { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }} - var helper = true +let closure = { + var helper = true // expected-warning {{variable 'helper' was never mutated; consider changing to 'let' constant}} return helper } diff --git a/test/expr/closure/inference.swift b/test/expr/closure/inference.swift index b1b536c53991f..0e9ac2a943f4b 100644 --- a/test/expr/closure/inference.swift +++ b/test/expr/closure/inference.swift @@ -34,10 +34,9 @@ func unnamed() { // Regression tests. var nestedClosuresWithBrokenInference = { f: Int in {} } - // expected-error@-1 {{closure expression is unused}} expected-note@-1 {{did you mean to use a 'do' statement?}} {{53-53=do }} - // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{44-44=;}} - // expected-error@-3 {{expected expression}} - // expected-error@-4 {{cannot find 'f' in scope}} + // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{44-44=;}} + // expected-error@-2 {{expected expression}} + // expected-error@-3 {{cannot find 'f' in scope}} // SR-11540 diff --git a/test/expr/closure/let.swift b/test/expr/closure/let.swift index 176629f7c9517..4d4bfdfd86846 100644 --- a/test/expr/closure/let.swift +++ b/test/expr/closure/let.swift @@ -9,11 +9,11 @@ func foo() { _ = { frob(x: x) }() // expected-error{{'x' is a 'let'}} _ = { x = 0 }() // expected-error{{'x' is a 'let'}} - _ = { frob(x: x); x = 0 }() // expected-error 2 {{'x' is a 'let'}} + _ = { frob(x: x); x = 0 }() // expected-error {{'x' is a 'let'}} } let a: Int { 1 } // expected-error{{'let' declarations cannot be computed properties}} let b: Int = 1 -{ didSet { print("didSet") } } // expected-error{{'let' declarations cannot be observing properties}} \ No newline at end of file +{ didSet { print("didSet") } } // expected-error{{'let' declarations cannot be observing properties}} diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift index f50823e037828..ab9f6ea21afae 100644 --- a/test/expr/unary/keypath/keypath.swift +++ b/test/expr/unary/keypath/keypath.swift @@ -1093,8 +1093,6 @@ func rdar74711236() { // `isSupported` should be an invalid declaration to trigger a crash in `map(\.option)` let isSupported = context!.supported().contains(type) return (isSupported ? [type] : []).map(\.option) - // expected-error@-1 {{value of type 'Any' has no member 'option'}} - // expected-note@-2 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}} } return [] }() diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift index 1f05959eb4448..c3348cce6ffc9 100644 --- a/test/stmt/statements.swift +++ b/test/stmt/statements.swift @@ -400,13 +400,20 @@ func test_is_as_patterns() { } // Fuzzing SourceKit: crash in Parser::parseStmtForEach(...) -func matching_pattern_recursion() { +func matching_pattern_recursion(zs: [Int]) { // expected-note {{'zs' declared here}} switch 42 { case { // expected-error {{expression pattern of type '() -> ()' cannot match values of type 'Int'}} for i in zs { } }: break } + + switch 42 { + case { + for i in ws { // expected-error {{cannot find 'ws' in scope; did you mean 'zs'?}} + } + }: break + } } // Swift's break operator in switch should be indicated in errors diff --git a/validation-test/Sema/type_checker_perf/fast/multi_statement_closure_with_simd_variable.swift b/validation-test/Sema/type_checker_perf/fast/multi_statement_closure_with_simd_variable.swift new file mode 100644 index 0000000000000..294ff03cb814c --- /dev/null +++ b/validation-test/Sema/type_checker_perf/fast/multi_statement_closure_with_simd_variable.swift @@ -0,0 +1,18 @@ +// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1 +// REQUIRES: objc_interop,no_asan + +import simd + +func test(_: () -> Void) {} + +test { + let a: simd_float2 = .init() + let b: simd_float2 = .init() + let c: simd_float2 = .init() + let d: simd_float2 = .init() + + let width: Float = 2 + + let p = Int(max(20, min(1000, (simd_distance(a, b) + simd_distance(b, c) + simd_distance(c, d)) / width / 4))) + print(p) +} diff --git a/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift b/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift index 176928ec6781b..36d9906941ced 100644 --- a/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift +++ b/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift @@ -17,7 +17,7 @@ struct M { } } -protocol P { // expected-note {{where 'Self' = 'M, R>'}} +protocol P { // expected-note {{where 'Self' = 'M, Int>'}} associatedtype A associatedtype B @@ -42,5 +42,4 @@ extension WritableKeyPath : P { struct X { var y: Int = 0 } var x = X() x ~> \X.y ≈> { a in a += 1; return 3 } -// expected-error@-1 {{referencing operator function '~>' on 'P' requires that 'M, R>' conform to 'P'}} -// expected-error@-2 {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} +//expected-error@-1 {{referencing operator function '~>' on 'P' requires that 'M, Int>' conform to 'P'}}