Skip to content

Commit ddc51c5

Browse files
committed
AST: Implement SE-0102, introducing new semantics for Never alongside @NoReturn
No migrator support yet, and the code for @NoReturn is still in place.
1 parent d118cd0 commit ddc51c5

File tree

61 files changed

+1293
-1401
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1293
-1401
lines changed

include/swift/AST/Builtins.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,10 @@ BUILTIN_MISC_OPERATION(ZeroInitializer, "zeroInitializer", "n", Special)
431431
/// once has type (Builtin.RawPointer, () -> ())
432432
BUILTIN_MISC_OPERATION(Once, "once", "", Special)
433433

434-
/// unreachable has type @noreturn () -> ()
434+
/// unreachable has type () -> Never
435435
BUILTIN_MISC_OPERATION(Unreachable, "unreachable", "", Special)
436436

437-
/// conditionallyUnreachable has type @noreturn () -> ()
437+
/// conditionallyUnreachable has type () -> Never
438438
BUILTIN_MISC_OPERATION(CondUnreachable, "conditionallyUnreachable", "", Special)
439439

440440
/// DestroyArray has type (T.Type, Builtin.RawPointer, Builtin.Word) -> ()

include/swift/AST/DiagnosticsSIL.def

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,6 @@ ERROR(assignment_to_immutable_value,none,
179179
ERROR(missing_return,none,
180180
"missing return in a %select{function|closure}1 expected to return %0",
181181
(Type, unsigned))
182-
ERROR(return_from_noreturn,none,
183-
"return from a 'noreturn' function", ())
184182
ERROR(non_exhaustive_switch,none,
185183
"switch must be exhaustive, consider adding a default clause", ())
186184
ERROR(guard_body_must_not_fallthrough,none,
@@ -190,7 +188,7 @@ WARNING(unreachable_code,none, "will never be executed", ())
190188
NOTE(unreachable_code_branch,none,
191189
"condition always evaluates to %select{false|true}0", (bool))
192190
NOTE(call_to_noreturn_note,none,
193-
"a call to a noreturn function", ())
191+
"a call to a never-returning function", ())
194192
WARNING(unreachable_code_after_stmt,none,
195193
"code after '%select{return|break|continue|throw}0' will never "
196194
"be executed", (unsigned))

lib/AST/Builtins.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,7 @@ static ValueDecl *getVoidErrorOperation(ASTContext &Context, Identifier Id) {
713713
static ValueDecl *getUnexpectedErrorOperation(ASTContext &Context,
714714
Identifier Id) {
715715
return getBuiltinFunction(Id, {Context.getExceptionType()},
716-
TupleType::getEmpty(Context),
717-
AnyFunctionType::ExtInfo().withIsNoReturn());
716+
Context.getNeverType());
718717
}
719718

720719
static ValueDecl *getCmpXChgOperation(ASTContext &Context, Identifier Id,
@@ -974,10 +973,8 @@ static ValueDecl *getIntToFPWithOverflowOperation(ASTContext &Context,
974973

975974
static ValueDecl *getUnreachableOperation(ASTContext &Context,
976975
Identifier Id) {
977-
// @noreturn () -> ()
978-
auto VoidTy = Context.TheEmptyTupleType;
979-
return getBuiltinFunction(Id, {}, VoidTy,
980-
AnyFunctionType::ExtInfo().withIsNoReturn(true));
976+
// () -> Never
977+
return getBuiltinFunction(Id, {}, Context.getNeverType());
981978
}
982979

983980
static ValueDecl *getOnceOperation(ASTContext &Context,
@@ -1192,7 +1189,7 @@ getSwiftFunctionTypeForIntrinsic(unsigned iid, ArrayRef<Type> TypeArgs,
11921189
Info = FunctionType::ExtInfo();
11931190
if (attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
11941191
llvm::Attribute::NoReturn))
1195-
Info = Info.withIsNoReturn(true);
1192+
ResultTy = Context.getNeverType();
11961193

11971194
return true;
11981195
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3428,10 +3428,6 @@ namespace {
34283428

34293429
void finishFuncDecl(const clang::FunctionDecl *decl,
34303430
AbstractFunctionDecl *result) {
3431-
if (decl->isNoReturn())
3432-
result->getAttrs().add(new (Impl.SwiftContext)
3433-
NoReturnAttr(/*IsImplicit=*/false));
3434-
34353431
// Keep track of inline function bodies so that we can generate
34363432
// IR from them using Clang's IR generator.
34373433
if ((decl->isInlined() || decl->hasAttr<clang::AlwaysInlineAttr>() ||

lib/ClangImporter/ImportType.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,12 +1518,12 @@ importFunctionType(DeclContext *dc,
15181518
if (!parameterList)
15191519
return Type();
15201520

1521-
FunctionType::ExtInfo extInfo;
1522-
extInfo = extInfo.withIsNoReturn(isNoReturn);
1521+
if (isNoReturn)
1522+
swiftResultTy = SwiftContext.getNeverType();
15231523

15241524
// Form the function type.
15251525
auto argTy = parameterList->getType(SwiftContext);
1526-
return FunctionType::get(argTy, swiftResultTy, extInfo);
1526+
return FunctionType::get(argTy, swiftResultTy);
15271527
}
15281528

15291529
ParameterList *ClangImporter::Implementation::importFunctionParameterList(
@@ -2430,9 +2430,13 @@ Type ClangImporter::Implementation::importMethodType(
24302430

24312431
// Form the parameter list.
24322432
*bodyParams = ParameterList::create(SwiftContext, swiftParams);
2433-
2433+
2434+
if (isNoReturn) {
2435+
origSwiftResultTy = SwiftContext.getNeverType();
2436+
swiftResultTy = SwiftContext.getNeverType();
2437+
}
2438+
24342439
FunctionType::ExtInfo extInfo;
2435-
extInfo = extInfo.withIsNoReturn(isNoReturn);
24362440

24372441
if (errorInfo) {
24382442
foreignErrorInfo = getForeignErrorInfo(*errorInfo, errorParamType,

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4063,7 +4063,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
40634063
Options.setArchetypeSelfTransform(transformType, VD->getDeclContext());
40644064
Options.PrintDefaultParameterPlaceholder = false;
40654065
Options.PrintImplicitAttrs = false;
4066-
Options.ExclusiveAttrList.push_back(DAK_NoReturn);
4066+
Options.SkipAttributes = true;
40674067
Options.PrintOverrideKeyword = false;
40684068
Options.PrintPropertyAccessors = false;
40694069
VD->print(Printer, Options);
@@ -4141,7 +4141,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41414141
llvm::raw_svector_ostream OS(DeclStr);
41424142
PrintOptions Options;
41434143
Options.PrintImplicitAttrs = false;
4144-
Options.ExclusiveAttrList.push_back(DAK_NoReturn);
4144+
Options.SkipAttributes = true;
41454145
Options.PrintDefaultParameterPlaceholder = false;
41464146
CD->print(OS, Options);
41474147
}

lib/SIL/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
797797
// Check that if the apply is of a noreturn callee, make sure that an
798798
// unreachable is the next instruction.
799799
if (AI->getModule().getStage() == SILStage::Raw ||
800-
!AI->getCallee()->getType().getAs<SILFunctionType>()->isNoReturn())
800+
!AI->isCalleeNoReturn())
801801
return;
802802
require(isa<UnreachableInst>(std::next(SILBasicBlock::iterator(AI))),
803803
"No return apply without an unreachable as a next instruction.");

lib/SILOptimizer/Analysis/AliasAnalysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,9 @@ AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
641641
}
642642

643643
bool AliasAnalysis::canApplyDecrementRefCount(FullApplySite FAS, SILValue Ptr) {
644-
// Treat applications of @noreturn functions as decrementing ref counts. This
644+
// Treat applications of no-return functions as decrementing ref counts. This
645645
// causes the apply to become a sink barrier for ref count increments.
646-
if (FAS.getCallee()->getType().getAs<SILFunctionType>()->isNoReturn())
646+
if (FAS.isCalleeNoReturn())
647647
return true;
648648

649649
/// If the pointer cannot escape to the function we are done.

lib/SILOptimizer/Analysis/CFG.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ findAllNonFailureExitBBs(SILFunction *F,
8181
// non-failure exit BB. Add it to our list and continue.
8282
auto PrevIter = std::prev(SILBasicBlock::iterator(TI));
8383
if (auto *AI = dyn_cast<ApplyInst>(&*PrevIter)) {
84-
if (AI->getSubstCalleeType()->isNoReturn() &&
84+
if (AI->isCalleeNoReturn() &&
8585
!isTrapNoReturnFunction(AI)) {
8686
BBs.push_back(&BB);
8787
continue;

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ void ClosureSpecCloner::populateCloned() {
673673
auto NoReturnApply = FullApplySite::isa(&*PrevIter);
674674

675675
// We insert the release value right before the no return apply so that if
676-
// the partial apply is passed into the @noreturn function as an @owned
676+
// the partial apply is passed into the no-return function as an @owned
677677
// value, we will retain the partial apply before we release it and
678678
// potentially eliminate it.
679679
Builder.setInsertionPoint(NoReturnApply.getInstruction());

lib/SILOptimizer/IPO/EagerSpecializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ void EagerDispatch::emitDispatchTo(SILFunction *NewFunc) {
301301
Result = Builder.createTuple(Loc, VoidTy, { });
302302

303303
// Function marked as @NoReturn must be followed by 'unreachable'.
304-
if (NewFunc->getLoweredFunctionType()->isNoReturn())
304+
if (NewFunc->isNoReturnFunction())
305305
Builder.createUnreachable(Loc);
306306
else {
307307
auto GenResultTy = GenericFunc->mapTypeIntoContext(

lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,9 @@ static void diagnoseMissingReturn(const UnreachableInst *UI,
4646
llvm_unreachable("unhandled case in MissingReturn");
4747
}
4848

49-
bool isNoReturn = F->getLoweredFunctionType()->isNoReturn();
50-
5149
// No action required if the function returns 'Void' or that the
5250
// function is marked 'noreturn'.
53-
if (ResTy->isVoid() || isNoReturn)
51+
if (ResTy->isVoid() || F->isNoReturnFunction())
5452
return;
5553

5654
SILLocation L = UI->getLoc();
@@ -100,24 +98,6 @@ static void diagnoseUnreachable(const SILInstruction *I,
10098
}
10199
}
102100

103-
static void diagnoseReturn(const SILInstruction *I, ASTContext &Context) {
104-
auto *TI = dyn_cast<TermInst>(I);
105-
if (!TI || !(isa<BranchInst>(TI) || isa<ReturnInst>(TI)))
106-
return;
107-
108-
const SILBasicBlock *BB = TI->getParent();
109-
const SILFunction *F = BB->getParent();
110-
111-
// Warn if we reach a return inside a noreturn function.
112-
if (F->getLoweredFunctionType()->isNoReturn()) {
113-
SILLocation L = TI->getLoc();
114-
if (L.is<ReturnLocation>())
115-
diagnose(Context, L.getSourceLoc(), diag::return_from_noreturn);
116-
if (L.is<ImplicitReturnLocation>())
117-
diagnose(Context, L.getSourceLoc(), diag::return_from_noreturn);
118-
}
119-
}
120-
121101
/// \brief Issue diagnostics whenever we see Builtin.static_report(1, ...).
122102
static void diagnoseStaticReports(const SILInstruction *I,
123103
SILModule &M) {
@@ -151,7 +131,6 @@ class EmitDFDiagnostics : public SILFunctionTransform {
151131
for (auto &BB : *getFunction())
152132
for (auto &I : BB) {
153133
diagnoseUnreachable(&I, M.getASTContext());
154-
diagnoseReturn(&I, M.getASTContext());
155134
diagnoseStaticReports(&I, M);
156135
}
157136
}

lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ static void setOutsideBlockUsesToUndef(SILInstruction *I) {
413413

414414
static SILInstruction *getAsCallToNoReturn(SILInstruction *I) {
415415
if (auto *AI = dyn_cast<ApplyInst>(I))
416-
if (AI->getOrigCalleeType()->isNoReturn())
416+
if (AI->isCalleeNoReturn())
417417
return AI;
418418

419419
if (auto *BI = dyn_cast<BuiltinInst>(I)) {
@@ -448,7 +448,7 @@ static SILInstruction *getPrecedingCallToNoReturn(SILBasicBlock &BB) {
448448
// The predecessor must be the normal edge from a try_apply
449449
// that invokes a noreturn function.
450450
if (auto TAI = dyn_cast<TryApplyInst>((*i)->getTerminator())) {
451-
if (TAI->getOrigCalleeType()->isNoReturn() &&
451+
if (TAI->isCalleeNoReturn() &&
452452
TAI->isNormalSuccessorRef(i.getSuccessorRef())) {
453453
if (!first) first = TAI;
454454
continue;

lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
499499
}
500500

501501
// Set up the return results.
502-
if (NewF->getLoweredFunctionType()->isNoReturn()) {
502+
if (NewF->isNoReturnFunction()) {
503503
Builder.createUnreachable(Loc);
504504
} else {
505505
Builder.createReturn(Loc, ReturnValue);

stdlib/public/core/Assert.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@ public func assertionFailure(
123123
/// * In -Ounchecked builds, the optimizer may assume that this
124124
/// function will never be called. Failure to satisfy that assumption
125125
/// is a serious programming error.
126-
@_transparent @noreturn
126+
@_transparent
127127
public func preconditionFailure(
128128
_ message: @autoclosure () -> String = String(),
129129
file: StaticString = #file, line: UInt = #line
130-
) {
130+
) -> Never {
131131
// Only check in debug and release mode. In release mode just trap.
132132
if _isDebugAssertConfiguration() {
133133
_assertionFailed("fatal error", message(), file, line,
@@ -139,11 +139,11 @@ public func preconditionFailure(
139139
}
140140

141141
/// Unconditionally print a `message` and stop execution.
142-
@_transparent @noreturn
142+
@_transparent
143143
public func fatalError(
144144
_ message: @autoclosure () -> String = String(),
145145
file: StaticString = #file, line: UInt = #line
146-
) {
146+
) -> Never {
147147
_assertionFailed("fatal error", message(), file, line,
148148
flags: _fatalErrorFlags())
149149
}
@@ -171,11 +171,11 @@ public func _precondition(
171171
}
172172
}
173173

174-
@_transparent @noreturn
174+
@_transparent
175175
public func _preconditionFailure(
176176
_ message: StaticString = StaticString(),
177177
file: StaticString = #file, line: UInt = #line
178-
) {
178+
) -> Never {
179179
_precondition(false, message, file: file, line: line)
180180
_conditionallyUnreachable()
181181
}
@@ -222,10 +222,11 @@ public func _debugPrecondition(
222222
}
223223
}
224224

225-
@_transparent @noreturn
225+
@_transparent
226226
public func _debugPreconditionFailure(
227227
_ message: StaticString = StaticString(),
228-
file: StaticString = #file, line: UInt = #line) {
228+
file: StaticString = #file, line: UInt = #line
229+
) -> Never {
229230
if _isDebugAssertConfiguration() {
230231
_precondition(false, message, file: file, line: line)
231232
}
@@ -251,11 +252,11 @@ public func _sanityCheck(
251252
#endif
252253
}
253254

254-
@_transparent @noreturn
255+
@_transparent
255256
public func _sanityCheckFailure(
256257
_ message: StaticString = StaticString(),
257258
file: StaticString = #file, line: UInt = #line
258-
) {
259+
) -> Never {
259260
_sanityCheck(false, message, file: file, line: line)
260261
_conditionallyUnreachable()
261262
}

stdlib/public/core/AssertCommon.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ func _reportUnimplementedInitializer(
109109
/// This function should not be inlined because it is cold and inlining just
110110
/// bloats code.
111111
@_versioned
112-
@noreturn @inline(never)
112+
@inline(never)
113113
@_semantics("stdlib_binary_only")
114114
func _assertionFailed(
115115
// FIXME(ABI): add argument labels to conform to API guidelines.
116116
_ prefix: StaticString, _ message: StaticString,
117117
_ file: StaticString, _ line: UInt,
118118
flags: UInt32
119-
) {
119+
) -> Never {
120120
prefix.withUTF8Buffer {
121121
(prefix) -> Void in
122122
message.withUTF8Buffer {
@@ -141,14 +141,14 @@ func _assertionFailed(
141141
/// This function should not be inlined because it is cold and inlining just
142142
/// bloats code.
143143
@_versioned
144-
@noreturn @inline(never)
144+
@inline(never)
145145
@_semantics("stdlib_binary_only")
146146
func _assertionFailed(
147147
// FIXME(ABI): add argument labels to conform to API guidelines.
148148
_ prefix: StaticString, _ message: String,
149149
_ file: StaticString, _ line: UInt,
150150
flags: UInt32
151-
) {
151+
) -> Never {
152152
prefix.withUTF8Buffer {
153153
(prefix) -> Void in
154154
message._withUnsafeBufferPointerToUTF8 {
@@ -173,15 +173,15 @@ func _assertionFailed(
173173
/// This function should not be inlined because it is cold and it inlining just
174174
/// bloats code.
175175
@_versioned
176-
@noreturn @inline(never)
176+
@inline(never)
177177
@_semantics("stdlib_binary_only")
178178
@_semantics("arc.programtermination_point")
179179
func _fatalErrorMessage(
180180
// FIXME(ABI): add argument labels to conform to API guidelines.
181181
_ prefix: StaticString, _ message: StaticString,
182182
_ file: StaticString, _ line: UInt,
183183
flags: UInt32
184-
) {
184+
) -> Never {
185185
#if INTERNAL_CHECKS_ENABLED
186186
prefix.withUTF8Buffer {
187187
(prefix) in
@@ -215,14 +215,14 @@ func _fatalErrorMessage(
215215

216216
/// Prints a fatal error message when an unimplemented initializer gets
217217
/// called by the Objective-C runtime.
218-
@_transparent @noreturn
218+
@_transparent
219219
public // COMPILER_INTRINSIC
220220
func _unimplementedInitializer(className: StaticString,
221221
initName: StaticString = #function,
222222
file: StaticString = #file,
223223
line: UInt = #line,
224224
column: UInt = #column
225-
) {
225+
) -> Never {
226226
// This function is marked @_transparent so that it is inlined into the caller
227227
// (the initializer stub), and, depending on the build configuration,
228228
// redundant parameter values (#file etc.) are eliminated, and don't leak
@@ -260,7 +260,6 @@ func _unimplementedInitializer(className: StaticString,
260260
}
261261

262262
// FIXME(ABI): rename to something descriptive.
263-
@noreturn
264263
public // COMPILER_INTRINSIC
265264
func _undefined<T>(
266265
_ message: @autoclosure () -> String = String(),

0 commit comments

Comments
 (0)