Merge pull request #17019 from slavapestov/never-fixes-4.2
Fix various bogus unreachable code warnings [4.2]
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index ccc7adb..55154c3 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -3978,7 +3978,7 @@
getRepresentation() == SILFunctionTypeRepresentation::Thick;
}
- bool isNoReturnFunction(); // Defined in SILType.cpp
+ bool isNoReturnFunction() const; // Defined in SILType.cpp
class ABICompatibilityCheckResult {
friend class SILFunctionType;
diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp
index e2160c5..a219de5 100644
--- a/lib/SIL/SILType.cpp
+++ b/lib/SIL/SILType.cpp
@@ -450,8 +450,13 @@
return false;
}
-bool SILFunctionType::isNoReturnFunction() {
- return getDirectFormalResultsType().getSwiftRValueType()->isUninhabited();
+bool SILFunctionType::isNoReturnFunction() const {
+ for (unsigned i = 0, e = getNumResults(); i < e; ++i) {
+ if (getResults()[i].getType()->isUninhabited())
+ return true;
+ }
+
+ return false;
}
#ifndef NDEBUG
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 32b3919..5c667b8 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -4255,6 +4255,9 @@
// Pop the argument scope.
argScope.pop();
+ if (substFnType->isNoReturnFunction())
+ loc.markAutoGenerated();
+
// Explode the direct results.
SILFunctionConventions substFnConv(substFnType, SGM.M);
SmallVector<ManagedValue, 4> directResults;
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 1fd7dd5..d5df851 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -433,6 +433,8 @@
ManagedValue base,
MaterializedLValue materialized,
bool isFinal) override {
+ loc.markAutoGenerated();
+
assert(base.isLValue());
SGF.B.createEndAccess(loc, base.getValue(), /*abort*/ false);
}
@@ -1565,6 +1567,8 @@
ManagedValue base,
MaterializedLValue materialized,
bool isFinal) override {
+ loc.markAutoGenerated();
+
// If this is final, we can consume the owner (stored as
// 'base'). If it isn't, we actually need to retain it, because
// we've still got a release active.
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index eca2a26..53e2c37 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -3416,7 +3416,12 @@
F.setBare(IsBare);
SILLocation loc(witness.getDecl());
- FullExpr scope(Cleanups, CleanupLocation::get(loc));
+ loc.markAutoGenerated();
+
+ CleanupLocation cleanupLoc(witness.getDecl());
+ cleanupLoc.markAutoGenerated();
+
+ FullExpr scope(Cleanups, cleanupLoc);
FormalEvaluationScope formalEvalScope(*this);
auto witnessKind = getWitnessDispatchKind(witness);
@@ -3493,7 +3498,7 @@
SILValue reqtResultValue = resultPlanner.execute(witnessResultValue);
scope.pop();
- B.createReturn(CleanupLocation::get(loc), reqtResultValue);
+ B.createReturn(loc, reqtResultValue);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index a24236b..372f9b1 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -404,6 +404,9 @@
if (!S->hasResult())
// Void return.
SGF.Cleanups.emitBranchAndCleanups(SGF.ReturnDest, Loc);
+ else if (S->getResult()->getType()->isUninhabited())
+ // Never return.
+ SGF.emitIgnoredExpr(S->getResult());
else
SGF.emitReturnExpr(Loc, S->getResult());
}
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
index 751b88e..a10d284 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
@@ -423,6 +423,20 @@
if (BI->getModule().isNoReturnBuiltinOrIntrinsic(BI->getName()))
return BI;
}
+
+ // These appear in accessors for stored properties with uninhabited
+ // type. Since a type containing an uninhabited stored property is
+ // itself uninhabited, we treat these identically to fatalError(), etc.
+ if (auto *SEI = dyn_cast<StructExtractInst>(I)) {
+ if (SEI->getType().getASTType()->isUninhabited())
+ return SEI;
+ }
+
+ if (auto *SEAI = dyn_cast<StructElementAddrInst>(I)) {
+ if (SEAI->getType().getASTType()->isUninhabited())
+ return SEAI;
+ }
+
return nullptr;
}
diff --git a/test/SILOptimizer/specialize.sil b/test/SILOptimizer/specialize.sil
index 6a655d4..09aae2d 100644
--- a/test/SILOptimizer/specialize.sil
+++ b/test/SILOptimizer/specialize.sil
@@ -630,9 +630,7 @@
%6 = function_ref @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
%7 = partial_apply %6(%5) : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
%8 = apply [nothrow] %1<Never>(%2, %7) : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
- dealloc_stack %2 : $*Never
- %12 = tuple ()
- return %12 : $()
+ unreachable
} // end sil function 'testGenericClosureSpecialization'
// Test a specialization of a self-recursive generic closure.
diff --git a/test/SILOptimizer/unreachable_code.swift b/test/SILOptimizer/unreachable_code.swift
index af5db68..6e5051b 100644
--- a/test/SILOptimizer/unreachable_code.swift
+++ b/test/SILOptimizer/unreachable_code.swift
@@ -330,9 +330,14 @@
// We should not report unreachable code inside protocol witness thunks
protocol Fooable {
+ init()
func foo() -> Never
}
struct Foo: Fooable {
+ init() { // no-warning
+ fatalError()
+ }
+
func foo() -> Never { // no-warning
while true {}
}
@@ -340,13 +345,66 @@
// We should not report unreachable code inside vtable thunks
class Base {
+ required init(x: Int) {
+ fatalError()
+ }
+
func foo(x: Int) -> Never {
while true {}
}
}
class Derived : Base {
+ required init(x: Int?) {
+ fatalError()
+ }
+
override func foo(x: Int?) -> Never {
while true {}
}
}
+
+// Inout writeback
+func takesInOut(value: inout SillyStruct) -> Never {
+ while true {}
+}
+
+struct SillyStruct {
+ mutating func mutatingMethod() -> Never {
+ takesInOut(value: &self)
+ }
+}
+
+// This triggers various problems
+public func genericMightBeNever<R>(
+ _ body: () -> R) -> R {
+ while true {}
+
+}
+
+func sillyGenericExample() -> Never {
+ return genericMightBeNever {
+ return genericMightBeNever {
+ return fatalError()
+ }
+ }
+}
+
+// https://bugs.swift.org/browse/SR-7472
+
+protocol P {
+ static var theThing: Self { get }
+}
+
+extension Never : P {
+ static var theThing: Never { return fatalError() }
+}
+
+func test<T: P>(_ type: T.Type) -> T {
+ return type.theThing
+}
+
+func f(i: Int?) {
+ guard i != nil else { Never.theThing }
+ guard i != nil else { test(Never.self) }
+}