Skip to content

Commit af9b68c

Browse files
author
Greg Titus
committed
Recheck UnresolvedSpecializeExpr after type variables are gone.
1 parent 0350023 commit af9b68c

File tree

5 files changed

+85
-10
lines changed

5 files changed

+85
-10
lines changed

lib/Sema/CSApply.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3225,8 +3225,37 @@ namespace {
32253225
}
32263226

32273227
Expr *visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) {
3228-
// Our specializations should have resolved the subexpr to the right type.
3229-
return expr->getSubExpr();
3228+
// Our specializations should have resolved the subexpr - recheck for
3229+
// validity.
3230+
auto subExpr = expr->getSubExpr();
3231+
while (1) {
3232+
if (auto apply = dyn_cast<ApplyExpr>(subExpr)) {
3233+
subExpr = apply->getFn();
3234+
} else if (auto ac = dyn_cast<AutoClosureExpr>(subExpr)) {
3235+
subExpr = ac->getSingleExpressionBody();
3236+
} else {
3237+
break;
3238+
}
3239+
}
3240+
3241+
if (auto tyExpr = dyn_cast<TypeExpr>(subExpr)) {
3242+
return subExpr;
3243+
}
3244+
3245+
auto diagnosis = diag::not_a_generic_definition;
3246+
if (auto declRef = dyn_cast<DeclRefExpr>(subExpr)) {
3247+
auto ty = declRef->getDecl()->getInterfaceType();
3248+
if (auto funTy = dyn_cast_or_null<AnyFunctionType>(ty)) {
3249+
if (!funTy->getOptGenericSignature().isNull()) {
3250+
diagnosis = diag::cannot_explicitly_specialize_generic_function;
3251+
}
3252+
}
3253+
}
3254+
auto &de = cs.getASTContext().Diags;
3255+
de.diagnose(subExpr->getLoc(), diagnosis);
3256+
de.diagnose(expr->getLAngleLoc(),
3257+
diag::while_parsing_as_left_angle_bracket);
3258+
return nullptr;
32303259
}
32313260

32323261
Expr *visitMemberRefExpr(MemberRefExpr *expr) {

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6602,6 +6602,7 @@ bool MissingGenericArgumentsFailure::diagnoseForAnchor(
66026602
bool MissingGenericArgumentsFailure::diagnoseParameter(
66036603
ASTNode anchor, GenericTypeParamType *GP) const {
66046604
auto &solution = getSolution();
6605+
auto &CS = solution.getConstraintSystem();
66056606
auto loc = ::getLoc(anchor);
66066607

66076608
auto *locator = getLocator();
@@ -6621,6 +6622,10 @@ bool MissingGenericArgumentsFailure::diagnoseParameter(
66216622
auto *NTD = castTo->getAnyNominal();
66226623
emitDiagnosticAt(loc, diag::unbound_generic_parameter_cast, GP,
66236624
NTD ? NTD->getDeclaredType() : castTo);
6625+
} else if (auto *USE = dyn_cast_or_null<UnresolvedSpecializeExpr>(
6626+
CS.getParentExpr(getAsExpr(anchor)))) {
6627+
emitDiagnosticAt(USE->getLoc(),
6628+
diag::cannot_explicitly_specialize_generic_function);
66246629
} else {
66256630
emitDiagnosticAt(loc, diag::unbound_generic_parameter, GP);
66266631
}

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,14 +1945,12 @@ namespace {
19451945
// We currently only support explicit specialization of generic types.
19461946
// FIXME: We could support explicit function specialization.
19471947
auto &de = CS.getASTContext().Diags;
1948-
if (baseTy->is<AnyFunctionType>()) {
1949-
de.diagnose(expr->getSubExpr()->getLoc(),
1950-
diag::cannot_explicitly_specialize_generic_function);
1951-
de.diagnose(expr->getLAngleLoc(),
1952-
diag::while_parsing_as_left_angle_bracket);
1953-
return Type();
1948+
if (auto funTy = dyn_cast<AnyFunctionType>(baseTy)) {
1949+
// Wait on diagnosis until after determining whether the func is
1950+
// generic or not
1951+
return baseTy;
19541952
}
1955-
1953+
19561954
if (AnyMetatypeType *meta = baseTy->getAs<AnyMetatypeType>()) {
19571955
auto *overloadLocator = CS.getConstraintLocator(expr->getSubExpr());
19581956
if (addSpecializationConstraint(overloadLocator,

test/Constraints/ambiguous_specialized_name_diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ func test() {
4444

4545
// FIXME(diagnostics): This should produce ambiguity diagnostic too
4646
S<Int>.staticFn()
47-
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
47+
// expected-error@-1 {{cannot explicitly specialize a generic function}}
4848
}

test/Sema/generic-arg-list.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
extension Int {
4+
func foo() -> Int {}
5+
var bar: Int {
6+
get {}
7+
}
8+
9+
func baz() -> Int {}
10+
func baz(_ x: Int = 0) -> Int {}
11+
12+
func gen<T>() -> T {} // expected-note {{in call to function 'gen()'}}
13+
}
14+
15+
// https://github.com/swiftlang/swift/issues/74857
16+
func test(i: Int) {
17+
let _ = i.foo<Int>() // expected-error {{cannot specialize a non-generic definition}}
18+
// expected-note@-1 {{while parsing this '<' as a type parameter bracket}}
19+
20+
let _ = i.gen<Int>() // expected-error {{cannot explicitly specialize a generic function}}
21+
22+
let _ = 0.foo<Int>() // expected-error {{cannot specialize a non-generic definition}}
23+
// expected-note@-1 {{while parsing this '<' as a type parameter bracket}}
24+
25+
// FIXME: These get parsed as postfix >, unless at the end of a block
26+
let _ = i.gen<Int> // expected-error {{'>' is not a postfix unary operator}}
27+
// expected-error@-1 {{binary operator '<' cannot be applied to operands of type '() -> ()' and '()'}}
28+
// expected-note@-2 {{overloads for '<' exist with these partially matching parameter lists: ((), ()), (AnyIndex, AnyIndex), (Character, Character), (Int, Int), (Int16, Int16), (Int32, Int32), (Int64, Int64), (Int8, Int8), (Never, Never), (ObjectIdentifier, ObjectIdentifier), (String, String), (String.Index, String.Index), (UInt, UInt), (UInt16, UInt16), (UInt32, UInt32), (UInt64, UInt64), (UInt8, UInt8), (Unicode.CanonicalCombiningClass, Unicode.CanonicalCombiningClass), (Unicode.Scalar, Unicode.Scalar), (_ValidUTF8Buffer.Index, _ValidUTF8Buffer.Index)}}
29+
let _ = i.baz<Int> // expected-error {{'>' is not a postfix unary operator}}
30+
// expected-error@-1 {{function produces expected type 'Int'; did you mean to call it with '()'?}}
31+
let _ = i.bar<Int> // expected-error {{'>' is not a postfix unary operator}}
32+
33+
let _ = 0.bar<Int> // expected-error {{cannot specialize a non-generic definition}}
34+
// expected-note@-1 {{while parsing this '<' as a type parameter bracket}}
35+
}
36+
37+
extension Bool {
38+
func foo<T>() -> T {}
39+
}
40+
41+
let _: () -> Bool = false.foo<Int> // expected-error {{cannot explicitly specialize a generic function}}
42+
// expected-note@-1 {{while parsing this '<' as a type parameter bracket}}
43+

0 commit comments

Comments
 (0)