Acknowledged

bug: strict type checker fails to compile code that checks existence of function using "has" and involves background code

import Toybox.Application;
import Toybox.Lang;
import Toybox.WatchUi;

(:background)
class MyApp extends Application.AppBase {
    hidden var view as MyView?;

    function initialize() {
        AppBase.initialize();
    }

    (:typecheck(false))
    function getInitialView() as Array<Views or InputDelegates>? {
        self.view = new MyView();
        return [ self.view ] as Array<Views or InputDelegates>;
    }

    function onSettingsChanged() as Void {
        if (view != null && isRunningInForeground()) {
            view.onSettingsChanged(1);
        }
    }
}

(:background)
function isRunningInForeground() as Boolean {
    return $ has :getApp;
}

function getApp() as GoalDFApp {
    return Application.getApp() as GoalDFApp;
}

class MyView extends WatchUi.Datafield {
    function initialize() {
        onSettingsChanged(0);
    }

    public function onSettingsChanged(settingsChangedFrom as Number) as Void {
    }
}

When compiling with 

project.typecheck = 3
I get these errors:
ERROR: fr955: MyApp.mc:65,12: Value 'onSettingsChanged' not available in all function scopes.
ERROR: fr955: MyApp.mc:65,12: Cannot find symbol ':onSettingsChanged' on type 'Null'.
However when setting typecheck to 0, 1 or 2 it compiles.

See: https://forums.garmin.com/developer/connect-iq/f/discussion/371237/value-onsettingschanged-not-available-in-all-function-scopes/

SDK 7.1.1

UPDATE: actually there's another similar bug. When I change the code to be system7 compatible:

    function getInitialView() as [Views] or [ Views, InputDelegates ] {
        view = new MyView();
        return [ self.view ];
    }

then with typecheck:3 I get:

ERROR: fr955: MyApp.mc:33,8: Value 'MyView' not available in all function scopes.
ERROR: fr955: MyApp.mc:33,8: Value 'initialize' not available in all function scopes.

UPDATE2:

even if I add 

(:typecheck(disableBackgroundCheck)) then the null check fails:
    (:typecheck(disableBackgroundCheck))
    function onSettingsChanged() as Void {
        if (view != null && isRunningInForeground()) {
            view.onSettingsChanged(1);
        }
    }
ERROR: fr955: MyApp.mc:70,12: Cannot find symbol ':onSettingsChanged' on type 'Null'.
  • classes that inherit from it should also inherit the annotations

    That's a tough one as annotations currently aren't inherited. If they were inherited in all cases, that would cause obvious problems. If they are only inherited in this case, that would be a different issue.

  • And I'll add, that Application.AppBase should have these annotations (implicit or explicit) and classes that inherit from it should also inherit the annotations. So getInitialView() method should be even loaded in foreground and glance, but not in background.

  • > a built-in foreground annotation

    Or a "not_background" annotation. ("foreground" would be problematic since things that are marked as glance and background are also present in the foreground.)

  • It seems that CIQ could either use:
    - a built-in foreground annotation

    - or even better, a way to negate annotations (so you could annotate a symbol as (not :background))

  • Not to state the obvious, but the type checker is upset because a function that exists in both BG and FG scopes (such as onSettingsChanged) is referring to things that only exist in the FG scope. The problem is that once you annotate a class as background, it's seemingly impossible to indicate that any of its members are foreground-only.

    For the same reason, getInitialView() will also fail to compile if the typecheck(false) annotation is removed and the return type is fixed.