Skip to content

Commit 46acf36

Browse files
johnniwintherwhesse
authored andcommitted
[cfe] Use effective target in redirecting factory tear off lowering
The tear-off lowering for a redirecting factory called the immediate target (even when this was also a redirecting factory) instead of the effective target. This caused problem in backends that don't support redirecting factories directly. Closes #47916 Change-Id: Iafb11c42c1e99e70ed44b0835473a8c69e995b01 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/235780 Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 2e9da5a commit 46acf36

File tree

61 files changed

+1966
-15
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1966
-15
lines changed

pkg/front_end/lib/src/fasta/scope.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ mixin ErroneousMemberBuilderMixin implements SourceMemberBuilder {
805805
}
806806

807807
@override
808-
LibraryBuilder get library {
808+
SourceLibraryBuilder get library {
809809
throw new UnsupportedError('AmbiguousMemberBuilder.library');
810810
}
811811

pkg/front_end/lib/src/fasta/source/source_class_builder.dart

+3
Original file line numberDiff line numberDiff line change
@@ -2808,6 +2808,9 @@ class _RedirectingConstructorsFieldBuilder extends DillFieldBuilder
28082808
_RedirectingConstructorsFieldBuilder(Field field, SourceClassBuilder parent)
28092809
: super(field, parent);
28102810

2811+
@override
2812+
SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
2813+
28112814
@override
28122815
void buildOutlineExpressions(
28132816
SourceLibraryBuilder library,

pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,6 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
129129
super(metadata, modifiers, returnType, name, typeVariables, formals,
130130
compilationUnit, charOffset, nativeMethodName);
131131

132-
@override
133-
SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
134-
135132
@override
136133
SourceClassBuilder get classBuilder =>
137134
super.classBuilder as SourceClassBuilder;
@@ -783,6 +780,9 @@ class SyntheticSourceConstructorBuilder extends DillConstructorBuilder
783780
_synthesizedFunctionNode = synthesizedFunctionNode,
784781
super(constructor, constructorTearOff, parent);
785782

783+
@override
784+
SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
785+
786786
// TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
787787
// confusion with patches.
788788
MemberBuilder? get actualOrigin {

pkg/front_end/lib/src/fasta/source/source_factory_builder.dart

+33-8
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ class RedirectingFactoryBuilder extends SourceFactoryBuilder {
407407
inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
408408
library, classBuilder, this, classBuilder!.scope, fileUri);
409409
Builder? targetBuilder = redirectionTarget.target;
410+
if (targetBuilder is SourceMemberBuilder) {
411+
// Ensure that target has been built.
412+
targetBuilder.buildOutlineExpressions(targetBuilder.library,
413+
classHierarchy, delayedActionPerformers, synthesizedFunctionNodes);
414+
}
410415
if (targetBuilder is FunctionBuilder) {
411416
target = targetBuilder.member;
412417
} else if (targetBuilder is DillMemberBuilder) {
@@ -457,14 +462,34 @@ class RedirectingFactoryBuilder extends SourceFactoryBuilder {
457462
new RedirectingFactoryBody(target, typeArguments, function);
458463
function.body!.parent = function;
459464
}
460-
if (_factoryTearOff != null &&
461-
(target is Constructor || target is Procedure && target.isFactory)) {
462-
synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
463-
_factoryTearOff!,
464-
target!,
465-
typeArguments ?? [],
466-
_tearOffTypeParameters!,
467-
library));
465+
if (_factoryTearOff != null) {
466+
Set<Procedure> seenTargets = {};
467+
while (target is Procedure && target.isRedirectingFactory) {
468+
if (!seenTargets.add(target)) {
469+
// Cyclic dependency.
470+
target = null;
471+
break;
472+
}
473+
RedirectingFactoryBody body =
474+
target.function.body as RedirectingFactoryBody;
475+
if (typeArguments != null) {
476+
Substitution substitution = Substitution.fromPairs(
477+
target.function.typeParameters, typeArguments);
478+
typeArguments =
479+
body.typeArguments?.map(substitution.substituteType).toList();
480+
} else {
481+
typeArguments = body.typeArguments;
482+
}
483+
target = body.target;
484+
}
485+
if (target is Constructor || target is Procedure && target.isFactory) {
486+
synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
487+
_factoryTearOff!,
488+
target!,
489+
typeArguments ?? [],
490+
_tearOffTypeParameters!,
491+
library));
492+
}
468493
}
469494
if (isConst && isPatch) {
470495
_finishPatch();

pkg/front_end/lib/src/fasta/source/source_field_builder.dart

-3
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,6 @@ class SourceFieldBuilder extends SourceMemberBuilderImpl
282282
_typeEnsured = true;
283283
}
284284

285-
@override
286-
SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
287-
288285
@override
289286
Member get member => _fieldEncoding.field;
290287

pkg/front_end/lib/src/fasta/source/source_member_builder.dart

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import 'source_class_builder.dart';
2525
abstract class SourceMemberBuilder implements MemberBuilder {
2626
MemberDataForTesting? get dataForTesting;
2727

28+
@override
29+
SourceLibraryBuilder get library;
30+
2831
/// Builds the core AST structures for this member as needed for the outline.
2932
void buildMembers(
3033
SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
@@ -87,6 +90,9 @@ abstract class SourceMemberBuilderImpl extends MemberBuilderImpl
8790
retainDataForTesting ? new MemberDataForTesting() : null,
8891
super(parent, charOffset, fileUri);
8992

93+
@override
94+
SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
95+
9096
bool get isRedirectingGenerativeConstructor => false;
9197

9298
@override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
abstract class A {
6+
const factory A() = B;
7+
}
8+
9+
abstract class B implements A {
10+
const factory B() = C;
11+
}
12+
13+
class C implements B {
14+
const C();
15+
}
16+
17+
main() {
18+
A.new;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A extends core::Object {
6+
static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
7+
static factory •() → self::A
8+
return self::B::•();
9+
static method _#new#tearOff() → self::A
10+
return new self::C::•();
11+
}
12+
abstract class B extends core::Object implements self::A {
13+
static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
14+
static factory •() → self::B
15+
return new self::C::•();
16+
static method _#new#tearOff() → self::B
17+
return new self::C::•();
18+
}
19+
class C extends core::Object implements self::B /*hasConstConstructor*/ {
20+
const constructor •() → self::C
21+
: super core::Object::•()
22+
;
23+
static method _#new#tearOff() → self::C
24+
return new self::C::•();
25+
}
26+
static method main() → dynamic {
27+
#C3;
28+
}
29+
30+
constants {
31+
#C1 = constructor-tearoff self::A::•
32+
#C2 = constructor-tearoff self::B::•
33+
#C3 = static-tearoff self::A::_#new#tearOff
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A extends core::Object {
6+
static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
7+
static factory •() → self::A
8+
return self::B::•();
9+
static method _#new#tearOff() → self::A
10+
return new self::C::•();
11+
}
12+
abstract class B extends core::Object implements self::A {
13+
static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
14+
static factory •() → self::B
15+
return new self::C::•();
16+
static method _#new#tearOff() → self::B
17+
return new self::C::•();
18+
}
19+
class C extends core::Object implements self::B /*hasConstConstructor*/ {
20+
const constructor •() → self::C
21+
: super core::Object::•()
22+
;
23+
static method _#new#tearOff() → self::C
24+
return new self::C::•();
25+
}
26+
static method main() → dynamic {
27+
#C3;
28+
}
29+
30+
constants {
31+
#C1 = constructor-tearoff self::A::•
32+
#C2 = constructor-tearoff self::B::•
33+
#C3 = static-tearoff self::A::_#new#tearOff
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
abstract class A {
2+
const factory A() = B;
3+
}
4+
5+
abstract class B implements A {
6+
const factory B() = C;
7+
}
8+
9+
class C implements B {
10+
const C();
11+
}
12+
13+
main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
abstract class A {
2+
const factory A() = B;
3+
}
4+
5+
abstract class B implements A {
6+
const factory B() = C;
7+
}
8+
9+
class C implements B {
10+
const C();
11+
}
12+
13+
main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A extends core::Object {
6+
static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
7+
static factory •() → self::A
8+
return self::B::•();
9+
static method _#new#tearOff() → self::A
10+
return new self::C::•();
11+
}
12+
abstract class B extends core::Object implements self::A {
13+
static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
14+
static factory •() → self::B
15+
return new self::C::•();
16+
static method _#new#tearOff() → self::B
17+
return new self::C::•();
18+
}
19+
class C extends core::Object implements self::B /*hasConstConstructor*/ {
20+
const constructor •() → self::C
21+
: super core::Object::•()
22+
;
23+
static method _#new#tearOff() → self::C
24+
return new self::C::•();
25+
}
26+
static method main() → dynamic {
27+
#C3;
28+
}
29+
30+
constants {
31+
#C1 = constructor-tearoff self::A::•
32+
#C2 = constructor-tearoff self::B::•
33+
#C3 = static-tearoff self::A::_#new#tearOff
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A extends core::Object {
6+
static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
7+
static factory •() → self::A
8+
return self::B::•();
9+
static method _#new#tearOff() → self::A
10+
return new self::C::•();
11+
}
12+
abstract class B extends core::Object implements self::A {
13+
static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
14+
static factory •() → self::B
15+
return new self::C::•();
16+
static method _#new#tearOff() → self::B
17+
return new self::C::•();
18+
}
19+
class C extends core::Object implements self::B /*hasConstConstructor*/ {
20+
const constructor •() → self::C
21+
: super core::Object::•()
22+
;
23+
static method _#new#tearOff() → self::C
24+
return new self::C::•();
25+
}
26+
static method main() → dynamic {
27+
#C3;
28+
}
29+
30+
constants {
31+
#C1 = constructor-tearoff self::A::•
32+
#C2 = constructor-tearoff self::B::•
33+
#C3 = static-tearoff self::A::_#new#tearOff
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A extends core::Object {
6+
static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
7+
static factory •() → self::A
8+
return self::B::•();
9+
static method _#new#tearOff() → self::A
10+
return new self::C::•();
11+
}
12+
abstract class B extends core::Object implements self::A {
13+
static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
14+
static factory •() → self::B
15+
return new self::C::•();
16+
static method _#new#tearOff() → self::B
17+
return new self::C::•();
18+
}
19+
class C extends core::Object implements self::B /*hasConstConstructor*/ {
20+
const constructor •() → self::C
21+
: super core::Object::•()
22+
;
23+
static method _#new#tearOff() → self::C
24+
return new self::C::•();
25+
}
26+
static method main() → dynamic
27+
;
28+
29+
30+
Extra constant evaluation status:
31+
Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916.dart:5:16 -> ConstructorTearOffConstant(A.)
32+
Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue47916.dart:9:16 -> ConstructorTearOffConstant(B.)
33+
Extra constant evaluation: evaluated: 9, effectively constant: 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A extends core::Object {
6+
static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
7+
static factory •() → self::A
8+
return self::B::•();
9+
static method _#new#tearOff() → self::A
10+
return new self::C::•();
11+
}
12+
abstract class B extends core::Object implements self::A {
13+
static final field dynamic _redirecting# = <dynamic>[#C2]/*isLegacy*/;
14+
static factory •() → self::B
15+
return new self::C::•();
16+
static method _#new#tearOff() → self::B
17+
return new self::C::•();
18+
}
19+
class C extends core::Object implements self::B /*hasConstConstructor*/ {
20+
const constructor •() → self::C
21+
: super core::Object::•()
22+
;
23+
static method _#new#tearOff() → self::C
24+
return new self::C::•();
25+
}
26+
static method main() → dynamic {
27+
#C3;
28+
}
29+
30+
constants {
31+
#C1 = constructor-tearoff self::A::•
32+
#C2 = constructor-tearoff self::B::•
33+
#C3 = static-tearoff self::A::_#new#tearOff
34+
}

0 commit comments

Comments
 (0)