Skip to content
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
4 changes: 0 additions & 4 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2012,10 +2012,6 @@ bool NominalTypeDecl::derivesProtocolConformance(ProtocolDecl *protocol) const {
if (!knownProtocol)
return false;

// All nominal types can derive their Error conformance.
if (*knownProtocol == KnownProtocolKind::Error)
return true;

if (auto *enumDecl = dyn_cast<EnumDecl>(this)) {
switch (*knownProtocol) {
// Enums with raw types can implicitly derive their RawRepresentable
Expand Down
161 changes: 0 additions & 161 deletions lib/Sema/DerivedConformanceError.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,167 +26,6 @@
using namespace swift;
using namespace DerivedConformance;

static void deriveBodyError_enum_code(AbstractFunctionDecl *codeDecl) {
// enum SomeEnum {
// case A,B,C,D
//
// @derived
// var code: Int {
// switch self {
// case A: return 0
// case B: return 1
// case C: return 2
// ...
// }
// }
// }
//
// TODO: Some convenient way to override the code if that's desired.

auto parentDC = codeDecl->getDeclContext();
ASTContext &C = parentDC->getASTContext();

auto enumDecl = parentDC->getAsEnumOrEnumExtensionContext();
Type enumType = parentDC->getDeclaredTypeInContext();

SmallVector<CaseStmt*, 4> cases;
SmallString<11> strBuf;

unsigned code = 0;
for (auto elt : enumDecl->getAllElements()) {
auto pat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
SourceLoc(), SourceLoc(),
Identifier(), elt, nullptr);
pat->setImplicit();

auto labelItem =
CaseLabelItem(/*IsDefault=*/false, pat, SourceLoc(), nullptr);

{
strBuf.clear();
llvm::raw_svector_ostream os(strBuf);
os << code;
}

auto codeStr = C.AllocateCopy(StringRef(strBuf));

auto returnExpr = new (C) IntegerLiteralExpr(codeStr, SourceLoc(),
/*implicit*/ true);
auto returnStmt = new (C) ReturnStmt(SourceLoc(), returnExpr,
/*implicit*/ true);

auto body = BraceStmt::create(C, SourceLoc(),
ASTNode(returnStmt), SourceLoc());

cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem,
/*HasBoundDecls=*/false, SourceLoc(),
body));

++code;
}

Stmt *bodyStmt;
// If the enum is empty, simply return zero. (It doesn't really matter, since
// the enum can't be instantiated regardless.)
if (cases.empty()) {
static const char zero[] = "0";
auto returnExpr = new (C) IntegerLiteralExpr(zero, SourceLoc(),
/*implicit*/ true);
bodyStmt = new (C) ReturnStmt(SourceLoc(), returnExpr,
/*implicit*/ true);
} else {
auto selfRef = createSelfDeclRef(codeDecl);
bodyStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(), selfRef,
SourceLoc(), cases, SourceLoc(), C);
}
auto body = BraceStmt::create(C, SourceLoc(),
ASTNode(bodyStmt),
SourceLoc());

codeDecl->setBody(body);
}

static void deriveBodyError_zero_code(AbstractFunctionDecl *codeDecl) {
// struct SomeStruct {
// @derived
// var code: Int { return 0 }
// }
//
// TODO: Some convenient way to override the code if that's desired.

auto parentDC = codeDecl->getDeclContext();
ASTContext &C = parentDC->getASTContext();

auto returnExpr = new (C) IntegerLiteralExpr("1", SourceLoc(),
/*implicit*/ true);
auto returnStmt = new (C) ReturnStmt(SourceLoc(), returnExpr,
/*implicit*/ true);

auto body = BraceStmt::create(C, SourceLoc(),
ASTNode(returnStmt), SourceLoc());

codeDecl->setBody(body);
}

static ValueDecl *deriveError_code(TypeChecker &tc, Decl *parentDecl,
NominalTypeDecl *nominal) {
// enum SomeEnum {
// case A,B,C,D
//
// @derived
// var code: Int {
// switch self {
// case A: return 0
// case B: return 1
// case C: return 2
// ...
// }
// }
// }

ASTContext &C = tc.Context;

auto intTy = C.getIntDecl()->getDeclaredType();

// Define the getter.
auto getterDecl = declareDerivedPropertyGetter(tc, parentDecl, nominal,
intTy, intTy,
/*isStatic=*/false,
/*isFinal=*/true);
if (isa<EnumDecl>(nominal))
getterDecl->setBodySynthesizer(&deriveBodyError_enum_code);
else
getterDecl->setBodySynthesizer(&deriveBodyError_zero_code);

// Define the property.
VarDecl *propDecl;
PatternBindingDecl *pbDecl;
std::tie(propDecl, pbDecl)
= declareDerivedReadOnlyProperty(tc, parentDecl, nominal, C.Id_code_,
intTy, intTy, getterDecl,
/*isStatic=*/false, /*isFinal=*/true);

auto dc = cast<IterableDeclContext>(parentDecl);
dc->addMember(getterDecl);
dc->addMember(propDecl);
dc->addMember(pbDecl);

return propDecl;

}

ValueDecl *DerivedConformance::deriveError(TypeChecker &tc,
Decl *parentDecl,
NominalTypeDecl *type,
ValueDecl *requirement) {
if (requirement->getName() == tc.Context.Id_code_)
return deriveError_code(tc, parentDecl, type);

tc.diagnose(requirement->getLoc(),
diag::broken_errortype_requirement);
return nullptr;
}

static void deriveBodyBridgedNSError_enum_nsErrorDomain(
AbstractFunctionDecl *domainDecl) {
// enum SomeEnum {
Expand Down
4 changes: 0 additions & 4 deletions lib/Sema/DerivedConformances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ ValueDecl *DerivedConformance::getDerivableRequirement(NominalTypeDecl *nominal,
if (name.isSimpleName(ctx.Id_hashValue))
return getRequirement(KnownProtocolKind::Hashable);

// Error._code
if (name.isSimpleName(ctx.Id_code_))
return getRequirement(KnownProtocolKind::Error);

// _BridgedNSError._nsErrorDomain
if (name.isSimpleName(ctx.Id_nsErrorDomain))
return getRequirement(KnownProtocolKind::BridgedNSError);
Expand Down
11 changes: 0 additions & 11 deletions lib/Sema/DerivedConformances.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,6 @@ ValueDecl *deriveHashable(TypeChecker &tc,
Decl *parentDecl,
NominalTypeDecl *type,
ValueDecl *requirement);

/// Derive an Error requirement for an enum type.
///
/// A unique string representation of the enum type will be used as the domain
/// for members of the enum, and each case will have its own integer code.
///
/// \returns the derived member, which will also be added to the type.
ValueDecl *deriveError(TypeChecker &tc,
Decl *parentDecl,
NominalTypeDecl *type,
ValueDecl *requirement);

/// Derive a _BridgedNSError requirement for an @objc enum type.
///
Expand Down
3 changes: 0 additions & 3 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4913,9 +4913,6 @@ ValueDecl *TypeChecker::deriveProtocolRequirement(DeclContext *DC,
case KnownProtocolKind::Hashable:
return DerivedConformance::deriveHashable(*this, Decl, TypeDecl, Requirement);

case KnownProtocolKind::Error:
return DerivedConformance::deriveError(*this, Decl, TypeDecl, Requirement);

case KnownProtocolKind::BridgedNSError:
return DerivedConformance::deriveBridgedNSError(*this, Decl, TypeDecl,
Requirement);
Expand Down
7 changes: 7 additions & 0 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,13 @@ static void filterValues(Type expectedTy, Module *expectedModule,
->getCanonicalSignature() != expectedGenericSig)
return true;

// If we don't expect a specific generic signature, ignore anything from a
// constrained extension.
if (!expectedGenericSig &&
isa<ExtensionDecl>(value->getDeclContext()) &&
cast<ExtensionDecl>(value->getDeclContext())->isConstrainedExtension())
return true;

// If we're looking at members of a protocol or protocol extension,
// filter by whether we expect to find something in a protocol extension or
// not. This lets us distinguish between a protocol member and a protocol
Expand Down
43 changes: 43 additions & 0 deletions stdlib/public/SDK/Foundation/NSError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,37 @@ public protocol CustomNSError : Error {
var errorUserInfo: [String : Any] { get }
}

public extension CustomNSError {
/// Default domain of the error.
static var errorDomain: String {
return String(reflecting: type(of: self))
}

/// The error code within the given domain.
var errorCode: Int {
return _swift_getDefaultErrorCode(self)
}

/// The default user-info dictionary.
var errorUserInfo: [String : Any] {
return [:]
}
}

extension CustomNSError where Self: RawRepresentable, Self.RawValue: SignedInteger {
// The error code of Error with integral raw values is the raw value.
public var errorCode: Int {
return numericCast(self.rawValue)
}
}

extension CustomNSError where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
// The error code of Error with integral raw values is the raw value.
public var errorCode: Int {
return numericCast(self.rawValue)
}
}

public extension Error where Self : CustomNSError {
/// Default implementation for customized NSErrors.
var _domain: String { return Self.errorDomain }
Expand All @@ -129,6 +160,18 @@ public extension Error where Self : CustomNSError {
var _code: Int { return self.errorCode }
}

public extension Error where Self: CustomNSError, Self: RawRepresentable,
Self.RawValue: SignedInteger {
/// Default implementation for customized NSErrors.
var _code: Int { return self.errorCode }
}

public extension Error where Self: CustomNSError, Self: RawRepresentable,
Self.RawValue: UnsignedInteger {
/// Default implementation for customized NSErrors.
var _code: Int { return self.errorCode }
}

public extension Error {
/// Retrieve the localized description for this error.
var localizedDescription: String {
Expand Down
23 changes: 22 additions & 1 deletion stdlib/public/core/ErrorType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,21 @@ public func _errorInMain(_ error: Error) {
fatalError("Error raised at top level: \(String(reflecting: error))")
}

/// Runtime function to determine the default code for an Error-conforming type.
@_silgen_name("swift_getDefaultErrorCode")
public func _swift_getDefaultErrorCode<T : Error>(_ x: T) -> Int

@available(*, unavailable, renamed: "Error")
public typealias ErrorType = Error

@available(*, unavailable, renamed: "Error")
public typealias ErrorProtocol = Error


extension Error {
public var _code: Int {
return _swift_getDefaultErrorCode(self)
}

public var _domain: String {
return String(reflecting: type(of: self))
}
Expand All @@ -204,3 +211,17 @@ extension Error {
#endif
}
}

extension Error where Self: RawRepresentable, Self.RawValue: SignedInteger {
// The error code of Error with integral raw values is the raw value.
public var _code: Int {
return numericCast(self.rawValue)
}
}

extension Error where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
// The error code of Error with integral raw values is the raw value.
public var _code: Int {
return numericCast(self.rawValue)
}
}
1 change: 1 addition & 0 deletions stdlib/public/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ set(swift_runtime_sources
Enum.cpp
ErrorObjectNative.cpp
Errors.cpp
ErrorDefaultImpls.cpp
Heap.cpp
HeapObject.cpp
KnownMetadata.cpp
Expand Down
59 changes: 59 additions & 0 deletions stdlib/public/runtime/ErrorDefaultImpls.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//===--- ErrorDefaultImpls.cpp - Error default implementations ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This implements helpers for the default implementations of Error protocol
// members.
//
//===----------------------------------------------------------------------===//

#include "swift/Runtime/Config.h"
#include "swift/Runtime/Metadata.h"
using namespace swift;

// @_silgen_name("swift_getDefaultErrorCode")
// func _swift_getDefaultErrorCode<T : Error>(_ x: T) -> Int
SWIFT_CC(swift) SWIFT_RT_ENTRY_VISIBILITY
extern "C" intptr_t swift_getDefaultErrorCode(OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error) {
intptr_t result;

switch (T->getKind()) {
case MetadataKind::Enum:
// Enum tags use negative values for payload cases, so adjust code to be
// in the range [0, num-cases).
result = T->vw_getEnumTag(error) +
T->getNominalTypeDescriptor()->Enum.getNumPayloadCases();
break;

case MetadataKind::Class:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
case MetadataKind::Function:
case MetadataKind::Struct:
case MetadataKind::Optional:
case MetadataKind::Opaque:
case MetadataKind::Tuple:
case MetadataKind::Existential:
case MetadataKind::Metatype:
case MetadataKind::ExistentialMetatype:
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
result = 1;
break;
}

// Destroy the value.
T->vw_destroy(error);
return result;
}
Loading