Skip to content

Commit e8f1784

Browse files
[Diagnostics] Adding member subscript tailored diagnostics fixit to string literals that matches a label of labeled tuples
1 parent 82fe84a commit e8f1784

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3457,7 +3457,7 @@ bool MissingMemberFailure::diagnoseForSubscriptMemberWithTupleBase() const {
34573457
// number only literals.
34583458
if (literal && NumericRegex.match(literal->getDigitsText())) {
34593459
unsigned int literalValue = 0;
3460-
literal->getDigitsText().getAsInteger(/*Radix*/ 0, literalValue);
3460+
literal->getDigitsText().getAsInteger(/*Radix=*/0, literalValue);
34613461

34623462
// Verify if the literal value is within the bounds of tuple elements.
34633463
if (!literal->isNegative() &&
@@ -3473,6 +3473,27 @@ bool MissingMemberFailure::diagnoseForSubscriptMemberWithTupleBase() const {
34733473
return true;
34743474
}
34753475
}
3476+
3477+
// For subscript access on tuple base types where the subscript index is a
3478+
// string literal expression which value matches a tuple element label,
3479+
// let's suggest tuple label access.
3480+
auto stringLiteral =
3481+
dyn_cast<StringLiteralExpr>(index->getSemanticsProvidingExpr());
3482+
if (stringLiteral && !stringLiteral->getValue().empty() &&
3483+
llvm::any_of(tupleType->getElements(), [&](TupleTypeElt element) {
3484+
return !element.getName().empty() &&
3485+
element.getName().str() == stringLiteral->getValue();
3486+
})) {
3487+
llvm::SmallString<16> dotAccess;
3488+
llvm::raw_svector_ostream OS(dotAccess);
3489+
OS << "." << stringLiteral->getValue();
3490+
3491+
emitDiagnostic(
3492+
diag::could_not_find_subscript_member_tuple_did_you_mean_use_dot,
3493+
baseType, stringLiteral->getValue())
3494+
.fixItReplace(index->getSourceRange(), OS.str());
3495+
return true;
3496+
}
34763497
}
34773498

34783499
emitDiagnostic(diag::could_not_find_subscript_member_tuple, baseType);

test/Constraints/members.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,8 +675,6 @@ let _ : [Int: Any] = [1 : .e] // expected-error {{type 'Any' has no member 'e'}}
675675
let _ : (Int, Any) = (1, .e) // expected-error {{type 'Any' has no member 'e'}}
676676
_ = (1, .e) // expected-error {{cannot infer contextual base in reference to member 'e'}}
677677

678-
// SR-13359
679-
680678
// SR-13359
681679
typealias Pair = (Int, Int)
682680
func testSR13359(_ pair: (Int, Int), _ alias: Pair, _ void: Void, labeled: (a: Int, b: Int)) {
@@ -713,4 +711,10 @@ func testSR13359(_ pair: (Int, Int), _ alias: Pair, _ void: Void, labeled: (a: I
713711
_ = labeled[0x00] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
714712
_ = labeled[0b00] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
715713

714+
// Suggesting use label access
715+
_ = labeled["a"] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; did you mean to use '.a'?}} {{14-19=.a}}
716+
_ = labeled["b"] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; did you mean to use '.b'?}} {{14-19=.b}}
717+
_ = labeled["c"] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
718+
_ = labeled[""] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
719+
716720
}

0 commit comments

Comments
 (0)