swifto
February 14, 2025, 3:26pm
1
Is there a way to provide a default case enum with argument.
The output of the below code is
Example Optional("admin")
Example Optional(main.UserType.userDefault))
If I print example?.rawValue
I get userDefault
, however is there a way to deifine args to the type for example something like
static var userDefault: Self(String) { get }
protocol DefaultCase: Equatable, CaseIterable, Decodable where Self: RawRepresentable {
static var userDefault: Self { get }
}
extension DefaultCase where RawValue: Decodable, RawValue: Equatable {
init?(rawValue: RawValue) {
self = Self.allCases.filter { $0.rawValue == rawValue }.first ?? .userDefault
}
init(from decoder: any Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(RawValue.self)
self = .init(rawValue: rawValue) ?? Self.userDefault
}
}
enum UserType: String, Codable, DefaultCase {
case admin
case user
case userDefault
}
var example = UserType(rawValue: "admin")
print("Example \(String(describing: example?.rawValue))")
example = UserType(rawValue: "asdas")
print("Example \(example?.rawValue))")
1 Like
Danny
February 14, 2025, 11:02pm
2
I'm trying to figure out if you're asking about enum cases with associated values. Can you elaborate?
(If not, this doesn't need to be restricted to enumerations.)
protocol InitializableFromAnyRawValue: RawRepresentable {
init()
}
extension InitializableFromAnyRawValue {
// You don't get to use the automatically-synthesized overload,
// if you just take away failability,
// rather than using a different signature.
init(_ rawValue: RawValue) {
self = .init(rawValue: rawValue) ?? .init()
}
}
extension InitializableFromAnyRawValue where Self: Decodable, RawValue: Decodable {
init(from decoder: any Decoder) throws {
self.init(try decoder.singleValueContainer().decode(RawValue.self))
}
}
extension UserType: InitializableFromAnyRawValue {
init() { self = .userDefault }
}
Pippin
(Ethan Pippin)
February 15, 2025, 1:28am
3
A macro that adds the default case and the initializers could theoretically work, however made an issue a while ago that adding a case is currently buggy.
opened 10:15PM - 16 Oct 23 UTC
bug
triage needed
**Description**
Attached member macro unable to add new cases to an enum when t… he enum conforms to a raw value.
**Steps to reproduce**
With the following implementation:
```swift
@attached(member, names: named(bar))
public macro AddEnumCase() = #externalMacro(module: "MyProjectMacrosMacros", type: "AddEnumCaseMacro")
public struct AddEnumCaseMacro: MemberMacro {
public static func expansion(
of node: AttributeSyntax,
providingMembersOf declaration: some DeclGroupSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
let newElement = try EnumCaseDeclSyntax("case bar")
return [DeclSyntax(newElement)]
}
}
// usage
@AddEnumCase
enum Foo: Int {
case swift
}
```
**Expected behavior**
Enum with added `bar` case
**Actual behavior**
<details>
<summary>Stack Trace</summary>
```
1. Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1)
2. Compiling with the current language version
3. While evaluating request ASTLoweringRequest(Lowering AST to SIL for module MyProjectMacrosClient)
4. While silgen emitValueConstructor SIL function "@$s21MyProjectMacrosClient3FooO8rawValueACSgSi_tcfC".
for 'init(rawValue:)' (in module 'MyProjectMacrosClient')
5. While evaluating request BodyInitKindRequest(MyProjectMacrosClient.(file).Foo.init(rawValue:))
6. While evaluating request ParseAbstractFunctionBodyRequest(MyProjectMacrosClient.(file).Foo.init(rawValue:))
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 swift-frontend 0x0000000102dcb14c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x0000000105949f2c llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x000000010168b10c SignalHandler(int) + 352
3 libsystem_platform.dylib 0x000000018d33da24 _sigtramp + 56
4 swift-frontend 0x00000001026e5760 deriveBodyRawRepresentable_init(swift::AbstractFunctionDecl*, void*) + 1012
5 swift-frontend 0x00000001026e5760 deriveBodyRawRepresentable_init(swift::AbstractFunctionDecl*, void*) + 1012
6 swift-frontend 0x0000000102fcfcac swift::SimpleRequest<swift::ParseAbstractFunctionBodyRequest, swift::BodyAndFingerprint (swift::AbstractFunctionDecl*), (swift::RequestFlags)4>::evaluateRequest(swift::ParseAbstractFunctionBodyRequest const&, swift::Evaluator&) + 296
7 swift-frontend 0x0000000103376e7c swift::ParseAbstractFunctionBodyRequest::OutputType swift::evaluateOrDefault<swift::ParseAbstractFunctionBodyRequest>(swift::Evaluator&, swift::ParseAbstractFunctionBodyRequest, swift::ParseAbstractFunctionBodyRequest::OutputType) + 1136
8 swift-frontend 0x000000010330f320 swift::AbstractFunctionDecl::getBody(bool) const + 304
9 swift-frontend 0x00000001029d2db8 swift::BodyInitKindRequest::evaluate(swift::Evaluator&, swift::ConstructorDecl*) const + 160
10 swift-frontend 0x00000001035c1d7c llvm::Expected<swift::BodyInitKindRequest::OutputType> swift::Evaluator::getResultCached<swift::BodyInitKindRequest, (void*)0>(swift::BodyInitKindRequest const&) + 1328
11 swift-frontend 0x0000000103364d20 swift::ConstructorDecl::getDelegatingOrChainedInitKind() const + 132
12 swift-frontend 0x00000001007d88b4 swift::Lowering::SILGenFunction::emitValueConstructor(swift::ConstructorDecl*) + 468
13 swift-frontend 0x00000001007a089c swift::Lowering::SILGenModule::emitFunctionDefinition(swift::SILDeclRef, swift::SILFunction*) + 7572
14 swift-frontend 0x00000001030ad63c emitOrDelayFunction(swift::Lowering::SILGenModule&, swift::SILDeclRef) (.llvm.12369091251732681984) + 168
15 swift-frontend 0x00000001030ae598 swift::Lowering::SILGenModule::emitConstructor(swift::ConstructorDecl*) + 336
16 swift-frontend 0x000000010385dbb4 (anonymous namespace)::SILGenType::emitType() (.llvm.16014246188637114379) + 228
17 swift-frontend 0x0000000103092c64 swift::ASTVisitor<swift::Lowering::SILGenModule, void, void, void, void, void, void>::visit(swift::Decl*) + 104
18 swift-frontend 0x00000001030bc608 swift::ASTLoweringRequest::evaluate(swift::Evaluator&, swift::ASTLoweringDescriptor) const + 2908
19 swift-frontend 0x0000000101ce44fc swift::SimpleRequest<swift::ASTLoweringRequest, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>> (swift::ASTLoweringDescriptor), (swift::RequestFlags)9>::evaluateRequest(swift::ASTLoweringRequest const&, swift::Evaluator&) + 200
20 swift-frontend 0x00000001030da948 llvm::Expected<swift::ASTLoweringRequest::OutputType> swift::Evaluator::getResultUncached<swift::ASTLoweringRequest>(swift::ASTLoweringRequest const&) + 584
21 swift-frontend 0x00000001030be3c8 swift::performASTLowering(swift::ModuleDecl*, swift::Lowering::TypeConverter&, swift::SILOptions const&, swift::IRGenOptions const*) + 152
22 swift-frontend 0x0000000105901df8 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 2992
23 swift-frontend 0x0000000105905474 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4568
24 swift-frontend 0x000000010524b4e0 swift::mainEntry(int, char const**) + 4116
25 dyld 0x000000018cf95058 start + 2224
LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted
Command SwiftEmitModule failed with a nonzero exit code
```
</details>
**Environment**
- `swift-driver version: 1.87.1 Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1)
Target: arm64-apple-macosx14.0`
- `Xcode 15.0 Build version 15A240d`
- Deployment target: `macOS 14.0`