Skip to content

Commit c6e828f

Browse files
authored
Merge pull request #3658 from slavapestov/replace-noreturn-with-never
SE-0102: Remove @NoReturn attribute and introduce an empty Never type
2 parents f72a823 + ddc51c5 commit c6e828f

File tree

78 files changed

+1424
-1474
lines changed

Some content is hidden

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

78 files changed

+1424
-1474
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,15 @@ class ASTContext {
440440
/// Retrieve the declaration of the "pointee" property of a pointer type.
441441
VarDecl *getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const;
442442

443+
/// Retrieve the declaration of Swift.Never.
444+
NominalTypeDecl *getNeverDecl() const;
445+
CanType getNeverType() const;
446+
443447
/// Retrieve the declaration of Swift.Void.
444448
TypeAliasDecl *getVoidDecl() const;
445449

446450
/// Retrieve the declaration of ObjectiveC.ObjCBool.
447-
StructDecl *getObjCBoolDecl();
451+
StructDecl *getObjCBoolDecl() const;
448452

449453
/// Retrieve the declaration of Foundation.NSError.
450454
ClassDecl *getNSErrorDecl() const;
@@ -481,7 +485,7 @@ class ASTContext {
481485
/// Retrieve the declaration of Swift.==(Int, Int) -> Bool.
482486
FuncDecl *getEqualIntDecl(LazyResolver *resolver) const;
483487

484-
/// Retrieve the declaration of Swift._unimplemented_initializer.
488+
/// Retrieve the declaration of Swift._unimplementedInitializer.
485489
FuncDecl *getUnimplementedInitializerDecl(LazyResolver *resolver) const;
486490

487491
/// Retrieve the declaration of Swift._undefined.
@@ -491,7 +495,7 @@ class ASTContext {
491495
FuncDecl *getIsOSVersionAtLeastDecl(LazyResolver *resolver) const;
492496

493497
/// Look for the declaration with the given name within the
494-
/// swift module.
498+
/// Swift module.
495499
void lookupInSwiftModule(StringRef name,
496500
SmallVectorImpl<ValueDecl *> &results) const;
497501

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))

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ NOTE(note_no_in_class_init_3plus,none,
10151015
"without initial values prevent synthesized initializers",
10161016
(Identifier, Identifier, Identifier, bool))
10171017
ERROR(missing_unimplemented_init_runtime,none,
1018-
"standard library error: missing _unimplemented_initializer", ())
1018+
"standard library error: missing _unimplementedInitializer", ())
10191019
ERROR(missing_undefined_runtime,none,
10201020
"standard library error: missing _undefined", ())
10211021
WARNING(unsupported_synthesize_init_variadic,none,

include/swift/AST/Types.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
392392
/// hasReferenceSemantics() - Do objects of this type have reference
393393
/// semantics?
394394
bool hasReferenceSemantics();
395-
395+
396+
/// Is this an uninhabited type, such as 'Never'?
397+
bool isNever();
398+
396399
/// Is this the 'Any' type?
397400
bool isAny();
398401

@@ -751,10 +754,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
751754
/// parameter replaced. Only makes sense for function members of types.
752755
Type replaceSelfParameterType(Type newSelf);
753756

754-
/// Returns a function type that is not 'noreturn', but is otherwise the same
755-
/// as this type.
756-
Type getWithoutNoReturn(unsigned UncurryLevel);
757-
758757
/// getRValueType - For an @lvalue type, retrieves the underlying object type.
759758
/// Otherwise, returns the type itself.
760759
Type getRValueType();

include/swift/SIL/SILFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ class SILFunction
215215
return LoweredType;
216216
}
217217

218+
bool isNoReturnFunction() const;
219+
218220
/// Unsafely rewrite the lowered type of this function.
219221
///
220222
/// This routine does not touch the entry block arguments

include/swift/SIL/SILInstruction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,10 @@ class ApplyInstBase<Impl, Base, false> : public Base {
10021002
return SubstCalleeType;
10031003
}
10041004

1005+
bool isCalleeNoReturn() const {
1006+
return getSubstCalleeSILType().isNoReturnFunction();
1007+
}
1008+
10051009
bool isCalleeThin() const {
10061010
auto Rep = getSubstCalleeType()->getRepresentation();
10071011
return Rep == FunctionType::Representation::Thin;
@@ -5077,6 +5081,11 @@ class ApplySite {
50775081
FOREACH_IMPL_RETURN(getSubstCalleeSILType());
50785082
}
50795083

5084+
/// Check if this is a call of a never-returning function.
5085+
bool isCalleeNoReturn() const {
5086+
FOREACH_IMPL_RETURN(isCalleeNoReturn());
5087+
}
5088+
50805089
bool isCalleeThin() const {
50815090
switch (getSubstCalleeType()->getRepresentation()) {
50825091
case SILFunctionTypeRepresentation::CFunctionPointer:

include/swift/SIL/SILType.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,11 @@ class SILType {
285285
/// True if the type, or the referenced type of an address type, is a
286286
/// scalar reference-counted type.
287287
bool isReferenceCounted(SILModule &M) const;
288-
288+
289+
/// Returns true if the referenced type is a function type that never
290+
/// returns.
291+
bool isNoReturnFunction() const;
292+
289293
/// Returns true if the referenced type has reference semantics.
290294
bool hasReferenceSemantics() const {
291295
return getSwiftRValueType().hasReferenceSemantics();

lib/AST/ASTContext.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ struct ASTContext::Implementation {
155155
/// The declaration of Swift.Unmanaged<T>
156156
NominalTypeDecl *UnmanagedDecl = nullptr;
157157

158+
/// The declaration of Swift.Never.
159+
NominalTypeDecl *NeverDecl = nullptr;
160+
158161
/// The declaration of Swift.Void.
159162
TypeAliasDecl *VoidDecl = nullptr;
160163

@@ -180,7 +183,7 @@ struct ASTContext::Implementation {
180183
/// func ==(Int, Int) -> Bool
181184
FuncDecl *EqualIntDecl = nullptr;
182185

183-
/// func _unimplemented_initializer(className: StaticString).
186+
/// func _unimplementedInitializer(className: StaticString).
184187
FuncDecl *UnimplementedInitializerDecl = nullptr;
185188

186189
/// func _undefined<T>(msg: StaticString, file: StaticString, line: UInt) -> T
@@ -710,7 +713,7 @@ NominalTypeDecl *ASTContext::getUnsafeMutablePointerDecl() const {
710713
NominalTypeDecl *ASTContext::getOpaquePointerDecl() const {
711714
if (!Impl.OpaquePointerDecl)
712715
Impl.OpaquePointerDecl
713-
= findStdlibType(*this, "OpaquePointer", 0);
716+
= findStdlibType(*this, "OpaquePointer", 0);
714717

715718
return Impl.OpaquePointerDecl;
716719
}
@@ -784,6 +787,17 @@ ASTContext::getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const {
784787
llvm_unreachable("bad pointer kind");
785788
}
786789

790+
NominalTypeDecl *ASTContext::getNeverDecl() const {
791+
if (!Impl.NeverDecl)
792+
Impl.NeverDecl = findStdlibType(*this, "Never", 0);
793+
794+
return Impl.NeverDecl;
795+
}
796+
797+
CanType ASTContext::getNeverType() const {
798+
return getNeverDecl()->getDeclaredType()->getCanonicalType();
799+
}
800+
787801
TypeAliasDecl *ASTContext::getVoidDecl() const {
788802
if (Impl.VoidDecl) {
789803
return Impl.VoidDecl;
@@ -802,10 +816,11 @@ TypeAliasDecl *ASTContext::getVoidDecl() const {
802816
return Impl.VoidDecl;
803817
}
804818

805-
StructDecl *ASTContext::getObjCBoolDecl() {
819+
StructDecl *ASTContext::getObjCBoolDecl() const {
806820
if (!Impl.ObjCBoolDecl) {
807821
SmallVector<ValueDecl *, 1> results;
808-
if (Module *M = getModuleByName(Id_ObjectiveC.str())) {
822+
auto *Context = const_cast<ASTContext *>(this);
823+
if (Module *M = Context->getModuleByName(Id_ObjectiveC.str())) {
809824
M->lookupValue({ }, getIdentifier("ObjCBool"), NLKind::UnqualifiedLookup,
810825
results);
811826
for (auto result : results) {
@@ -1004,7 +1019,7 @@ ASTContext::getUnimplementedInitializerDecl(LazyResolver *resolver) const {
10041019

10051020
// Look for the function.
10061021
CanType input, output;
1007-
auto decl = findLibraryIntrinsic(*this, "_unimplemented_initializer",
1022+
auto decl = findLibraryIntrinsic(*this, "_unimplementedInitializer",
10081023
resolver);
10091024
if (!decl || !isNonGenericIntrinsic(decl, input, output))
10101025
return nullptr;

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/AST/Type.cpp

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ bool TypeBase::hasReferenceSemantics() {
8989
return getCanonicalType().hasReferenceSemantics();
9090
}
9191

92+
bool TypeBase::isNever() {
93+
if (auto nominalDecl = getAnyNominal())
94+
if (auto enumDecl = dyn_cast<EnumDecl>(nominalDecl))
95+
if (enumDecl->getAllElements().empty())
96+
return true;
97+
98+
return false;
99+
}
100+
92101
bool TypeBase::isAny() {
93102
return isEqual(getASTContext().TheAnyType);
94103
}
@@ -919,27 +928,6 @@ Type TypeBase::replaceSelfParameterType(Type newSelf) {
919928
fnTy->getExtInfo());
920929
}
921930

922-
Type TypeBase::getWithoutNoReturn(unsigned UncurryLevel) {
923-
if (UncurryLevel == 0)
924-
return this;
925-
926-
auto *FnType = this->castTo<AnyFunctionType>();
927-
Type InputType = FnType->getInput();
928-
Type ResultType = FnType->getResult()->getWithoutNoReturn(UncurryLevel - 1);
929-
auto TheExtInfo = FnType->getExtInfo().withIsNoReturn(false);
930-
if (auto *GFT = dyn_cast<GenericFunctionType>(FnType)) {
931-
return GenericFunctionType::get(GFT->getGenericSignature(),
932-
InputType, ResultType,
933-
TheExtInfo);
934-
}
935-
if (auto *PFT = dyn_cast<PolymorphicFunctionType>(FnType)) {
936-
return PolymorphicFunctionType::get(InputType, ResultType,
937-
&PFT->getGenericParams(),
938-
TheExtInfo);
939-
}
940-
return FunctionType::get(InputType, ResultType, TheExtInfo);
941-
}
942-
943931
/// Retrieve the object type for a 'self' parameter, digging into one-element
944932
/// tuples, inout types, and metatypes.
945933
Type TypeBase::getRValueInstanceType() {

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/IRGen/GenClangType.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,11 @@ GenClangType::visitBoundGenericType(CanBoundGenericType type) {
489489
}
490490

491491
clang::CanQualType GenClangType::visitEnumType(CanEnumType type) {
492+
// Special case: Uninhabited enums are not @objc, so we don't
493+
// know what to do below, but we can just convert to 'void'.
494+
if (type->isNever())
495+
return Converter.convert(IGM, IGM.Context.TheEmptyTupleType);
496+
492497
assert(type->getDecl()->isObjC() && "not an @objc enum?!");
493498

494499
// @objc enums lower to their raw types.

lib/SIL/SILFunction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,11 @@ Type SILFunction::mapTypeOutOfContext(Type type) const {
294294
type);
295295
}
296296

297+
bool SILFunction::isNoReturnFunction() const {
298+
return SILType::getPrimitiveObjectType(getLoweredFunctionType())
299+
.isNoReturnFunction();
300+
}
301+
297302
SILBasicBlock *SILFunction::createBasicBlock() {
298303
return new (getModule()) SILBasicBlock(this);
299304
}

lib/SIL/SILType.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ bool SILType::isReferenceCounted(SILModule &M) const {
7070
return M.getTypeLowering(*this).isReferenceCounted();
7171
}
7272

73+
bool SILType::isNoReturnFunction() const {
74+
if (auto funcTy = dyn_cast<SILFunctionType>(getSwiftRValueType())) {
75+
if (funcTy->isNoReturn())
76+
return true;
77+
78+
return funcTy->getSILResult().getSwiftRValueType()->isNever();
79+
}
80+
81+
return false;
82+
}
83+
7384
std::string SILType::getAsString() const {
7485
std::string Result;
7586
llvm::raw_string_ostream OS(Result);

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.");

0 commit comments

Comments
 (0)