Skip to content

Commit ad4d623

Browse files
authored
Merge pull request #27382 from theblixguy/fix/SR-11522
[CSApply] Don't diagnose a 'static let none' as ambiguous none unless its an enum type
2 parents 325204b + b3d7962 commit ad4d623

File tree

2 files changed

+137
-18
lines changed

2 files changed

+137
-18
lines changed

lib/Sema/CSApply.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,28 +2475,37 @@ namespace {
24752475
baseTyUnwrapped,
24762476
memberName,
24772477
defaultMemberLookupOptions);
2478-
2479-
// Lookup didn't find anything, so return
2478+
2479+
// Filter out any functions, instance members, enum cases with
2480+
// associated values or variables whose type does not match the
2481+
// contextual type.
2482+
results.filter([&](const LookupResultEntry entry, bool isOuter) {
2483+
if (auto member = entry.getValueDecl()) {
2484+
if (isa<FuncDecl>(member))
2485+
return false;
2486+
if (member->isInstanceMember())
2487+
return false;
2488+
if (auto EED = dyn_cast<EnumElementDecl>(member)) {
2489+
return !EED->hasAssociatedValues();
2490+
}
2491+
if (auto VD = dyn_cast<VarDecl>(member)) {
2492+
auto baseType = DSCE->getType()->lookThroughAllOptionalTypes();
2493+
return VD->getInterfaceType()->isEqual(baseType);
2494+
}
2495+
}
2496+
2497+
// Filter out anything that's not one of the above. We don't care
2498+
// if we have a typealias named 'none' or a struct/class named
2499+
// 'none'.
2500+
return false;
2501+
});
2502+
24802503
if (results.empty()) {
24812504
return;
24822505
}
24832506

24842507
if (auto member = results.front().getValueDecl()) {
2485-
// Lookup returned a member that is an instance member,
2486-
// so return
2487-
if (member->isInstanceMember()) {
2488-
return;
2489-
}
2490-
2491-
// Return if the member is an enum case w/ assoc values, as we only
2492-
// care (for now) about cases with no assoc values (like none)
2493-
if (auto EED = dyn_cast<EnumElementDecl>(member)) {
2494-
if (EED->hasAssociatedValues()) {
2495-
return;
2496-
}
2497-
}
2498-
2499-
// Emit a diagnostic with some fixits
2508+
// Emit a diagnostic with some fix-its
25002509
auto baseTyName = baseTy->getCanonicalType().getString();
25012510
auto baseTyUnwrappedName = baseTyUnwrapped->getString();
25022511
auto loc = DSCE->getLoc();

test/decl/enum/enumtest.swift

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,4 +441,114 @@ class C {}
441441
protocol P {}
442442

443443
enum E : C & P {}
444-
// expected-error@-1 {{inheritance from class-constrained protocol composition type 'C & P'}}
444+
// expected-error@-1 {{inheritance from class-constrained protocol composition type 'C & P'}}
445+
446+
// SR-11522
447+
448+
enum EnumWithStaticNone1 {
449+
case a
450+
static let none = 1
451+
}
452+
453+
enum EnumWithStaticNone2 {
454+
case a
455+
static let none = EnumWithStaticNone2.a
456+
}
457+
458+
enum EnumWithStaticNone3 {
459+
case a
460+
static let none = EnumWithStaticNone3.a
461+
var none: EnumWithStaticNone3 { return .a }
462+
}
463+
464+
enum EnumWithStaticNone4 {
465+
case a
466+
var none: EnumWithStaticNone4 { return .a }
467+
static let none = EnumWithStaticNone4.a
468+
}
469+
470+
enum EnumWithStaticFuncNone1 {
471+
case a
472+
static func none() -> Int { return 1 }
473+
}
474+
475+
enum EnumWithStaticFuncNone2 {
476+
case a
477+
static func none() -> EnumWithStaticFuncNone2 { return .a }
478+
}
479+
480+
/// Make sure we don't diagnose 'static let none = 1', but do diagnose 'static let none = TheEnum.anotherCase' ///
481+
482+
let _: EnumWithStaticNone1? = .none // Okay
483+
let _: EnumWithStaticNone2? = .none // expected-warning {{assuming you mean 'Optional<EnumWithStaticNone2>.none'; did you mean 'EnumWithStaticNone2.none' instead?}}
484+
// expected-note@-1 {{explicitly specify 'Optional' to silence this warning}}{{31-31=Optional}}
485+
// expected-note@-2 {{use 'EnumWithStaticNone2.none' instead}}{{31-31=EnumWithStaticNone2}}
486+
487+
/// Make sure we diagnose if we have both static and instance 'none' member regardless of source order ///
488+
489+
let _: EnumWithStaticNone3? = .none // expected-warning {{assuming you mean 'Optional<EnumWithStaticNone3>.none'; did you mean 'EnumWithStaticNone3.none' instead?}}
490+
// expected-note@-1 {{explicitly specify 'Optional' to silence this warning}}{{31-31=Optional}}
491+
// expected-note@-2 {{use 'EnumWithStaticNone3.none' instead}}{{31-31=EnumWithStaticNone3}}
492+
let _: EnumWithStaticNone4? = .none // expected-warning {{assuming you mean 'Optional<EnumWithStaticNone4>.none'; did you mean 'EnumWithStaticNone4.none' instead?}}
493+
// expected-note@-1 {{explicitly specify 'Optional' to silence this warning}}{{31-31=Optional}}
494+
// expected-note@-2 {{use 'EnumWithStaticNone4.none' instead}}{{31-31=EnumWithStaticNone4}}
495+
496+
/// Make sure we don't diagnose 'static func none -> T' ///
497+
498+
let _: EnumWithStaticFuncNone1? = .none // Okay
499+
let _: EnumWithStaticFuncNone2? = .none // Okay
500+
501+
/// Make sure we diagnose generic ones as well including conditional ones ///
502+
503+
enum GenericEnumWithStaticNone<T> {
504+
case a
505+
static var none: GenericEnumWithStaticNone<Int> { .a }
506+
}
507+
508+
let _: GenericEnumWithStaticNone<Int>? = .none // expected-warning {{assuming you mean 'Optional<GenericEnumWithStaticNone<Int>>.none'; did you mean 'GenericEnumWithStaticNone<Int>.none' instead?}}
509+
// expected-note@-1 {{explicitly specify 'Optional' to silence this warning}}{{42-42=Optional}}
510+
// expected-note@-2 {{use 'GenericEnumWithStaticNone<Int>.none' instead}}{{42-42=GenericEnumWithStaticNone<Int>}}
511+
let _: GenericEnumWithStaticNone<String>? = .none // Okay
512+
let _: GenericEnumWithStaticNone? = .none // FIXME(SR-11535): This should be diagnosed
513+
514+
enum GenericEnumWithoutNone<T> {
515+
case a
516+
}
517+
518+
extension GenericEnumWithoutNone where T == Int {
519+
static var none: GenericEnumWithoutNone<Int> { .a }
520+
}
521+
522+
let _: GenericEnumWithoutNone<Int>? = .none // expected-warning {{assuming you mean 'Optional<GenericEnumWithoutNone<Int>>.none'; did you mean 'GenericEnumWithoutNone<Int>.none' instead?}}
523+
// expected-note@-1 {{explicitly specify 'Optional' to silence this warning}}{{39-39=Optional}}
524+
// expected-note@-2 {{use 'GenericEnumWithoutNone<Int>.none' instead}}{{39-39=GenericEnumWithoutNone<Int>}}
525+
let _: GenericEnumWithoutNone<String>? = .none // Okay
526+
527+
// A couple of edge cases that shouldn't trigger the warning //
528+
529+
enum EnumWithStructNone {
530+
case bar
531+
struct none {}
532+
}
533+
534+
enum EnumWithTypealiasNone {
535+
case bar
536+
typealias none = EnumWithTypealiasNone
537+
}
538+
539+
enum EnumWithBothStructAndComputedNone {
540+
case bar
541+
struct none {}
542+
var none: EnumWithBothStructAndComputedNone { . bar }
543+
}
544+
545+
enum EnumWithBothTypealiasAndComputedNone {
546+
case bar
547+
typealias none = EnumWithBothTypealiasAndComputedNone
548+
var none: EnumWithBothTypealiasAndComputedNone { . bar }
549+
}
550+
551+
let _: EnumWithStructNone? = .none // Okay
552+
let _: EnumWithTypealiasNone? = .none // Okay
553+
let _: EnumWithBothStructAndComputedNone? = .none // Okay
554+
let _: EnumWithBothTypealiasAndComputedNone? = .none // Okay

0 commit comments

Comments
 (0)