Version 2.14.0-348.0.dev
Merge commit '639665cc4e8a2865a54044eed81445f82dc2a276' into 'dev'
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 3cb1a0f..9548d6e 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -182,6 +182,22 @@
return false;
}
+ /// Build types for type annotations in new [nodes].
+ void resolveTypeAnnotations(
+ List<ast.AstNode> nodes, {
+ ClassElementImpl? classElement,
+ }) {
+ var nodesToBuildType = NodesToBuildType();
+ var resolver = ReferenceResolver(linker, nodesToBuildType, element);
+ if (classElement != null) {
+ resolver.enterScopeClassElement(classElement);
+ }
+ for (var node in nodes) {
+ node.accept(resolver);
+ }
+ TypesBuilder(linker).build(nodesToBuildType);
+ }
+
for (var linkingUnit in units) {
for (var declaration in linkingUnit.node.declarations) {
if (declaration is ast.ClassDeclarationImpl) {
@@ -206,17 +222,7 @@
);
var classElement = declaration.declaredElement as ClassElementImpl;
elementBuilder.buildMacroClassMembers(classElement, newMembers);
-
- // TODO(scheglov) extract
- {
- var nodesToBuildType = NodesToBuildType();
- var resolver =
- ReferenceResolver(linker, nodesToBuildType, element);
- for (var newMember in newMembers) {
- newMember.accept(resolver);
- }
- TypesBuilder(linker).build(nodesToBuildType);
- }
+ resolveTypeAnnotations(newMembers, classElement: classElement);
}
}
}
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 9268b91..1cba245 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -45,6 +45,10 @@
scope = libraryElement.scope,
isNNBD = libraryElement.isNonNullableByDefault;
+ void enterScopeClassElement(ClassElementImpl element) {
+ scope = TypeParameterScope(scope, element.typeParameters);
+ }
+
@override
void visitBlockFunctionBody(BlockFunctionBody node) {}
@@ -53,9 +57,6 @@
var outerScope = scope;
var element = node.declaredElement as ClassElementImpl;
- element.accessors; // create elements
- element.constructors; // create elements
- element.methods; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
@@ -102,7 +103,6 @@
var outerScope = scope;
var element = node.declaredElement as ConstructorElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
LinkingNodeContext(node, scope);
@@ -158,7 +158,6 @@
var outerScope = scope;
var element = node.declaredElement as FieldFormalParameterElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
@@ -180,7 +179,6 @@
var outerScope = scope;
var element = node.declaredElement as ExecutableElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(outerScope, element.typeParameters);
LinkingNodeContext(node, scope);
@@ -208,9 +206,6 @@
node.returnType?.accept(this);
node.typeParameters?.accept(this);
-
- var function = element.aliasedElement as GenericFunctionTypeElementImpl;
- function.parameters; // create elements
node.parameters.accept(this);
nodesToBuildType.addDeclaration(node);
@@ -223,7 +218,6 @@
var outerScope = scope;
var element = node.declaredElement as ParameterElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
@@ -287,7 +281,6 @@
var outerScope = scope;
var element = node.declaredElement as ExecutableElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
LinkingNodeContext(node, scope);
@@ -305,9 +298,6 @@
var outerScope = scope;
var element = node.declaredElement as MixinElementImpl;
- element.accessors; // create elements
- element.constructors; // create elements
- element.methods; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 8c5f16e..814a92b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -21298,6 +21298,61 @@
''');
}
+ test_macro_observable_generic() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+class A<T> {
+ @observable
+ T _f;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @39
+ typeParameters
+ covariant T @41
+ defaultType: dynamic
+ fields
+ _f @64
+ metadata
+ Annotation
+ atSign: @ @48
+ element: macro_annotations.dart::@getter::observable
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::observable
+ staticType: null
+ token: observable @49
+ type: T
+ synthetic f @-1
+ type: T
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get _f @-1
+ returnType: T
+ synthetic set _f @-1
+ parameters
+ requiredPositional __f @-1
+ type: T
+ returnType: void
+ get f @-1
+ returnType: T
+ set f @-1
+ parameters
+ requiredPositional val @-1
+ type: T
+ returnType: void
+''');
+ }
+
test_main_class() async {
var library = await checkLibrary('class main {}');
checkElementText(library, r'''
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
index 4646515..2725aac 100644
--- a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -78,9 +78,8 @@
..fileOffset = charOffset
..fileEndOffset = charEndOffset
..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault,
- _factoryTearOff = createConstructorTearOffProcedure(
- name, libraryBuilder, libraryBuilder.fileUri, charOffset,
- forAbstractClassOrEnum: false),
+ _factoryTearOff = createFactoryTearOffProcedure(
+ name, libraryBuilder, libraryBuilder.fileUri, charOffset),
super(metadata, modifiers, returnType, name, typeVariables, formals,
libraryBuilder, charOffset, nativeMethodName) {
this.asyncModifier = asyncModifier;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index b012042..78e98ed 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -5,7 +5,6 @@
library fasta.function_type_alias_builder;
import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/type_algebra.dart' show substitute, uniteNullabilities;
@@ -20,7 +19,6 @@
import '../problems.dart' show unhandled;
import '../source/source_library_builder.dart';
-import '../util/helpers.dart';
import 'class_builder.dart';
import 'library_builder.dart';
@@ -113,10 +111,28 @@
// as stated in the docs? It is not needed for the implementation.
List<TypeBuilder>? unaliasTypeArguments(List<TypeBuilder>? typeArguments);
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers);
+ /// Returns the lowering for the constructor or factory named [name] on the
+ /// effective target class of this typedef.
+ ///
+ /// For instance, if we have
+ ///
+ /// class A<T> {
+ /// A();
+ /// }
+ /// typedef F = A<int>;
+ /// typedef G = F;
+ /// typedef H<X, Y> = A<X>;
+ ///
+ /// the lowering will create
+ ///
+ /// A<int> _#F#new#tearOff() => new A<int>();
+ /// A<int> _#G#new#tearOff() => new A<int>();
+ /// A<int> _#H#new#tearOff<X, Y>() => new A<X>();
+ ///
+ /// which will be return by [findConstructorOrFactory] on `F`, `G`, `H` with
+ /// name 'new' or ''.
+ Procedure? findConstructorOrFactory(
+ String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary);
}
abstract class TypeAliasBuilderImpl extends TypeDeclarationBuilderImpl
@@ -494,6 +510,17 @@
}
return currentTypeArguments;
}
+
+ Map<Name, Procedure>? get tearOffs;
+
+ Procedure? findConstructorOrFactory(
+ String text, int charOffset, Uri uri, LibraryBuilder accessingLibrary) {
+ if (tearOffs != null) {
+ Name name = new Name(text == 'new' ? '' : text, accessingLibrary.library);
+ return tearOffs![name];
+ }
+ return null;
+ }
}
/// Used to detect cycles in the declaration of a typedef
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index e52ce9a..4c1afba 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -6,29 +6,7 @@
import 'dart:convert' show jsonDecode;
-import 'package:kernel/ast.dart'
- show
- Class,
- ConstantExpression,
- Constructor,
- DartType,
- DynamicType,
- Expression,
- Extension,
- Field,
- FunctionType,
- Library,
- ListLiteral,
- Member,
- NamedNode,
- NeverType,
- Procedure,
- ProcedureKind,
- Reference,
- StaticGet,
- StringConstant,
- StringLiteral,
- Typedef;
+import 'package:kernel/ast.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
@@ -122,8 +100,23 @@
isBuilt = true;
library.classes.forEach(addClass);
library.extensions.forEach(addExtension);
+
+ Map<String, Map<Name, Procedure>> tearOffs = {};
+ List<Procedure> nonTearOffs = [];
+ for (Procedure procedure in library.procedures) {
+ List<Object>? names = extractTypedefNameFromTearOff(procedure.name);
+ if (names != null) {
+ Map<Name, Procedure> map = tearOffs[names[0] as String] ??= {};
+ map[names[1] as Name] = procedure;
+ } else {
+ nonTearOffs.add(procedure);
+ }
+ }
+ nonTearOffs.forEach(addMember);
library.procedures.forEach(addMember);
- library.typedefs.forEach(addTypedef);
+ for (Typedef typedef in library.typedefs) {
+ addTypedef(typedef, tearOffs[typedef.name]);
+ }
library.fields.forEach(addMember);
if (isReadyToFinalizeExports) {
@@ -285,12 +278,12 @@
return declaration;
}
- void addTypedef(Typedef typedef) {
+ void addTypedef(Typedef typedef, Map<Name, Procedure>? tearOffs) {
DartType? type = typedef.type;
if (type is FunctionType && type.typedefType == null) {
unhandled("null", "addTypedef", typedef.fileOffset, typedef.fileUri);
}
- addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, this),
+ addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, tearOffs, this),
typedef.fileOffset);
}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index f78420c..6dc3d32 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -4,8 +4,7 @@
library fasta.dill_typedef_builder;
-import 'package:kernel/ast.dart' show DartType, InvalidType, NullType, Typedef;
-import 'package:kernel/core_types.dart';
+import 'package:kernel/ast.dart';
import '../builder/library_builder.dart';
import '../builder/metadata_builder.dart';
@@ -15,20 +14,20 @@
import '../problems.dart' show unimplemented;
-import '../util/helpers.dart';
-
import 'dill_class_builder.dart' show computeTypeVariableBuilders;
import 'dill_library_builder.dart' show DillLibraryBuilder;
class DillTypeAliasBuilder extends TypeAliasBuilderImpl {
final Typedef typedef;
+ final Map<Name, Procedure>? tearOffs;
+
List<TypeVariableBuilder>? _typeVariables;
TypeBuilder? _type;
DartType? thisType;
- DillTypeAliasBuilder(this.typedef, DillLibraryBuilder parent)
+ DillTypeAliasBuilder(this.typedef, this.tearOffs, DillLibraryBuilder parent)
: super(null, typedef.name, parent, typedef.fileOffset);
List<MetadataBuilder> get metadata {
@@ -91,10 +90,4 @@
@override
bool get isNullAlias => typedef.type is NullType;
-
- @override
- void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
- // TODO(johnniwinther): Remove the need for this.
- }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 2383c40..6cf584a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -23,6 +23,18 @@
library);
}
+/// Creates the synthesized name to use for the lowering of the tear off of a
+/// constructor or factory by the given [constructorName] in [library].
+Name typedefTearOffName(
+ String typedefName, String constructorName, Library library) {
+ return new Name(
+ '$_tearOffNamePrefix'
+ '$typedefName#'
+ '${constructorName.isEmpty ? 'new' : constructorName}'
+ '$_tearOffNameSuffix',
+ library);
+}
+
/// Returns the name of the corresponding constructor or factory if [name] is
/// the synthesized name of a lowering of the tear off of a constructor or
/// factory. Returns `null` otherwise.
@@ -34,11 +46,37 @@
String text =
name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
text = text.substring(_tearOffNamePrefix.length);
+ if (text.contains('#')) {
+ return null;
+ }
return text == 'new' ? '' : text;
}
return null;
}
+/// If [name] is the synthesized name of a lowering of a typedef tear off, a
+/// list containing the [String] name of the typedef and the [Name] name of the
+/// corresponding constructor or factory is returned. Returns `null` otherwise.
+List<Object>? extractTypedefNameFromTearOff(Name name) {
+ if (name.text.startsWith(_tearOffNamePrefix) &&
+ name.text.endsWith(_tearOffNameSuffix) &&
+ name.text.length >
+ _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
+ String text =
+ name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
+ text = text.substring(_tearOffNamePrefix.length);
+ int hashIndex = text.indexOf('#');
+ if (hashIndex == -1) {
+ return null;
+ }
+ String typedefName = text.substring(0, hashIndex);
+ String constructorName = text.substring(hashIndex + 1);
+ constructorName = constructorName == 'new' ? '' : constructorName;
+ return [typedefName, new Name(constructorName, name.library)];
+ }
+ return null;
+}
+
/// Creates the [Procedure] for the lowering of a generative constructor of
/// the given [name] in [compilationUnit].
///
@@ -58,11 +96,45 @@
return null;
}
-/// Creates the parameters and body for [tearOff] based on [constructor].
+/// Creates the [Procedure] for the lowering of a non-redirecting factory of
+/// the given [name] in [compilationUnit].
+///
+/// If constructor tear off lowering is not enabled, `null` is returned.
+Procedure? createFactoryTearOffProcedure(String name,
+ SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset) {
+ if (compilationUnit
+ .loader.target.backendTarget.isFactoryTearOffLoweringEnabled) {
+ return _createTearOffProcedure(
+ compilationUnit,
+ constructorTearOffName(name, compilationUnit.library),
+ fileUri,
+ fileOffset);
+ }
+ return null;
+}
+
+/// Creates the [Procedure] for the lowering of a typedef tearoff of a
+/// constructor of the given [name] in with the typedef defined in
+/// [libraryBuilder].
+Procedure createTypedefTearOffProcedure(String typedefName, String name,
+ SourceLibraryBuilder libraryBuilder, Uri fileUri, int fileOffset) {
+ return _createTearOffProcedure(
+ libraryBuilder,
+ typedefTearOffName(typedefName, name, libraryBuilder.library),
+ fileUri,
+ fileOffset);
+}
+
+/// Creates the parameters and body for [tearOff] based on [constructor] in
+/// [enclosingClass].
void buildConstructorTearOffProcedure(Procedure tearOff, Member constructor,
Class enclosingClass, SourceLibraryBuilder libraryBuilder) {
- assert(constructor is Constructor ||
- (constructor is Procedure && constructor.isFactory));
+ assert(
+ constructor is Constructor ||
+ (constructor is Procedure && constructor.isFactory) ||
+ (constructor is Procedure && constructor.isStatic),
+ "Unexpected constructor tear off target $constructor "
+ "(${constructor.runtimeType}).");
int fileOffset = tearOff.fileOffset;
@@ -91,6 +163,58 @@
updatePrivateMemberName(tearOff, libraryBuilder);
}
+/// Creates the parameters and body for [tearOff] for a typedef tearoff of
+/// [constructor] in [enclosingClass] with [typeParameters] as the typedef
+/// parameters and [typeArguments] as the arguments passed to the
+/// [enclosingClass].
+void buildTypedefTearOffProcedure(
+ Procedure tearOff,
+ Member constructor,
+ Class enclosingClass,
+ List<TypeParameter> typeParameters,
+ List<DartType> typeArguments,
+ SourceLibraryBuilder libraryBuilder) {
+ assert(
+ constructor is Constructor ||
+ (constructor is Procedure && constructor.isFactory) ||
+ (constructor is Procedure && constructor.isStatic),
+ "Unexpected constructor tear off target $constructor "
+ "(${constructor.runtimeType}).");
+
+ int fileOffset = tearOff.fileOffset;
+
+ FunctionNode function = constructor.function!;
+ List<TypeParameter> classTypeParameters;
+ if (constructor is Constructor) {
+ // Generative constructors implicitly have the type parameters of the
+ // enclosing class.
+ classTypeParameters = enclosingClass.typeParameters;
+ } else {
+ // Factory constructors explicitly copy over the type parameters of the
+ // enclosing class.
+ classTypeParameters = function.typeParameters;
+ }
+
+ FreshTypeParameters freshTypeParameters =
+ _createFreshTypeParameters(typeParameters, tearOff.function);
+
+ Substitution substitution = freshTypeParameters.substitution;
+ if (!substitution.isEmpty) {
+ if (typeArguments.isNotEmpty) {
+ // Translate [typeArgument] into the context of the synthesized procedure.
+ typeArguments = new List<DartType>.generate(typeArguments.length,
+ (int index) => substitution.substituteType(typeArguments[index]));
+ }
+ }
+ _createParameters(tearOff, function,
+ Substitution.fromPairs(classTypeParameters, typeArguments));
+ Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+ _createTearOffBody(tearOff, constructor, arguments);
+ tearOff.function.fileOffset = tearOff.fileOffset;
+ tearOff.function.fileEndOffset = tearOff.fileOffset;
+ updatePrivateMemberName(tearOff, libraryBuilder);
+}
+
/// Copies the parameter types from [constructor] to [tearOff].
///
/// These might have been inferred and therefore not available when the
@@ -125,25 +249,6 @@
}
}
-void copyTearOffDefaultValues(Procedure tearOff, FunctionNode function) {
- CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
- for (int i = 0; i < function.positionalParameters.length; i++) {
- VariableDeclaration tearOffParameter =
- tearOff.function.positionalParameters[i];
- VariableDeclaration constructorParameter = function.positionalParameters[i];
- tearOffParameter.initializer =
- cloner.cloneOptional(constructorParameter.initializer);
- tearOffParameter.initializer?.parent = tearOffParameter;
- }
- for (int i = 0; i < function.namedParameters.length; i++) {
- VariableDeclaration tearOffParameter = tearOff.function.namedParameters[i];
- VariableDeclaration constructorParameter = function.namedParameters[i];
- tearOffParameter.initializer =
- cloner.cloneOptional(constructorParameter.initializer);
- tearOffParameter.initializer?.parent = tearOffParameter;
- }
-}
-
/// Creates the parameters for the redirecting factory [tearOff] based on the
/// [redirectingConstructor] declaration.
FreshTypeParameters buildRedirectingFactoryTearOffProcedureParameters(
@@ -194,79 +299,6 @@
identicalSignatures: false);
}
-/// Creates the synthesized name to use for the lowering of the tear off of a
-/// typedef in [library] using [index] for a unique name within the library.
-Name typedefTearOffName(int index, Library library) {
- return new Name(
- '$_tearOffNamePrefix'
- '${index}'
- '$_tearOffNameSuffix',
- library);
-}
-
-/// Creates a top level procedure to be used as the lowering for the typedef
-/// tear off [node] of a target of type [targetType]. [fileUri] together with
-/// the `fileOffset` of [node] is used as the location for the procedure.
-/// [index] is used to create a unique name for the procedure within
-/// [libraryBuilder].
-Procedure createTypedefTearOffLowering(SourceLibraryBuilder libraryBuilder,
- TypedefTearOff node, FunctionType targetType, Uri fileUri, int index) {
- int fileOffset = node.fileOffset;
- Procedure tearOff = _createTearOffProcedure(
- libraryBuilder,
- typedefTearOffName(index, libraryBuilder.library),
- fileUri,
- node.fileOffset);
- FreshTypeParameters freshTypeParameters =
- _createFreshTypeParameters(node.typeParameters, tearOff.function);
- Substitution substitution = freshTypeParameters.substitution;
-
- List<DartType> typeArguments = node.typeArguments;
- if (typeArguments.isNotEmpty) {
- if (!substitution.isEmpty) {
- // Translate [typeArgument] into the context of the synthesized procedure.
- typeArguments = new List<DartType>.generate(typeArguments.length,
- (int index) => substitution.substituteType(typeArguments[index]));
- }
- // Instantiate [targetType] with [typeArguments].
- targetType =
- Substitution.fromPairs(targetType.typeParameters, typeArguments)
- .substituteType(targetType.withoutTypeParameters) as FunctionType;
- }
-
- for (DartType constructorParameter in targetType.positionalParameters) {
- VariableDeclaration tearOffParameter = new VariableDeclaration(null,
- type: substitution.substituteType(constructorParameter))
- ..fileOffset = fileOffset;
- tearOff.function.positionalParameters.add(tearOffParameter);
- tearOffParameter.parent = tearOff.function;
- }
- for (NamedType constructorParameter in targetType.namedParameters) {
- VariableDeclaration tearOffParameter = new VariableDeclaration(
- constructorParameter.name,
- type: substitution.substituteType(constructorParameter.type),
- isRequired: constructorParameter.isRequired)
- ..fileOffset = fileOffset;
- tearOff.function.namedParameters.add(tearOffParameter);
- tearOffParameter.parent = tearOff.function;
- }
- tearOff.function.returnType =
- substitution.substituteType(targetType.returnType);
- tearOff.function.requiredParameterCount = targetType.requiredParameterCount;
-
- Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
- Expression constructorInvocation = new FunctionInvocation(
- FunctionAccessKind.FunctionType, node.expression, arguments,
- functionType: targetType)
- ..fileOffset = tearOff.fileOffset;
- tearOff.function.body = new ReturnStatement(constructorInvocation)
- ..fileOffset = tearOff.fileOffset
- ..parent = tearOff.function;
- tearOff.function.fileOffset = tearOff.fileOffset;
- tearOff.function.fileEndOffset = tearOff.fileOffset;
- return tearOff;
-}
-
/// Creates the synthesized [Procedure] node for a tear off lowering by the
/// given [name].
Procedure _createTearOffProcedure(SourceLibraryBuilder libraryBuilder,
@@ -351,7 +383,9 @@
/// Creates the tear of body for [tearOff] which calls [target] with
/// [arguments].
void _createTearOffBody(Procedure tearOff, Member target, Arguments arguments) {
- assert(target is Constructor || (target is Procedure && target.isFactory));
+ assert(target is Constructor ||
+ (target is Procedure && target.isFactory) ||
+ (target is Procedure && target.isStatic));
Expression constructorInvocation;
if (target is Constructor) {
constructorInvocation = new ConstructorInvocation(target, arguments)
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 7a251c4..4a0b5ca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -3220,6 +3220,13 @@
if (_helper.isProperRenameForClass(aliasBuilder!.typedef)) {
return tearOffExpression;
}
+ Procedure? tearOffLowering = aliasBuilder
+ .findConstructorOrFactory(
+ name.text, nameOffset, _uri, _helper.libraryBuilder);
+ if (tearOffLowering != null) {
+ return _helper.forest
+ .createStaticTearOff(token.charOffset, tearOffLowering);
+ }
FreshTypeParameters freshTypeParameters =
getFreshTypeParameters(aliasBuilder.typedef.typeParameters);
List<DartType>? substitutedTypeArguments;
@@ -3230,6 +3237,7 @@
.add(freshTypeParameters.substitute(builtTypeArgument));
}
}
+
tearOffExpression = _helper.forest.createTypedefTearOff(
token.charOffset,
freshTypeParameters.freshTypeParameters,
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 01cf218..104b239 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -258,16 +258,8 @@
typeParameters: freshTypeParameters.freshTypeParameters,
requiredParameterCount: resultType.requiredParameterCount,
typedefType: null);
- Expression replacement = node;
- if (!inferrer.isTopLevel &&
- inferrer.library.loader.target.backendTarget
- .isTypedefTearOffLoweringEnabled) {
- replacement = inferrer.library.getTypedefTearOffLowering(
- node, expressionType, inferrer.helper!.uri);
- }
-
ExpressionInferenceResult inferredResult =
- inferrer.instantiateTearOff(resultType, typeContext, replacement);
+ inferrer.instantiateTearOff(resultType, typeContext, node);
Expression ensuredResultExpression =
inferrer.ensureAssignableResult(typeContext, inferredResult);
return new ExpressionInferenceResult(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index a378dec..00e445c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -326,6 +326,7 @@
installDefaultSupertypes();
installSyntheticConstructors(myClasses);
loader.resolveConstructors();
+ loader.installTypedefTearOffs();
component =
link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
computeCoreTypes();
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index c4c13ce..cead87b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -81,8 +81,6 @@
import '../import.dart' show Import;
-import '../kernel/constructor_tearoff_lowering.dart';
-
import '../kernel/internal_ast.dart';
import '../kernel/kernel_builder.dart'
@@ -4237,15 +4235,23 @@
uncheckedTypedefTypes.clear();
}
- int _typedefTearOffLoweringIndex = 0;
-
- Expression getTypedefTearOffLowering(
- TypedefTearOff node, FunctionType targetType, Uri fileUri) {
- assert(loader.target.backendTarget.isTypedefTearOffLoweringEnabled);
- Procedure tearOff = createTypedefTearOffLowering(
- this, node, targetType, fileUri, _typedefTearOffLoweringIndex++);
- library.addProcedure(tearOff);
- return new StaticTearOff(tearOff)..fileOffset = node.fileOffset;
+ void installTypedefTearOffs() {
+ Iterator<Builder> iterator = this.iterator;
+ while (iterator.moveNext()) {
+ Builder? declaration = iterator.current;
+ while (declaration != null) {
+ if (declaration is SourceTypeAliasBuilder) {
+ declaration.buildTypedefTearOffs(this,
+ (Procedure procedure) {
+ procedure.isStatic = true;
+ if (!declaration!.isPatch && !declaration.isDuplicate) {
+ library.addProcedure(procedure);
+ }
+ });
+ }
+ declaration = declaration.next;
+ }
+ }
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index db885ca..ed43189 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -124,6 +124,7 @@
import 'source_class_builder.dart' show SourceClassBuilder;
import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_type_alias_builder.dart';
class SourceLoader extends Loader {
/// The [FileSystem] which should be used to access files.
@@ -719,6 +720,16 @@
ticker.logMs("Resolved $count constructors");
}
+ void installTypedefTearOffs() {
+ if (target.backendTarget.isTypedefTearOffLoweringEnabled) {
+ for (LibraryBuilder library in builders.values) {
+ if (library.loader == this && library is SourceLibraryBuilder) {
+ library.installTypedefTearOffs();
+ }
+ }
+ }
+ }
+
void finishTypeVariables(ClassBuilder object, TypeBuilder dynamicType) {
int count = 0;
for (LibraryBuilder library in builders.values) {
@@ -1202,9 +1213,9 @@
} else if (declaration is MemberBuilder) {
declaration.buildOutlineExpressions(library, coreTypes,
delayedActionPerformers, synthesizedFunctionNodes);
- } else if (declaration is TypeAliasBuilder) {
- declaration.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
+ } else if (declaration is SourceTypeAliasBuilder) {
+ declaration.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
} else {
assert(
declaration is PrefixBuilder ||
diff --git a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
index ae4fbb9..9961217 100644
--- a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
@@ -4,17 +4,7 @@
library fasta.source_type_alias_builder;
-import 'package:kernel/ast.dart'
- show
- DartType,
- DynamicType,
- InvalidType,
- TypeParameter,
- TypeParameterType,
- Typedef,
- TypedefType,
- VariableDeclaration,
- getAsTypeArguments;
+import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
@@ -33,6 +23,7 @@
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/type_builder.dart';
@@ -40,6 +31,9 @@
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/kernel_target.dart';
+
import '../util/helpers.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
@@ -54,6 +48,8 @@
DartType? thisType;
+ Map<Name, Procedure>? tearOffs;
+
SourceTypeAliasBuilder(
List<MetadataBuilder>? metadata,
String name,
@@ -253,11 +249,11 @@
allowSuperBounded: false);
}
- @override
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
MetadataBuilder.buildAnnotations(
typedef, metadata, library, null, null, fileUri);
if (typeVariables != null) {
@@ -266,5 +262,42 @@
library, null, null, coreTypes, delayedActionPerformers);
}
}
+ _tearOffDependencies?.forEach((Procedure tearOff, Member target) {
+ InterfaceType targetType = typedef.type as InterfaceType;
+ buildTypedefTearOffProcedure(tearOff, target, target.enclosingClass!,
+ typedef.typeParameters, targetType.typeArguments, library);
+ synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
+ new Map<TypeParameter, DartType>.fromIterables(
+ target.enclosingClass!.typeParameters, targetType.typeArguments),
+ target.function!,
+ tearOff.function));
+ });
+ }
+
+ Map<Procedure, Member>? _tearOffDependencies;
+
+ void buildTypedefTearOffs(
+ SourceLibraryBuilder library, void Function(Procedure) f) {
+ TypeDeclarationBuilder? declaration = unaliasDeclaration(null);
+ if (declaration is ClassBuilder) {
+ tearOffs = {};
+ _tearOffDependencies = {};
+ declaration
+ .forEachConstructor((String constructorName, MemberBuilder builder) {
+ Member? target = builder.invokeTarget;
+ if (target != null) {
+ if (target is Procedure && target.isRedirectingFactory) {
+ target = builder.readTarget!;
+ }
+ Name targetName =
+ new Name(constructorName, declaration.library.library);
+ Procedure tearOff = tearOffs![targetName] =
+ createTypedefTearOffProcedure(
+ name, constructorName, library, fileUri, charOffset);
+ _tearOffDependencies![tearOff] = target;
+ f(tearOff);
+ }
+ });
+ }
}
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
index 8c8090d..b93adae 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
@@ -48,10 +48,10 @@
Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:23:11 -> InstantiationConstant(A.fact<int*>)
Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:24:11 -> RedirectingFactoryTearOffConstant(A.redirect)
Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:25:11 -> InstantiationConstant(A.redirect<int*>)
-Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:26:11 -> TypedefTearOffConstant(A.<T><int>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:26:11 -> TypedefTearOffConstant(<T>A.<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:27:11 -> InstantiationConstant(A.<int*>)
-Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:28:11 -> TypedefTearOffConstant(A.fact<T><int>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:28:11 -> TypedefTearOffConstant(<T>A.fact<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:29:11 -> InstantiationConstant(A.fact<int*>)
-Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:30:11 -> TypedefTearOffConstant(A.redirect<T><int>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:30:11 -> TypedefTearOffConstant(<T>A.redirect<int>)
Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:31:11 -> InstantiationConstant(A.redirect<int*>)
Extra constant evaluation: evaluated: 23, effectively constant: 18
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart
new file mode 100644
index 0000000..aa3ec2f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'main_lib.dart';
+
+typedef H<X, Y> = A<Y>;
+
+// TODO(johnniwinther): Use 'var' here when dependency on inferred parameter
+// types is handled.
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+
+main() {
+ expect(true, identical(F_new, F_new_lib));
+ expect(false, identical(F_new, F_named_lib));
+ expect(false, identical(F_new, F_fact_lib));
+ expect(false, identical(F_new, F_redirect_lib));
+ expect(false, identical(F_new, G_new_lib));
+ expect(false, identical(F_new, G_named_lib));
+ expect(false, identical(F_new, G_fact_lib));
+ expect(false, identical(F_new, G_redirect_lib));
+ expect(false, identical(F_new, H_new));
+ expect(false, identical(F_new, H_named));
+ expect(false, identical(F_new, H_fact));
+ expect(false, identical(F_new, H_redirect));
+
+ expect(false, identical(F_named, F_new_lib));
+ expect(true, identical(F_named, F_named_lib));
+ expect(false, identical(F_named, F_fact_lib));
+ expect(false, identical(F_named, F_redirect_lib));
+ expect(false, identical(F_named, G_new_lib));
+ expect(false, identical(F_named, G_named_lib));
+ expect(false, identical(F_named, G_fact_lib));
+ expect(false, identical(F_named, G_redirect_lib));
+ expect(false, identical(F_named, H_new));
+ expect(false, identical(F_named, H_named));
+ expect(false, identical(F_named, H_fact));
+ expect(false, identical(F_named, H_redirect));
+
+ expect(false, identical(F_fact, F_new_lib));
+ expect(false, identical(F_fact, F_named_lib));
+ expect(true, identical(F_fact, F_fact_lib));
+ expect(false, identical(F_fact, F_redirect_lib));
+ expect(false, identical(F_fact, G_new_lib));
+ expect(false, identical(F_fact, G_named_lib));
+ expect(false, identical(F_fact, G_fact_lib));
+ expect(false, identical(F_fact, G_redirect_lib));
+ expect(false, identical(F_fact, H_new));
+ expect(false, identical(F_fact, H_named));
+ expect(false, identical(F_fact, H_fact));
+ expect(false, identical(F_fact, H_redirect));
+
+ expect(false, identical(F_redirect, F_new_lib));
+ expect(false, identical(F_redirect, F_named_lib));
+ expect(false, identical(F_redirect, F_fact_lib));
+ expect(true, identical(F_redirect, F_redirect_lib));
+ expect(false, identical(F_redirect, G_new_lib));
+ expect(false, identical(F_redirect, G_named_lib));
+ expect(false, identical(F_redirect, G_fact_lib));
+ expect(false, identical(F_redirect, G_redirect_lib));
+ expect(false, identical(F_redirect, H_new));
+ expect(false, identical(F_redirect, H_named));
+ expect(false, identical(F_redirect, H_fact));
+ expect(false, identical(F_redirect, H_redirect));
+}
+
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect
new file mode 100644
index 0000000..2dc1f69
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..a5b6962
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let Never #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect
new file mode 100644
index 0000000..4d2dfc1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+import 'main_lib.dart';
+typedef H<X, Y> = A<Y>;
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect
new file mode 100644
index 0000000..2dc1f69
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect
new file mode 100644
index 0000000..f1af048
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new;
+static field dynamic H_named;
+static field dynamic H_fact;
+static field dynamic H_redirect;
+static field dynamic F_new;
+static field dynamic F_named;
+static field dynamic F_fact;
+static field dynamic F_redirect;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ ;
+ constructor named(mai::A::T% a, [core::int? b]) → mai::A<mai::A::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b, core::int c}) → mai::A<mai::A::fact::T%>
+ ;
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b, core::int c}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib;
+static field dynamic F_named_lib;
+static field dynamic F_fact_lib;
+static field dynamic F_redirect_lib;
+static field dynamic G_new_lib;
+static field dynamic G_named_lib;
+static field dynamic G_fact_lib;
+static field dynamic G_redirect_lib;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..a5b6962
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let Never #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart
new file mode 100644
index 0000000..a57b86b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<T> {
+ A();
+ A.named(T a, [int? b]);
+ factory A.fact(T a, {int? b, int c = 42}) => new A();
+ factory A.redirect() = A;
+}
+
+typedef F<X, Y> = A<Y>;
+typedef G<X, Y> = A<Y>;
+
+dynamic F_new_lib = F.new;
+dynamic F_named_lib = F.named;
+dynamic F_fact_lib = F.fact;
+dynamic F_redirect_lib = F.redirect;
+
+dynamic G_new_lib = G.new;
+dynamic G_named_lib = G.named;
+dynamic G_fact_lib = G.fact;
+dynamic G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options
new file mode 100644
index 0000000..bfe6dc8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options
@@ -0,0 +1 @@
+main_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
new file mode 100644
index 0000000..8bd470e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'typedef_identical_lib.dart';
+
+typedef H<X, Y> = A<Y>;
+
+// TODO(johnniwinther): Use 'var' here when dependency on inferred parameter
+// types is handled.
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+
+main() {
+ expect(true, identical(F_new, F_new_lib));
+ expect(false, identical(F_new, F_named_lib));
+ expect(false, identical(F_new, F_fact_lib));
+ expect(false, identical(F_new, F_redirect_lib));
+ expect(false, identical(F_new, G_new_lib));
+ expect(false, identical(F_new, G_named_lib));
+ expect(false, identical(F_new, G_fact_lib));
+ expect(false, identical(F_new, G_redirect_lib));
+ expect(false, identical(F_new, H_new));
+ expect(false, identical(F_new, H_named));
+ expect(false, identical(F_new, H_fact));
+ expect(false, identical(F_new, H_redirect));
+
+ expect(false, identical(F_named, F_new_lib));
+ expect(true, identical(F_named, F_named_lib));
+ expect(false, identical(F_named, F_fact_lib));
+ expect(false, identical(F_named, F_redirect_lib));
+ expect(false, identical(F_named, G_new_lib));
+ expect(false, identical(F_named, G_named_lib));
+ expect(false, identical(F_named, G_fact_lib));
+ expect(false, identical(F_named, G_redirect_lib));
+ expect(false, identical(F_named, H_new));
+ expect(false, identical(F_named, H_named));
+ expect(false, identical(F_named, H_fact));
+ expect(false, identical(F_named, H_redirect));
+
+ expect(false, identical(F_fact, F_new_lib));
+ expect(false, identical(F_fact, F_named_lib));
+ expect(true, identical(F_fact, F_fact_lib));
+ expect(false, identical(F_fact, F_redirect_lib));
+ expect(false, identical(F_fact, G_new_lib));
+ expect(false, identical(F_fact, G_named_lib));
+ expect(false, identical(F_fact, G_fact_lib));
+ expect(false, identical(F_fact, G_redirect_lib));
+ expect(false, identical(F_fact, H_new));
+ expect(false, identical(F_fact, H_named));
+ expect(false, identical(F_fact, H_fact));
+ expect(false, identical(F_fact, H_redirect));
+
+ expect(false, identical(F_redirect, F_new_lib));
+ expect(false, identical(F_redirect, F_named_lib));
+ expect(false, identical(F_redirect, F_fact_lib));
+ expect(true, identical(F_redirect, F_redirect_lib));
+ expect(false, identical(F_redirect, G_new_lib));
+ expect(false, identical(F_redirect, G_named_lib));
+ expect(false, identical(F_redirect, G_fact_lib));
+ expect(false, identical(F_redirect, G_redirect_lib));
+ expect(false, identical(F_redirect, H_new));
+ expect(false, identical(F_redirect, H_named));
+ expect(false, identical(F_redirect, H_fact));
+ expect(false, identical(F_redirect, H_redirect));
+}
+
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
new file mode 100644
index 0000000..98b8997
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
new file mode 100644
index 0000000..b956c9c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let Never #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
new file mode 100644
index 0000000..0f1bd66
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+import 'typedef_identical_lib.dart';
+typedef H<X, Y> = A<Y>;
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
new file mode 100644
index 0000000..98b8997
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
new file mode 100644
index 0000000..7f142cf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field dynamic H_new;
+static field dynamic H_named;
+static field dynamic H_fact;
+static field dynamic H_redirect;
+static field dynamic F_new;
+static field dynamic F_named;
+static field dynamic F_fact;
+static field dynamic F_redirect;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ ;
+ constructor named(typ::A::T% a, [core::int? b]) → typ::A<typ::A::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b, core::int c}) → typ::A<typ::A::fact::T%>
+ ;
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b, core::int c}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib;
+static field dynamic F_named_lib;
+static field dynamic F_fact_lib;
+static field dynamic F_redirect_lib;
+static field dynamic G_new_lib;
+static field dynamic G_named_lib;
+static field dynamic G_fact_lib;
+static field dynamic G_redirect_lib;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
new file mode 100644
index 0000000..b956c9c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let Never #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
new file mode 100644
index 0000000..a57b86b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<T> {
+ A();
+ A.named(T a, [int? b]);
+ factory A.fact(T a, {int? b, int c = 42}) => new A();
+ factory A.redirect() = A;
+}
+
+typedef F<X, Y> = A<Y>;
+typedef G<X, Y> = A<Y>;
+
+dynamic F_new_lib = F.new;
+dynamic F_named_lib = F.named;
+dynamic F_fact_lib = F.fact;
+dynamic F_redirect_lib = F.redirect;
+
+dynamic G_new_lib = G.new;
+dynamic G_named_lib = G.named;
+dynamic G_fact_lib = G.fact;
+dynamic G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
index 08a9470..f68f95f 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
@@ -143,14 +143,14 @@
^" in f2a{<inapplicable>}.<core::num>(0);
f2a<core::String>(){() → self::A};
};
- dynamic f2b = #C3;
+ dynamic f2b = #C2;
dynamic c2b = f2b{dynamic}.call();
self::expect(true, c2b is{ForNonNullableByDefault} self::A);
dynamic c2c = f2b{dynamic}.call<core::int>();
self::expect(true, c2c is{ForNonNullableByDefault} self::A);
self::throws(() → dynamic => f2b{dynamic}.call(0));
self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
- () → self::B<core::String> f3a = #C5;
+ () → self::B<core::String> f3a = #C4;
self::B<core::String> c3a = f3a(){() → self::B<core::String>};
self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
@@ -165,7 +165,7 @@
f3a<String>(); // error
^" in f3a{<inapplicable>}.<core::String>();
};
- dynamic f3b = #C5;
+ dynamic f3b = #C4;
dynamic c3b = f3b{dynamic}.call();
self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
@@ -173,7 +173,7 @@
self::expect("", c3a.{self::B::field2}{core::String});
self::throws(() → dynamic => f3b{dynamic}.call(0));
self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
- (core::int) → self::B<core::String> f3c = #C7;
+ (core::int) → self::B<core::String> f3c = #C6;
self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
@@ -191,7 +191,7 @@
f3c<String>(0); // error
^" in f3c{<inapplicable>}.<core::String>(0);
};
- dynamic f3d = #C7;
+ dynamic f3d = #C6;
dynamic c3d = f3d{dynamic}.call(42);
self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
@@ -200,7 +200,7 @@
self::throws(() → dynamic => f3d{dynamic}.call());
self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
- (core::int, core::String) → self::B<core::String> f3e = #C9;
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
@@ -217,7 +217,7 @@
f3e<String>(0, ''); // error
^" in f3e{<inapplicable>}.<core::String>(0, "");
};
- dynamic f3f = #C9;
+ dynamic f3f = #C8;
dynamic c3f = f3f{dynamic}.call(42, "foo");
self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
@@ -226,7 +226,7 @@
self::throws(() → dynamic => c3f{dynamic}.call());
self::throws(() → dynamic => c3f{dynamic}.call(0));
self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
- <X extends core::num>() → self::B<X> f4a = #C10;
+ <X extends core::num>() → self::B<X> f4a = #C9;
self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
@@ -240,7 +240,7 @@
^" in f4a{<inapplicable>}.<core::num>(0);
f4a<core::String>(){() → self::B<core::String>};
};
- dynamic f4b = #C11;
+ dynamic f4b = #C9;
dynamic c4c = f4b{dynamic}.call();
self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
@@ -249,7 +249,7 @@
self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
self::throws(() → dynamic => f4b{dynamic}.call(0));
self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
- <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C12;
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
@@ -267,7 +267,7 @@
f5a<core::String, core::String>(){() → self::B<core::String>};
f5a<core::num, core::num>(){() → self::B<core::num>};
};
- dynamic f5b = #C13;
+ dynamic f5b = #C10;
dynamic c5c = f5b{dynamic}.call();
self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
@@ -283,7 +283,7 @@
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C14}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -296,32 +296,45 @@
}
throw "Expected exception";
}
-static method _#0#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#1#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#2#tearOff<X extends core::num>() → self::B<self::_#2#tearOff::X>
- return (#C4)<self::_#2#tearOff::X>(){() → self::B<self::_#2#tearOff::X>};
-static method _#3#tearOff<X extends core::num>() → self::B<self::_#3#tearOff::X>
- return (#C4)<self::_#3#tearOff::X>(){() → self::B<self::_#3#tearOff::X>};
-static method _#4#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#4#tearOff::X>
- return (#C4)<self::_#4#tearOff::X>(){() → self::B<self::_#4#tearOff::X>};
-static method _#5#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#5#tearOff::X>
- return (#C4)<self::_#5#tearOff::X>(){() → self::B<self::_#5#tearOff::X>};
+static method _#DA1#new#tearOff() → self::A
+ return new self::A::•();
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB1#_#tearOff(core::int field1, core::String field2) → self::B<core::String>
+ return new self::B::_<core::String>(field1, field2);
+static method _#DB1#new#tearOff() → self::B<core::String>
+ return new self::B::•<core::String>();
+static method _#DB1#foo#tearOff(core::int field1) → self::B<core::String>
+ return new self::B::foo<core::String>(field1);
+static method _#DB1#bar#tearOff(core::int i, core::String j) → self::B<core::String>
+ return self::B::bar<core::String>(i, j);
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
constants {
#C1 = static-tearoff self::A::_#new#tearOff
- #C2 = static-tearoff self::_#0#tearOff
- #C3 = static-tearoff self::_#1#tearOff
- #C4 = static-tearoff self::B::_#new#tearOff
- #C5 = instantiation self::B::_#new#tearOff <core::String>
- #C6 = static-tearoff self::B::_#foo#tearOff
- #C7 = instantiation self::B::_#foo#tearOff <core::String>
- #C8 = static-tearoff self::B::_#bar#tearOff
- #C9 = instantiation self::B::_#bar#tearOff <core::String>
- #C10 = static-tearoff self::_#2#tearOff
- #C11 = static-tearoff self::_#3#tearOff
- #C12 = static-tearoff self::_#4#tearOff
- #C13 = static-tearoff self::_#5#tearOff
- #C14 = false
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
index 151872a..f5bd2bb 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
@@ -143,14 +143,14 @@
^" in f2a{<inapplicable>}.<core::num>(0);
f2a<core::String>(){() → self::A};
};
- dynamic f2b = #C3;
+ dynamic f2b = #C2;
dynamic c2b = f2b{dynamic}.call();
self::expect(true, c2b is{ForNonNullableByDefault} self::A);
dynamic c2c = f2b{dynamic}.call<core::int>();
self::expect(true, c2c is{ForNonNullableByDefault} self::A);
self::throws(() → dynamic => f2b{dynamic}.call(0));
self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
- () → self::B<core::String> f3a = #C5;
+ () → self::B<core::String> f3a = #C4;
self::B<core::String> c3a = f3a(){() → self::B<core::String>};
self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
@@ -165,7 +165,7 @@
f3a<String>(); // error
^" in f3a{<inapplicable>}.<core::String>();
};
- dynamic f3b = #C5;
+ dynamic f3b = #C4;
dynamic c3b = f3b{dynamic}.call();
self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
@@ -173,7 +173,7 @@
self::expect("", c3a.{self::B::field2}{core::String});
self::throws(() → dynamic => f3b{dynamic}.call(0));
self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
- (core::int) → self::B<core::String> f3c = #C7;
+ (core::int) → self::B<core::String> f3c = #C6;
self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
@@ -191,7 +191,7 @@
f3c<String>(0); // error
^" in f3c{<inapplicable>}.<core::String>(0);
};
- dynamic f3d = #C7;
+ dynamic f3d = #C6;
dynamic c3d = f3d{dynamic}.call(42);
self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
@@ -200,7 +200,7 @@
self::throws(() → dynamic => f3d{dynamic}.call());
self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
- (core::int, core::String) → self::B<core::String> f3e = #C9;
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
@@ -217,7 +217,7 @@
f3e<String>(0, ''); // error
^" in f3e{<inapplicable>}.<core::String>(0, "");
};
- dynamic f3f = #C9;
+ dynamic f3f = #C8;
dynamic c3f = f3f{dynamic}.call(42, "foo");
self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
@@ -226,7 +226,7 @@
self::throws(() → dynamic => c3f{dynamic}.call());
self::throws(() → dynamic => c3f{dynamic}.call(0));
self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
- <X extends core::num>() → self::B<X> f4a = #C10;
+ <X extends core::num>() → self::B<X> f4a = #C9;
self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
@@ -240,7 +240,7 @@
^" in f4a{<inapplicable>}.<core::num>(0);
f4a<core::String>(){() → self::B<core::String>};
};
- dynamic f4b = #C11;
+ dynamic f4b = #C9;
dynamic c4c = f4b{dynamic}.call();
self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
@@ -249,7 +249,7 @@
self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
self::throws(() → dynamic => f4b{dynamic}.call(0));
self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
- <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C12;
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
@@ -267,7 +267,7 @@
f5a<core::String, core::String>(){() → self::B<core::String>};
f5a<core::num, core::num>(){() → self::B<core::num>};
};
- dynamic f5b = #C13;
+ dynamic f5b = #C10;
dynamic c5c = f5b{dynamic}.call();
self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
@@ -283,7 +283,7 @@
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C14}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -296,32 +296,45 @@
}
throw "Expected exception";
}
-static method _#0#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#1#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#2#tearOff<X extends core::num>() → self::B<self::_#2#tearOff::X>
- return (#C4)<self::_#2#tearOff::X>(){() → self::B<self::_#2#tearOff::X>};
-static method _#3#tearOff<X extends core::num>() → self::B<self::_#3#tearOff::X>
- return (#C4)<self::_#3#tearOff::X>(){() → self::B<self::_#3#tearOff::X>};
-static method _#4#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#4#tearOff::X>
- return (#C4)<self::_#4#tearOff::X>(){() → self::B<self::_#4#tearOff::X>};
-static method _#5#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#5#tearOff::X>
- return (#C4)<self::_#5#tearOff::X>(){() → self::B<self::_#5#tearOff::X>};
+static method _#DA1#new#tearOff() → self::A
+ return new self::A::•();
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB1#_#tearOff(core::int field1, core::String field2) → self::B<core::String>
+ return new self::B::_<core::String>(field1, field2);
+static method _#DB1#new#tearOff() → self::B<core::String>
+ return new self::B::•<core::String>();
+static method _#DB1#foo#tearOff(core::int field1) → self::B<core::String>
+ return new self::B::foo<core::String>(field1);
+static method _#DB1#bar#tearOff(core::int i, core::String j) → self::B<core::String>
+ return self::B::bar<core::String>(i, j);
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
constants {
#C1 = static-tearoff self::A::_#new#tearOff
- #C2 = static-tearoff self::_#0#tearOff
- #C3 = static-tearoff self::_#1#tearOff
- #C4 = static-tearoff self::B::_#new#tearOff
- #C5 = instantiation self::B::_#new#tearOff <core::String>
- #C6 = static-tearoff self::B::_#foo#tearOff
- #C7 = instantiation self::B::_#foo#tearOff <core::String>
- #C8 = static-tearoff self::B::_#bar#tearOff
- #C9 = instantiation self::B::_#bar#tearOff <core::String>
- #C10 = static-tearoff self::_#2#tearOff
- #C11 = static-tearoff self::_#3#tearOff
- #C12 = static-tearoff self::_#4#tearOff
- #C13 = static-tearoff self::_#5#tearOff
- #C14 = false
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
index 630a7de..d485819 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
@@ -143,14 +143,14 @@
^" in f2a{<inapplicable>}.<core::num>(0);
f2a<core::String>(){() → self::A};
};
- dynamic f2b = #C3;
+ dynamic f2b = #C2;
dynamic c2b = f2b{dynamic}.call();
self::expect(true, c2b is{ForNonNullableByDefault} self::A);
dynamic c2c = f2b{dynamic}.call<core::int>();
self::expect(true, c2c is{ForNonNullableByDefault} self::A);
self::throws(() → dynamic => f2b{dynamic}.call(0));
self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
- () → self::B<core::String> f3a = #C5;
+ () → self::B<core::String> f3a = #C4;
self::B<core::String> c3a = f3a(){() → self::B<core::String>};
self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
@@ -165,7 +165,7 @@
f3a<String>(); // error
^" in f3a{<inapplicable>}.<core::String>();
};
- dynamic f3b = #C5;
+ dynamic f3b = #C4;
dynamic c3b = f3b{dynamic}.call();
self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
@@ -173,7 +173,7 @@
self::expect("", c3a.{self::B::field2}{core::String});
self::throws(() → dynamic => f3b{dynamic}.call(0));
self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
- (core::int) → self::B<core::String> f3c = #C7;
+ (core::int) → self::B<core::String> f3c = #C6;
self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
@@ -191,7 +191,7 @@
f3c<String>(0); // error
^" in f3c{<inapplicable>}.<core::String>(0);
};
- dynamic f3d = #C7;
+ dynamic f3d = #C6;
dynamic c3d = f3d{dynamic}.call(42);
self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
@@ -200,7 +200,7 @@
self::throws(() → dynamic => f3d{dynamic}.call());
self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
- (core::int, core::String) → self::B<core::String> f3e = #C9;
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
@@ -217,7 +217,7 @@
f3e<String>(0, ''); // error
^" in f3e{<inapplicable>}.<core::String>(0, "");
};
- dynamic f3f = #C9;
+ dynamic f3f = #C8;
dynamic c3f = f3f{dynamic}.call(42, "foo");
self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
@@ -226,7 +226,7 @@
self::throws(() → dynamic => c3f{dynamic}.call());
self::throws(() → dynamic => c3f{dynamic}.call(0));
self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
- <X extends core::num>() → self::B<X> f4a = #C10;
+ <X extends core::num>() → self::B<X> f4a = #C9;
self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
@@ -240,7 +240,7 @@
^" in f4a{<inapplicable>}.<core::num>(0);
f4a<core::String>(){() → self::B<core::String>};
};
- dynamic f4b = #C11;
+ dynamic f4b = #C9;
dynamic c4c = f4b{dynamic}.call();
self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
@@ -249,7 +249,7 @@
self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
self::throws(() → dynamic => f4b{dynamic}.call(0));
self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
- <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C12;
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
@@ -267,7 +267,7 @@
f5a<core::String, core::String>(){() → self::B<core::String>};
f5a<core::num, core::num>(){() → self::B<core::num>};
};
- dynamic f5b = #C13;
+ dynamic f5b = #C10;
dynamic c5c = f5b{dynamic}.call();
self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
@@ -283,7 +283,7 @@
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C14}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -296,32 +296,45 @@
}
throw "Expected exception";
}
-static method _#0#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#1#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#2#tearOff<X extends core::num>() → self::B<self::_#2#tearOff::X>
- return (#C4)<self::_#2#tearOff::X>(){() → self::B<self::_#2#tearOff::X>};
-static method _#3#tearOff<X extends core::num>() → self::B<self::_#3#tearOff::X>
- return (#C4)<self::_#3#tearOff::X>(){() → self::B<self::_#3#tearOff::X>};
-static method _#4#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#4#tearOff::X>
- return (#C4)<self::_#4#tearOff::X>(){() → self::B<self::_#4#tearOff::X>};
-static method _#5#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#5#tearOff::X>
- return (#C4)<self::_#5#tearOff::X>(){() → self::B<self::_#5#tearOff::X>};
+static method _#DA1#new#tearOff() → self::A
+ return new self::A::•();
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB1#_#tearOff(core::int field1, core::String field2) → self::B<core::String>
+ return new self::B::_<core::String>(field1, field2);
+static method _#DB1#new#tearOff() → self::B<core::String>
+ return new self::B::•<core::String>();
+static method _#DB1#foo#tearOff(core::int field1) → self::B<core::String>
+ return new self::B::foo<core::String>(field1);
+static method _#DB1#bar#tearOff(core::int i, core::String j) → self::B<core::String>
+ return self::B::bar<core::String>(i, j);
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
constants {
#C1 = static-tearoff self::A::_#new#tearOff
- #C2 = static-tearoff self::_#0#tearOff
- #C3 = static-tearoff self::_#1#tearOff
- #C4 = static-tearoff self::B::_#new#tearOff
- #C5 = instantiation self::B::_#new#tearOff <core::String*>
- #C6 = static-tearoff self::B::_#foo#tearOff
- #C7 = instantiation self::B::_#foo#tearOff <core::String*>
- #C8 = static-tearoff self::B::_#bar#tearOff
- #C9 = instantiation self::B::_#bar#tearOff <core::String*>
- #C10 = static-tearoff self::_#2#tearOff
- #C11 = static-tearoff self::_#3#tearOff
- #C12 = static-tearoff self::_#4#tearOff
- #C13 = static-tearoff self::_#5#tearOff
- #C14 = false
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String*>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String*>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String*>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
index be18978..a3bed2d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
@@ -40,3 +40,31 @@
;
static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
;
+static method _#DA1#new#tearOff() → self::A
+ return new self::A::•();
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB1#_#tearOff(core::int field1, core::String field2) → self::B<core::String>
+ return new self::B::_<core::String>(field1, field2);
+static method _#DB1#new#tearOff() → self::B<core::String>
+ return new self::B::•<core::String>();
+static method _#DB1#foo#tearOff(core::int field1) → self::B<core::String>
+ return new self::B::foo<core::String>(field1);
+static method _#DB1#bar#tearOff(core::int i, core::String j) → self::B<core::String>
+ return self::B::bar<core::String>(i, j);
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
index 3190b63..e905181 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
@@ -143,14 +143,14 @@
^" in f2a{<inapplicable>}.<core::num>(0);
f2a<core::String>(){() → self::A};
};
- dynamic f2b = #C3;
+ dynamic f2b = #C2;
dynamic c2b = f2b{dynamic}.call();
self::expect(true, c2b is{ForNonNullableByDefault} self::A);
dynamic c2c = f2b{dynamic}.call<core::int>();
self::expect(true, c2c is{ForNonNullableByDefault} self::A);
self::throws(() → dynamic => f2b{dynamic}.call(0));
self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
- () → self::B<core::String> f3a = #C5;
+ () → self::B<core::String> f3a = #C4;
self::B<core::String> c3a = f3a(){() → self::B<core::String>};
self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
@@ -165,7 +165,7 @@
f3a<String>(); // error
^" in f3a{<inapplicable>}.<core::String>();
};
- dynamic f3b = #C5;
+ dynamic f3b = #C4;
dynamic c3b = f3b{dynamic}.call();
self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
@@ -173,7 +173,7 @@
self::expect("", c3a.{self::B::field2}{core::String});
self::throws(() → dynamic => f3b{dynamic}.call(0));
self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
- (core::int) → self::B<core::String> f3c = #C7;
+ (core::int) → self::B<core::String> f3c = #C6;
self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
@@ -191,7 +191,7 @@
f3c<String>(0); // error
^" in f3c{<inapplicable>}.<core::String>(0);
};
- dynamic f3d = #C7;
+ dynamic f3d = #C6;
dynamic c3d = f3d{dynamic}.call(42);
self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
@@ -200,7 +200,7 @@
self::throws(() → dynamic => f3d{dynamic}.call());
self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
- (core::int, core::String) → self::B<core::String> f3e = #C9;
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
@@ -217,7 +217,7 @@
f3e<String>(0, ''); // error
^" in f3e{<inapplicable>}.<core::String>(0, "");
};
- dynamic f3f = #C9;
+ dynamic f3f = #C8;
dynamic c3f = f3f{dynamic}.call(42, "foo");
self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
@@ -226,7 +226,7 @@
self::throws(() → dynamic => c3f{dynamic}.call());
self::throws(() → dynamic => c3f{dynamic}.call(0));
self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
- <X extends core::num>() → self::B<X> f4a = #C10;
+ <X extends core::num>() → self::B<X> f4a = #C9;
self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
@@ -240,7 +240,7 @@
^" in f4a{<inapplicable>}.<core::num>(0);
f4a<core::String>(){() → self::B<core::String>};
};
- dynamic f4b = #C11;
+ dynamic f4b = #C9;
dynamic c4c = f4b{dynamic}.call();
self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
@@ -249,7 +249,7 @@
self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
self::throws(() → dynamic => f4b{dynamic}.call(0));
self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
- <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C12;
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
@@ -267,7 +267,7 @@
f5a<core::String, core::String>(){() → self::B<core::String>};
f5a<core::num, core::num>(){() → self::B<core::num>};
};
- dynamic f5b = #C13;
+ dynamic f5b = #C10;
dynamic c5c = f5b{dynamic}.call();
self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
@@ -283,7 +283,7 @@
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C14}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -296,32 +296,45 @@
}
throw "Expected exception";
}
-static method _#0#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#1#tearOff<unrelated X extends core::num>() → self::A
- return (#C1)(){() → self::A};
-static method _#2#tearOff<X extends core::num>() → self::B<self::_#2#tearOff::X>
- return (#C4)<self::_#2#tearOff::X>(){() → self::B<self::_#2#tearOff::X>};
-static method _#3#tearOff<X extends core::num>() → self::B<self::_#3#tearOff::X>
- return (#C4)<self::_#3#tearOff::X>(){() → self::B<self::_#3#tearOff::X>};
-static method _#4#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#4#tearOff::X>
- return (#C4)<self::_#4#tearOff::X>(){() → self::B<self::_#4#tearOff::X>};
-static method _#5#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#5#tearOff::X>
- return (#C4)<self::_#5#tearOff::X>(){() → self::B<self::_#5#tearOff::X>};
+static method _#DA1#new#tearOff() → self::A
+ return new self::A::•();
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB1#_#tearOff(core::int field1, core::String field2) → self::B<core::String>
+ return new self::B::_<core::String>(field1, field2);
+static method _#DB1#new#tearOff() → self::B<core::String>
+ return new self::B::•<core::String>();
+static method _#DB1#foo#tearOff(core::int field1) → self::B<core::String>
+ return new self::B::foo<core::String>(field1);
+static method _#DB1#bar#tearOff(core::int i, core::String j) → self::B<core::String>
+ return self::B::bar<core::String>(i, j);
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
constants {
#C1 = static-tearoff self::A::_#new#tearOff
- #C2 = static-tearoff self::_#0#tearOff
- #C3 = static-tearoff self::_#1#tearOff
- #C4 = static-tearoff self::B::_#new#tearOff
- #C5 = instantiation self::B::_#new#tearOff <core::String*>
- #C6 = static-tearoff self::B::_#foo#tearOff
- #C7 = instantiation self::B::_#foo#tearOff <core::String*>
- #C8 = static-tearoff self::B::_#bar#tearOff
- #C9 = instantiation self::B::_#bar#tearOff <core::String*>
- #C10 = static-tearoff self::_#2#tearOff
- #C11 = static-tearoff self::_#3#tearOff
- #C12 = static-tearoff self::_#4#tearOff
- #C13 = static-tearoff self::_#5#tearOff
- #C14 = false
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String*>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String*>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String*>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index b961189..8082cff 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -32,6 +32,8 @@
constructor_tearoffs/inferred_constructor_tear_off: FormatterCrash
constructor_tearoffs/instantiation: FormatterCrash
constructor_tearoffs/lowering/inferred_constructor_tear_off: FormatterCrash
+constructor_tearoffs/lowering/typedef_from_dill/main: FormatterCrash
+constructor_tearoffs/lowering/typedef_identical: FormatterCrash
constructor_tearoffs/nongeneric_tearoff_with_context: FormatterCrash
constructor_tearoffs/nongeneric_tearoff_without_context: FormatterCrash
constructor_tearoffs/redirecting_constructors: FormatterCrash
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2dd4cf9..0009adc 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -13116,8 +13116,8 @@
@override
void toTextInternal(AstPrinter printer) {
- printer.writeConstant(tearOffConstant);
printer.writeTypeParameters(parameters);
+ printer.writeConstant(tearOffConstant);
printer.writeTypeArguments(types);
}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index bb2aace..6885c8a 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -354,7 +354,7 @@
/// synthesized top level functions.
int get enabledConstructorTearOffLowerings;
- /// Returns `true` if lowering of constructor tear offs is enabled.
+ /// Returns `true` if lowering of generative constructor tear offs is enabled.
///
/// This is determined by the [enabledConstructorTearOffLowerings] mask.
bool get isConstructorTearOffLoweringEnabled =>
@@ -362,6 +362,15 @@
ConstructorTearOffLowering.constructors) !=
0;
+ /// Returns `true` if lowering of non-redirecting factory tear offs is
+ /// enabled.
+ ///
+ /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+ bool get isFactoryTearOffLoweringEnabled =>
+ (enabledConstructorTearOffLowerings &
+ ConstructorTearOffLowering.factories) !=
+ 0;
+
/// Returns `true` if lowering of redirecting factory tear offs is enabled.
///
/// This is determined by the [enabledConstructorTearOffLowerings] mask.
@@ -643,16 +652,19 @@
}
class ConstructorTearOffLowering {
- /// Create static functions to use as tear offs of constructors and.
+ /// Create static functions to use as tear offs of generative constructors.
static const int constructors = 1 << 0;
+ /// Create static functions to use as tear offs of non-redirecting factories.
+ static const int factories = 1 << 1;
+
/// Create static functions to use as tear offs of redirecting factories.
- static const int redirectingFactories = 1 << 1;
+ static const int redirectingFactories = 1 << 2;
/// Create top level functions to use as tear offs of typedefs that are not
/// proper renames.
- static const int typedefs = 1 << 2;
+ static const int typedefs = 1 << 3;
static const int none = 0;
- static const int all = (1 << 3) - 1;
+ static const int all = (1 << 4) - 1;
}
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 65d35ce..7d40798 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -371,6 +371,20 @@
*/
DART_EXPORT int64_t Dart_TimelineGetMicros();
+/**
+ * Returns a raw timestamp in from the monotonic clock.
+ *
+ * \return A raw timestamp from the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicks();
+
+/**
+ * Returns the frequency of the monotonic clock.
+ *
+ * \return The frequency of the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency();
+
/** Timeline stream for Dart API calls */
#define DART_TIMELINE_STREAM_API (1 << 0)
/** Timeline stream for compiler events */
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index ebe4a4b..283841a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6163,10 +6163,6 @@
return ServiceIsolate::IsServiceIsolate(iso);
}
-DART_EXPORT int64_t Dart_TimelineGetMicros() {
- return OS::GetCurrentMonotonicMicros();
-}
-
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
@@ -6308,6 +6304,18 @@
#endif
}
+DART_EXPORT int64_t Dart_TimelineGetMicros() {
+ return OS::GetCurrentMonotonicMicros();
+}
+
+DART_EXPORT int64_t Dart_TimelineGetTicks() {
+ return OS::GetCurrentMonotonicTicks();
+}
+
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency() {
+ return OS::GetCurrentMonotonicFrequency();
+}
+
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
#if defined(SUPPORT_TIMELINE)
const bool api_enabled = (stream_mask & DART_TIMELINE_STREAM_API) != 0;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 2be540b..50b0ab9 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -9082,6 +9082,19 @@
EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
}
+TEST_CASE(DartAPI_TimelineClock) {
+ int64_t micros1 = Dart_TimelineGetMicros();
+ int64_t ticks1 = Dart_TimelineGetTicks();
+ int64_t frequency1 = Dart_TimelineGetTicksFrequency();
+ OS::Sleep(1);
+ int64_t micros2 = Dart_TimelineGetMicros();
+ int64_t ticks2 = Dart_TimelineGetTicks();
+ int64_t frequency2 = Dart_TimelineGetTicksFrequency();
+ EXPECT_NE(micros1, micros2);
+ EXPECT_NE(ticks1, ticks2);
+ EXPECT_EQ(frequency1, frequency2);
+}
+
static void HintFreedNative(Dart_NativeArguments args) {
int64_t size = 0;
EXPECT_VALID(Dart_GetNativeIntegerArgument(args, 0, &size));
diff --git a/tools/VERSION b/tools/VERSION
index c32c3d3..778bf10 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 347
+PRERELEASE 348
PRERELEASE_PATCH 0
\ No newline at end of file