Skip to content

const Constructor parameters are never considered const #2000

Open
@ltOgt

Description

@ltOgt

If a class defines a const constructor, it can be created either as const or as regular internally final object.
Should this const-in-const-context notion not apply to the parameters as well?

Take e.g.:

class CanConst {
  final int value;
  const CanConst(this.value);
}

Here const v = 1; const CanConst(1) works but (int v) => const CanConst(v); does not.
=> parameter must be constant when used in constant context.

Where as const v = 1; CanConst(1) and (int v) => CanConst(v); both work.
=> parameter must not be constant when used outside constant context.

==> parameter behaves like it is const-in-const-context


Since the parameter is currently not const-in-const-context, we get e.g. the following:

const canConst = CanConst(1);
const canNotConst = CanNotConst(1); // Error
const canNotConstContainer = CanNotConstContainer(CanNotConst(1)); // Error

class CanConst {
  final int value;
  const CanConst(this.value);
}

class CanNotConst {
  final int value;
  CanNotConst(this.value);
}

class CanNotConstContainer {
  final CanNotConst cnc;
  const CanNotConstContainer(this.cnc);  // No Error
}

Which I think should be warned about in const CanNotConstContainer(this.cnc) since CanNotConst will never be able to be const.


Further, we get counter-intuitive (at least to me) behaviour with trying to make classes constant:

Starting with this non-constant class:

class MyClass {
  final int value;
  final MyOtherClass other;

  MyClass(this.value, this.other);
  MyClass.sameOther(int value)
      : this.value = value,
        other = MyOtherClass(value);
}

class MyOtherClass {
  final in value;
  const MyOtherClass(this.value);
}

We can make the default constructor const since MyOtherClass has a const constructor:

class MyClass {
  // ...
  const MyClass(this.value, this.other);
}
const myConst = MyClass(1, MyOtherClass(1));

However, we cant do:

class MyClass {
  // ...
  const MyClass.sameOther(int value)
      // why does this work ...
      : this.value = value,
        // ... but this does not
        other = MyOtherClass(value);
  // ----------^^^^^^^^^^^^^^^^^^^^^
  // Invalid const value
}

Since the const part of the constructor is only used in const context, I had the following mental model:

Used in const context.

class MyClass {
  const int value;
  const MyOtherClass other;

  const MyClass(this.value, this.other);
  const MyClass.sameOther(const int value)
      : this.value = value,
        other = const MyOtherClass(value);
}

Used outside of const context.

class MyClass {
  final int value;
  final MyOtherClass other;

  MyClass(this.value, this.other);
  MyClass.sameOther(int value)
      : this.value = value,
        other = MyOtherClass(value);
}

P.S.
I recently assumed that fields of an object created via const would be const as well, which might be related (even if only in my wrong mental model)
(#1868 (comment))

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhanced-constRequests or proposals about enhanced constant expressionsrequestRequests to resolve a particular developer problem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions