class indent in swift, history?


(Will Stanton) #1

Hello Chris and perhaps core team members,

The comments on tab-levels for `switch` made me want to ask about the considerations that went into class and protocol-level indentation.

Sorry if my wording isn’t precise, but in Objective-C, functions can (should) be at the same 0-indent level as the class:
@implementation Foo
// No indent!
- (void)doSomething {
}
@end

However, in Swift, method and nested types are indented by default:
class Foo : Bar {
  // Things indented!
  enum Types {
  }
  func doSomething() {
  }
}

Was the change mostly driven by the desire for protocol+class+struct+enum consistency in ‘increasing’ the scope+indent level? Were there other considerations?
Why didn’t the language evolve into something like this to reduce the use of horizontal whitespace, allowing class functions/types at the root/top level? Like:
@class Foo : Bar
enum Types {
}
func doSomething() {
}
@end

Regards,
Will Stanton

···

On Mar 7, 2017, at 12:52 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

I can understand how you might find this unnerving, but it is important to understand that Swift and Objective-C/C have different semantics when it comes to case labels: in Swift, a case label *is* a scope, and *is* part of the switch statement. In Objective-C, a case label is just a label, like any other goto label: it is not a scope and is not necessarily a direct child of the switch statement.

C and Objective-C’s behavior is what leads to obscure but important things like Duff’s device (https://en.wikipedia.org/wiki/Duff’s_device).

In contrast, Swift fixes the scoping, fallthrough, and other related problems all in one fell swoop, and ensures that cases are directly nested under the switch (unlike in C, where they can be nested under other statements within the switch). Because the case/default labels are *part of* the switch in Swift, it makes sense for them to be indented at the same level.

While I can respect that you aesthetically have a preference for the Objective-C way of doing things, the rationale for this behavior change wasn’t arbitrary and wasn’t due to "LLVM style". It is an important reflection of the core semantics of the language model.

Finally, conservation of horizontal whitespace is important for comprehension of code, particularly w.r.t. readability and maintenance. This is why statements like guard exist: to reduce nesting and indentation, directing the attention of someone reading and maintaining code to the important parts.


(Derrick Ho) #2

It might have to do with C history. Anything inside two curly braces
usually had an increased indentation level.

I always thought the switch statement was an oddball for not indenting the
cases.

···

On Tue, Mar 7, 2017 at 1:42 AM Will Stanton via swift-evolution < swift-evolution@swift.org> wrote:

Hello Chris and perhaps core team members,

The comments on tab-levels for `switch` made me want to ask about the
considerations that went into class and protocol-level indentation.

Sorry if my wording isn’t precise, but in Objective-C, functions can
(should) be at the same 0-indent level as the class:
@implementation Foo
// No indent!
- (void)doSomething {
}
@end

However, in Swift, method and nested types are indented by default:
class Foo : Bar {
        // Things indented!
        enum Types {
        }
        func doSomething() {
        }
}

Was the change mostly driven by the desire for protocol+class+struct+enum
consistency in ‘increasing’ the scope+indent level? Were there other
considerations?
Why didn’t the language evolve into something like this to reduce the use
of horizontal whitespace, allowing class functions/types at the root/top
level? Like:
@class Foo : Bar
enum Types {
}
func doSomething() {
}
@end

Regards,
Will Stanton

> On Mar 7, 2017, at 12:52 AM, Chris Lattner via swift-evolution < > swift-evolution@swift.org> wrote:
>
> I can understand how you might find this unnerving, but it is important
to understand that Swift and Objective-C/C have different semantics when it
comes to case labels: in Swift, a case label *is* a scope, and *is* part
of the switch statement. In Objective-C, a case label is just a label,
like any other goto label: it is not a scope and is not necessarily a
direct child of the switch statement.
>
> C and Objective-C’s behavior is what leads to obscure but important
things like Duff’s device (https://en.wikipedia.org/wiki/Duff’s_device).
>
> In contrast, Swift fixes the scoping, fallthrough, and other related
problems all in one fell swoop, and ensures that cases are directly nested
under the switch (unlike in C, where they can be nested under other
statements within the switch). Because the case/default labels are *part
of* the switch in Swift, it makes sense for them to be indented at the same
level.
>
> While I can respect that you aesthetically have a preference for the
Objective-C way of doing things, the rationale for this behavior change
wasn’t arbitrary and wasn’t due to “LLVM style”. It is an important
reflection of the core semantics of the language model.
>
> Finally, conservation of horizontal whitespace is important for
comprehension of code, particularly w.r.t. readability and maintenance.
This is why statements like guard exist: to reduce nesting and indentation,
directing the attention of someone reading and maintaining code to the
important parts.
>

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #3

Hi Will,

Good question: the general rationale is that true nesting implies indentation in Swift. Cases are not indented under “switch” because they are part of the switch statement, and, similarly, didSet is part of the property it is defined on. In contrast, nested types really are nested, they aren’t part of the enclosing declaration.

-Chris

···

On Mar 6, 2017, at 10:42 PM, Will Stanton <willstanton1@yahoo.com> wrote:

Hello Chris and perhaps core team members,

The comments on tab-levels for `switch` made me want to ask about the considerations that went into class and protocol-level indentation.

Sorry if my wording isn’t precise, but in Objective-C, functions can (should) be at the same 0-indent level as the class:
@implementation Foo
// No indent!
- (void)doSomething {
}
@end

However, in Swift, method and nested types are indented by default:
class Foo : Bar {
  // Things indented!
  enum Types {
  }
  func doSomething() {
  }
}

Was the change mostly driven by the desire for protocol+class+struct+enum consistency in ‘increasing’ the scope+indent level? Were there other considerations?
Why didn’t the language evolve into something like this to reduce the use of horizontal whitespace, allowing class functions/types at the root/top level? Like:
@class Foo : Bar
enum Types {
}
func doSomething() {
}
@end

Regards,
Will Stanton

On Mar 7, 2017, at 12:52 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

I can understand how you might find this unnerving, but it is important to understand that Swift and Objective-C/C have different semantics when it comes to case labels: in Swift, a case label *is* a scope, and *is* part of the switch statement. In Objective-C, a case label is just a label, like any other goto label: it is not a scope and is not necessarily a direct child of the switch statement.

C and Objective-C’s behavior is what leads to obscure but important things like Duff’s device (https://en.wikipedia.org/wiki/Duff’s_device).

In contrast, Swift fixes the scoping, fallthrough, and other related problems all in one fell swoop, and ensures that cases are directly nested under the switch (unlike in C, where they can be nested under other statements within the switch). Because the case/default labels are *part of* the switch in Swift, it makes sense for them to be indented at the same level.

While I can respect that you aesthetically have a preference for the Objective-C way of doing things, the rationale for this behavior change wasn’t arbitrary and wasn’t due to "LLVM style". It is an important reflection of the core semantics of the language model.

Finally, conservation of horizontal whitespace is important for comprehension of code, particularly w.r.t. readability and maintenance. This is why statements like guard exist: to reduce nesting and indentation, directing the attention of someone reading and maintaining code to the important parts.


(Saagar Jha) #4

I believe the indentation is more a signal for a new scope than curly braces. Swift doesn’t indent its switch cases since they’re a part of the same scope, while nested types and methods are a new scope.

Saagar Jha

···

On Mar 7, 2017, at 05:38, Derrick Ho via swift-evolution <swift-evolution@swift.org> wrote:

It might have to do with C history. Anything inside two curly braces usually had an increased indentation level.

I always thought the switch statement was an oddball for not indenting the cases.
On Tue, Mar 7, 2017 at 1:42 AM Will Stanton via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Chris and perhaps core team members,

The comments on tab-levels for `switch` made me want to ask about the considerations that went into class and protocol-level indentation.

Sorry if my wording isn’t precise, but in Objective-C, functions can (should) be at the same 0-indent level as the class:
@implementation Foo
// No indent!
- (void)doSomething {
}
@end

However, in Swift, method and nested types are indented by default:
class Foo : Bar {
        // Things indented!
        enum Types {
        }
        func doSomething() {
        }
}

Was the change mostly driven by the desire for protocol+class+struct+enum consistency in ‘increasing’ the scope+indent level? Were there other considerations?
Why didn’t the language evolve into something like this to reduce the use of horizontal whitespace, allowing class functions/types at the root/top level? Like:
@class Foo : Bar
enum Types {
}
func doSomething() {
}
@end

Regards,
Will Stanton

> On Mar 7, 2017, at 12:52 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> I can understand how you might find this unnerving, but it is important to understand that Swift and Objective-C/C have different semantics when it comes to case labels: in Swift, a case label *is* a scope, and *is* part of the switch statement. In Objective-C, a case label is just a label, like any other goto label: it is not a scope and is not necessarily a direct child of the switch statement.
>
> C and Objective-C’s behavior is what leads to obscure but important things like Duff’s device (https://en.wikipedia.org/wiki/Duff’s_device).
>
> In contrast, Swift fixes the scoping, fallthrough, and other related problems all in one fell swoop, and ensures that cases are directly nested under the switch (unlike in C, where they can be nested under other statements within the switch). Because the case/default labels are *part of* the switch in Swift, it makes sense for them to be indented at the same level.
>
> While I can respect that you aesthetically have a preference for the Objective-C way of doing things, the rationale for this behavior change wasn’t arbitrary and wasn’t due to “LLVM style”. It is an important reflection of the core semantics of the language model.
>
> Finally, conservation of horizontal whitespace is important for comprehension of code, particularly w.r.t. readability and maintenance. This is why statements like guard exist: to reduce nesting and indentation, directing the attention of someone reading and maintaining code to the important parts.
>

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #5

I'm not sure that it's Swift-specific, this just seems to be what Xcode does even if you're working in another language; I use Xcode to do PHP and Javascript as well (it's not the best for these but I already have it so it's an obvious choice), and it does the same thing for switch statements.

It's a matter of personal preference; personally I do indent switch cases but only if all of them are simple (i.e- the case and its content can be put on a single line without being too noisy looking), but if one or more of the cases are multi-line then I use the default (cases not indented, but contents are).

I think the point is that it's (sort of) one scope, since you can use the fallthrough keyword to process multiple cases if you want to, the switch and cases just determines at what point you dive into that scope.

It makes sense when you think about how switch statements actually execute; in essence the contents of each case are usually structured as one big lump of code, with jumps to break out of it once the case is complete. The switch itself is some form of conditional matching to pick which case is triggered, resulting in a jump to the correct location. While this is similar to how if statements work behind the scenes, you can't fall-through (only one branch is ever executed, never both).

···

On 7 Mar 2017, at 15:24, Saagar Jha via swift-evolution <swift-evolution@swift.org> wrote:

I believe the indentation is more a signal for a new scope than curly braces. Swift doesn’t indent its switch cases since they’re a part of the same scope, while nested types and methods are a new scope.


(Adrian Zubarev) #6

The latter slightly confused me for a second and I had to double check. You’re saying that cases are not indented “because” they are part of the switch statement, but observers like willSet and didSet are indented even if they are part of the property they are defined on. What’s the point I’m missing in this argument? (I’m precisely talking about the comparison between cases and observers, not about the indent elsewhere.)

···

--
Adrian Zubarev
Sent with Airmail

Am 8. März 2017 um 07:29:35, Chris Lattner via swift-evolution (swift-evolution@swift.org) schrieb:

Hi Will,

Good question: the general rationale is that true nesting implies indentation in Swift. Cases are not indented under “switch” because they are part of the switch statement, and, similarly, didSet is part of the property it is defined on. In contrast, nested types really are nested, they aren’t part of the enclosing declaration.

-Chris

On Mar 6, 2017, at 10:42 PM, Will Stanton <willstanton1@yahoo.com> wrote:

Hello Chris and perhaps core team members,

The comments on tab-levels for `switch` made me want to ask about the considerations that went into class and protocol-level indentation.

Sorry if my wording isn’t precise, but in Objective-C, functions can (should) be at the same 0-indent level as the class:
@implementation Foo
// No indent!
- (void)doSomething {
}
@end

However, in Swift, method and nested types are indented by default:
class Foo : Bar {
// Things indented!
enum Types {
}
func doSomething() {
}
}

Was the change mostly driven by the desire for protocol+class+struct+enum consistency in ‘increasing’ the scope+indent level? Were there other considerations?
Why didn’t the language evolve into something like this to reduce the use of horizontal whitespace, allowing class functions/types at the root/top level? Like:
@class Foo : Bar
enum Types {
}
func doSomething() {
}
@end

Regards,
Will Stanton

On Mar 7, 2017, at 12:52 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

I can understand how you might find this unnerving, but it is important to understand that Swift and Objective-C/C have different semantics when it comes to case labels: in Swift, a case label *is* a scope, and *is* part of the switch statement. In Objective-C, a case label is just a label, like any other goto label: it is not a scope and is not necessarily a direct child of the switch statement.

C and Objective-C’s behavior is what leads to obscure but important things like Duff’s device (https://en.wikipedia.org/wiki/Duff’s_device).

In contrast, Swift fixes the scoping, fallthrough, and other related problems all in one fell swoop, and ensures that cases are directly nested under the switch (unlike in C, where they can be nested under other statements within the switch). Because the case/default labels are *part of* the switch in Swift, it makes sense for them to be indented at the same level.

While I can respect that you aesthetically have a preference for the Objective-C way of doing things, the rationale for this behavior change wasn’t arbitrary and wasn’t due to "LLVM style". It is an important reflection of the core semantics of the language model.

Finally, conservation of horizontal whitespace is important for comprehension of code, particularly w.r.t. readability and maintenance. This is why statements like guard exist: to reduce nesting and indentation, directing the attention of someone reading and maintaining code to the important parts.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Will Stanton) #7

Hello Chris, and all,

Thanks for the replies and explanation!

There have been moments when I felt like it would be nice if most functions could start at the 1-indent level. But I think I agree: true/consistent nesting is good motivation for the additional indent level. Still, in those times, I wondered why Swift wasn’t more Obj-C-like. So, now I know, and thanks again!

Regards,
Will Stanton

···

On Mar 8, 2017, at 1:29 AM, Chris Lattner <clattner@nondot.org> wrote:

Hi Will,

Good question: the general rationale is that true nesting implies indentation in Swift. Cases are not indented under “switch” because they are part of the switch statement, and, similarly, didSet is part of the property it is defined on. In contrast, nested types really are nested, they aren’t part of the enclosing declaration.

-Chris

On Mar 6, 2017, at 10:42 PM, Will Stanton <willstanton1@yahoo.com> wrote:

Hello Chris and perhaps core team members,

The comments on tab-levels for `switch` made me want to ask about the considerations that went into class and protocol-level indentation.

Sorry if my wording isn’t precise, but in Objective-C, functions can (should) be at the same 0-indent level as the class:
@implementation Foo
// No indent!
- (void)doSomething {
}
@end

However, in Swift, method and nested types are indented by default:
class Foo : Bar {
  // Things indented!
  enum Types {
  }
  func doSomething() {
  }
}

Was the change mostly driven by the desire for protocol+class+struct+enum consistency in ‘increasing’ the scope+indent level? Were there other considerations?
Why didn’t the language evolve into something like this to reduce the use of horizontal whitespace, allowing class functions/types at the root/top level? Like:
@class Foo : Bar
enum Types {
}
func doSomething() {
}
@end

Regards,
Will Stanton

On Mar 7, 2017, at 12:52 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

I can understand how you might find this unnerving, but it is important to understand that Swift and Objective-C/C have different semantics when it comes to case labels: in Swift, a case label *is* a scope, and *is* part of the switch statement. In Objective-C, a case label is just a label, like any other goto label: it is not a scope and is not necessarily a direct child of the switch statement.

C and Objective-C’s behavior is what leads to obscure but important things like Duff’s device (https://en.wikipedia.org/wiki/Duff’s_device).

In contrast, Swift fixes the scoping, fallthrough, and other related problems all in one fell swoop, and ensures that cases are directly nested under the switch (unlike in C, where they can be nested under other statements within the switch). Because the case/default labels are *part of* the switch in Swift, it makes sense for them to be indented at the same level.

While I can respect that you aesthetically have a preference for the Objective-C way of doing things, the rationale for this behavior change wasn’t arbitrary and wasn’t due to "LLVM style". It is an important reflection of the core semantics of the language model.

Finally, conservation of horizontal whitespace is important for comprehension of code, particularly w.r.t. readability and maintenance. This is why statements like guard exist: to reduce nesting and indentation, directing the attention of someone reading and maintaining code to the important parts.


(Haravikk) #8

willSet and didSet have their own distinct scope; they execute independently, however a switch statement is effectively a single scope because of the ability to use fallthrough to visit later cases.

To try and illustrate, consider the following switch statement:

  switch(foo) {
  case 1:
    print("Case 1")
  case 2:
    print("Case 2")
    fallthrough
  default:
    print("Default")
  }

If foo is equal to 2, the output will be both "Case 2" and "Default". Another way to think of this is in terms of how a switch statement actually executes, the above would become something resembling the following (using rough pseudo-code):

  if (foo == 1) jump @case1
  else if (foo == 2) jump @case2
  else jump @default

  @case1
  print("Case 1")
  jump @end
  @case2
  print("Case 2")
  // no jump because of fallthrough
  @default
  print("Default")
  jump @end

  @end

I don't know if that helps clear it up, but while syntactically a switch statement's cases are grouped with the code that they trigger, this is just because it's easier to work with; in reality the entire content of the switch is one contiguous run of code that you jump into (and possibly out of) as determined by some form of test at the start. The ability for a case to fallthrough (no jump to the end) means that it's possible to execute multiple cases, unlike an if-statement where only one branch is ever executed.

The lack of indentation is a good reminder that a case should be thought of more as a label, and that its condition is actually checked at the switch(foo) part of the construct.

···

On 8 Mar 2017, at 08:35, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

The latter slightly confused me for a second and I had to double check. You’re saying that cases are not indented “because” they are part of the switch statement, but observers like willSet and didSet are indented even if they are part of the property they are defined on. What’s the point I’m missing in this argument? (I’m precisely talking about the comparison between cases and observers, not about the indent elsewhere.)


(Chris Lattner) #9

I was confused by an apparent bug in SourceKit. It looks like top level properties are indented like this:

var zzd : Int = 12 {
didSet {
  print(42)
}
}

But that didSet/willSet are indented when inside of a class:

  var zzd : Int = 12 {
    didSet {
      print(42)
    }
  }

This should clearly be consistent, and the second is the right way to do it, but this behavior invalidates my argument. The new argument I’d make is that things with braces should definitely be indented :-). I retain the argument that cases are “part of” the switch statement itself.

-Chris

···

On Mar 8, 2017, at 12:35 AM, Adrian Zubarev <adrian.zubarev@devandartist.com> wrote:

The latter slightly confused me for a second and I had to double check. You’re saying that cases are not indented “because” they are part of the switch statement, but observers like willSet and didSet are indented even if they are part of the property they are defined on. What’s the point I’m missing in this argument? (I’m precisely talking about the comparison between cases and observers, not about the indent elsewhere.)


(Rob Mayoff) #10

A switch statement has a separate scope for every case, including default.
Example:

switch Int() {
case 0:
    let m = "zero"
    fallthrough
default:
    Swift.print(m)
}

Result:

Playground execution failed: error: MyPlayground.playground:2:17: error:
use of unresolved identifier 'm'
    Swift.print(m)

···

On Wed, Mar 8, 2017 at 5:09 AM, Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

willSet and didSet have their own distinct scope; they execute
independently, however a switch statement is effectively a single scope
because of the ability to use fallthrough to visit later cases.


(Adrian Zubarev) #11

Wow the former looks very odd to me. Sure, there are these edge cases across the language which are inconsistent. I myself have filed a bug to always add a trailing space after an operator in operator function for readability and to allow ligatures to render correctly in cases like func == <… compared to func ==<… (but the idea was to add always a space after the operator in functions, even for func == (…). This would add another inconsistency if we’re speaking precisely about function declarations, but I think it’s a valuable tradeoff, especially if you consider that operator functions have it’s own special rule when it comes to the function labels.

I must disagree about braces. To me everything which is multi-lined and inside braces *should* be indented even if the inner part is *part of* the outer statement itself, because that behavior is consistent across the whole language (if we’re not speaking about comment styles).

You can easily imagine a switch statement without braces with some kind of end or endswitch to indicate the end of the statement. Such a switch statement would clearly not need any indent for it’s cases, however I believe most of us felt odd learning Swift and realizing our switch cases are not indented. Don’t get me wrong here, I myself hardly learned to life with that behavior. :wink: However sometimes, when I want to write small cases in one line the switch statement looks very odd with its closing brace.

// without braces
switch ab

case .a:
   print("a")
    
case .b:
   print("b")
    
endswitch

// VS. our switch statement
// and aligned results (not necessarily needed)
switch ab {
case .a: print("a")
case .b: print("b")
}

// Without the alignment it doesn't feel that odd anymore
switch ab {
case .a:
   print("a")
case .b:
   print("b")
}

// But the aligned version cries for indent here
switch ab {
   case .a: print("a")
   case .b: print("b")
}

···

--
Adrian Zubarev
Sent with Airmail

Am 9. März 2017 um 06:25:21, Chris Lattner (clattner@nondot.org) schrieb:

On Mar 8, 2017, at 12:35 AM, Adrian Zubarev <adrian.zubarev@devandartist.com> wrote:

The latter slightly confused me for a second and I had to double check. You’re saying that cases are not indented “because” they are part of the switch statement, but observers like willSet and didSet are indented even if they are part of the property they are defined on. What’s the point I’m missing in this argument? (I’m precisely talking about the comparison between cases and observers, not about the indent elsewhere.)

I was confused by an apparent bug in SourceKit. It looks like top level properties are indented like this:

var zzd : Int = 12 {
didSet {
print(42)
}
}

But that didSet/willSet are indented when inside of a class:

var zzd : Int = 12 {
didSet {
print(42)
}
}

This should clearly be consistent, and the second is the right way to do it, but this behavior invalidates my argument. The new argument I’d make is that things with braces should definitely be indented :-). I retain the argument that cases are “part of” the switch statement itself.

-Chris


(Haravikk) #12

I think I'm using the term scope in a confusing way, but I think I thought of a better way to explain it anyway:

When it comes to indenting the switch, the switch itself, and its cases, are actually all part of the same "level", because they're actually a leading conditional plus a bunch of labels to jump to, no new scope has occurred yet. It's only once you've jumped to a label that any kind of narrowing can actually occur.

To go back to my example of how a switch statement actually works, here's what it looks like again with jumps and labels, this time with case contents indented to show variable scope:

  if (foo == 1) jump @case1
  else if (foo == 2) jump @case2
  else jump @default

  @case1
    print("Case 1")
    jump @end
  @case2
    print("Case 2")
    // no jump because of fallthrough
  @default
    print("Default")
    jump @end
  @end

Perhaps the term block would have been better; the switch contents are a contiguous block of code that you jump into, the variable scope occurs because you can't guarantee that a previous case was visited and fell through. Thus the case conditions/labels themselves are not of a more limited scope because they're testing for and setting up a jump to the correct location. Just like how an if statement's condition isn't indented, because they're essentially the same thing.

···

On 8 Mar 2017, at 17:23, Rob Mayoff via swift-evolution <swift-evolution@swift.org> wrote:

On Wed, Mar 8, 2017 at 5:09 AM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
willSet and didSet have their own distinct scope; they execute independently, however a switch statement is effectively a single scope because of the ability to use fallthrough to visit later cases.

A switch statement has a separate scope for every case, including default. Example:

switch Int() {
case 0:
    let m = "zero"
    fallthrough
default:
    Swift.print(m)
}

Result:

Playground execution failed: error: MyPlayground.playground:2:17: error: use of unresolved identifier 'm'
    Swift.print(m)