[cfe] Separate inference and error reporting in super parameters of extension type constructors

This is a follow-up to
https://dart-review.googlesource.com/c/sdk/+/331048/comment/fbe89f66_bcf80d94/

Part of https://github.com/dart-lang/sdk/issues/49731

Change-Id: I989cc3d3031e0bc4e66be1e28454443f918d20e4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/333003
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Chloe Stefantsova 2023-11-01 12:52:30 +00:00 committed by Commit Queue
parent 0dc86856ca
commit 3c4a74bc38
11 changed files with 133 additions and 9 deletions

View file

@ -2816,15 +2816,29 @@ class OutlineBuilder extends StackListenerImpl {
}
}
}
if (formals == null &&
declarationContext == DeclarationContext.ExtensionType &&
kind == MemberKind.PrimaryConstructor) {
if (declarationContext == DeclarationContext.ExtensionType &&
kind == MemberKind.PrimaryConstructor &&
formals == null) {
// In case of primary constructors of extension types, an error is
// reported by the parser if the formals together with the parentheses
// around them are missing. To distinguish that case from the case of the
// formal parameters present, but lacking the representation field, we
// pass the empty list further along instead of `null`.
formals = const [];
} else if ((declarationContext == DeclarationContext.ExtensionType &&
kind == MemberKind.PrimaryConstructor ||
declarationContext ==
DeclarationContext.ExtensionTypeConstructor) &&
formals != null) {
for (FormalParameterBuilder formal in formals) {
if (formal.isSuperInitializingFormal) {
libraryBuilder.addProblem(
messageExtensionTypeConstructorWithSuperFormalParameter,
formal.charOffset,
formal.name.length,
formal.fileUri);
}
}
}
push(beginToken.charOffset);
push(formals ?? NullValues.FormalParameters);

View file

@ -35,7 +35,6 @@ import '../messages.dart'
show
LocatedMessage,
Message,
messageExtensionTypeConstructorWithSuperFormalParameter,
messageMoreThanOneSuperInitializer,
messageRedirectingConstructorWithAnotherInitializer,
messageRedirectingConstructorWithMultipleRedirectInitializers,
@ -1176,11 +1175,6 @@ class SourceExtensionTypeConstructorBuilder
if (formal.isSuperInitializingFormal) {
TypeBuilder formalTypeBuilder = formal.type;
if (formalTypeBuilder is InferableTypeBuilder) {
libraryBuilder.addProblem(
messageExtensionTypeConstructorWithSuperFormalParameter,
formal.charOffset,
formal.name.length,
formal.fileUri);
formalTypeBuilder.registerType(const InvalidType());
}
}

View file

@ -13,3 +13,5 @@ extension type E2(int foo) {
extension type E3(int foo) {
E3.named(this.foo, [super.bar = null]);
}
extension type E4(super.foo) {} // Error.

View file

@ -14,6 +14,14 @@ library;
// E3.named(this.foo, [super.bar = null]);
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Extension type constructors can't declare super formal parameters.
// extension type E4(super.foo) {} // Error.
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Expected a representation type.
// extension type E4(super.foo) {} // Error.
// ^^^
//
import self as self;
import "dart:core" as core;
@ -38,6 +46,11 @@ extension type E3(core::int foo) {
constructor named = self::E3|constructor#named;
constructor tearoff named = self::E3|constructor#_#named#tearOff;
}
extension type E4(dynamic foo) {
abstract inline-class-member representation-field get foo() → dynamic;
constructor • = self::E4|constructor#;
constructor tearoff • = self::E4|constructor#_#new#tearOff;
}
static inline-class-member method E1|constructor#(core::int foo) → self::E1 /* = core::int */ {
lowered final self::E1 /* = core::int */ #this = foo;
return #this;
@ -74,6 +87,12 @@ static inline-class-member method E3|constructor#named(core::int foo, [has-decla
}
static inline-class-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3 /* = core::int */
return self::E3|constructor#named(foo, bar);
static inline-class-member method E4|constructor#(dynamic foo) → self::E4 /* = dynamic */ {
lowered final self::E4 /* = dynamic */ #this = foo;
return #this;
}
static inline-class-member method E4|constructor#_#new#tearOff(dynamic foo) → self::E4 /* = dynamic */
return self::E4|constructor#(foo);
constants {
#C1 = null

View file

@ -14,6 +14,14 @@ library;
// E3.named(this.foo, [super.bar = null]);
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Extension type constructors can't declare super formal parameters.
// extension type E4(super.foo) {} // Error.
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Expected a representation type.
// extension type E4(super.foo) {} // Error.
// ^^^
//
import self as self;
import "dart:core" as core;
@ -38,6 +46,11 @@ extension type E3(core::int foo) {
constructor named = self::E3|constructor#named;
constructor tearoff named = self::E3|constructor#_#named#tearOff;
}
extension type E4(dynamic foo) {
abstract inline-class-member representation-field get foo() → dynamic;
constructor • = self::E4|constructor#;
constructor tearoff • = self::E4|constructor#_#new#tearOff;
}
static inline-class-member method E1|constructor#(core::int foo) → self::E1 /* = core::int */ {
lowered final self::E1 /* = core::int */ #this = foo;
return #this;
@ -74,6 +87,12 @@ static inline-class-member method E3|constructor#named(core::int foo, [has-decla
}
static inline-class-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3 /* = core::int */
return self::E3|constructor#named(foo, bar);
static inline-class-member method E4|constructor#(dynamic foo) → self::E4 /* = dynamic */ {
lowered final self::E4 /* = dynamic */ #this = foo;
return #this;
}
static inline-class-member method E4|constructor#_#new#tearOff(dynamic foo) → self::E4 /* = dynamic */
return self::E4|constructor#(foo);
constants {
#C1 = null

View file

@ -7,3 +7,4 @@ extension type E2(int foo) {
extension type E3(int foo) {
E3.named(this.foo, [super.bar = null]);
}
extension type E4(super.foo) {}

View file

@ -7,3 +7,4 @@ extension type E2(int foo) {
extension type E3(int foo) {
E3.named(this.foo, [super.bar = null]);
}
extension type E4(super.foo) {}

View file

@ -14,6 +14,14 @@ library;
// E3.named(this.foo, [super.bar = null]);
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Extension type constructors can't declare super formal parameters.
// extension type E4(super.foo) {} // Error.
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Expected a representation type.
// extension type E4(super.foo) {} // Error.
// ^^^
//
import self as self;
import "dart:core" as core;
@ -38,6 +46,11 @@ extension type E3(core::int foo) {
constructor named = self::E3|constructor#named;
constructor tearoff named = self::E3|constructor#_#named#tearOff;
}
extension type E4(dynamic foo) {
abstract inline-class-member representation-field get foo() → dynamic;
constructor • = self::E4|constructor#;
constructor tearoff • = self::E4|constructor#_#new#tearOff;
}
static inline-class-member method E1|constructor#(core::int foo) → self::E1 /* = core::int */ {
lowered final self::E1 /* = core::int */ #this = foo;
return #this;
@ -74,6 +87,12 @@ static inline-class-member method E3|constructor#named(core::int foo, [has-decla
}
static inline-class-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3 /* = core::int */
return self::E3|constructor#named(foo, bar);
static inline-class-member method E4|constructor#(dynamic foo) → self::E4 /* = dynamic */ {
lowered final self::E4 /* = dynamic */ #this = foo;
return #this;
}
static inline-class-member method E4|constructor#_#new#tearOff(dynamic foo) → self::E4 /* = dynamic */
return self::E4|constructor#(foo);
constants {
#C1 = null

View file

@ -14,6 +14,14 @@ library;
// E3.named(this.foo, [super.bar = null]);
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Extension type constructors can't declare super formal parameters.
// extension type E4(super.foo) {} // Error.
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Expected a representation type.
// extension type E4(super.foo) {} // Error.
// ^^^
//
import self as self;
import "dart:core" as core;
@ -38,6 +46,11 @@ extension type E3(core::int foo) {
constructor named = self::E3|constructor#named;
constructor tearoff named = self::E3|constructor#_#named#tearOff;
}
extension type E4(dynamic foo) {
abstract inline-class-member representation-field get foo() → dynamic;
constructor • = self::E4|constructor#;
constructor tearoff • = self::E4|constructor#_#new#tearOff;
}
static inline-class-member method E1|constructor#(core::int foo) → self::E1 /* = core::int */ {
lowered final self::E1 /* = core::int */ #this = foo;
return #this;
@ -74,6 +87,12 @@ static inline-class-member method E3|constructor#named(core::int foo, [has-decla
}
static inline-class-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3 /* = core::int */
return self::E3|constructor#named(foo, bar);
static inline-class-member method E4|constructor#(dynamic foo) → self::E4 /* = dynamic */ {
lowered final self::E4 /* = dynamic */ #this = foo;
return #this;
}
static inline-class-member method E4|constructor#_#new#tearOff(dynamic foo) → self::E4 /* = dynamic */
return self::E4|constructor#(foo);
constants {
#C1 = null

View file

@ -14,6 +14,14 @@ library;
// E3.named(this.foo, [super.bar = null]);
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Extension type constructors can't declare super formal parameters.
// extension type E4(super.foo) {} // Error.
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Expected a representation type.
// extension type E4(super.foo) {} // Error.
// ^^^
//
import self as self;
import "dart:core" as core;
@ -38,6 +46,11 @@ extension type E3(core::int foo) {
constructor named = self::E3|constructor#named;
constructor tearoff named = self::E3|constructor#_#named#tearOff;
}
extension type E4(dynamic foo) {
abstract inline-class-member representation-field get foo() → dynamic;
constructor • = self::E4|constructor#;
constructor tearoff • = self::E4|constructor#_#new#tearOff;
}
static inline-class-member method E1|constructor#(core::int foo) → self::E1 /* = core::int */
;
static inline-class-member method E1|constructor#_#new#tearOff(core::int foo) → self::E1 /* = core::int */
@ -62,3 +75,7 @@ static inline-class-member method E3|constructor#named(core::int foo, [has-decla
;
static inline-class-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3 /* = core::int */
return self::E3|constructor#named(foo, bar);
static inline-class-member method E4|constructor#(dynamic foo) → self::E4 /* = dynamic */
;
static inline-class-member method E4|constructor#_#new#tearOff(dynamic foo) → self::E4 /* = dynamic */
return self::E4|constructor#(foo);

View file

@ -14,6 +14,14 @@ library;
// E3.named(this.foo, [super.bar = null]);
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Extension type constructors can't declare super formal parameters.
// extension type E4(super.foo) {} // Error.
// ^^^
//
// pkg/front_end/testcases/extension_types/issue53212.dart:17:25: Error: Expected a representation type.
// extension type E4(super.foo) {} // Error.
// ^^^
//
import self as self;
import "dart:core" as core;
@ -38,6 +46,11 @@ extension type E3(core::int foo) {
constructor named = self::E3|constructor#named;
constructor tearoff named = self::E3|constructor#_#named#tearOff;
}
extension type E4(dynamic foo) {
abstract inline-class-member representation-field get foo() → dynamic;
constructor • = self::E4|constructor#;
constructor tearoff • = self::E4|constructor#_#new#tearOff;
}
static inline-class-member method E1|constructor#(core::int foo) → self::E1 /* = core::int */ {
lowered final self::E1 /* = core::int */ #this = foo;
return #this;
@ -74,6 +87,12 @@ static inline-class-member method E3|constructor#named(core::int foo, [has-decla
}
static inline-class-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3 /* = core::int */
return self::E3|constructor#named(foo, bar);
static inline-class-member method E4|constructor#(dynamic foo) → self::E4 /* = dynamic */ {
lowered final self::E4 /* = dynamic */ #this = foo;
return #this;
}
static inline-class-member method E4|constructor#_#new#tearOff(dynamic foo) → self::E4 /* = dynamic */
return self::E4|constructor#(foo);
constants {
#C1 = null