Coder Social home page Coder Social logo

Comments (4)

andcea avatar andcea commented on September 27, 2024 1

@rubenferreira97 when using a variable pattern the variable type becomes ChildB<dynamic, dynamic>, which is why it works. The type should be kept as ChildB<A, dynamic>

from language.

rubenferreira97 avatar rubenferreira97 commented on September 27, 2024

Using a variable pattern works:

sealed class BaseType<A> {}

class ChildA<A> extends BaseType<A> {}

class ChildB<A, B> extends BaseType<A> {}

test<A>(BaseType<A> a) => switch (a) {
      ChildA _ => "ChildA",
      ChildB _ => "ChildB",
    };

void main() {
  for (int i = 0; i < 10; i++) {
    print('hello ${i + 1}');
  }
}

I try to always follow @lrhn's advice 'Always use the object pattern' #2963 (comment). However, this advice does not work here. It seems you have encountered a different analysis between an object pattern and a variable pattern. I don't know if it's a bug.

Maybe it's impossible due the differences between them, but I really wish that the object and variable patterns could be consistent with each other.

from language.

rubenferreira97 avatar rubenferreira97 commented on September 27, 2024

True, I tried the following explicit version and it still errors:

test<A>(BaseType<A> a) => switch (a) {
      ChildA<A>() => "ChildA",
      ChildB<A, dynamic>() => "ChildB",
    };

I can't find a valid reason for this not to work, but maybe the Dart team can answer 🙂.

from language.

lrhn avatar lrhn commented on September 27, 2024

This is likely working as specified, and it is a known short-coming of the exhaustiveness algorithm.

The algorithm sees ChildB<A, Object?> and doesn't know how B of Child<A, B> affects exhausting the supertype BaseType<A>, since there is no B in the supertype.
So it gives up, and says you have to exhaust all of ChildB, meaning ChildB<Object?, Object?>, otherwise it can't be sure that you've exhausted all values of ChildB that can be a BaseType<A>. (That's called "overapproximation" in the specification. It's a guaranteed sound approximation to what you need to exhaust, but not minimal.)

A larger example showing the same thing:

sealed class BaseType<A> {}

class ChildA<A> extends BaseType<A> {}

class ChildB<A, B> extends BaseType<A> {}

test<A>(BaseType<A> a) => switch (a) {
      // Not exahustive. Infers type arguments and promotes.
      ChildA() => "ChildA: "
          "${a..st<E<ChildA<A>>>()}",
      ChildB() => "ChildB: "
          "${a..st<E<ChildB<A, Object?>>>()}",
    };

test2<A>(BaseType<A> a) => switch (a) {
      // Exhaustive. Instantiates to bounds, does not promote.
      ChildA v => "ChildA: "
          "${a..st<E<BaseType<A>>>()}, "
          "${v..st<E<ChildA<Object?>>>()}",
      ChildB v => "ChildB: "
          "${a..st<E<BaseType<A>>>()}, "
          "${v..st<E<ChildB<Object?, Object?>>>()}",
    };

test3<A>(BaseType<A> a) => switch (a) {
      // Not exahustive. Explicit type arguments, promotes.
      ChildA<A> v => "ChildA: "
          "${a..st<E<ChildA<A>>>()}, "
          "${v..st<E<ChildA<A>>>()}",
      ChildB<A, Object?> v => "ChildB: "
          "${a..st<E<ChildB<A, Object?>>>()}, "
          "${v..st<E<ChildB<A, Object?>>>()}",
    };

test4<A>(BaseType<A> a) => switch (a) {
      // Exhaustive. Explicit super-typed arguments.
      ChildA<A> v => "ChildA: "
          "${a..st<E<ChildA<A>>>()}, "
          "${v..st<E<ChildA<A>>>()}",
      ChildB<Object?, Object?> v => "ChildB: "
          "${a..st<E<BaseType<A>>>()}, "
          "${v..st<E<ChildB<Object?, Object?>>>()}",
    };

extension<T> on T {
  void st<X extends E<T>>() {}
}

typedef E<T> = T Function(T);

The two switches where the second case pattern doesn't cover all of ChildB<Object?, Object?> are not exhaustive. The two cases where they do, are.

See also dart-lang/sdk#53486

from language.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.