Skip to content

Check for duplicate literal switch cases #11257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 31, 2017

Conversation

ffried
Copy link
Contributor

@ffried ffried commented Jul 29, 2017

This adds a check for duplicate literal switch cases. It covers string, integer and float literals. Corresponding tests were added as well.

According to @CodaFi this should resolve rdar://28301984.

// FIXME: Pessimistically using IEEEquad here is bad and we should
// actually figure out the bitwidth. But it's too early in Sema.
auto *FLE = cast<FloatLiteralExpr>(EL);
decltype(FloatLiteralCache)::iterator it;
Copy link
Contributor

@CodaFi CodaFi Jul 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was left over from an experiment, could you remove it?

case 2.5: break // expected-note {{first occurence of identical literal pattern is here}}
case 2.5: break // expected-warning {{literal value is already handled by previous pattern; is this intentional?}}
case 3.5: break
default: break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests look good, but could you add some extra duplicate cases in

  • Different positions e.g.
      case 1.5: break
      case 2.5: break //
      case 2.5: break //
      case 3.5: break
      case 2.5: break //
      default: break
  • Different levels of normalization:
      case 1.5: break
      case 1.5000: break
      case 1.500: break

///
      case 1
      case 0b1
      case 0x1

@CodaFi CodaFi requested a review from nkcsgexi July 29, 2017 17:21
@ffried ffried force-pushed the case_redundancy_check branch from fa3835b to 35d7377 Compare July 29, 2017 18:01
@CodaFi
Copy link
Contributor

CodaFi commented Jul 29, 2017

Xi should also take a look at this, but in the mean time

@swift-ci please smoke test.

"literal value is already handled by previous pattern; "
"is this intentional?",())
NOTE(redundant_particular_literal_case_here,none,
"first occurence of identical literal pattern is here", ())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: this should be "occurrence"

@@ -3773,6 +3773,11 @@ NOTE(missing_particular_case,none,
"add missing case: '%0'", (StringRef))
WARNING(redundant_particular_case,none,
"case is already handled by previous patterns; consider removing it",())
WARNING(redundant_particular_literal_case,none,
"literal value is already handled by previous pattern; "
"is this intentional?",())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: since there's no way to silence this warning without removing the redundant case, it's not actually possible for the user to answer the question "is this intentional?"--therefore, probably best to use the same wording as above (i.e. "consider removing it").

@ffried ffried force-pushed the case_redundancy_check branch from 35d7377 to 7eb7ac7 Compare July 30, 2017 08:06
@ffried
Copy link
Contributor Author

ffried commented Jul 30, 2017

@xwu done and done

@CodaFi
Copy link
Contributor

CodaFi commented Jul 31, 2017

@swift-ci please smoke test

@jrose-apple
Copy link
Contributor

I don't mind if this patch doesn't catch this case, but can you add a test like the following?

switch (x, y) {
case (0, 0): break
case (0, 1): break // not duplicate
case (1, 0): break // not duplicate
case (0, 0): break // duplicate
default: break
}

(and make sure it doesn't warn on the second and third cases)

@nkcsgexi
Copy link
Contributor

nkcsgexi commented Jul 31, 2017

Could you also add a test for matching several cases in single case statement like:

func main(_ a: Int) -> String {
  switch a {
  case 1, 2: return ""
  case 1, 2: return ""
  case 2, 3: return ""
  default: return ""
  }
}

SpaceEngine(TypeChecker &C, SwitchStmt *SS) : TC(C), Switch(SS) {}

bool checkRedundantLiteral(const Pattern *Pat, Expr *&PrevPattern) {
if (Pat->getKind() != PatternKind::Expr) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: could we put return false into the next line?

if (Pat->getKind() != PatternKind::Expr) return false;
auto *ExprPat = cast<ExprPattern>(Pat);
auto *MatchExpr = ExprPat->getSubExpr();
if (!MatchExpr || !isa<LiteralExpr>(MatchExpr)) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

This adds a check for duplicate literal switch cases. It covers string, integer and float literals. Corresponding tests were added as well.
@ffried ffried force-pushed the case_redundancy_check branch from 7eb7ac7 to e3fa190 Compare July 31, 2017 19:19
@ffried
Copy link
Contributor Author

ffried commented Jul 31, 2017

@jrose-apple Done. Added a test with a tuple for each of the literal types.

@ffried
Copy link
Contributor Author

ffried commented Jul 31, 2017

@nkcsgexi Done: Added test with multiple cases handled in a single case statement for each of the literal type.

Also done: Added a line break, as well as curly brackets to the two ifs.

@CodaFi
Copy link
Contributor

CodaFi commented Jul 31, 2017

@swift-ci please smoke test and merge

@swift-ci swift-ci merged commit 26a98b4 into swiftlang:master Jul 31, 2017
@ffried ffried deleted the case_redundancy_check branch August 1, 2017 05:12
@ianpartridge
Copy link
Contributor

ianpartridge commented Aug 1, 2017

With this PR, the following code prints a warning:

let i: Int = 1
switch i {
  case 0: print("0")
  case 1, -1: print("1 or -1")  // Warning: Literal value is already handled by previous pattern; consider removing it
  default: print("something else")
}

That doesn't look right to me...?

@ffried
Copy link
Contributor Author

ffried commented Aug 1, 2017

@ianpartridge Yep, that's definitively a bug. Will open another PR fixing this asap.

@CodaFi Should we revert this PR until then?

@ffried
Copy link
Contributor Author

ffried commented Aug 2, 2017

@ianpartridge #11286 should fix this.

@ianpartridge
Copy link
Contributor

I confirm it does - thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants