Skip to content

Commit dab0e74

Browse files
bitjammertkremenek
authored andcommitted
Optional case lowercase improvements: 26481304 (#2715)
* [Sema] Properly diagnose Optional lowercase rename of None/Some Because Optional static var .None and static func .Some unavailable stubs that were put in the standard library aren't imported from C/Objective-C, the path that diagnoses renaming enum cases to lowercase isn't triggered. rdar://problem/26481304 * Optional case lowercase cleanups - Use == operator for identifier comparison - Add a test where the Optional isn't the top-level type rdar://problem/26481304
1 parent 23ba0ee commit dab0e74

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "TypeChecker.h"
1919
#include "GenericTypeResolver.h"
20+
#include "swift/Basic/StringExtras.h"
2021
#include "swift/AST/ExprHandle.h"
2122
#include "swift/AST/ASTWalker.h"
2223
#include "swift/AST/ASTVisitor.h"
@@ -1384,9 +1385,29 @@ bool TypeChecker::coercePatternToType(Pattern *&P, DeclContext *dc, Type type,
13841385
if (type->getAnyNominal())
13851386
elt = lookupEnumMemberElement(*this, dc, type, EEP->getName());
13861387
if (!elt) {
1387-
if (!type->is<ErrorType>())
1388+
if (!type->is<ErrorType>()) {
1389+
// Lowercasing of Swift.Optional's cases is handled in the
1390+
// standard library itself, not through the clang importer,
1391+
// so we have to do this check here. Additionally, .Some
1392+
// isn't a static VarDecl, so the existing mechanics in
1393+
// extractEnumElement won't work.
1394+
if (type->getAnyNominal() == Context.getOptionalDecl()) {
1395+
if (EEP->getName().str() == "None" ||
1396+
EEP->getName().str() == "Some") {
1397+
SmallString<4> Rename;
1398+
camel_case::toLowercaseWord(EEP->getName().str(), Rename);
1399+
diagnose(EEP->getLoc(), diag::availability_decl_unavailable_rename,
1400+
EEP->getName(), /*replaced*/false,
1401+
/*special kind*/0, Rename.str())
1402+
.fixItReplace(EEP->getLoc(), Rename.str());
1403+
1404+
}
1405+
return true;
1406+
}
1407+
13881408
diagnose(EEP->getLoc(), diag::enum_element_pattern_member_not_found,
13891409
EEP->getName().str(), type);
1410+
}
13901411
return true;
13911412
}
13921413
enumTy = type;

test/1_stdlib/OptionalRenames.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-parse-verify-swift
2+
3+
func getInt(x: Int) -> Int? {
4+
if x == 0 {
5+
return .None // expected-error {{'None' has been renamed to 'none'}} {{13-17=none}}
6+
}
7+
return .Some(1) // expected-error {{'Some' has been renamed to 'some'}} {{11-15=some}}
8+
}
9+
10+
let x = Optional.Some(1) // expected-error {{'Some' has been renamed to 'some'}} {{18-22=some}}
11+
12+
switch x {
13+
case .None: break // expected-error {{'None' has been renamed to 'none'}} {{9-13=none}}
14+
case .Some(let x): print(x) // expected-error {{'Some' has been renamed to 'some'}} {{9-13=some}}
15+
}
16+
17+
let optionals: (Int?, Int?) = (Optional.Some(1), .None)
18+
// expected-error@-1 {{'Some' has been renamed to 'some'}} {{41-45=some}}
19+
// expected-error@-2 {{'None' has been renamed to 'none'}} {{51-55=none}}
20+
21+
switch optionals {
22+
case (.None, .none): break // expected-error {{'None' has been renamed to 'none'}} {{10-14=none}}
23+
case (.Some(let left), .some(let right)): break // expected-error {{'Some' has been renamed to 'some'}} {{10-14=some}}
24+
default: break
25+
}
26+

0 commit comments

Comments
 (0)