Skip to content

Commit f102876

Browse files
committed
Improve diagnostics for unbound archetypes coming from a type, to indicate
information about where the archetype was defined. Before: t.swift:6:17: error: generic parameter 'T' could not be inferred var a : Int = A.foo() ^ After: t.swift:6:17: error: generic parameter 'T' could not be inferred var a : Int = A.foo() ^ t.swift:2:8: note: 'T' declared as parameter to type 'A' struct A<T> { ^
1 parent 2910d54 commit f102876

File tree

5 files changed

+26
-8
lines changed

5 files changed

+26
-8
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ NOTE(note_call_to_initializer,none,
595595
NOTE(note_init_parameter,none,
596596
"in initialization of parameter %0", (Identifier))
597597

598+
598599
ERROR(missing_nullary_call,none,
599600
"function produces expected type %0; did you mean to call it with '()'?",
600601
(Type))
@@ -672,6 +673,8 @@ ERROR(unbound_generic_parameter,none,
672673
"generic parameter %0 could not be inferred", (Type))
673674
ERROR(unbound_generic_parameter_cast,none,
674675
"generic parameter %0 could not be inferred in cast to %1", (Type, Type))
676+
NOTE(archetype_declared_in_type,none,
677+
"%0 declared as parameter to type %1", (Type, Type))
675678

676679

677680
ERROR(string_index_not_integer,none,

lib/Sema/CSDiag.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4733,6 +4733,12 @@ static void diagnoseUnboundArchetype(Expr *overallExpr,
47334733
tc.diagnose(ECE->getLoc(), diag::unbound_generic_parameter_cast,
47344734
archetype, ECE->getCastTypeLoc().getType())
47354735
.highlight(ECE->getCastTypeLoc().getSourceRange());
4736+
4737+
// Emit a note specifying where this came from, if we can find it.
4738+
if (auto *ND = ECE->getCastTypeLoc().getType()
4739+
->getNominalOrBoundGenericNominal())
4740+
tc.diagnose(ND, diag::archetype_declared_in_type, archetype,
4741+
ND->getDeclaredType());
47364742
return;
47374743
}
47384744

@@ -4744,19 +4750,28 @@ static void diagnoseUnboundArchetype(Expr *overallExpr,
47444750
// If we have an anchor, drill into it to emit a
47454751
// "note: archetype declared here".
47464752
if (!anchor) return;
4747-
4753+
4754+
4755+
if (auto TE = dyn_cast<TypeExpr>(anchor)) {
4756+
if (auto *ND = TE->getInstanceType()->getNominalOrBoundGenericNominal())
4757+
tc.diagnose(ND, diag::archetype_declared_in_type, archetype,
4758+
ND->getDeclaredType());
4759+
return;
4760+
}
4761+
47484762
ConcreteDeclRef resolved;
47494763

47504764
// Simple case: direct reference to a declaration.
47514765
if (auto dre = dyn_cast<DeclRefExpr>(anchor))
47524766
resolved = dre->getDeclRef();
47534767

47544768
// Simple case: direct reference to a declaration.
4755-
if (auto mre = dyn_cast<MemberRefExpr>(anchor))
4756-
resolved = mre->getMember();
4769+
if (auto MRE = dyn_cast<MemberRefExpr>(anchor))
4770+
resolved = MRE->getMember();
47574771

4758-
if (auto ctorRef = dyn_cast<OtherConstructorDeclRefExpr>(anchor))
4759-
resolved = ctorRef->getDeclRef();
4772+
if (auto OCDRE = dyn_cast<OtherConstructorDeclRefExpr>(anchor))
4773+
resolved = OCDRE->getDeclRef();
4774+
47604775

47614776
// We couldn't resolve the locator to a declaration, so we're done.
47624777
if (!resolved)

test/Constraints/construction.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ enum Z {
2020
init(_ x: Int, _ y: Int) { self = .point(x, y) }
2121
}
2222

23-
enum Optional<T> {
23+
enum Optional<T> { // expected-note {{'T' declared as parameter to type 'Optional'}}
2424
case none
2525
case value(T)
2626

test/Constraints/generics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func r22509125<T>(a : T?) { // expected-note {{in call to function 'r22509125'}}
185185

186186

187187
// <rdar://problem/24267414> QoI: error: cannot convert value of type 'Int' to specified type 'Int'
188-
struct R24267414<T> {
188+
struct R24267414<T> { // expected-note {{'T' declared as parameter to type 'R24267414'}}
189189
static func foo() -> Int {}
190190
}
191191
var _ : Int = R24267414.foo() // expected-error {{generic parameter 'T' could not be inferred}}

test/Constraints/incomplete_function_ref.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %target-parse-verify-swift
22

3-
struct MyCollection<Element> {
3+
struct MyCollection<Element> { // expected-note {{'Element' declared as parameter to type 'MyCollection'}}
44
func map<T>(transform: (Element) -> T) -> MyCollection<T> {
55
fatalError("implement")
66
}

0 commit comments

Comments
 (0)