Skip to content

Commit 861f47f

Browse files
author
Josh Learn
authored
Merge pull request #38777 from guitard0g/unreachable-keypath
[diagnose-unreachable] Fix incorrect diagnostic on keypath creation
2 parents 54b88bf + a1bde15 commit 861f47f

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,7 +2692,6 @@ getRepresentativeAccessorForKeyPath(AbstractStorageDecl *storage) {
26922692
}
26932693

26942694
static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
2695-
SILLocation loc,
26962695
AbstractStorageDecl *property,
26972696
SubstitutionMap subs,
26982697
GenericEnvironment *genericEnv,
@@ -2759,6 +2758,8 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
27592758
auto name = Mangle::ASTMangler()
27602759
.mangleKeyPathGetterThunkHelper(property, genericSig, baseType,
27612760
subs, expansion);
2761+
auto loc = RegularLocation::getAutoGeneratedLocation();
2762+
27622763
SILGenFunctionBuilder builder(SGM);
27632764
auto thunk = builder.getOrCreateSharedFunction(
27642765
loc, name, signature, IsBare, IsNotTransparent,
@@ -2806,7 +2807,6 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
28062807
auto baseSubstValue = emitKeyPathRValueBase(subSGF, property,
28072808
loc, baseArg,
28082809
baseType, subs);
2809-
28102810
auto subscriptIndices =
28112811
loadIndexValuesForKeyPathComponent(subSGF, loc, property,
28122812
indexes, indexPtrArg);
@@ -2832,7 +2832,6 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
28322832
}
28332833

28342834
static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
2835-
SILLocation loc,
28362835
AbstractStorageDecl *property,
28372836
SubstitutionMap subs,
28382837
GenericEnvironment *genericEnv,
@@ -2907,6 +2906,7 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
29072906
auto name = Mangle::ASTMangler()
29082907
.mangleKeyPathSetterThunkHelper(property, genericSig, baseType,
29092908
subs, expansion);
2909+
auto loc = RegularLocation::getAutoGeneratedLocation();
29102910

29112911
SILGenFunctionBuilder builder(SGM);
29122912
auto thunk = builder.getOrCreateSharedFunction(
@@ -3536,13 +3536,13 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
35363536
// expected by the key path runtime.
35373537
auto id = getIdForKeyPathComponentComputedProperty(*this, var,
35383538
strategy);
3539-
auto getter = getOrCreateKeyPathGetter(*this, loc,
3539+
auto getter = getOrCreateKeyPathGetter(*this,
35403540
var, subs,
35413541
needsGenericContext ? genericEnv : nullptr,
35423542
expansion, {}, baseTy, componentTy);
35433543

35443544
if (isSettableInComponent()) {
3545-
auto setter = getOrCreateKeyPathSetter(*this, loc,
3545+
auto setter = getOrCreateKeyPathSetter(*this,
35463546
var, subs,
35473547
needsGenericContext ? genericEnv : nullptr,
35483548
expansion, {}, baseTy, componentTy);
@@ -3587,7 +3587,7 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
35873587
}
35883588

35893589
auto id = getIdForKeyPathComponentComputedProperty(*this, decl, strategy);
3590-
auto getter = getOrCreateKeyPathGetter(*this, loc,
3590+
auto getter = getOrCreateKeyPathGetter(*this,
35913591
decl, subs,
35923592
needsGenericContext ? genericEnv : nullptr,
35933593
expansion,
@@ -3596,7 +3596,7 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
35963596

35973597
auto indexPatternsCopy = getASTContext().AllocateCopy(indexPatterns);
35983598
if (isSettableInComponent()) {
3599-
auto setter = getOrCreateKeyPathSetter(*this, loc,
3599+
auto setter = getOrCreateKeyPathSetter(*this,
36003600
decl, subs,
36013601
needsGenericContext ? genericEnv : nullptr,
36023602
expansion,

test/SILGen/sil_locations.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,3 +417,29 @@ func testWhile() {
417417

418418

419419
}
420+
421+
// Check that the sil location of keypath getter/setter functions is
422+
// marked as autogenerated.
423+
struct Struct {
424+
var structProperty: InnerStruct {
425+
get { InnerStruct() }
426+
set(newStruct) { }
427+
}
428+
429+
struct InnerStruct {}
430+
}
431+
432+
func testKeyPathGetterSetterAutogen() -> Struct.InnerStruct {
433+
let kp = \Struct.structProperty
434+
var s = Struct()
435+
let innerS = Struct.InnerStruct()
436+
437+
s[keyPath: kp] = innerS
438+
return s[keyPath: kp]
439+
// Autogenerated keypath getter
440+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s13sil_locations6StructV14structProperty{{[_0-9a-zA-Z]*}}TK
441+
// CHECK: load {{.*}} loc "<compiler-generated>":0:0{{.*}}<invalid loc>:auto_gen
442+
// Autogenerated keypath setter
443+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s13sil_locations6StructV14structProperty{{[_0-9a-zA-Z]*}}Tk
444+
// CHECK: load {{.*}} loc "<compiler-generated>":0:0{{.*}}<invalid loc>:auto_gen
445+
}

test/SILOptimizer/diagnose_unreachable.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,3 +470,48 @@ extension Collection {
470470
}
471471
}
472472

473+
// rdar://80415811
474+
// Incorrect unreachable code diagnostic for keypath to empty Enum caused by
475+
// the generated keypath getter function having an uninhabited return type.
476+
// The getter function was previously tied to the source location of the
477+
// corresponding keypath expression, which caused it to be diagnosed as
478+
// user code. The getter and setter functions now have an autogenerated
479+
// source location so we should not expect an unreachable code warning until
480+
// the keypath expression is actually used.
481+
struct StructWithNeverProp {
482+
var property: Never {
483+
fatalError()
484+
}
485+
}
486+
487+
func keypathToEmptyEnum() -> Never {
488+
// Check that the generated keypath getter function for this property
489+
// does not trigger an unreachable code warning here.
490+
let kp = \StructWithNeverProp.property // no warning
491+
let s = StructWithNeverProp()
492+
// Emit a diagnostic here becase the keypath is actually used.
493+
let prop = s[keyPath: kp]
494+
// expected-warning@-1 {{will never be executed}} \
495+
// expected-note {{a call to a never-returning function}} \
496+
// expected-warning {{constant 'prop' inferred to have type 'Never', which is an enum with no cases}} \
497+
// expected-note {{add an explicit type annotation to silence this warning}}
498+
return prop
499+
}
500+
501+
struct OuterStruct {
502+
public let innerEnum: InnerEnum
503+
public enum InnerEnum { }
504+
}
505+
506+
@dynamicMemberLookup
507+
public enum DynamicLookupEnum {
508+
subscript<T>(dynamicMember keyPath: KeyPath<OuterStruct, T>) -> T {
509+
fatalError()
510+
}
511+
}
512+
513+
func keypathWithDynamicLookup() {
514+
// Check that we still don't diagnose the keypath getter as unreachable
515+
// when used in conjuction with a dynamicMemberLookup enum.
516+
let _ = \DynamicLookupEnum.innerEnum // no warning
517+
}

0 commit comments

Comments
 (0)