Swift Cannot Infer Type from Context

Swift cannot infer type from context

This question can only really be answered by a compiler engineer at Apple, and per the above commenters it could / should be considered a bug, but it is definitely a hole in their shorthand syntax. For questions like these, I have gotten good results from posting to devforums.

The simple rule though is that whenever you have multiple lines / need to use the return keyword, you must either explicitly define the return type, or the type of the value being captured. This limitation might be due to the fact that in the compact / degenerate case, you are guaranteed to only have one point of exit - val in val, where as when you use a return keyword, it is possible to have multiple return points. In this latter case, you might return an Int on one line return 1, and return nil on another. In that case, it would be reasonable to have the compiler complain to make the assumption explicit. In short, this would require more sophisticated type inference in the compiler, and they might not have gotten to that yet.

So TL;DR, I agree with the suggestion to report this as a bug, and in the meantime, specify a return type from the closure. The point remains though that the compiler has enough context to infer the correct type, as you stated.

Note, that in addition to your example, these cases also work:

// inferring var dict as a context for lines below
var dict = arrayToDictionary([1, 2, 3], { val in val })

// dict is already defined, so this works:
dict = arrayToDictionary([1, 2, 3], { val in return val })

// explicit final type, compiler infers backwards
let d2:Dictionary<Int, Int> = arrayToDictionary([1, 2, 3], { val in val })

// explicit return type, compiler infers "forewards"
let d3 = arrayToDictionary([1, 2, 3], { val -> Int in return val })

SwiftUI: Cannot infer contextual base in reference to member

As @jnpdx is referring to with the Xcode versions, the Swift version may not be the same. In Swift 5.4, SE-0287 was implemented.

This proposal allowed for implicit member chains. You can read more on the proposal linked, but this sums it up pretty well:

This proposal suggests the expansion of implicit member syntax to more complex expressions than just a single static member or function. Specifically, implicit member syntax would be allowed to cover chains of member references.

Code such as Color.red.opacity(0.5) can now be simplified to .red.opacity(0.5), similar to in your example.

Xcode 12.5 is required to use Swift 5.4, so let the team know to upgrade.

unable to infer type in flatMap

From what I can see in your code... you haven't told it what result is. Even reading it as a human I can't tell what it is supposed to be.

Your fetchData function returns an AnyPublisher of generic type T.

Your getCountryStats function takes that generic type T into a flatMap function and returns an AnyPublisher of type [CountryDayOneResponse].

But at no point do you tell it what T is. You don't even tell it what result is. Only the output of the flatMap function.

What is the type of result expected to be?

Edit after comment.

If you want your result to be [CountryOneDayResponse] then this code will do...

func getCountryStats(for countryName: String) -> AnyPublisher<[CountryDayOneResponse], ErrorType> {
let url = RestEndpoints.countryStats(countryName: countryName).endpoint()

let publisher: AnyPublisher<[CountryDayOneResponse], ErrorType> = NetworkManager().fetchData(url: url)

return publisher
.flatMap{ Just(Array($0.sorted(by: {$0.date > $1.date}))) }
.eraseToAnyPublisher()
}

You don't need to switch on the result like you are doing in the flatMap as the flatMap will only be entered if the publisher returns a non-error. So you can treat the input of the flatMap as the success type of the publisher [CountryOneDayResponse].

Unable to infer closure type in the current context

The reason why it is not inferring the closure type is because the try statement is not handled. This means that the closure expected to "catch" the error, but in your case, you forgot the do-try-catch rule.

Therefore you can try the following answer which will catch your errors:

do {
let imageAsData = try Data(contentsOf: imageURL)
let image = UIImage(data: imageAsData)
let ImageObject = Image()
ImageObject.image = image
self.arrayOfImgObj.append(ImageObject)
} catch {
print("imageURL was not able to be converted into data") // Assert or add an alert
}

You can then assert an error (for testing), or what I would personally do, is set up an alert.

This way the app wouldn't crash, but instead, notify the user. I find this very helpful when on the go and my device isn't plugged in - so I can see the error messages instead of a blank crash with no idea what happened.



Related Topics



Leave a reply



Submit