Skip to content

Commit 82fe84a

Browse files
[Diagnostics] Restricting member subscript tailored diagnostics to literal within bounds of tuple elements
1 parent 061e69b commit 82fe84a

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3450,16 +3450,28 @@ bool MissingMemberFailure::diagnoseForSubscriptMemberWithTupleBase() const {
34503450
if (SE->getNumArguments() == 1) {
34513451
auto *literal =
34523452
dyn_cast<IntegerLiteralExpr>(index->getSemanticsProvidingExpr());
3453-
if (literal && !literal->isNegative()) {
3454-
llvm::SmallString<4> dotAccess;
3455-
llvm::raw_svector_ostream OS(dotAccess);
3456-
OS << "." << literal->getDigitsText();
34573453

3458-
emitDiagnostic(
3459-
diag::could_not_find_subscript_member_tuple_did_you_mean_use_dot,
3460-
baseType, literal->getDigitsText())
3461-
.fixItReplace(index->getSourceRange(), OS.str());
3462-
return true;
3454+
llvm::Regex NumericRegex("^[0-9]+$");
3455+
// Literal expressions may have other types of representations e.g. 0x01,
3456+
// 0b01. So let's make sure to only suggest this tailored literal fix-it for
3457+
// number only literals.
3458+
if (literal && NumericRegex.match(literal->getDigitsText())) {
3459+
unsigned int literalValue = 0;
3460+
literal->getDigitsText().getAsInteger(/*Radix*/ 0, literalValue);
3461+
3462+
// Verify if the literal value is within the bounds of tuple elements.
3463+
if (!literal->isNegative() &&
3464+
literalValue < tupleType->getNumElements()) {
3465+
llvm::SmallString<4> dotAccess;
3466+
llvm::raw_svector_ostream OS(dotAccess);
3467+
OS << "." << literalValue;
3468+
3469+
emitDiagnostic(
3470+
diag::could_not_find_subscript_member_tuple_did_you_mean_use_dot,
3471+
baseType, literal->getDigitsText())
3472+
.fixItReplace(index->getSourceRange(), OS.str());
3473+
return true;
3474+
}
34633475
}
34643476
}
34653477

test/Constraints/members.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,23 +675,42 @@ 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+
678680
// SR-13359
679681
typealias Pair = (Int, Int)
680682
func testSR13359(_ pair: (Int, Int), _ alias: Pair, _ void: Void, labeled: (a: Int, b: Int)) {
681683
_ = pair[0] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; did you mean to use '.0'?}} {{11-14=.0}}
684+
_ = pair[1] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; did you mean to use '.1'?}} {{11-14=.1}}
685+
_ = pair[2] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
686+
_ = pair[100] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
682687
_ = pair["strting"] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
683688
_ = pair[-1] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
684689
_ = pair[1, 1] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
685690
_ = void[0] // expected-error {{value of type 'Void' has no subscripts}}
691+
// Other representations of literals
692+
_ = pair[0x00] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
693+
_ = pair[0b00] // expected-error {{cannot access element using subscript for tuple type '(Int, Int)'; use '.' notation instead}} {{none}}
686694

687695
_ = alias[0] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); did you mean to use '.0'?}} {{12-15=.0}}
696+
_ = alias[1] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); did you mean to use '.1'?}} {{12-15=.1}}
697+
_ = alias[2] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
698+
_ = alias[100] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
688699
_ = alias["strting"] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
689700
_ = alias[-1] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
690701
_ = alias[1, 1] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
702+
_ = alias[0x00] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
703+
_ = alias[0b00] // expected-error {{cannot access element using subscript for tuple type 'Pair' (aka '(Int, Int)'); use '.' notation instead}} {{none}}
691704

692705
// Labeled tuple base
693706
_ = labeled[0] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; did you mean to use '.0'?}} {{14-17=.0}}
707+
_ = labeled[1] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; did you mean to use '.1'?}} {{14-17=.1}}
708+
_ = labeled[2] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
709+
_ = labeled[100] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
694710
_ = labeled["strting"] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
695711
_ = labeled[-1] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
696712
_ = labeled[1, 1] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
713+
_ = labeled[0x00] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
714+
_ = labeled[0b00] // expected-error {{cannot access element using subscript for tuple type '(a: Int, b: Int)'; use '.' notation instead}} {{none}}
715+
697716
}

0 commit comments

Comments
 (0)