Cannot determine if container access is using container type

I'm getting a warning:

"Cannot determine if container access is using container type"

Using SDK 8.3.0

What can I do to get rid of that warning?
(What is the container type in that case?)

The code works perfectly!

Thanks for helping!

  • add casting shifterArray[i] as Whatever

    or maybe you need: (shifterArray as ShifterArray)[i]

  • But if bikeShifter.getComponentIdentifiers() is the API method AntPlus.Device.getComponentIdentifiers(), it should already be typed to to return Array<Number>.

    If it is in fact a non-API function, then the real solution is for that function to return the correct type.

    I say this all the time, but casting in Monkey C is very dangerous (and misleading). I would avoid making a habit of thoughtlessly adding casts to fix whatever type problems may come up, because if you do this all the time, it can obscure real problems. And it also defeats the purpose of type checking in the first place. (Monkey C lets you cast any type to any other type, so you could banish almost any type error using a cast, but it's often not the right thing to do.)

    The worst design decision of Monkey Types was to make type declarations and type casts use the same keyword (as), because type declarations make your code safer, while type casts make your code more dangerous.

    I don't even know if there's any other language which uses such similar-looking syntax to do those 2 things which are almost completely opposite (in a few senses).

    (What is the container type in that case?)

    What do you see if you hover over shifterArray? (e.g. on the line starting with "var shifterArray = ...")

    That's the type the compiler thinks shifterArray is.

    In this case, I would guess that the compiler doesn't even know if shifterArray is an array or not. 

    Easy way to recreate the issue:

    [both someArray and foo() are at the global scope, so someArray is a global variable]

    ^ here what the error message is really saying is that  someArray is accessed with an integer index, but the compiler doesn't know if it's a container that accepts integer indices (like an Array). (Note that the initial value is an array, but for non-local variables, the compiler wants a type declaration, because it's possible to reassign a non-local variable to a value with adifferent type in a way that the compiler wouldn't know if or when you did so, unlike the case with local variables.

    If we tell the compiler that someArray is always an Array, the warning goes away:

  • Class: Toybox.AntPlus.Device

  • bikeShifter.getBatteryStatus( (shifterArray as Array)[i] ) would be my first guess.

    Did you specify input and return Types in the specification of function getBatteryStatus() {} ?

    like function getBatteryStatus(arg as Numeric) as BatteryStatus;

  • I am asking whether bikeShifter is in fact an instance of AntPlus.Device or not. If it is, then the return value of bikeShifter.getComponentIdentifiers() should already be typed correctly (as Array<Number>), as per the doc linked above.

    I am further asking what the compiler thinks the type of shifterArray is. Again you can see by hovering over shifterArray.

    To be 100% clear, I think the 2 warnings are most likely referring to shifterArray[i], NOT getBatteryStatus() or getProductInfo().

    You can easily test my guess by adding some separate test line like this:

    var test = shifterArray[i];

    If I am right, that line should receive the same warning.

    EDIT: it seems that you confirmed that bikeShifter is an AntPlus.Device after all.

    Then I would ask that you hover over shifterArray and see what type the compiler thinks it is.

    Something isn't right here (maybe it's an SDK bug, idk)

  • > "Cannot determine if container access is using container type"

    To reiterate what I think the error message means: it means the compiler thinks you are trying to access a container - e.g. x[5] - but it doesn't know what kind of container x is (or if x is even a container at all).

    That's why I think the warnings are all about shifterArray[i].

    Yeah, maybe if you just randomly add some casts, the problem will go away. That doesn't help you understand why the warnings appeared in the first place.

    To take things to an extreme, every time you get a type error, you could just add a cast even if it's the wrong thing to do and it could lead to crash. Or you could just turn off type checking [*].

    [*] in fact I see this advice all the time

  • (shifterArray as ShifterArray)[i]
    bikeShifter.getBatteryStatus( (shifterArray as Array)[i] ) would be my first guess.
    I think the 2 warnings are most likely referring to shifterArray[i]

    var test = shifterArray[i];

    Yes! Throws the same warning!

    var batStatus = bikeShifter.getBatteryStatus((shifterArray as Array)[i]);

    This does the trick!

    Thank you all!

     

     

  • var batStatus = bikeShifter.getBatteryStatus((shifterArray as Array)[i]);

    This does the trick!

    Like I said, if bikeShifter is indeed AntPlus.Device, then bikeShifter.getComponentIdentifiers() should return Array<Number> as per the API docs, and that should be type of shifterArray.

    So it should be unnecessary to cast shifterArray.

    It seems to me that there is a bug somewhere (maybe in the SDK)

    Maybe:

    - the return value of getComponentIdentifiers() is untyped or typed incorrectly

    or

    - somehow the compiler is losing track of the type of shifterArray

    But again, if you're not really interested in figuring out the actual problem, it's up to you. Personally I would leave the warnings in.

    From my perspective, "shifterArray as Array" is:

    1) (at best) useless, if shifterArray is already an Array, as you're just casting the type to what it should already be.

    2) (at worst) worse than useless, if shifterArray is not really an Array, as the cast could lead to problems at runtime

    I think 1) is probably the case tho.

  • Or it could be an issue in your code.

    One problem with the code you provided is that it doesn't show how bikeShifter is declared. Instead, the reader is left to guess.

    If it's some global or class variable (as opposed to a local variable), and you didn't specify that it must be AntPlus.Device, then that would explain the problem.

    e.g. This would cause the problem:

    class Foo {
      var bikeShifter; // no type
    }

    In this case, every access to bikeShifter would be untyped, which means that the return value of bikeShifter.getComponentIdentifiers() would also be untyped.

    The fix would be to write something like this:

    class Foo {
      var bikeShifter as AntPlus.Device or Null;
    }

    I bet I know why you don't want to do this. Because bikeShifter is uninitialized and maybe you don't want to constantly check it for Null in places where you feel it would be unnecessary. But that's the correct way to fix the problem.

    Ofc the cast "works", but it obscures the reason behind the problem in the first place, and it's also a bad practice in general.

  • Again I will say that if the strategy for "fixing" type errors in general is to just use a cast, may as well just turn off type checking altogether. You're giving yourself a false sense of security (in general).