diff --git a/pkg/front_end/lib/src/fragment/constructor/body_builder_context.dart b/pkg/front_end/lib/src/fragment/constructor/body_builder_context.dart index 85abd61f811..c562610b5d6 100644 --- a/pkg/front_end/lib/src/fragment/constructor/body_builder_context.dart +++ b/pkg/front_end/lib/src/fragment/constructor/body_builder_context.dart @@ -152,6 +152,9 @@ class ConstructorBodyBuilderContext extends BodyBuilderContext { scopeProviderInfo // Coverage-ignore(suite): Not run. ?.scope, + scopeProviderInfo + // Coverage-ignore(suite): Not run. + ?.thisVariable, ); } diff --git a/pkg/front_end/lib/src/fragment/constructor/declaration.dart b/pkg/front_end/lib/src/fragment/constructor/declaration.dart index 4c4c26f1186..b05f037a543 100644 --- a/pkg/front_end/lib/src/fragment/constructor/declaration.dart +++ b/pkg/front_end/lib/src/fragment/constructor/declaration.dart @@ -761,8 +761,16 @@ mixin _ConstructorEncodingMixin List? get thisTypeParameters => _encoding.thisTypeParameters; @override - void registerFunctionBody(Statement? body, Scope? scope) { - _encoding.registerFunctionBody(body: body, scope: scope); + void registerFunctionBody( + Statement? body, + Scope? scope, + VariableDeclaration? thisVariable, + ) { + _encoding.registerFunctionBody( + body: body, + scope: scope, + thisVariable: thisVariable, + ); } @override @@ -1461,7 +1469,11 @@ abstract class ConstructorFragmentDeclaration { SourceConstructorBuilder constructorBuilder, ); - void registerFunctionBody(Statement? body, Scope? scope); + void registerFunctionBody( + Statement? body, + Scope? scope, + VariableDeclaration? thisVariable, + ); void registerNoBodyConstructor(); diff --git a/pkg/front_end/lib/src/fragment/constructor/encoding.dart b/pkg/front_end/lib/src/fragment/constructor/encoding.dart index c53caadfdf0..e4845967ca6 100644 --- a/pkg/front_end/lib/src/fragment/constructor/encoding.dart +++ b/pkg/front_end/lib/src/fragment/constructor/encoding.dart @@ -87,7 +87,11 @@ abstract class ConstructorEncoding { ConstructorFragmentDeclaration constructorDeclaration, ); - void registerFunctionBody({required Statement? body, Scope? scope}); + void registerFunctionBody({ + required Statement? body, + Scope? scope, + VariableDeclaration? thisVariable, + }); void registerNoBodyConstructor(); @@ -131,11 +135,16 @@ class RegularConstructorEncoding implements ConstructorEncoding { _isEnumConstructor = isEnumConstructor; @override - void registerFunctionBody({required Statement? body, Scope? scope}) { + void registerFunctionBody({ + required Statement? body, + Scope? scope, + VariableDeclaration? thisVariable, + }) { if (body != null) { _constructor.function.registerFunctionBody(body); } _constructor.function.scope = scope; + _constructor.function.thisVariable = thisVariable; } @override @@ -511,11 +520,16 @@ mixin _ExtensionTypeConstructorEncodingMixin } @override - void registerFunctionBody({required Statement? body, Scope? scope}) { + void registerFunctionBody({ + required Statement? body, + Scope? scope, + VariableDeclaration? thisVariable, + }) { if (body != null) { _constructor.function.registerFunctionBody(body); } _constructor.function.scope = scope; + _constructor.function.thisVariable = thisVariable; } @override diff --git a/pkg/front_end/lib/src/fragment/factory/body_builder_context.dart b/pkg/front_end/lib/src/fragment/factory/body_builder_context.dart index 5cb364c76dd..968dc00131d 100644 --- a/pkg/front_end/lib/src/fragment/factory/body_builder_context.dart +++ b/pkg/front_end/lib/src/fragment/factory/body_builder_context.dart @@ -87,6 +87,9 @@ class FactoryBodyBuilderContext extends BodyBuilderContext { ?.scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: scopeProviderInfo + // Coverage-ignore(suite): Not run. + ?.thisVariable, ); } diff --git a/pkg/front_end/lib/src/fragment/factory/declaration.dart b/pkg/front_end/lib/src/fragment/factory/declaration.dart index b1ac1ae2f20..86c47ede535 100644 --- a/pkg/front_end/lib/src/fragment/factory/declaration.dart +++ b/pkg/front_end/lib/src/fragment/factory/declaration.dart @@ -373,12 +373,14 @@ class FactoryDeclarationImpl required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { _encoding.registerFunctionBody( body: body, scope: scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: thisVariable, ); } @@ -421,6 +423,7 @@ abstract class FactoryFragmentDeclaration { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); DartType get returnTypeContext; diff --git a/pkg/front_end/lib/src/fragment/factory/encoding.dart b/pkg/front_end/lib/src/fragment/factory/encoding.dart index 9bb605374b8..eae6cfee229 100644 --- a/pkg/front_end/lib/src/fragment/factory/encoding.dart +++ b/pkg/front_end/lib/src/fragment/factory/encoding.dart @@ -532,6 +532,7 @@ class FactoryEncoding implements InferredTypeListener { scope: null, asyncMarker: AsyncMarker.Sync, emittedValueType: null, + thisVariable: null, ); _procedure.function.redirectingFactoryTarget = new RedirectingFactoryTarget.error(message); @@ -826,6 +827,7 @@ class FactoryEncoding implements InferredTypeListener { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { assert( asyncMarker == AsyncMarker.Sync, @@ -843,6 +845,7 @@ class FactoryEncoding implements InferredTypeListener { ); } _procedure.function.scope = scope; + _procedure.function.thisVariable = thisVariable; } void becomeNative(SourceLoader loader) { diff --git a/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart b/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart index 50850035b87..fbeec4e7308 100644 --- a/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart +++ b/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart @@ -74,6 +74,9 @@ class GetterFragmentBodyBuilderContext extends BodyBuilderContext { ?.scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: scopeProviderInfo + // Coverage-ignore(suite): Not run. + ?.thisVariable, ); } diff --git a/pkg/front_end/lib/src/fragment/getter/declaration.dart b/pkg/front_end/lib/src/fragment/getter/declaration.dart index 58970491c8d..2e19e114ee3 100644 --- a/pkg/front_end/lib/src/fragment/getter/declaration.dart +++ b/pkg/front_end/lib/src/fragment/getter/declaration.dart @@ -309,6 +309,7 @@ class RegularGetterDeclaration required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { assert( asyncMarker == asyncModifier, @@ -320,6 +321,7 @@ class RegularGetterDeclaration scope: scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: thisVariable, ); } @@ -367,6 +369,7 @@ abstract class GetterFragmentDeclaration { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); DartType get returnTypeContext; diff --git a/pkg/front_end/lib/src/fragment/getter/encoding.dart b/pkg/front_end/lib/src/fragment/getter/encoding.dart index 84f0cab29b7..626e4e79b91 100644 --- a/pkg/front_end/lib/src/fragment/getter/encoding.dart +++ b/pkg/front_end/lib/src/fragment/getter/encoding.dart @@ -182,6 +182,7 @@ sealed class GetterEncoding implements InferredTypeListener { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); } @@ -466,6 +467,7 @@ mixin _DirectGetterEncodingMixin implements GetterEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { if (body != null) { function.registerFunctionBody( @@ -475,6 +477,7 @@ mixin _DirectGetterEncodingMixin implements GetterEncoding { ); } function.scope = scope; + function.thisVariable = thisVariable; } } @@ -814,6 +817,7 @@ mixin _ExtensionInstanceGetterEncodingMixin implements GetterEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { if (body != null) { function.registerFunctionBody( @@ -823,5 +827,6 @@ mixin _ExtensionInstanceGetterEncodingMixin implements GetterEncoding { ); } function.scope = scope; + function.thisVariable = thisVariable; } } diff --git a/pkg/front_end/lib/src/fragment/method/body_builder_context.dart b/pkg/front_end/lib/src/fragment/method/body_builder_context.dart index 87a660c8def..ab812201c5e 100644 --- a/pkg/front_end/lib/src/fragment/method/body_builder_context.dart +++ b/pkg/front_end/lib/src/fragment/method/body_builder_context.dart @@ -79,6 +79,7 @@ class MethodFragmentBodyBuilderContext extends BodyBuilderContext { scope: scopeProviderInfo?.scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: scopeProviderInfo?.thisVariable, ); } diff --git a/pkg/front_end/lib/src/fragment/method/declaration.dart b/pkg/front_end/lib/src/fragment/method/declaration.dart index e4bd945ef32..a20b996e7ed 100644 --- a/pkg/front_end/lib/src/fragment/method/declaration.dart +++ b/pkg/front_end/lib/src/fragment/method/declaration.dart @@ -278,12 +278,14 @@ class MethodDeclarationImpl required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { _encoding.registerFunctionBody( body: body, scope: scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: thisVariable, ); } @@ -307,6 +309,7 @@ abstract class MethodFragmentDeclaration { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); DartType get returnTypeContext; diff --git a/pkg/front_end/lib/src/fragment/method/encoding.dart b/pkg/front_end/lib/src/fragment/method/encoding.dart index 6cb98725a52..b5e0dd59d75 100644 --- a/pkg/front_end/lib/src/fragment/method/encoding.dart +++ b/pkg/front_end/lib/src/fragment/method/encoding.dart @@ -98,6 +98,7 @@ sealed class MethodEncoding implements InferredTypeListener { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); } @@ -393,6 +394,7 @@ mixin _DirectMethodEncodingMixin implements MethodEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { if (body != null) { function.registerFunctionBody( @@ -402,6 +404,7 @@ mixin _DirectMethodEncodingMixin implements MethodEncoding { ); } function.scope = scope; + function.thisVariable = thisVariable; } } @@ -796,6 +799,7 @@ mixin _ExtensionInstanceMethodEncodingMixin implements MethodEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { if (body != null) { function.registerFunctionBody( @@ -805,6 +809,7 @@ mixin _ExtensionInstanceMethodEncodingMixin implements MethodEncoding { ); } function.scope = scope; + function.thisVariable = thisVariable; } /// Creates a top level function that creates a tear off of an extension diff --git a/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart b/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart index 8e236509a08..cb1ed9444fa 100644 --- a/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart +++ b/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart @@ -76,6 +76,9 @@ class SetterBodyBuilderContext extends BodyBuilderContext { ?.scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: scopeProviderInfo + // Coverage-ignore(suite): Not run. + ?.thisVariable, ); } diff --git a/pkg/front_end/lib/src/fragment/setter/declaration.dart b/pkg/front_end/lib/src/fragment/setter/declaration.dart index 8c6defcec06..e0566e2bfb7 100644 --- a/pkg/front_end/lib/src/fragment/setter/declaration.dart +++ b/pkg/front_end/lib/src/fragment/setter/declaration.dart @@ -310,6 +310,7 @@ class RegularSetterDeclaration required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { List? declaredFormals = _fragment.declaredFormals; if (declaredFormals == null || @@ -354,6 +355,7 @@ class RegularSetterDeclaration scope: scope, asyncMarker: asyncMarker, emittedValueType: emittedValueType, + thisVariable: thisVariable, ); } @@ -404,6 +406,7 @@ abstract class SetterFragmentDeclaration { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); DartType get returnTypeContext; diff --git a/pkg/front_end/lib/src/fragment/setter/encoding.dart b/pkg/front_end/lib/src/fragment/setter/encoding.dart index 8fc33ba5112..746cb38b206 100644 --- a/pkg/front_end/lib/src/fragment/setter/encoding.dart +++ b/pkg/front_end/lib/src/fragment/setter/encoding.dart @@ -198,6 +198,7 @@ sealed class SetterEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }); } @@ -480,6 +481,7 @@ mixin _DirectSetterEncodingMixin implements SetterEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { if (body != null) { function.registerFunctionBody( @@ -489,6 +491,7 @@ mixin _DirectSetterEncodingMixin implements SetterEncoding { ); } function.scope = scope; + function.thisVariable = thisVariable; } } @@ -849,6 +852,7 @@ mixin _ExtensionInstanceSetterEncodingMixin implements SetterEncoding { required Scope? scope, required AsyncMarker asyncMarker, required DartType? emittedValueType, + required VariableDeclaration? thisVariable, }) { if (body != null) { function.registerFunctionBody( @@ -858,5 +862,6 @@ mixin _ExtensionInstanceSetterEncodingMixin implements SetterEncoding { ); } function.scope = scope; + function.thisVariable = thisVariable; } } diff --git a/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart b/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart index f86efb64b02..dc80048e7f8 100644 --- a/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart +++ b/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart @@ -35,6 +35,7 @@ class ScopeProviderInfo { final ScopeProviderInfoKind kind; Scope? scope; + VariableDeclaration? thisVariable; ScopeProviderInfo({required this.kind}); } @@ -260,6 +261,9 @@ class LoopDepthAllocationStrategy required CaptureKind captureKind, }) { CollectorScopeProviderInfo currentScope = _currentScopeProviderInfo!; + if (variable is ThisVariable) { + currentScope.thisVariable = variable; + } // Delegation happens when the current variable is not uncaptured (that is, // it's either captured or assert-captured), and there's a collector to diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart index 327ec92ead5..3e5ea9af643 100644 --- a/pkg/kernel/lib/clone.dart +++ b/pkg/kernel/lib/clone.dart @@ -886,6 +886,7 @@ class CloneVisitorNotMembers .map(clone) .toList(); List named = node.namedParameters.map(clone).toList(); + VariableDeclaration? thisVariable = cloneOptional(node.thisVariable); final DartType? futureValueType = node.emittedValueType != null ? visitType(node.emittedValueType!) : null; @@ -894,6 +895,7 @@ class CloneVisitorNotMembers typeParameters: typeParameters, positionalParameters: positional, namedParameters: named, + thisVariable: thisVariable, requiredParameterCount: node.requiredParameterCount, returnType: visitType(node.returnType), asyncMarker: node.asyncMarker, diff --git a/pkg/kernel/lib/src/ast/functions.dart b/pkg/kernel/lib/src/ast/functions.dart index 2d9c5afc1ba..44181fbdd77 100644 --- a/pkg/kernel/lib/src/ast/functions.dart +++ b/pkg/kernel/lib/src/ast/functions.dart @@ -41,6 +41,7 @@ class FunctionNode extends TreeNode implements ScopeProvider, ContextConsumer { int requiredParameterCount; List positionalParameters; List namedParameters; + VariableDeclaration? thisVariable; DartType returnType; // Not null. Statement? _body; @@ -110,6 +111,7 @@ class FunctionNode extends TreeNode implements ScopeProvider, ContextConsumer { this.asyncMarker = AsyncMarker.Sync, AsyncMarker? dartAsyncMarker, this.emittedValueType, + this.thisVariable, }) : this.positionalParameters = positionalParameters ?? [], this.requiredParameterCount = diff --git a/pkg/kernel/lib/src/equivalence.dart b/pkg/kernel/lib/src/equivalence.dart index ef7e09715d0..55c79d1aeef 100644 --- a/pkg/kernel/lib/src/equivalence.dart +++ b/pkg/kernel/lib/src/equivalence.dart @@ -4367,6 +4367,9 @@ class EquivalenceStrategy { if (!checkFunctionNode_namedParameters(visitor, node, other)) { result = visitor.resultOnInequivalence; } + if (!checkFunctionNode_thisVariable(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } if (!checkFunctionNode_returnType(visitor, node, other)) { result = visitor.resultOnInequivalence; } @@ -10832,6 +10835,18 @@ class EquivalenceStrategy { ); } + bool checkFunctionNode_thisVariable( + EquivalenceVisitor visitor, + FunctionNode node, + FunctionNode other, + ) { + return visitor.checkNodes( + node.thisVariable, + other.thisVariable, + 'thisVariable', + ); + } + bool checkFunctionNode_returnType( EquivalenceVisitor visitor, FunctionNode node,