Skip to content

Commit a1987ec

Browse files
authored
Merge pull request #30283 from xedin/rdar-60185506
Revert "[ConstraintSystem] Make it possible to infer subtype bindings…
2 parents b2edf20 + 1352878 commit a1987ec

15 files changed

+82
-105
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,14 @@ void ConstraintSystem::inferTransitiveSupertypeBindings(
3030
llvm::SmallVector<Constraint *, 4> subtypeOf;
3131
// First, let's collect all of the `subtype` constraints associated
3232
// with this type variable.
33-
llvm::copy_if(
34-
bindings.Sources, std::back_inserter(subtypeOf),
35-
[&](const Constraint *constraint) -> bool {
36-
if (constraint->getKind() != ConstraintKind::Subtype &&
37-
constraint->getKind() != ConstraintKind::ArgumentConversion &&
38-
constraint->getKind() != ConstraintKind::OperatorArgumentConversion)
39-
return false;
40-
41-
auto rhs = simplifyType(constraint->getSecondType());
42-
return rhs->getAs<TypeVariableType>() == typeVar;
43-
});
33+
llvm::copy_if(bindings.Sources, std::back_inserter(subtypeOf),
34+
[&](const Constraint *constraint) -> bool {
35+
if (constraint->getKind() != ConstraintKind::Subtype)
36+
return false;
37+
38+
auto rhs = simplifyType(constraint->getSecondType());
39+
return rhs->getAs<TypeVariableType>() == typeVar;
40+
});
4441

4542
if (subtypeOf.empty())
4643
return;
@@ -635,7 +632,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
635632
continue;
636633

637634
literalBindings.push_back(
638-
{defaultType, AllowedBindingKind::Exact, constraint});
635+
{defaultType, AllowedBindingKind::Subtypes, constraint});
639636
continue;
640637
}
641638

@@ -661,7 +658,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
661658
if (!matched) {
662659
exactTypes.insert(defaultType->getCanonicalType());
663660
literalBindings.push_back(
664-
{defaultType, AllowedBindingKind::Exact, constraint});
661+
{defaultType, AllowedBindingKind::Subtypes, constraint});
665662
}
666663

667664
break;

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9221,8 +9221,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
92219221
// subscript, which requires changes to declaration to become mutable.
92229222
if (auto last = locator.last()) {
92239223
impact += (last->is<LocatorPathElt::FunctionResult>() ||
9224-
last->is<LocatorPathElt::SubscriptMember>() ||
9225-
last->is<LocatorPathElt::KeyPathDynamicMember>())
9224+
last->is<LocatorPathElt::SubscriptMember>())
92269225
? 1
92279226
: 0;
92289227
}

lib/Sema/CSStep.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -619,15 +619,6 @@ class TypeVariableStep final : public BindingStep<TypeVarBindingProducer> {
619619
/// Check whether attempting type variable binding choices should
620620
/// be stopped, because optimal solution has already been found.
621621
bool shouldStopAt(const TypeVariableBinding &choice) const override {
622-
if (CS.shouldAttemptFixes()) {
623-
// Let's always attempt default types inferred from literals
624-
// in diagnostic mode because that could lead to better
625-
// diagnostics if the problem is contextual like argument/parameter
626-
// conversion or collection element mismatch.
627-
if (choice.hasDefaultedProtocol())
628-
return false;
629-
}
630-
631622
// If we were able to solve this without considering
632623
// default literals, don't bother looking at default literals.
633624
return AnySolved && choice.hasDefaultedProtocol() &&

lib/Sema/ConstraintSystem.cpp

Lines changed: 38 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,61 +2776,45 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
27762776

27772777
auto &DE = cs.getASTContext().Diags;
27782778

2779-
llvm::SmallDenseMap<TypeVariableType *,
2780-
std::pair<GenericTypeParamType *, SourceLoc>, 4>
2781-
genericParams;
2782-
// Consider only representative type variables shared across
2783-
// all of the solutions.
2784-
for (auto *typeVar : cs.getTypeVariables()) {
2785-
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
2786-
auto *locator = typeVar->getImpl().getLocator();
2787-
auto *repr = cs.getRepresentative(typeVar);
2788-
// If representative is another generic parameter let's
2789-
// use its generic parameter type instead of originator's,
2790-
// but it's possible that generic parameter is equated to
2791-
// some other type e.g.
2792-
//
2793-
// func foo<T>(_: T) -> T {}
2794-
//
2795-
// In this case when reference to function `foo` is "opened"
2796-
// type variable representing `T` would be equated to
2797-
// type variable representing a result type of the reference.
2798-
if (auto *reprGP = repr->getImpl().getGenericParameter())
2799-
GP = reprGP;
2800-
2801-
genericParams[repr] = {GP, locator->getAnchor()->getLoc()};
2802-
}
2803-
}
2779+
llvm::SmallDenseMap<TypeVariableType *, SmallVector<Type, 4>> conflicts;
28042780

2805-
llvm::SmallDenseMap<std::pair<GenericTypeParamType *, SourceLoc>,
2806-
SmallVector<Type, 4>>
2807-
conflicts;
2781+
for (const auto &binding : solutions[0].typeBindings) {
2782+
auto *typeVar = binding.first;
28082783

2809-
for (const auto &entry : genericParams) {
2810-
auto *typeVar = entry.first;
2811-
auto GP = entry.second;
2784+
if (!typeVar->getImpl().getGenericParameter())
2785+
continue;
28122786

28132787
llvm::SmallSetVector<Type, 4> arguments;
2814-
for (const auto &solution : solutions) {
2815-
auto type = solution.typeBindings.lookup(typeVar);
2816-
// Contextual opaque result type is uniquely identified by
2817-
// declaration it's associated with, so we have to compare
2818-
// declarations instead of using pointer equality on such types.
2819-
if (auto *opaque = type->getAs<OpaqueTypeArchetypeType>()) {
2820-
auto *decl = opaque->getDecl();
2821-
arguments.remove_if([&](Type argType) -> bool {
2822-
if (auto *otherOpaque = argType->getAs<OpaqueTypeArchetypeType>()) {
2823-
return decl == otherOpaque->getDecl();
2788+
arguments.insert(binding.second);
2789+
2790+
if (!llvm::all_of(solutions.slice(1), [&](const Solution &solution) {
2791+
auto binding = solution.typeBindings.find(typeVar);
2792+
if (binding == solution.typeBindings.end())
2793+
return false;
2794+
2795+
// Contextual opaque result type is uniquely identified by
2796+
// declaration it's associated with, so we have to compare
2797+
// declarations instead of using pointer equality on such types.
2798+
if (auto *opaque =
2799+
binding->second->getAs<OpaqueTypeArchetypeType>()) {
2800+
auto *decl = opaque->getDecl();
2801+
arguments.remove_if([&](Type argType) -> bool {
2802+
if (auto *otherOpaque =
2803+
argType->getAs<OpaqueTypeArchetypeType>()) {
2804+
return decl == otherOpaque->getDecl();
2805+
}
2806+
return false;
2807+
});
28242808
}
2825-
return false;
2826-
});
2827-
}
28282809

2829-
arguments.insert(type);
2830-
}
2810+
arguments.insert(binding->second);
2811+
return true;
2812+
}))
2813+
continue;
28312814

2832-
if (arguments.size() > 1)
2833-
conflicts[GP].append(arguments.begin(), arguments.end());
2815+
if (arguments.size() > 1) {
2816+
conflicts[typeVar].append(arguments.begin(), arguments.end());
2817+
}
28342818
}
28352819

28362820
auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * {
@@ -2847,10 +2831,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
28472831

28482832
bool diagnosed = false;
28492833
for (auto &conflict : conflicts) {
2850-
SourceLoc loc;
2851-
GenericTypeParamType *GP;
2852-
2853-
std::tie(GP, loc) = conflict.first;
2834+
auto *typeVar = conflict.first;
2835+
auto *locator = typeVar->getImpl().getLocator();
28542836
auto conflictingArguments = conflict.second;
28552837

28562838
llvm::SmallString<64> arguments;
@@ -2875,8 +2857,10 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
28752857
},
28762858
[&OS] { OS << " vs. "; });
28772859

2878-
DE.diagnose(loc, diag::conflicting_arguments_for_generic_parameter, GP,
2879-
OS.str());
2860+
auto *anchor = locator->getAnchor();
2861+
DE.diagnose(anchor->getLoc(),
2862+
diag::conflicting_arguments_for_generic_parameter,
2863+
typeVar->getImpl().getGenericParameter(), OS.str());
28802864
diagnosed = true;
28812865
}
28822866

test/Constraints/array_literal.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ useDoubleList([1.0,2,3])
5050
useDoubleList([1.0,2.0,3.0])
5151

5252
useIntDict(["Niners" => 31, "Ravens" => 34])
53-
useIntDict(["Niners" => 31, "Ravens" => 34.0]) // expected-error{{cannot convert value of type 'Double' to expected element type 'Int'}}
53+
useIntDict(["Niners" => 31, "Ravens" => 34.0]) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Int'}}
5454
// <rdar://problem/22333090> QoI: Propagate contextual information in a call to operands
5555
useDoubleDict(["Niners" => 31, "Ravens" => 34.0])
5656
useDoubleDict(["Niners" => 31.0, "Ravens" => 34])

test/Constraints/closures.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,13 @@ extension Collection {
456456
}
457457
}
458458
func fn_r28909024(n: Int) {
459-
return (0..<10).r28909024 { // expected-error {{unexpected non-void return value in void function}} expected-note {{did you mean to add a return type?}}
459+
// FIXME(diagnostics): Unfortunately there is no easy way to fix this diagnostic issue at the moment
460+
// because the problem is related to ordering of the bindings - we'd attempt to bind result of the expression
461+
// to contextual type of `Void` which prevents solver from discovering correct types for range - 0..<10
462+
// (since both arguments are literal they are ranked lower than contextual type).
463+
//
464+
// Good diagnostic for this is - `unexpected non-void return value in void function`
465+
return (0..<10).r28909024 { // expected-error {{type of expression is ambiguous without more context}}
460466
_ in true
461467
}
462468
}

test/Constraints/default_literals.swift

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,3 @@ extension Int {
4242

4343

4444
var (div, mod) = (9 / 4, 9 % 4)
45-
46-
// rdar://problem/56212087 - solver fails to infer correct type for a generic parameter (Any vs. String)
47-
func test_transitive_inference_of_default_literal_types() {
48-
func foo<T: ExpressibleByStringLiteral>(_: String, _: T) -> T {
49-
fatalError()
50-
}
51-
52-
func bar(_: Any?) {}
53-
54-
bar(foo("", "")) // Ok
55-
}

test/Constraints/operator.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,14 @@ extension Int {
254254
}
255255

256256
_ = 1 ^^ 2 ^^ 3 * 4 // expected-error {{adjacent operators are in unordered precedence groups 'PowerPrecedence' and 'MultiplicationPrecedence'}}
257+
258+
// rdar://problem/60185506 - Ambiguity with Float comparison
259+
func rdar_60185506() {
260+
struct X {
261+
var foo: Float
262+
}
263+
264+
func test(x: X?) {
265+
let _ = (x?.foo ?? 0) <= 0.5 // Ok
266+
}
267+
}

test/Generics/deduction.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,8 @@ func foo() {
319319
let j = min(Int(3), Float(2.5)) // expected-error{{conflicting arguments to generic parameter 'T' ('Int' vs. 'Float')}}
320320
let k = min(A(), A()) // expected-error{{global function 'min' requires that 'A' conform to 'Comparable'}}
321321
let oi : Int? = 5
322-
let l = min(3, oi) // expected-error{{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
323-
// expected-note@-1 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
324-
// expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
322+
let l = min(3, oi) // expected-error{{global function 'min' requires that 'Int?' conform to 'Comparable'}}
323+
// expected-note@-1{{wrapped type 'Int' satisfies this requirement}}
325324
}
326325

327326
infix operator +&

test/Parse/omit_return.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ var fvs_stubMyOwnFatalError: () {
10051005
var fvs_forceTryExplicit: String {
10061006
get { "ok" }
10071007
set {
1008-
return try! failableIdentity("shucks") // expected-error {{unexpected non-void return value in void function}}
1008+
return try! failableIdentity("shucks") // expected-error {{cannot convert value of type 'String' to expected argument type '()'}}
10091009
}
10101010
}
10111011

test/attr/attr_dynamic_member_lookup.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,9 @@ func keypath_with_subscripts(_ arr: SubscriptLens<[Int]>,
600600

601601
func keypath_with_incorrect_return_type(_ arr: Lens<Array<Int>>) {
602602
for idx in 0..<arr.count {
603-
// expected-error@-1 {{cannot convert value of type 'Lens<Int>' to expected argument type 'Int'}}
603+
// expected-error@-1 {{protocol 'Sequence' requires that 'Lens<Int>' conform to 'Strideable'}}
604+
// expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'Lens<Int>'}}
605+
// expected-error@-3 {{referencing operator function '..<' on 'Comparable' requires that 'Lens<Int>' conform to 'Comparable'}}
604606
let _ = arr[idx]
605607
}
606608
}

test/decl/typealias/generic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ _ = A<String, Int>(a: "foo", // expected-error {{cannot convert value of type 'S
103103
b: 42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
104104
_ = B(a: 12, b: 42)
105105
_ = B(a: 12, b: 42 as Float)
106-
_ = B(a: "foo", b: 42) // expected-error {{conflicting arguments to generic parameter 'T1' ('String' vs. 'Int')}}
106+
_ = B(a: "foo", b: 42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
107107
_ = C(a: "foo", b: 42)
108108
_ = C(a: 42, // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
109109
b: 42)

test/expr/expressions.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -791,9 +791,8 @@ func testNilCoalescePrecedence(cond: Bool, a: Int?, r: ClosedRange<Int>?) {
791791

792792
// ?? should have lower precedence than range and arithmetic operators.
793793
let r1 = r ?? (0...42) // ok
794-
let r2 = (r ?? 0)...42 // not ok
795-
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'ClosedRange<Int>'}}
796-
// expected-error@-2 {{cannot convert value of type 'ClosedRange<Int>' to expected argument type 'Int'}}
794+
let r2 = (r ?? 0)...42 // not ok: expected-error 2 {{cannot convert value of type 'Int' to expected argument type 'ClosedRange<Int>'}}
795+
// expected-error@-1 {{referencing operator function '...' on 'Comparable' requires that 'ClosedRange<Int>' conform to 'Comparable'}}
797796
let r3 = r ?? 0...42 // parses as the first one, not the second.
798797

799798

test/type/protocol_composition.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ takesP1AndP2([Swift.AnyObject & P1 & P2]())
173173
takesP1AndP2([AnyObject & protocol_composition.P1 & P2]())
174174
takesP1AndP2([AnyObject & P1 & protocol_composition.P2]())
175175
takesP1AndP2([DoesNotExist & P1 & P2]()) // expected-error {{use of unresolved identifier 'DoesNotExist'}}
176-
takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}} expected-error {{cannot call value of non-function type 'Array<_>'}}
176+
takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}}
177177

178178
typealias T08 = P1 & inout P2 // expected-error {{'inout' may only be used on parameters}}
179179
typealias T09 = P1 & __shared P2 // expected-error {{'__shared' may only be used on parameters}}

validation-test/stdlib/FixedPointDiagnostics.swift.gyb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
// RUN: %line-directive %t/main.swift -- %target-swift-frontend -typecheck -verify -swift-version 4.2 %t/main.swift
44

55
func testUnaryMinusInUnsigned() {
6-
var a: UInt8 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt8'}} expected-note * {{}} expected-warning * {{}}
6+
var a: UInt8 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt8'}} expected-note * {{}} expected-warning * {{}}
77

8-
var b: UInt16 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt16'}} expected-note * {{}} expected-warning * {{}}
8+
var b: UInt16 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt16'}} expected-note * {{}} expected-warning * {{}}
99

10-
var c: UInt32 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt32'}} expected-note * {{}} expected-warning * {{}}
10+
var c: UInt32 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt32'}} expected-note * {{}} expected-warning * {{}}
1111

12-
var d: UInt64 = -(1) // expected-error {{cannot convert value of type 'Int' to specified type 'UInt64'}} expected-note * {{}} expected-warning * {{}}
12+
var d: UInt64 = -(1) // expected-error {{no '-' candidates produce the expected contextual result type 'UInt64'}} expected-note * {{}} expected-warning * {{}}
1313
}
1414

1515
// Int and UInt are not identical to any fixed-size integer type

0 commit comments

Comments
 (0)