Skip to content

Commit 91fd42d

Browse files
authored
Merge pull request #22701 from xedin/rdar-47980354
[CSDiagnostics] Imporove requirement diagnostics originating in conte…
2 parents e8f56e1 + a7c66ca commit 91fd42d

File tree

5 files changed

+52
-12
lines changed

5 files changed

+52
-12
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ ValueDecl *RequirementFailure::getDeclRef() const {
137137

138138
auto *anchor = getRawAnchor();
139139
auto *locator = cs.getConstraintLocator(anchor);
140+
141+
if (isFromContextualType()) {
142+
auto type = cs.getContextualType();
143+
assert(type);
144+
auto *alias = dyn_cast<TypeAliasType>(type.getPointer());
145+
return alias ? alias->getDecl() : type->getAnyGeneric();
146+
}
147+
140148
if (auto *AE = dyn_cast<CallExpr>(anchor)) {
141149
assert(isa<TypeExpr>(AE->getFn()));
142150
ConstraintLocatorBuilder ctor(locator);
@@ -190,6 +198,12 @@ GenericSignature *RequirementFailure::getSignature(ConstraintLocator *locator) {
190198
llvm_unreachable("Type requirement failure should always have signature");
191199
}
192200

201+
bool RequirementFailure::isFromContextualType() const {
202+
auto path = getLocator()->getPath();
203+
assert(!path.empty());
204+
return path.front().getKind() == ConstraintLocator::ContextualType;
205+
}
206+
193207
const DeclContext *RequirementFailure::getRequirementDC() const {
194208
// In case of conditional requirement failure, we don't
195209
// have to guess where the it comes from.

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ class RequirementFailure : public FailureDiagnostic {
236236
/// Determine whether this is a conditional requirement failure.
237237
bool isConditional() const { return bool(Conformance); }
238238

239+
/// Check whether this requirement comes from the contextual type
240+
/// that root expression is coerced/converted into.
241+
bool isFromContextualType() const;
242+
239243
/// Retrieve declaration contextual where current
240244
/// requirement has been introduced.
241245
const DeclContext *getRequirementDC() const;

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2466,7 +2466,8 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24662466
assert(!expr->isSemanticallyInOutExpr());
24672467

24682468
// Save the locator we're using for the expression.
2469-
Locator = cs.getConstraintLocator(expr);
2469+
Locator =
2470+
cs.getConstraintLocator(expr, ConstraintLocator::ContextualType);
24702471

24712472
// Collect constraints from the pattern.
24722473
initType = cs.generateConstraints(pattern, Locator);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
struct A<T> {}
4+
5+
extension A where T == Int32 { // expected-note 2 {{where 'T' = 'Int'}}
6+
struct B : ExpressibleByIntegerLiteral { // expected-note {{where 'T' = 'Int'}}
7+
typealias E = Int
8+
typealias IntegerLiteralType = Int
9+
10+
init(integerLiteral: IntegerLiteralType) {}
11+
}
12+
13+
typealias C = Int
14+
}
15+
16+
let _: A<Int>.B = 0
17+
// expected-error@-1 {{referencing struct 'B' on 'A' requires the types 'Int' and 'Int32' be equivalent}}
18+
let _: A<Int>.C = 0
19+
// expected-error@-1 {{referencing type alias 'C' on 'A' requires the types 'Int' and 'Int32' be equivalent}}
20+
let _: A<Int>.B.E = 0
21+
// expected-error@-1 {{referencing type alias 'E' on 'A.B' requires the types 'Int' and 'Int32' be equivalent}}

test/Generics/conditional_conformances_literals.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ func arraySameType() {
3030

3131
let _: SameType = arrayWorks
3232
let _: SameType = arrayFails
33-
// expected-error@-1 {{let 'arrayFails' requires the types 'Fails' and 'Works' be equivalent}}
33+
// expected-error@-1 {{protocol 'SameType' requires the types 'Fails' and 'Works' be equivalent}}
3434

3535
let _: SameType = [works] as [Works]
3636
let _: SameType = [fails] as [Fails]
37-
// expected-error@-1 {{generic struct 'Array' requires the types 'Fails' and 'Works' be equivalent}}
37+
// expected-error@-1 {{protocol 'SameType' requires the types 'Fails' and 'Works' be equivalent}}
3838

3939
let _: SameType = [works] as SameType
4040
let _: SameType = [fails] as SameType
@@ -55,11 +55,11 @@ func dictionarySameType() {
5555

5656
let _: SameType = dictWorks
5757
let _: SameType = dictFails
58-
// expected-error@-1 {{let 'dictFails' requires the types 'Fails' and 'Works' be equivalent}}
58+
// expected-error@-1 {{protocol 'SameType' requires the types 'Fails' and 'Works' be equivalent}}
5959

6060
let _: SameType = [0 : works] as [Int : Works]
6161
let _: SameType = [0 : fails] as [Int : Fails]
62-
// expected-error@-1 {{generic struct 'Dictionary' requires the types 'Fails' and 'Works' be equivalent}}
62+
// expected-error@-1 {{protocol 'SameType' requires the types 'Fails' and 'Works' be equivalent}}
6363

6464
let _: SameType = [0 : works] as SameType
6565
let _: SameType = [0 : fails] as SameType
@@ -76,15 +76,15 @@ func arrayConforms() {
7676

7777
let _: Conforms = [works]
7878
let _: Conforms = [fails]
79-
// expected-error@-1 {{generic struct 'Array' requires that 'Fails' conform to 'Conforms'}}
79+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
8080

8181
let _: Conforms = arrayWorks
8282
let _: Conforms = arrayFails
83-
// expected-error@-1 {{let 'arrayFails' requires that 'Fails' conform to 'Conforms'}}
83+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
8484

8585
let _: Conforms = [works] as [Works]
8686
let _: Conforms = [fails] as [Fails]
87-
// expected-error@-1 {{eneric struct 'Array' requires that 'Fails' conform to 'Conforms'}}
87+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
8888

8989
let _: Conforms = [works] as Conforms
9090
let _: Conforms = [fails] as Conforms
@@ -101,15 +101,15 @@ func dictionaryConforms() {
101101

102102
let _: Conforms = [0 : works]
103103
let _: Conforms = [0 : fails]
104-
// expected-error@-1 {{generic struct 'Dictionary' requires that 'Fails' conform to 'Conforms'}}
104+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
105105

106106
let _: Conforms = dictWorks
107107
let _: Conforms = dictFails
108-
// expected-error@-1 {{let 'dictFails' requires that 'Fails' conform to 'Conforms'}}
108+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
109109

110110
let _: Conforms = [0 : works] as [Int : Works]
111111
let _: Conforms = [0 : fails] as [Int : Fails]
112-
// expected-error@-1 {{generic struct 'Dictionary' requires that 'Fails' conform to 'Conforms'}}
112+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
113113

114114
let _: Conforms = [0 : works] as Conforms
115115
let _: Conforms = [0 : fails] as Conforms
@@ -123,7 +123,7 @@ func dictionaryConforms() {
123123
func combined() {
124124
let _: Conforms = [[0: [1 : [works]]]]
125125
let _: Conforms = [[0: [1 : [fails]]]]
126-
// expected-error@-1 {{generic struct 'Array' requires that 'Fails' conform to 'Conforms'}}
126+
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
127127

128128
// Needs self conforming protocols:
129129
let _: Conforms = [[0: [1 : [works]] as Conforms]]

0 commit comments

Comments
 (0)