Skip to content

Commit 875b203

Browse files
authored
Merge pull request #25111 from xedin/diag-conditional-req-in-self-5.1
[5.1][ConstraintSystem] Deplay opening generic requirements until after co…
2 parents 732bbf7 + befcf5f commit 875b203

File tree

7 files changed

+76
-15
lines changed

7 files changed

+76
-15
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,8 @@ Type ConstraintSystem::openFunctionType(
606606
OpenedTypeMap &replacements,
607607
DeclContext *innerDC,
608608
DeclContext *outerDC,
609-
bool skipProtocolSelfConstraint) {
609+
bool skipProtocolSelfConstraint,
610+
bool skipGenericRequirements) {
610611
Type type;
611612

612613
if (auto *genericFn = funcType->getAs<GenericFunctionType>()) {
@@ -616,7 +617,8 @@ Type ConstraintSystem::openFunctionType(
616617
genericFn->getGenericSignature(),
617618
skipProtocolSelfConstraint,
618619
locator,
619-
replacements);
620+
replacements,
621+
skipGenericRequirements);
620622

621623
// Transform the parameters and output type.
622624
llvm::SmallVector<AnyFunctionType::Param, 4> openedParams;
@@ -1072,7 +1074,8 @@ void ConstraintSystem::openGeneric(
10721074
GenericSignature *sig,
10731075
bool skipProtocolSelfConstraint,
10741076
ConstraintLocatorBuilder locator,
1075-
OpenedTypeMap &replacements) {
1077+
OpenedTypeMap &replacements,
1078+
bool skipGenericRequirements) {
10761079
if (sig == nullptr)
10771080
return;
10781081

@@ -1099,6 +1102,9 @@ void ConstraintSystem::openGeneric(
10991102

11001103
bindArchetypesFromContext(*this, outerDC, locatorPtr, replacements);
11011104

1105+
if (skipGenericRequirements)
1106+
return;
1107+
11021108
// Add the requirements as constraints.
11031109
openGenericRequirements(
11041110
outerDC, sig, skipProtocolSelfConstraint, locator,
@@ -1302,9 +1308,12 @@ ConstraintSystem::getTypeOfMemberReference(
13021308
}
13031309
}
13041310

1311+
// While opening member function type, let's delay opening requirements
1312+
// to allow contextual types to affect the situation.
13051313
openedType = openFunctionType(funcType, numRemovedArgumentLabels,
13061314
locator, replacements, innerDC, outerDC,
1307-
/*skipProtocolSelfConstraint=*/true);
1315+
/*skipProtocolSelfConstraint=*/true,
1316+
/*skipGenericRequirements=*/true);
13081317

13091318
if (!outerDC->getSelfProtocolDecl()) {
13101319
// Class methods returning Self as well as constructors get the
@@ -1348,6 +1357,19 @@ ConstraintSystem::getTypeOfMemberReference(
13481357
addSelfConstraint(*this, baseOpenedTy, selfObjTy, locator);
13491358
}
13501359

1360+
// Open generic requirements after self constraint has been
1361+
// applied and contextual types have been propagated. This
1362+
// helps diagnostics because instead of self type conversion
1363+
// failing we'll get a generic requirement constraint failure
1364+
// if mismatch is related to generic parameters which is much
1365+
// easier to diagnose.
1366+
if (auto *genericFn = funcType->getAs<GenericFunctionType>()) {
1367+
openGenericRequirements(
1368+
outerDC, genericFn->getGenericSignature(),
1369+
/*skipProtocolSelfConstraint=*/true, locator,
1370+
[&](Type type) { return openType(type, replacements); });
1371+
}
1372+
13511373
// Compute the type of the reference.
13521374
Type type;
13531375
if (!value->isInstanceMember() || isInstance) {

lib/Sema/ConstraintSystem.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,6 +2325,9 @@ class ConstraintSystem {
23252325
/// \param skipProtocolSelfConstraint Whether to skip the constraint on a
23262326
/// protocol's 'Self' type.
23272327
///
2328+
/// \param skipGenericRequirements Whether to skip opening generic
2329+
/// requirements asscoiated with given function type.
2330+
///
23282331
/// \returns The opened type, or \c type if there are no archetypes in it.
23292332
Type openFunctionType(
23302333
AnyFunctionType *funcType,
@@ -2333,16 +2336,18 @@ class ConstraintSystem {
23332336
OpenedTypeMap &replacements,
23342337
DeclContext *innerDC,
23352338
DeclContext *outerDC,
2336-
bool skipProtocolSelfConstraint);
2339+
bool skipProtocolSelfConstraint,
2340+
bool skipGenericRequirements = false);
23372341

2338-
/// Open the generic parameter list and its requirements, creating
2339-
/// type variables for each of the type parameters.
2342+
/// Open the generic parameter list and (if requested) its requirements,
2343+
/// creating type variables for each of the type parameters.
23402344
void openGeneric(DeclContext *innerDC,
23412345
DeclContext *outerDC,
23422346
GenericSignature *signature,
23432347
bool skipProtocolSelfConstraint,
23442348
ConstraintLocatorBuilder locator,
2345-
OpenedTypeMap &replacements);
2349+
OpenedTypeMap &replacements,
2350+
bool skipGenericRequirements = false);
23462351

23472352
/// Given generic signature open its generic requirements,
23482353
/// using substitution function, and record them in the

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,14 @@ static Optional<RequirementMatch> findMissingGenericRequirementForSolutionFix(
749749
Type selfTy = proto->getSelfInterfaceType().subst(reqSubMap);
750750
if (type->isEqual(selfTy)) {
751751
type = conformance->getType();
752+
753+
// e.g. `extension P where Self == C { func foo() { ... } }`
754+
// and `C` doesn't actually conform to `P`.
755+
if (type->isEqual(missingType)) {
756+
requirementKind = RequirementKind::Conformance;
757+
missingType = proto->getDeclaredType();
758+
}
759+
752760
if (auto agt = type->getAs<AnyGenericType>())
753761
type = agt->getDecl()->getDeclaredInterfaceType();
754762
return missingRequirementMatch(type);

test/Constraints/members.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,3 +627,30 @@ func rdar_50467583_and_50909555() {
627627
s[1] // expected-error {{static member 'subscript' cannot be used on instance of type 'S'}} {{5-6=S}}
628628
}
629629
}
630+
631+
// SR-9396 (rdar://problem/46427500) - Nonsensical error message related to constrained extensions
632+
struct SR_9396<A, B> {}
633+
634+
extension SR_9396 where A == Bool { // expected-note {{where 'A' = 'Int'}}
635+
func foo() {}
636+
}
637+
638+
func test_sr_9396(_ s: SR_9396<Int, Double>) {
639+
s.foo() // expected-error {{referencing instance method 'foo()' on 'SR_9396' requires the types 'Int' and 'Bool' be equivalent}}
640+
}
641+
642+
// rdar://problem/34770265 - Better diagnostic needed for constrained extension method call
643+
extension Dictionary where Key == String { // expected-note {{where 'Key' = 'Int'}}
644+
func rdar_34770265_key() {}
645+
}
646+
647+
extension Dictionary where Value == String { // expected-note {{where 'Value' = 'Int'}}
648+
func rdar_34770265_val() {}
649+
}
650+
651+
func test_34770265(_ dict: [Int: Int]) {
652+
dict.rdar_34770265_key()
653+
// expected-error@-1 {{referencing instance method 'rdar_34770265_key()' on 'Dictionary' requires the types 'Int' and 'String' be equivalent}}
654+
dict.rdar_34770265_val()
655+
// expected-error@-1 {{referencing instance method 'rdar_34770265_val()' on 'Dictionary' requires the types 'Int' and 'String' be equivalent}}
656+
}

test/Serialization/extension-of-typealias.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func test(x: Int) {
4141
x.addedMember()
4242
[x].addedMember()
4343
[x].addedMemberInt()
44-
([] as [Bool]).addedMemberInt() // expected-error {{'[Bool]' is not convertible to 'Array<Int>'}}
44+
([] as [Bool]).addedMemberInt() // expected-error {{referencing instance method 'addedMemberInt()' on 'Array' requires the types 'Bool' and 'Int' be equivalent}}
4545
}
4646

4747
#endif

test/decl/nested/type_in_type.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ protocol ExpressibleByDogLiteral {}
377377
struct Kitten : ExpressibleByCatLiteral {}
378378
struct Puppy : ExpressibleByDogLiteral {}
379379

380-
struct Claws<A: ExpressibleByCatLiteral> { // expected-note {{'A' declared as parameter to type 'Claws'}}
381-
struct Fangs<B: ExpressibleByDogLiteral> { }
380+
struct Claws<A: ExpressibleByCatLiteral> {
381+
struct Fangs<B: ExpressibleByDogLiteral> { } // expected-note {{where 'B' = 'NotADog'}}
382382
}
383383

384384
struct NotADog {}
@@ -401,9 +401,8 @@ func test() {
401401
// expected-error@-1 {{cannot convert value of type 'Claws<_>.Fangs<_>' to specified type 'Claws.Fangs<Puppy>'}}
402402
let _: Claws.Fangs<NotADog> = something()
403403
// expected-error@-1 {{generic parameter 'T' could not be inferred}} // FIXME: bad diagnostic
404-
_ = Claws.Fangs<NotADog>()
405-
// expected-error@-1 {{generic parameter 'A' could not be inferred}}
406-
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}}
404+
_ = Claws.Fangs<NotADog>() // TODO(diagnostics): There should be two errors here - "cannot infer A" and "NotADog conformance to ExpressibleByDogLiteral"
405+
// expected-error@-1 {{referencing initializer 'init()' on 'Claws.Fangs' requires that 'NotADog' conform to 'ExpressibleByDogLiteral'}}
407406
}
408407

409408
// https://bugs.swift.org/browse/SR-4379

test/decl/protocol/conforms/self.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ protocol HasDefault {
5050

5151
extension HasDefault where Self == SillyClass {
5252
func foo() {}
53-
// expected-note@-1 {{candidate has non-matching type '<Self> () -> ()'}}
53+
// expected-note@-1 {{candidate would match if 'SillyClass' conformed to 'HasDefault'}}
5454
}
5555

5656
extension SillyClass : HasDefault {}

0 commit comments

Comments
 (0)