13

I'm using the Nimble assertion framework for unit testing in Swift (Xcode 6.3 beta). It works fine, but the compiler gives a warning for one of the lines in the Nimble source code:

public func expect<T>(expression: () -> T?, file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T> {
    return Expectation(
        expression: Expression(
            expression: expression,
            location: SourceLocation(file: file, line: line),
            isClosure: true))
}

The warning is for the first line:

Closure parameter prior to parameters with default arguments will not be treated as a trailing closure

It's not a very serious issue, but I'd like to keep the number of compiler warnings low (zero) in my projects. Is there a way to remove this warning?

Community
  • 1
  • 1
Bedford
  • 1,136
  • 2
  • 12
  • 36

4 Answers4

25

You can avoid the warning if the method signature will look like:

public func expect<T>(expression: (() -> T?), file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T> 

added extra parenthesis around the first argument, tested with Swift 2.0 and Xcode 7.1

Another way of fixing it is to have all attributes with default value before the closure attribute as trailing closure is a quite convenient thing to have

Julian
  • 9,299
  • 5
  • 48
  • 65
3

@Julian Król answer is wrong for two reasons:

  1. the code snippet demonstrate the wrong syntax, the correct will be:

public func expect<T>(expression: (() -> T?), file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T>

  1. even with right syntax in Xcode 7.1 it does not fix the issue, cause you can not call this methods with trailing closure- it will give you compile error like Missing argument for parameter #1 in call.

With provided code you will only get rid of warning but you will not be able to use trailing closure when you call this function.

It fixes warning because in Swift tuple with one child is interchangeable with just single variable. And even ((((value)))) is the same as just value. Also looks like compiler does not recognize tuple with closure child as standalone closure in function arguments list.

Ilya Puchka
  • 141
  • 1
  • 9
  • thanks for correcting me, I mistyped it, anyway I would put the closure as a last attribute to be able to use the trailing thing if any attribute with default value is on the list. Fixed my answer, upvote for a good eye :) – Julian Nov 19 '15 at 21:39
-1

To all the future readers of this topic: the answer is just for the case, when you have trailing closures. AFAIK, there is no way you can suppress Swift warnings like you would do in Objective-C (disable warnings for specific lines), maybe when the source of the Swift compiler will be open source, there will be some valid solutions, and this answer will be updated. Until then, you can check these answers (not Swift specific):

In Xcode, how to suppress all warnings in specific source files?

Is there a way to suppress warnings in Xcode?

If you can change the signature of expect, then put the parameter expression to the end, like:

public func expect<T>(file: String = __FILE__, line: UInt = __LINE__, expression: () -> T?) -> Expectation<T>

To be honest, it is poor design to have a closure parameter as the first parameter.

Community
  • 1
  • 1
Dániel Nagy
  • 11,815
  • 9
  • 50
  • 58
  • 2
    Thank you. I'm new to Swift and I thought arguments with default values must stay at the end of the argument list. – Bedford Mar 15 '15 at 16:42
  • 1
    I think arguments with default values should be at the end of the list, too. If you have a closure AND default arguments, that makes this warning unavoidable. – SimplGy Jun 04 '15 at 11:24
  • @SimplGy I agree, but in this case you can do this workaround. But it is defenitely a better style to have the default values at the end of the parameter list. – Dániel Nagy Jun 04 '15 at 11:26
  • 1
    I think you suggest changing the underlying library? That's not a workaround. I would like to write a function in my own code that has a closure, then default params. Is there a workaround that allows me to do this? I don't think I can squelch that warning. – SimplGy Jun 04 '15 at 12:08
  • @SimplGy in that case there is no workaround. Or if it is, I would be happy to know what is it. – Dániel Nagy Jun 04 '15 at 12:17
  • I am sorry, but this cannot be the right answer, for two reasons. 1) The question was not about avoiding the warning, but supressing the compiler warning. 2) Sometime you can't change the signature, because you either do not own the code, or sometime you have to have it this way (for example, if you want an optional parameter as well -which as to be at the end-). I am not sure why this answer was marked as correct. – Jeremy Chone Jul 08 '15 at 17:02
  • @JeremyChone because it solved the OPs problem:) In this very case, it worked, although it is not a general solution for the problem. – Dániel Nagy Jul 08 '15 at 19:41
  • 1
    @DánielNagy it's a workaround, and I am not sure we should mark workaround answers as the correct ones. Also, I am not sure we should recommend new developers to fork an external library to supress a compiler warning. I have been searching google for a while to supress swift warning, and it is not an easy task, and ironically this post comes on top of most search, which is frustrating because the question was spot on , but the answer is a bad workaround IMO. This should been a comment at best. – Jeremy Chone Jul 08 '15 at 22:51
  • Downvoted this answer because it's a workaround, and doesn't solve the general problem. – Andrew Theken Jul 17 '15 at 13:23
  • @JeremyChone, were you able to figure it out? I'm unable to find a way to suppress swift compiler warning. – Zmey Sep 05 '15 at 18:47
-2

Looks like a very serious warning to me, that you most definitely should not ignore. It seems that what you think is a function call with a closure parameter is actually a function call without a closure parameter, followed by a closure.

You easily avoid the warning and fix the problem by putting the closure into the parameter list, or assigning it to a variable before the call and passing that variable.

gnasher729
  • 51,477
  • 5
  • 75
  • 98