diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 335f8cb96dc..5b8eb766bbd 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -30,17 +30,14 @@ void ConstraintSystem::inferTransitiveSupertypeBindings( llvm::SmallVector subtypeOf; // First, let's collect all of the `subtype` constraints associated // with this type variable. - llvm::copy_if( - bindings.Sources, std::back_inserter(subtypeOf), - [&](const Constraint *constraint) -> bool { - if (constraint->getKind() != ConstraintKind::Subtype && - constraint->getKind() != ConstraintKind::ArgumentConversion && - constraint->getKind() != ConstraintKind::OperatorArgumentConversion) - return false; + llvm::copy_if(bindings.Sources, std::back_inserter(subtypeOf), + [&](const Constraint *constraint) -> bool { + if (constraint->getKind() != ConstraintKind::Subtype) + return false; - auto rhs = simplifyType(constraint->getSecondType()); - return rhs->getAs() == typeVar; - }); + auto rhs = simplifyType(constraint->getSecondType()); + return rhs->getAs() == typeVar; + }); if (subtypeOf.empty()) return; @@ -635,7 +632,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const { continue; literalBindings.push_back( - {defaultType, AllowedBindingKind::Exact, constraint}); + {defaultType, AllowedBindingKind::Subtypes, constraint}); continue; } @@ -661,7 +658,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const { if (!matched) { exactTypes.insert(defaultType->getCanonicalType()); literalBindings.push_back( - {defaultType, AllowedBindingKind::Exact, constraint}); + {defaultType, AllowedBindingKind::Subtypes, constraint}); } break; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 93f8c6dcda8..b95b575df9a 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9221,8 +9221,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( // subscript, which requires changes to declaration to become mutable. if (auto last = locator.last()) { impact += (last->is() || - last->is() || - last->is()) + last->is()) ? 1 : 0; } diff --git a/lib/Sema/CSStep.h b/lib/Sema/CSStep.h index 54d2c863654..1b9317a8cd8 100644 --- a/lib/Sema/CSStep.h +++ b/lib/Sema/CSStep.h @@ -619,15 +619,6 @@ protected: /// Check whether attempting type variable binding choices should /// be stopped, because optimal solution has already been found. bool shouldStopAt(const TypeVariableBinding &choice) const override { - if (CS.shouldAttemptFixes()) { - // Let's always attempt default types inferred from literals - // in diagnostic mode because that could lead to better - // diagnostics if the problem is contextual like argument/parameter - // conversion or collection element mismatch. - if (choice.hasDefaultedProtocol()) - return false; - } - // If we were able to solve this without considering // default literals, don't bother looking at default literals. return AnySolved && choice.hasDefaultedProtocol() && diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index ecefad1941d..25d18bbc78d 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -2776,61 +2776,45 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, auto &DE = cs.getASTContext().Diags; - llvm::SmallDenseMap, 4> - genericParams; - // Consider only representative type variables shared across - // all of the solutions. - for (auto *typeVar : cs.getTypeVariables()) { - if (auto *GP = typeVar->getImpl().getGenericParameter()) { - auto *locator = typeVar->getImpl().getLocator(); - auto *repr = cs.getRepresentative(typeVar); - // If representative is another generic parameter let's - // use its generic parameter type instead of originator's, - // but it's possible that generic parameter is equated to - // some other type e.g. - // - // func foo(_: T) -> T {} - // - // In this case when reference to function `foo` is "opened" - // type variable representing `T` would be equated to - // type variable representing a result type of the reference. - if (auto *reprGP = repr->getImpl().getGenericParameter()) - GP = reprGP; + llvm::SmallDenseMap> conflicts; - genericParams[repr] = {GP, locator->getAnchor()->getLoc()}; - } - } + for (const auto &binding : solutions[0].typeBindings) { + auto *typeVar = binding.first; - llvm::SmallDenseMap, - SmallVector> - conflicts; - - for (const auto &entry : genericParams) { - auto *typeVar = entry.first; - auto GP = entry.second; + if (!typeVar->getImpl().getGenericParameter()) + continue; llvm::SmallSetVector arguments; - for (const auto &solution : solutions) { - auto type = solution.typeBindings.lookup(typeVar); - // Contextual opaque result type is uniquely identified by - // declaration it's associated with, so we have to compare - // declarations instead of using pointer equality on such types. - if (auto *opaque = type->getAs()) { - auto *decl = opaque->getDecl(); - arguments.remove_if([&](Type argType) -> bool { - if (auto *otherOpaque = argType->getAs()) { - return decl == otherOpaque->getDecl(); + arguments.insert(binding.second); + + if (!llvm::all_of(solutions.slice(1), [&](const Solution &solution) { + auto binding = solution.typeBindings.find(typeVar); + if (binding == solution.typeBindings.end()) + return false; + + // Contextual opaque result type is uniquely identified by + // declaration it's associated with, so we have to compare + // declarations instead of using pointer equality on such types. + if (auto *opaque = + binding->second->getAs()) { + auto *decl = opaque->getDecl(); + arguments.remove_if([&](Type argType) -> bool { + if (auto *otherOpaque = + argType->getAs()) { + return decl == otherOpaque->getDecl(); + } + return false; + }); } - return false; - }); - } - arguments.insert(type); + arguments.insert(binding->second); + return true; + })) + continue; + + if (arguments.size() > 1) { + conflicts[typeVar].append(arguments.begin(), arguments.end()); } - - if (arguments.size() > 1) - conflicts[GP].append(arguments.begin(), arguments.end()); } auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * { @@ -2847,10 +2831,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, bool diagnosed = false; for (auto &conflict : conflicts) { - SourceLoc loc; - GenericTypeParamType *GP; - - std::tie(GP, loc) = conflict.first; + auto *typeVar = conflict.first; + auto *locator = typeVar->getImpl().getLocator(); auto conflictingArguments = conflict.second; llvm::SmallString<64> arguments; @@ -2875,8 +2857,10 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs, }, [&OS] { OS << " vs. "; }); - DE.diagnose(loc, diag::conflicting_arguments_for_generic_parameter, GP, - OS.str()); + auto *anchor = locator->getAnchor(); + DE.diagnose(anchor->getLoc(), + diag::conflicting_arguments_for_generic_parameter, + typeVar->getImpl().getGenericParameter(), OS.str()); diagnosed = true; } diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift index 73e772791ab..0ac54dd5355 100644 --- a/test/Constraints/array_literal.swift +++ b/test/Constraints/array_literal.swift @@ -50,7 +50,7 @@ useDoubleList([1.0,2,3]) useDoubleList([1.0,2.0,3.0]) useIntDict(["Niners" => 31, "Ravens" => 34]) -useIntDict(["Niners" => 31, "Ravens" => 34.0]) // expected-error{{cannot convert value of type 'Double' to expected element type 'Int'}} +useIntDict(["Niners" => 31, "Ravens" => 34.0]) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Int'}} // QoI: Propagate contextual information in a call to operands useDoubleDict(["Niners" => 31, "Ravens" => 34.0]) useDoubleDict(["Niners" => 31.0, "Ravens" => 34]) diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index aeffde64859..0d1109f6ab8 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -456,7 +456,13 @@ extension Collection { } } func fn_r28909024(n: Int) { - return (0..<10).r28909024 { // expected-error {{unexpected non-void return value in void function}} expected-note {{did you mean to add a return type?}} + // FIXME(diagnostics): Unfortunately there is no easy way to fix this diagnostic issue at the moment + // because the problem is related to ordering of the bindings - we'd attempt to bind result of the expression + // to contextual type of `Void` which prevents solver from discovering correct types for range - 0..<10 + // (since both arguments are literal they are ranked lower than contextual type). + // + // Good diagnostic for this is - `unexpected non-void return value in void function` + return (0..<10).r28909024 { // expected-error {{type of expression is ambiguous without more context}} _ in true } } diff --git a/test/Constraints/default_literals.swift b/test/Constraints/default_literals.swift index 02f79b446f6..f52e85ec2ac 100644 --- a/test/Constraints/default_literals.swift +++ b/test/Constraints/default_literals.swift @@ -42,14 +42,3 @@ extension Int { var (div, mod) = (9 / 4, 9 % 4) - -// rdar://problem/56212087 - solver fails to infer correct type for a generic parameter (Any vs. String) -func test_transitive_inference_of_default_literal_types() { - func foo(_: String, _: T) -> T { - fatalError() - } - - func bar(_: Any?) {} - - bar(foo("", "")) // Ok -} diff --git a/test/Generics/deduction.swift b/test/Generics/deduction.swift index d35e1d38416..f4b28eb794a 100644 --- a/test/Generics/deduction.swift +++ b/test/Generics/deduction.swift @@ -319,9 +319,8 @@ func foo() { let j = min(Int(3), Float(2.5)) // expected-error{{conflicting arguments to generic parameter 'T' ('Int' vs. 'Float')}} let k = min(A(), A()) // expected-error{{global function 'min' requires that 'A' conform to 'Comparable'}} let oi : Int? = 5 - let l = min(3, oi) // expected-error{{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}} - // expected-note@-1 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} - // expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} + let l = min(3, oi) // expected-error{{global function 'min' requires that 'Int?' conform to 'Comparable'}} + // expected-note@-1{{wrapped type 'Int' satisfies this requirement}} } infix operator +& diff --git a/test/Parse/omit_return.swift b/test/Parse/omit_return.swift index 07544df94e8..6a1a3b39f43 100644 --- a/test/Parse/omit_return.swift +++ b/test/Parse/omit_return.swift @@ -1005,7 +1005,7 @@ var fvs_stubMyOwnFatalError: () { var fvs_forceTryExplicit: String { get { "ok" } set { - return try! failableIdentity("shucks") // expected-error {{unexpected non-void return value in void function}} + return try! failableIdentity("shucks") // expected-error {{cannot convert value of type 'String' to expected argument type '()'}} } } diff --git a/test/attr/attr_dynamic_member_lookup.swift b/test/attr/attr_dynamic_member_lookup.swift index a98e650d44d..357ea7f0af9 100644 --- a/test/attr/attr_dynamic_member_lookup.swift +++ b/test/attr/attr_dynamic_member_lookup.swift @@ -600,7 +600,10 @@ func keypath_with_subscripts(_ arr: SubscriptLens<[Int]>, func keypath_with_incorrect_return_type(_ arr: Lens>) { for idx in 0..' to expected argument type 'Int'}} + // expected-error@-1 {{protocol 'Sequence' requires that 'Lens' conform to 'Strideable'}} + // expected-error@-2 {{protocol 'Sequence' requires that 'Lens.Stride' conform to 'SignedInteger'}} + // expected-error@-3 {{cannot convert value of type 'Int' to expected argument type 'Lens'}} + // expected-error@-4 {{referencing operator function '..<' on 'Comparable' requires that 'Lens' conform to 'Comparable'}} let _ = arr[idx] } } diff --git a/test/decl/typealias/generic.swift b/test/decl/typealias/generic.swift index 3d6678db37b..27a6c4f4790 100644 --- a/test/decl/typealias/generic.swift +++ b/test/decl/typealias/generic.swift @@ -103,7 +103,7 @@ _ = A(a: "foo", // expected-error {{cannot convert value of type 'S b: 42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} _ = B(a: 12, b: 42) _ = B(a: 12, b: 42 as Float) -_ = B(a: "foo", b: 42) // expected-error {{conflicting arguments to generic parameter 'T1' ('String' vs. 'Int')}} +_ = B(a: "foo", b: 42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} _ = C(a: "foo", b: 42) _ = C(a: 42, // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} b: 42) diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 95b23de79e9..d7d8f7126cc 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -791,9 +791,8 @@ func testNilCoalescePrecedence(cond: Bool, a: Int?, r: ClosedRange?) { // ?? should have lower precedence than range and arithmetic operators. let r1 = r ?? (0...42) // ok - let r2 = (r ?? 0)...42 // not ok - // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'ClosedRange'}} - // expected-error@-2 {{cannot convert value of type 'ClosedRange' to expected argument type 'Int'}} + let r2 = (r ?? 0)...42 // not ok: expected-error 2 {{cannot convert value of type 'Int' to expected argument type 'ClosedRange'}} + // expected-error@-1 {{referencing operator function '...' on 'Comparable' requires that 'ClosedRange' conform to 'Comparable'}} let r3 = r ?? 0...42 // parses as the first one, not the second. diff --git a/test/type/protocol_composition.swift b/test/type/protocol_composition.swift index 602cb721a11..b78a9af3a5f 100644 --- a/test/type/protocol_composition.swift +++ b/test/type/protocol_composition.swift @@ -173,7 +173,7 @@ takesP1AndP2([Swift.AnyObject & P1 & P2]()) takesP1AndP2([AnyObject & protocol_composition.P1 & P2]()) takesP1AndP2([AnyObject & P1 & protocol_composition.P2]()) takesP1AndP2([DoesNotExist & P1 & P2]()) // expected-error {{use of unresolved identifier 'DoesNotExist'}} -takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}} expected-error {{cannot call value of non-function type 'Array<_>'}} +takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}} typealias T08 = P1 & inout P2 // expected-error {{'inout' may only be used on parameters}} typealias T09 = P1 & __shared P2 // expected-error {{'__shared' may only be used on parameters}} diff --git a/validation-test/stdlib/FixedPointDiagnostics.swift.gyb b/validation-test/stdlib/FixedPointDiagnostics.swift.gyb index d025940e14c..e091805af22 100644 --- a/validation-test/stdlib/FixedPointDiagnostics.swift.gyb +++ b/validation-test/stdlib/FixedPointDiagnostics.swift.gyb @@ -3,13 +3,13 @@ // RUN: %line-directive %t/main.swift -- %target-swift-frontend -typecheck -verify -swift-version 4.2 %t/main.swift func testUnaryMinusInUnsigned() { - var a: UInt8 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt8'}} expected-note * {{}} expected-warning * {{}} + var a: UInt8 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt8'}} expected-note * {{}} expected-warning * {{}} - var b: UInt16 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt16'}} expected-note * {{}} expected-warning * {{}} + var b: UInt16 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt16'}} expected-note * {{}} expected-warning * {{}} - var c: UInt32 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt32'}} expected-note * {{}} expected-warning * {{}} + var c: UInt32 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt32'}} expected-note * {{}} expected-warning * {{}} - var d: UInt64 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt64'}} expected-note * {{}} expected-warning * {{}} + var d: UInt64 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt64'}} expected-note * {{}} expected-warning * {{}} } // Int and UInt are not identical to any fixed-size integer type