Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String repetition operator in const expression: spec and VM disagree #23429

Open
DartBot opened this issue May 11, 2015 · 5 comments
Open

String repetition operator in const expression: spec and VM disagree #23429

DartBot opened this issue May 11, 2015 · 5 comments
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@DartBot
Copy link

DartBot commented May 11, 2015

[Edit Aug 2019 eernstg: The remaining task for this issue seems to be to ensure the completeness of certain error messages, cf. this comment.]


This issue was originally filed by @chalin


There seems to be a mismatch between the treatment of the String repetition operator (*) in const contexts as defined in the Dart Language Spec (DLS) [1] vs. the VM.

Consider the following definition of class A taken from the code sample given in the commentary of Section 16.12.2, "Const" of the DLS. The code sample in the commentary is meant to illustrate the handling of an uncaught exception raised during the evaluation of a constant expression.

  class A {
    final x;
    const A(p) : x = p * 5; // (A)
  }
  const ax = const A('x'); // (B)
  const ok = const A(5); // legal

  void main() {
    print(ax == const A('x')); // -> true, so the constructor of A is const
    print(ax.x); // -> xxxxx
    print(ok.x); // -> 25
  }

Two points. According to the DLS:

(1) No warning should be reported at (A), but the analyzer reports "expression of type 'num' expected".
(2) A compile-time error should be reported at (B), but no error is reported.

Point (2) seems to be a result of the String repetition operator (*) being considered a legal operator in some const expression contexts (contrary to what the spec currently permits). Note that a direct use of String repetition does result in a compile-time error:

  const c = '!' * 5; // compile time error (matches spec)

Was there any reason for having originally excluded String repetition from being used in const contexts? It seems harmless to support it (especially given that it is partially supported in the VM already :). In any case, the sample code above shows that there is a mismatch between the spec and the VM.

Note that the (apparently) spurious analyzer warning of point (1) is also the subject of issue #16839.

[1]: http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf "DLS v1.6"

What version of the product are you using?
Dart SDK version 1.10.0

On what operating system?
Mac OSX

@lrhn
Copy link
Member

lrhn commented May 15, 2015

This may be an aspect of issue #392.

String repetition was added after the spec was written, so it was not excluded originally - it has just never been added.

There is some reason to not allowing it as a compile-time constant expression - you can write a simple compile-time constant expression that requires incredible amounts of memory. At runtime, it's simple to just throw an OutOfMemoryError, but doing it in the compiler might be unexpected.
(Not that you can't do it without String.* if you really want, it just takes more space than "a"*(1<<100) ).


Added Area-VM, Triaged labels.

@DartBot
Copy link
Author

DartBot commented May 15, 2015

This comment was originally written by @mhausner


Lasse is right, this is an incarnation of issue #392. The VM does not completely implement the concept of "potentially constant" expressions well. It can't fully analyze the expression at the call site (B).

@DartBot DartBot added Type-Defect area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. labels May 15, 2015
@kevmoo kevmoo added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) and removed triaged labels Mar 1, 2016
@srawlins
Copy link
Member

Thangs have changed in recent years, including const evaluation recently. Now the VM takes the example above and prints, without throwing:

true
xxxxx
25

The analyzer still prints two errors though, at const ax = const A('x'); // (B) and print(ax == const A('x'));:

  error • Evaluation of this constant expression throws an exception at /Users/srawlins/code/dart-sdk/23429.dart:6:12 • const_eval_throws_exception
  error • Evaluation of this constant expression throws an exception at /Users/srawlins/code/dart-sdk/23429.dart:10:15 • const_eval_throws_exception
2 errors found.

Is the bug now in analyzer?

@srawlins
Copy link
Member

CC @eernstg regarding const-in-spec question.

@eernstg
Copy link
Member

eernstg commented Aug 20, 2019

Good catch! We have the rule here that

it is a compile-time error if substitution of the actual arguments
for the formal parameters yields an initializing expression e in the initializer list
of k which is not a constant expression.

so since const A('x') by substitution yields 'x' * 5, which is (still) not a constant expression, const A('x') is a compile-time error.

So the analyzer reports the errors as it should. But the VM also reports the errors today (as of commit 464cea0), when I'm running this program:

class A {
  final x;
  const A(p) : x = p * 5;
}
const ax = const A('x'); // Compile-time error.
const ok = const A(5);

void main() {
  print(ax == const A('x')); // Compile-time error.
  print(ax.x);
  print(ok.x);
}

Here's the response that I get from dart:

n022.dart:3:22: Error: The method '*' can't be invoked on '"x"' within a const context.
  const A(p) : x = p * 5;
                     ^
n022.dart:5:7: Context: While analyzing:
const ax = const A('x'); // Compile-time error.
      ^
n022.dart:3:22: Error: The method '*' can't be invoked on '"x"' within a const context.
  const A(p) : x = p * 5;
                     ^

This is correct in the sense that we should get two error messages, and we do get two; but it's a significant omission that the second one doesn't have the accompanying Context: While analyzing: message. Without that message the developer can't know where to search for the <constObjectExpression> that caused the error.

This basically means that the remaining task for this issue is to make sure that the Context is printed for all errors arising due to the substitution-yields-const check, not just some of them.

I tried to reproduce this behavior:

Now the VM takes the example above and prints, without throwing: ...

and it seems to occur with every version of dart older than 2.5.0-dev.2.0. So it's a very recent fix that just needs a fix-fix. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

5 participants