Skip to content

Fixits for @noreturn -> Never (SE-0102) #3720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/ABI.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,6 @@ mangled in to disambiguate.
impl-function-attribute ::= 'Cm' // compatible with Swift method
impl-function-attribute ::= 'CO' // compatible with ObjC method
impl-function-attribute ::= 'Cw' // compatible with protocol witness
impl-function-attribute ::= 'N' // noreturn
impl-function-attribute ::= 'G' // generic
impl-function-attribute ::= 'g' // pseudogeneric
impl-parameter ::= impl-convention type
Expand All @@ -1029,8 +1028,8 @@ types. However, in some cases it is more useful to encode the exact
implementation details of a function type.

Any ``<impl-function-attribute>`` productions must appear in the order
in which they are specified above: e.g. a noreturn C function is
mangled with ``CcN``. ``g`` and ``G`` are exclusive and mark the presence
in which they are specified above: e.g. a pseudogeneric C function is
mangled with ``Ccg``. ``g`` and ``G`` are exclusive and mark the presence
of a generic signature immediately following.

Note that the convention and function-attribute productions do not
Expand Down
14 changes: 5 additions & 9 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1216,8 +1216,8 @@ flow, such as a non-``Void`` function failing to ``return`` a value, or a
``switch`` statement failing to cover all possible values of its subject.
The guaranteed dead code elimination pass can eliminate truly unreachable
basic blocks, or ``unreachable`` instructions may be dominated by applications
of ``@noreturn`` functions. An ``unreachable`` instruction that survives
guaranteed DCE and is not immediately preceded by a ``@noreturn``
of functions returning uninhabited types. An ``unreachable`` instruction that
survives guaranteed DCE and is not immediately preceded by an no-return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/an/a/ ?

application is a dataflow error.

Runtime Failure
Expand Down Expand Up @@ -3912,12 +3912,8 @@ in the following ways:
- A class tuple element of the destination type may be a superclass or
subclass of the source type's corresponding tuple element.

The function types may also differ in attributes, with the following
caveats:

- The ``convention`` attribute cannot be changed.
- A ``@noreturn`` function may be converted to a non-``@noreturn``
type and vice-versa.
The function types may also differ in attributes, except that the
``convention`` attribute cannot be changed.

thin_function_to_pointer
````````````````````````
Expand Down Expand Up @@ -4133,7 +4129,7 @@ unreachable
Indicates that control flow must not reach the end of the current basic block.
It is a dataflow error if an unreachable terminator is reachable from the entry
point of a function and is not immediately preceded by an ``apply`` of a
``@noreturn`` function.
no-return function.

return
``````
Expand Down
28 changes: 3 additions & 25 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4838,35 +4838,13 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
/// depending on the function context.
bool argumentNameIsAPIByDefault() const;

/// \brief Returns the "natural" number of argument clauses taken by this
/// function. This value is one for free-standing functions, and two for
/// methods.
unsigned getNumParameterLists() const {
return AbstractFunctionDeclBits.NumParameterLists;
}

/// \brief Returns the "natural" number of argument clauses taken by this
/// function. This value is always at least one, and it may be more if the
/// function is implicitly or explicitly curried.
///
/// For example, this function:
/// \code
/// func negate(x : Int) -> Int { return -x }
/// \endcode
/// has a natural argument count of 1 if it is freestanding. If it is
/// a method, it has a natural argument count of 2, as does this
/// curried function:
/// \code
/// func add(x : Int)(y : Int) -> Int { return x + y }
/// \endcode
///
/// This value never exceeds the number of chained function types
/// in the function's type, but it can be less for functions which
/// return a value of function type:
/// \code
/// func const(x : Int) -> () -> Int { return { x } } // NAC==1
/// \endcode
unsigned getNaturalArgumentCount() const {
return getNumParameterLists();
}

/// \brief Returns the parameter pattern(s) for the function definition that
/// determine the parameter names bound in the function body.
///
Expand Down
8 changes: 3 additions & 5 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,9 @@ ERROR(function_type_access,none,
WARNING(non_trailing_closure_before_default_args,none,
"closure parameter prior to parameters with default arguments will "
"not be treated as a trailing closure", ())
ERROR(noreturn_not_supported,none,
"'@noreturn' has been removed; functions that never return should have a "
"return type of 'Never' instead", ())

// Extensions
ERROR(non_nominal_extension,none,
Expand Down Expand Up @@ -1326,8 +1329,6 @@ NOTE(protocol_witness_mutating_conflict,none,
"candidate is marked 'mutating' but protocol does not allow it", ())
NOTE(protocol_witness_settable_conflict,none,
"candidate is not settable, but protocol requires it", ())
NOTE(protocol_witness_noreturn_conflict,none,
"candidate is not @noreturn, but protocol requires it", ())
NOTE(protocol_witness_rethrows_conflict,none,
"candidate is not 'rethrows', but protocol requires it", ())
NOTE(protocol_witness_throws_conflict,none,
Expand Down Expand Up @@ -1775,9 +1776,6 @@ ERROR(final_not_on_accessors,none,
"'final' cannot be applied to accessors, it must be put on the "
"%select{var|let|subscript}0", (unsigned))

ERROR(override_noreturn_with_return,none,
"an override of a @noreturn method should also be @noreturn", ())

ERROR(override_rethrows_with_non_rethrows,none,
"override of 'rethrows' %select{method|initializer}0 should also "
"be 'rethrows'", (bool))
Expand Down
2 changes: 0 additions & 2 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2844,8 +2844,6 @@ class AbstractClosureExpr : public Expr, public DeclContext {
return parameterList ? parameterList : ArrayRef<const ParameterList *>();
}

unsigned getNaturalArgumentCount() const { return 1; }

/// \brief Retrieve the result type of this closure.
Type getResultType() const;

Expand Down
57 changes: 14 additions & 43 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2125,15 +2125,14 @@ class AnyFunctionType : public TypeBase {
// you'll need to adjust both the Bits field below and
// BaseType::AnyFunctionTypeBits.

// |representation|isAutoClosure|noReturn|noEscape|throws|
// | 0 .. 3 | 4 | 5 | 6 | 7 |
// |representation|isAutoClosure|noEscape|throws|
// | 0 .. 3 | 4 | 5 | 6 |
//
enum : uint16_t { RepresentationMask = 0x00F };
enum : uint16_t { AutoClosureMask = 0x010 };
enum : uint16_t { NoReturnMask = 0x020 };
enum : uint16_t { NoEscapeMask = 0x040 };
enum : uint16_t { ThrowsMask = 0x080 };
enum : uint16_t { ExplicitlyEscapingMask = 0x100 };
enum : uint16_t { NoEscapeMask = 0x020 };
enum : uint16_t { ThrowsMask = 0x040 };
enum : uint16_t { ExplicitlyEscapingMask = 0x080 };

uint16_t Bits;

Expand All @@ -2148,23 +2147,20 @@ class AnyFunctionType : public TypeBase {
}

// Constructor for polymorphic type.
ExtInfo(Representation Rep, bool IsNoReturn, bool Throws) {
Bits = ((unsigned) Rep) |
(IsNoReturn ? NoReturnMask : 0) |
(Throws ? ThrowsMask : 0);
ExtInfo(Representation Rep, bool Throws) {
Bits = ((unsigned) Rep) | (Throws ? ThrowsMask : 0);
}

// Constructor with no defaults.
ExtInfo(Representation Rep, bool IsNoReturn,
ExtInfo(Representation Rep,
bool IsAutoClosure, bool IsNoEscape, bool IsExplicitlyEscaping,
bool Throws)
: ExtInfo(Rep, IsNoReturn, Throws) {
: ExtInfo(Rep, Throws) {
Bits |= (IsAutoClosure ? AutoClosureMask : 0);
Bits |= (IsNoEscape ? NoEscapeMask : 0);
Bits |= (IsExplicitlyEscaping ? ExplicitlyEscapingMask : 0);
}

bool isNoReturn() const { return Bits & NoReturnMask; }
bool isAutoClosure() const { return Bits & AutoClosureMask; }
bool isNoEscape() const { return Bits & NoEscapeMask; }
bool isExplicitlyEscaping() const { return Bits & ExplicitlyEscapingMask; }
Expand Down Expand Up @@ -2211,12 +2207,6 @@ class AnyFunctionType : public TypeBase {
return ExtInfo((Bits & ~RepresentationMask)
| (unsigned)Rep);
}
ExtInfo withIsNoReturn(bool IsNoReturn = true) const {
if (IsNoReturn)
return ExtInfo(Bits | NoReturnMask);
else
return ExtInfo(Bits & ~NoReturnMask);
}
ExtInfo withIsAutoClosure(bool IsAutoClosure = true) const {
if (IsAutoClosure)
return ExtInfo(Bits | AutoClosureMask);
Expand Down Expand Up @@ -2285,10 +2275,6 @@ class AnyFunctionType : public TypeBase {
return getExtInfo().getRepresentation();
}

bool isNoReturn() const {
return getExtInfo().isNoReturn();
}

/// \brief True if this type allows an implicit conversion from a function
/// argument expression of type T to a function of type () -> T.
bool isAutoClosure() const {
Expand Down Expand Up @@ -2866,14 +2852,13 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
class ExtInfo {
// Feel free to rearrange or add bits, but if you go over 15,
// you'll need to adjust both the Bits field below and
// BaseType::AnyFunctionTypeBits.
// TypeBase::AnyFunctionTypeBits.

// |representation|noReturn|pseudogeneric|
// | 0 .. 3 | 4 | 5 |
// |representation|pseudogeneric|
// | 0 .. 3 | 4 |
//
enum : uint16_t { RepresentationMask = 0x00F };
enum : uint16_t { NoReturnMask = 0x010 };
enum : uint16_t { PseudogenericMask = 0x020 };
enum : uint16_t { PseudogenericMask = 0x010 };

uint16_t Bits;

Expand All @@ -2886,19 +2871,15 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
ExtInfo() : Bits(0) { }

// Constructor for polymorphic type.
ExtInfo(Representation rep, bool isNoReturn, bool isPseudogeneric) {
ExtInfo(Representation rep, bool isPseudogeneric) {
Bits = ((unsigned) rep) |
(isNoReturn ? NoReturnMask : 0) |
(isPseudogeneric ? PseudogenericMask : 0);
}

/// Is this function pseudo-generic? A pseudo-generic function
/// is not permitted to dynamically depend on its type arguments.
bool isPseudogeneric() const { return Bits & PseudogenericMask; }

/// Do functions of this type return normally?
bool isNoReturn() const { return Bits & NoReturnMask; }

/// What is the abstract representation of this function value?
Representation getRepresentation() const {
return Representation(Bits & RepresentationMask);
Expand Down Expand Up @@ -2956,12 +2937,6 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
return ExtInfo((Bits & ~RepresentationMask)
| (unsigned)Rep);
}
ExtInfo withIsNoReturn(bool IsNoReturn = true) const {
if (IsNoReturn)
return ExtInfo(Bits | NoReturnMask);
else
return ExtInfo(Bits & ~NoReturnMask);
}
ExtInfo withIsPseudogeneric(bool isPseudogeneric = true) const {
if (isPseudogeneric)
return ExtInfo(Bits | PseudogenericMask);
Expand Down Expand Up @@ -3207,10 +3182,6 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
return getExtInfo().getRepresentation();
}

bool isNoReturn() const {
return getExtInfo().isNoReturn();
}

bool isPseudogeneric() const {
return getExtInfo().isPseudogeneric();
}
Expand Down
6 changes: 1 addition & 5 deletions include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 255; // Last change: bind_memory instruction
const uint16_t VERSION_MINOR = 256; // Last change: remove noreturn bit

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down Expand Up @@ -587,7 +587,6 @@ namespace decls_block {
TypeIDField, // output
FunctionTypeRepresentationField, // representation
BCFixed<1>, // auto-closure?
BCFixed<1>, // noreturn?
BCFixed<1>, // noescape?
BCFixed<1>, // explicitlyEscaping?
BCFixed<1> // throws?
Expand Down Expand Up @@ -681,7 +680,6 @@ namespace decls_block {
TypeIDField, // output
DeclIDField, // decl that owns the generic params
FunctionTypeRepresentationField, // representation
BCFixed<1>, // noreturn?
BCFixed<1> // throws?
// Trailed by its generic parameters, if the owning decl ID is 0.
>;
Expand All @@ -691,7 +689,6 @@ namespace decls_block {
TypeIDField, // input
TypeIDField, // output
FunctionTypeRepresentationField, // representation
BCFixed<1>, // noreturn?
BCFixed<1>, // throws?
BCArray<TypeIDField> // generic parameters
// followed by requirements
Expand All @@ -701,7 +698,6 @@ namespace decls_block {
SIL_FUNCTION_TYPE,
ParameterConventionField, // callee convention
SILFunctionTypeRepresentationField, // representation
BCFixed<1>, // noreturn?
BCFixed<1>, // pseudogeneric?
BCFixed<1>, // error result?
BCFixed<30>, // number of parameters
Expand Down
1 change: 0 additions & 1 deletion lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2869,7 +2869,6 @@ namespace {
break;
}

printFlag(T->isNoReturn(), "noreturn");
printFlag(T->isAutoClosure(), "autoclosure");
printFlag(T->isNoEscape(), "noescape");
printFlag(T->isExplicitlyEscaping(), "escaping");
Expand Down
6 changes: 0 additions & 6 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3752,9 +3752,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
break;
}
}

if (info.isNoReturn())
Printer << "@noreturn ";
}

void printFunctionExtInfo(SILFunctionType::ExtInfo info) {
Expand Down Expand Up @@ -3789,9 +3786,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

if (info.isPseudogeneric())
Printer << "@pseudogeneric ";

if (info.isNoReturn())
Printer << "@noreturn ";
}

void visitFunctionType(FunctionType *T) {
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2304,7 +2304,7 @@ struct ASTNodeBase {};
// If a decl has the Throws bit set, the function type should throw,
// and vice versa.
auto fnTy = AFD->getType()->castTo<AnyFunctionType>();
for (unsigned i = 1, e = AFD->getNaturalArgumentCount(); i != e; ++i)
for (unsigned i = 1, e = AFD->getNumParameterLists(); i != e; ++i)
fnTy = fnTy->getResult()->castTo<AnyFunctionType>();

if (AFD->hasThrows() != fnTy->getExtInfo().throws()) {
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ static ValueDecl *getOnceOperation(ASTContext &Context,
auto HandleTy = Context.TheRawPointerType;
auto VoidTy = Context.TheEmptyTupleType;
auto Thin = FunctionType::ExtInfo(FunctionTypeRepresentation::Thin,
/*noreturn*/ false, /*throws*/ false);
/*throws*/ false);

auto BlockTy = FunctionType::get(VoidTy, VoidTy, Thin);
return getBuiltinFunction(Id, {HandleTy, BlockTy}, VoidTy);
Expand Down
8 changes: 4 additions & 4 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1426,12 +1426,12 @@ static Type mapSignatureParamType(ASTContext &ctx, Type type) {
/// we may need to compare the extended information.
///
/// In the type of the function declaration, none of the extended information
/// is relevant. We cannot overload purely on @noreturn, 'throws', or the
/// calling convention of the declaration itself.
/// is relevant. We cannot overload purely on 'throws' or the calling
/// convention of the declaration itself.
///
/// For function parameter types, we do want to be able to overload on
/// 'throws', since that is part of the mangled symbol name, but not
/// @noreturn or @noescape.
/// @noescape.
static AnyFunctionType::ExtInfo
mapSignatureExtInfo(AnyFunctionType::ExtInfo info,
bool topLevelFunction) {
Expand Down Expand Up @@ -4415,7 +4415,7 @@ Type FuncDecl::getResultType() const {
if (resultTy->is<ErrorType>())
return resultTy;

for (unsigned i = 0, e = getNaturalArgumentCount(); i != e; ++i)
for (unsigned i = 0, e = getNumParameterLists(); i != e; ++i)
resultTy = resultTy->castTo<AnyFunctionType>()->getResult();

if (!resultTy)
Expand Down
2 changes: 0 additions & 2 deletions lib/AST/Mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,6 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) {
// <impl-function-attribute> ::= 'Cc' // C global function
// <impl-function-attribute> ::= 'Cm' // Swift method
// <impl-function-attribute> ::= 'CO' // ObjC method
// <impl-function-attribute> ::= 'N' // noreturn
// <impl-function-attribute> ::= 'g' // pseudogeneric
// <impl-function-attribute> ::= 'G' // generic
// <impl-parameter> ::= <impl-convention> <type>
Expand Down Expand Up @@ -1042,7 +1041,6 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) {
break;
}

if (fn->isNoReturn()) Buffer << 'N';
if (fn->isPolymorphic()) {
Buffer << (fn->isPseudogeneric() ? 'g' : 'G');
mangleGenericSignature(fn->getGenericSignature());
Expand Down
Loading