Use of types in the dart2js Dart implementation

97 views
Skip to first unread message

Fabio Strocco

unread,
Jan 26, 2015, 4:43:40 AM1/26/15
to compil...@dartlang.org
Hi, I am implementing an extension of the dartanalyzer tool that runs more aggressive type checkers. Among other things, it checks that the return type of each overriding method is a subtype of the return type
declared in the overridden method. Going though the dart2js implementation (at least /pkg/compiler/lib/src) the checker found some use of overriding in the form

class C {
  T aMethod(...) ....
}

class D extends C {
  S aMethod(...) ....
}

where S >: T (i.e. S is a supertype of T), but these issues seem to be easy to fix without introducing additional type errors. So my question is: is it just an oversight or there is some real desing issue? I list some concrete example



In file "dart_types.dart"

abstract class DartType {
  ...
  /// Returns an occurrence of a type variable within this type, if any.
  TypeVariableType get typeVariableOccurrence => null;
  ...
}

class TypeVariableType extends DartType {
  ...
  DartType get typeVariableOccurrence => this;
}

class FunctionType extends DartType {
  ...
  DartType get typeVariableOccurrence ....
}

where DartType >: TypeVariableType, even if it does not seems that any getter returns something different from TypeVariableType

------------------------------------------------

In file "elements/modelx.dart"

abstract class ExecutableElement extends Element
    implements TypedElement, AstElement {
  MemberElement get memberContext;
}

class LocalVariableElementX extends VariableElementX
    implements LocalVariableElement {
   ...
   ExecutableElement get memberContext => executableContext.memberContext;
   ...
}

where ExecutableElement >: MemberElement

-----------------------

file "resolution/signatures.dart

abstract class Visitor<R> {
  R visitIdentifier(Identifier node) => visitExpression(node);
  ...
  R visitSend(Send node) => visitExpression(node);
  ...
}

class SignatureResolver extends MappingVisitor<FormalElementX> {
  ... 
  Element visitIdentifier(Identifier node) {
    return createParameter(node, null);
  }

  ...
}

where Element >: FormalElementX, so why isn't the MappintVisitor formal parameter here instantiated to Element instead of FormalElementX?




----------------------------------------------------


Another question is concerning the use of dynamic. Sometimes types are omitted when defining method, but then they are provided in the subclass. Why? Is that because of the lack of union types? For example


class ErroneousElementX extends ElementX implements ErroneousElement {
  final MessageKind messageKind;
  final Map messageArguments;

  ErroneousElementX(this.messageKind, this.messageArguments,
                    String name, Element enclosing)
      : super(name, ElementKind.ERROR, enclosing);

  bool get isTopLevel => false;

  bool get isSynthesized => true;

  AbstractFieldElement abstractField;

  unsupported() {
    throw 'unsupported operation on erroneous element';
  }

  get asyncMarker => AsyncMarker.SYNC;
  Link<MetadataAnnotation> get metadata => unsupported();
  bool get hasNode => false;
  get node => unsupported();
  get hasResolvedAst => false;
  get resolvedAst => unsupported();
  get type => unsupported();
  get cachedNode => unsupported();
  get functionSignature => unsupported();
  get patch => null;
  get origin => this;
  get immediateRedirectionTarget => unsupported();
  get nestedClosures => unsupported();
  get memberContext => unsupported();
  get executableContext => unsupported();
  get isExternal => unsupported();
}

The unsupported method only throws an exception. What is the reason why unsupported cannot declare Object or void return types?


Thank you in Advance

Florian Loitsch

unread,
Jan 26, 2015, 12:42:08 PM1/26/15
to Fabio Strocco, Dart Compiler Developers, Stephan Herhut, Johnni Winther
We will look at the

On Mon Jan 26 2015 at 10:43:41 AM Fabio Strocco <fabios...@gmail.com> wrote:
Hi, I am implementing an extension of the dartanalyzer tool that runs more aggressive type checkers. Among other things, it checks that the return type of each overriding method is a subtype of the return type
declared in the overridden method. Going though the dart2js implementation (at least /pkg/compiler/lib/src) the checker found some use of overriding in the form

class C {
  T aMethod(...) ....
}

class D extends C {
  S aMethod(...) ....
}

where S >: T (i.e. S is a supertype of T), but these issues seem to be easy to fix without introducing additional type errors. So my question is: is it just an oversight or there is some real desing issue? I list some concrete example



In file "dart_types.dart"

abstract class DartType {
  ...
  /// Returns an occurrence of a type variable within this type, if any.
  TypeVariableType get typeVariableOccurrence => null;
  ...
}

class TypeVariableType extends DartType {
  ...
  DartType get typeVariableOccurrence => this;
This is probably just an oversight.
 
}

class FunctionType extends DartType {
  ...
  DartType get typeVariableOccurrence ....
ditto. 

}

where DartType >: TypeVariableType, even if it does not seems that any getter returns something different from TypeVariableType

------------------------------------------------

In file "elements/modelx.dart"

abstract class ExecutableElement extends Element
    implements TypedElement, AstElement {
  MemberElement get memberContext;
}

class LocalVariableElementX extends VariableElementX
    implements LocalVariableElement {
   ...
   ExecutableElement get memberContext => executableContext.memberContext;
Probably an oversight too.
 
   ...
}

where ExecutableElement >: MemberElement

-----------------------

file "resolution/signatures.dart

abstract class Visitor<R> {
  R visitIdentifier(Identifier node) => visitExpression(node);
  ...
  R visitSend(Send node) => visitExpression(node);
  ...
}

class SignatureResolver extends MappingVisitor<FormalElementX> {
  ... 
  Element visitIdentifier(Identifier node) {
I think this should just be changed to FormalElementX visitIdentifier ... 
It could, but it would be more to write. Why bother? It's more code for nothing. After all, it doesn't return anything.

thanks. 


Thank you in Advance

To unsubscribe from this group and stop receiving emails from it, send an email to compiler-dev+unsubscribe@dartlang.org.

Fabio Strocco

unread,
Jan 27, 2015, 11:57:59 AM1/27/15
to compil...@dartlang.org, fabios...@gmail.com, her...@google.com, johnni...@google.com
Ok, thanks for the info, I just wanted to make sure that there is no particular design patter that requires that.


Thank you in Advance

To unsubscribe from this group and stop receiving emails from it, send an email to compiler-dev...@dartlang.org.

Karl Klose

unread,
Feb 2, 2015, 4:00:26 AM2/2/15
to Fabio Strocco, compil...@dartlang.org, Stephan Herhut, Johnni Winther
Hi Fabio,

looks like a nice tool to have.

Except for the missing type annotations in ErroneousElementX, these seems to be either oversights or the result of manual refactorings, where the Dart type system did not issue a warning and thus they have been undetected.

On the use of dynamic in ErroneousElementX: unsupported could return Object or void (as Florian said). The result types of the methods that it overwrites are actually not that important, because this class is an error marker and calls to these methods should be checked against the interface type Element (or some subclass).


Phil Quitslund

unread,
Feb 2, 2015, 10:57:30 AM2/2/15
to Karl Klose, Fabio Strocco, compil...@dartlang.org, Stephan Herhut, Johnni Winther
Great stuff Fabio!

A variation on this one in particular is something I was thinking of implementing in the dart linter [1].

Among other things, it checks that the return type of each overriding method is a subtype of the return type
declared in the overridden method. 

[1] I'll have the main driver and some test scaffolding updated later today.  In the meantime, feel free to ping me directly or file issues if you want to chat about how our efforts might overlap.

Cheers!

-phil


--
Phil Quitslund
Software Engineer
Google, Inc.

Fabio Strocco

unread,
Feb 3, 2015, 10:09:37 AM2/3/15
to compil...@dartlang.org, karl...@google.com, fabios...@gmail.com, her...@google.com, johnni...@google.com
Hi, thanks for the quick replies. I am curious to understand what is the "dart linter" doing with respect to types.

I attached a partial result of the warnings I got by re-analyzing dart2js after updating the sources to the last development version.
Each entry is a warning, unfortunately each entry only contains the offset to locate the warning (number of characters from the beginning of the file) instead of the line number, I apologize for that.
It would be interesting for my project to see how many of these bugs can be easilly fixed. My intuition is many.

---------------------
Non Message-Safe Overrding: 16
---------------------
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:analyzableElement, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:21647, length:17>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:analyzableElement, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:27731, length:17>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:requiredParameters, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:52910, length:18>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:optionalParameters, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:52952, length:18>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:orderedOptionalParameters, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:53107, length:25>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:firstOptionalParameter, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:54167, length:22>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:immediateRedirectionTarget, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:60612, length:26>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/elements/modelx.dart, node:analyzableElement, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:63791, length:17>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/closure.dart, node:analyzableElement, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:5006, length:17>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/closure.dart, node:rawType, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:5239, length:7>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/closure.dart, node:thisType, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:5259, length:8>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/closure.dart, node:analyzableElement, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:9456, length:17>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/resolution/signatures.dart, node:visitSendSet, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:8274, length:12>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/resolution/signatures.dart, node:visitFunctionExpression, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:8814, length:23>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart, node:memberContext, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:46419, length:13>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/js_backend/minify_namer.dart, node:names, error:Method return type must be a subtype of method in the superclass for Message-Safe programs, offset:15773, length:5>



---------------------
Non Message-Safe function assignment: 2
---------------------
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart, node:subbuild(node.thenExpression), error:The argument type '{0}' cannot be assigned to the parameter type '{1}', offset:16611, length:29>
<file:/home/fstrocco/Desktop/PhD/Dart/DartSources/dartRep/dart-repo/dart/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart, node:subbuild(node.elseExpression), error:The argument type '{0}' cannot be assigned to the parameter type '{1}', offset:16650, length:29>
Reply all
Reply to author
Forward
0 new messages