sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Const callable objects are not treated as functions in const contexts

Open jeremy-deutsch opened this issue 2 years ago • 4 comments

If a callable object is initialized as a const, it isn't treated the same as a normal function would be in const contexts. (This happens when it's initialized inline as well.)

This is reproducible by copy-pasting the below code into dartpad (Dart version 3.0.3 at the time of writing this):

class IsAFunction {
  const IsAFunction();
  
  void call() => print('hello, world!');
}

class UsesAFunction {
  final Function fn;
  
  const UsesAFunction(this.fn);
}

const function = IsAFunction();

// This is fine...
final usesAFunction = UsesAFunction(function);

// But this isn't.
const constUsesAFunction = UsesAFunction(function);

The error messages don't seem to point in any specific direction:

image

jeremy-deutsch avatar Jun 09 '23 18:06 jeremy-deutsch

That sounds like it's working as intended.

A "callable object" is an object with a call method. When called as a function, it implicitly calls the call method, which cannot be a constant operation. If occurring in a function-typed context, an implicit tear-off of the call method is inserted, so e works like (e.call). That again cannot happen in a constant context, since instance method tear-off is not a constant operation.

So, in line 19, the const constUsesAFunction = UsesAFunction(function); is equivalent to const constUsesAFunction = UsesAFunction(function.call);, which is not a valid constant expression.

Or, in other words, it's treated exactly the same in constant and non-constant contexts, its just that the way it's treated is not valid in a constant context.

lrhn avatar Jun 09 '23 20:06 lrhn

Even if it's intended that this doesn't compile, could we update this issue to address the error messaging here? I don't think any of what you just pointed out is clear from the given errors - the error messaging seemed to indicate that the type was Null instead of Function (which is why I thought it wasn't being recognized as a function).

It would be nice here to have an error along the lines of "IsAFunction.call is not const" or something

jeremy-deutsch avatar Jun 09 '23 20:06 jeremy-deutsch

Let's reopen as a request for better messages!

lrhn avatar Jun 12 '23 13:06 lrhn

I just tried this on 'main'. The first and last of the three diagnostics are still being reported, but the second appears to be gone.

The first one is the relevant diagnostic, though it would be better if the message were specialized to indicate why the argument isn't a constant expression.

The third should be suppressed any time there are errors in the initializer because those errors are likely to be more specific.

I'm also seeing an implicit_call_tearoff (because of the way my test project is configured. It should also be suppressed in this case.

bwilkerson avatar Jun 06 '25 21:06 bwilkerson