skip icon indicating copy to clipboard operation
skip copied to clipboard

`.environment(\.font, .custom(...))` type inference fails with a confusing error message

Open dfabulich opened this issue 10 months ago • 4 comments

In SwiftUI, you can use the .environment() modifier to set a custom default font, like this:

.environment(\.font, .custom("Protest Guerrilla", size: 30.0))

But Skip has a type inference bug in this code: you have to call it with Font.custom() and not with simply .custom(), or it will fail to compile on Android.

I know that type-inference bugs are something I just have to deal with in Skip, but instead of saying, "Cannot infer type for this parameter", I get a really cryptic error message.

To reproduce this bug, I forked the Showcase app https://github.com/dfabulich/skipapp-showcase/tree/environment-font-bug-example and added a one-line commit: https://github.com/dfabulich/skipapp-showcase/commit/4d55295eeccc98e66e33a313b59d27ace864779c

Expected: Build fails with "Cannot infer type for this parameter" error

Actual:

Argument type mismatch: actual type is 'kotlin.Function1<ERROR CLASS: Unknown return lambda parameter type, ERROR CLASS: Unknown return lambda parameter type>', but 'kotlin.String' was expected.

dfabulich avatar Feb 19 '25 19:02 dfabulich

Thanks for the report. Could also use .font(.custom...)

aabewhite avatar Feb 19 '25 19:02 aabewhite

Could also use .font(.custom...)

.font(.custom…) does work, and the type is correctly inferred, but the whole point of setting the environment() font is that it applies to all subviews recursively, so I don't have to add .font(.custom("My Font", size: 15)) on every Text() view in my app.

dfabulich avatar Feb 19 '25 23:02 dfabulich

I think there's a misunderstanding. .font(_:) is defined on View and establishes the default font for everything in the View. It is exactly equivalent to .environment(.font, ...)

The same pattern applies to most SwiftUI modifiers - it is very rare to need to set .environment(.key, ...) directly

aabewhite avatar Feb 20 '25 05:02 aabewhite

TIL! https://developer.apple.com/documentation/swiftui/view/font(_:)

Font information flows down the view hierarchy as part of the environment, and remains in effect unless overridden at the level of an individual view or view container.

So, I guess the .font() modifier just makes an .environment call under the hood…?

FWIW, this is the top hit in Google Search for changing the default font. https://stackoverflow.com/a/75992302/54829

So I think this issue is still a bit of a footgun for folks who don't know that .font() affects the environment.

dfabulich avatar Feb 21 '25 01:02 dfabulich