sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Could error messages for incompatible function types be improved to show the conflicting parameters?

Open rrousselGit opened this issue 2 years ago • 2 comments

Hello!

While debugging some tests for a code-generator I'm working on, I faced the following error:

Screenshot 2023-06-21 at 17 25 55
The redirected constructor '_FunctionParameter2 Function(int? Function(int?, {required int b, int c}), int? Function(int?, [int]), T? Function<T extends num>(T?), List<ImplementsAliasFirst> Function(ImplementsAliasFirst))' has incompatible parameters with 'FunctionParameter Function(int? Function(int?, {required int b, int c})?, int? Function(int?, [int]), T? Function<T extends num>(T?)?, List<ImplementsAliasFirst> Function(ImplementsAliasFirst)?)'.
Try redirecting to a different 

Where the source is:

@freezed
class FunctionParameter with _$FunctionParameter {
  // [...]
  factory FunctionParameter.second(
    int? simpleNamed(int? a, {required int b, int c})?,
    int? simplePositional(int? a, [int b]),
    T? generic<T extends num>(T? a)?,
    List<ImplementsAliasFirst> generated(ImplementsAliasFirst a)?,
  ) = _FunctionParameter2;
}

...

class _FunctionParameter2 implements FunctionParameter {
  _FunctionParameter2(
    this.simpleNamed,
    this.simplePositional,
    this.generic,
    this.generated,
  );
  final int? Function(int? a, {required int b, int c}) simpleNamed;
  final int? Function(int? a, [int b]) simplePositional;
  final T? Function<T extends num>(T? a) generic;
  final List<ImplementsAliasFirst> Function(ImplementsAliasFirst a) generated;
}

Although the error is correct, it's not humanly readable (at least not without squinting eyes really hard 😛)

It'd be great if the error could be expanded a bit like when there's a pub get version conflict. When there's a version conflict, it creates a chain of problem/cause until it pinpoints one specific package.

The error could follow a similar logic to be:

The redirected constructor <...> has incompatible parameters with <...>.
-> The constructor FunctionParameter.second expects a parameter "simpleNamed" of type <...> but the redirected constructor expects the type <...>
   -> The parameter simpleNamed of FunctionParameter.second is nullable, but _FunctionParameter2 defines simpleNamed as non-nullable
/* do the same with other conflicting parameters */

This would make it much easier to understand the error.

rrousselGit avatar Jun 21 '23 15:06 rrousselGit

Another alternative is a possible "diff" between the types.

For example when there's a conflict between void Function(int?) and void Function(int), we could show:

Screenshot 2023-06-21 at 17 36 22

rrousselGit avatar Jun 21 '23 15:06 rrousselGit

I like the diff suggestion, but the diagnostics have to be displayable in contexts where we can't provide that kind of UI.

So what we should implement is the first suggestion: include a list of the places where the signatures differ. The diff algorithm should have some intelligence for degenerate cases. For example, if the signatures differ in almost every way, then it probably isn't worth trying to enumerate all of the differences. But if they differ in just one or two parameters, then calling out those places specifically would make sense.

Note: This probably applies equally to record types.

bwilkerson avatar Jun 06 '25 21:06 bwilkerson