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

bug using redirecting constructor in initializer of extension type #55135

Closed
curt-weber opened this issue Mar 2, 2024 · 11 comments
Closed

bug using redirecting constructor in initializer of extension type #55135

curt-weber opened this issue Mar 2, 2024 · 11 comments
Assignees
Labels
area-front-end Use area-front-end for front end / CFE / kernel format related issues. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@curt-weber
Copy link

Extension types don't seem to support typed data, for instance Float64x2.
There is a restriction that typed_data isn't extended, but that applies to other types like int, double, which extension types can use.

import 'dart:math';
import 'dart:typed_data';

extension type const Point._(Float64x2 point) implements Float64x2 {
  Point(double x, double y) : point = Float64x2(x, y);
  double get distance => sqrt(point.x * point.x + point.y * point.y);
}

void main() => print(Point(0, 0)); // prints null

I was checking to see if extension types would be more performant in the case of Offset, but using List<double> is actually slower from my tests.

@lrhn
Copy link
Member

lrhn commented Mar 3, 2024

That sounds like a bug. You should be able to subtype typed data with extension types.

@srawlins
Copy link
Member

srawlins commented Mar 3, 2024

Are you running this with DDC? For my part, this code:

import 'dart:math';
import 'dart:typed_data';

extension type const Point._(Float64x2 point) implements Float64x2 {
  Point(double x, double y) : point = Float64x2(x, y);
  double get distance => sqrt(point.x * point.x + point.y * point.y);
}

void main() {
  print('Float64x2: ${Float64x2(0, 0)}');
  print(Point(0, 0));
  print('Point: ${Point(0, 0)}');
}

prints this with the Dart VM (3.3.0):

Float64x2: [0.000000, 0.000000]
[0.000000, 0.000000]
Point: [0.000000, 0.000000]

and prints this in DartPad (DDC):

Float64x2: [0, 0]
null
Script error.

with the following exception in the console:

Uncaught TypeError: Cannot read properties of undefined (reading 'Symbol(dartx.toString)')
    at Object.strSafe (operations.dart:1072:38)
    at Object.main$0 [as main] (<anonymous>:69:33)
    at Object.main$ [as main] (<anonymous>:47:10)
    at <anonymous>:106:26
    at Object.execCb (require.js:5:16727)
    at e.check (require.js:5:10499)
    at e.<anonymous> (require.js:5:12915)
    at require.js:5:1542
    at require.js:5:13376
    at each (require.js:5:1020)
    at e.emit (require.js:5:13344)
    at e.check (require.js:5:11058)
    at e.enable (require.js:5:13242)
    at e.init (require.js:5:9605)
    at a (require.js:5:8305)
    at Object.completeLoad (require.js:5:15962)
    at HTMLScriptElement.onScriptLoad (require.js:5:16882)

suggesting some weird things: Point(0, 0) acts like null, except it is a value that doesn't even have a toString() method on it?

@cmkweber
Copy link

cmkweber commented Mar 3, 2024

Yes, I should have mentioned that was in DartPad. Initially was trying to add it to a List<Point> but that wasn’t working and not showing the exception in DartPad for some reason.

@curt-weber
Copy link
Author

Should this get moved to the sdk repo as a bug?

@srawlins srawlins transferred this issue from dart-lang/language Mar 7, 2024
@srawlins srawlins added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. labels Mar 7, 2024
@sigmundch
Copy link
Member

It appears this is triggering issues on both web compilers, coincidentally. Likely these are different bugs.

Both trigger when the initializer of the extension type representation field uses a redirecting factory constructor (which Float64x2 happens to have). Here is an standalone repro of this:

class B implements A {
  final int x = 1;
}
abstract class A {
  int get x;
  factory A() = B;
}

extension type C._(A point) implements A {
  C() : point = A(); // << initializer is redirecting factory
}

void main() {
  print(A().x);
  print(C().x);
}

This program compiles in DDC, but like above gets null instead of an instance of B when calling C(). Changing the initializer to use B() instead of A() works as expected.

Dart2js surprisingly crashes! Here is the crash error for the same program:

Internal Error: The compiler crashed when compiling this element.
  factory A() = B;
          ^
The compiler is broken.

When compiling the above element, the compiler crashed. It is not
possible to tell if this is caused by a problem in your program or
not. Regardless, the compiler should not crash.

The Dart team would greatly appreciate if you would take a moment to
report this problem at http://dartbug.com/new.

Please include the following information:

* the name and version of your operating system,

* the Dart SDK build number (3.4.0-179.0.dev), and

* the entire message you see here (including the full stack trace
  below as well as the source location above).

The compiler crashed: Null check operator used on a null value
#0      ClosureDataBuilder.createClosureEntities.processModel (package:compiler/src/js_model/closure.dart:375:59)
#1      ClosureDataBuilder.createClosureEntities.<anonymous closure>.<anonymous closure> (package:compiler/src/js_model/closure.dart:436:9)
#2      DiagnosticReporter.withCurrentElement (package:compiler/src/diagnostics/diagnostic_listener.dart:159:15)
#3      ClosureDataBuilder.createClosureEntities.<anonymous closure> (package:compiler/src/js_model/closure.dart:435:17)
#4      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
#5      ClosureDataBuilder.createClosureEntities (package:compiler/src/js_model/closure.dart:434:19)
#6      JClosedWorldBuilder.convertClosedWorld (package:compiler/src/js_model/js_world_builder.dart:172:41)
#7      JsBackendStrategy.createJClosedWorld (package:compiler/src/js_model/js_strategy.dart:184:52)
#8      Compiler.closeResolution (package:compiler/src/compiler.dart:743:25)
#9      Compiler.computeClosedWorld (package:compiler/src/compiler.dart:385:9)
#10     Compiler.produceClosedWorld (package:compiler/src/compiler.dart:534:21)
#11     Compiler.runSequentialPhases (package:compiler/src/compiler.dart:643:39)
<asynchronous suspension>
#12     Compiler.runInternal.<anonymous closure> (package:compiler/src/compiler.dart:317:7)
<asynchronous suspension>
#13     Compiler.runInternal (package:compiler/src/compiler.dart:316:5)
<asynchronous suspension>
#14     Compiler.run.<anonymous closure> (package:compiler/src/compiler.dart:237:11)
<asynchronous suspension>
#15     compile.<anonymous closure> (package:compiler/compiler_api.dart:255:30)
<asynchronous suspension>
#16     compile.compilationDone (package:compiler/src/dart2js.dart:730:3)
<asynchronous suspension>
#17     main (package:compiler/src/dart2js.dart:1240:3)
<asynchronous suspension>

@nshahan
Copy link
Contributor

nshahan commented Mar 7, 2024

cc @johnniwinther

This looks like an issue with the lowering of redirecting factory constructors for both js compilers. @sigmundch example above looks like a good reproduction of the problem.

@nshahan nshahan added area-front-end Use area-front-end for front end / CFE / kernel format related issues. and removed web-dart2js web-dev-compiler labels Mar 7, 2024
@fishythefish
Copy link
Member

#55079 is likely the same bug in dart2js.

@sigmundch sigmundch removed web-dart2js web-dev-compiler area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. labels Mar 8, 2024
@sigmundch
Copy link
Member

Moving temporarily to area-frontend, we can move it back if in fact it's an issue on the web compilers.

@sigmundch sigmundch changed the title Extension types on typed_data bug using redirecting constructor in initializer of extension type Mar 8, 2024
@chloestefantsova
Copy link
Contributor

I might have a solution. I'm working on it in https://dart-review.googlesource.com/c/sdk/+/357161.

@sigmundch
Copy link
Member

Thanks so much for the fix @chloestefantsova!

@chloestefantsova @johnniwinther - since the fix is fairly contained, it seems it may be worth considering filing a cherry-pick request for it. What do you think?

@chloestefantsova
Copy link
Contributor

@chloestefantsova @johnniwinther - since the fix is fairly contained, it seems it may be worth considering filing a cherry-pick request for it. What do you think?

That's a good idea. I've just filed #55194.

copybara-service bot pushed a commit that referenced this issue Mar 19, 2024
…Child

The added method is required for the resolution of redirection targets
to work: it replaces the immediate target invocation node with the
final target invocation node.

Closes #55135

Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/357161
Cherry-pick-request: #55194
Change-Id: I96643c5af0ca91209cd936aee78f13c416679275
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/357600
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-front-end Use area-front-end for front end / CFE / kernel format related issues. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

9 participants