Skip to content

Commit

Permalink
Version 3.3.0-246.0.dev
Browse files Browse the repository at this point in the history
Merge 6bca706 into dev
  • Loading branch information
Dart CI committed Dec 20, 2023
2 parents 1732c4c + 6bca706 commit ed415d9
Show file tree
Hide file tree
Showing 17 changed files with 604 additions and 305 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,19 @@ class RemoveUnusedLocalVariable extends ResolvedCorrectionProducer {
final declarationStatement = declarationList.parent;
if (declarationStatement is VariableDeclarationStatement) {
if (declarationList.variables.length == 1) {
_commands.add(
_DeleteStatementCommand(
utils: utils,
statement: declarationStatement,
),
);
final initializer = declarationList.variables.first.initializer;
if (initializer is MethodInvocation) {
_commands.add(_DeleteSourceRangeCommand(
sourceRange: SourceRange(declarationStatement.offset,
initializer.offset - declarationStatement.offset)));
} else {
_commands.add(
_DeleteStatementCommand(
utils: utils,
statement: declarationStatement,
),
);
}
} else {
_commands.add(
_DeleteNodeInListCommand(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,36 @@ void f() {
''');
}

Future<void> test_assigned_inAssignment2() async {
await resolveTestCode(r'''
void f() {
var x = 1, y = 2;
print(x);
}
''');
await assertHasFix(r'''
void f() {
var x = 1;
print(x);
}
''');
}

Future<void> test_assigned_inDeclaration() async {
await resolveTestCode(r'''
List<String> l = [];
void f(str) {
final removed = l.remove(str);
}
''');
await assertHasFix(r'''
List<String> l = [];
void f(str) {
l.remove(str);
}
''');
}

Future<void> test_notInFunctionBody() async {
await resolveTestCode(r'''
var a = [for (var v = 0;;) 0];
Expand Down
3 changes: 3 additions & 0 deletions pkg/analyzer/lib/src/generated/exhaustiveness.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ class AnalyzerSealedClassOperations
LibraryElement library = sealedClass.library;
outer:
for (Element declaration in library.topLevelElements) {
if (declaration is ExtensionTypeElement) {
continue;
}
if (declaration != sealedClass && declaration is InterfaceElement) {
bool checkType(InterfaceType? type) {
if (type?.element == sealedClass) {
Expand Down
6 changes: 3 additions & 3 deletions pkg/analyzer/messages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18796,7 +18796,7 @@ FfiCode:
import 'dart:ffi';

@Native()
Array<Int> f;
Array<Int> [!f!];
```

#### Common fixes
Expand Down Expand Up @@ -18835,7 +18835,7 @@ FfiCode:
import 'dart:ffi';

@Native()
int f;
int [!f!];
```

#### Common fixes
Expand Down Expand Up @@ -18879,7 +18879,7 @@ FfiCode:

class C {
@Native<Int>()
external int f;
external int [!f!];
}
```

Expand Down
33 changes: 33 additions & 0 deletions pkg/analyzer/test/src/diagnostics/non_exhaustive_switch_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,39 @@ void f(A x) {
]);
}

test_alwaysExhaustive_sealedClass_hasExtensionType_1of1() async {
await assertNoErrorsInCode(r'''
sealed class A {}
class B extends A {}
extension type EA(A it) implements A {}
void f(A x) {
switch (x) {
case B():
break;
}
}
''');
}

test_alwaysExhaustive_sealedClass_hasExtensionType_1of2() async {
await assertErrorsInCode(r'''
sealed class A {}
class B extends A {}
class C extends A {}
extension type EA(A it) implements A {}
void f(A x) {
switch (x) {
case B():
break;
}
}
''', [
error(CompileTimeErrorCode.NON_EXHAUSTIVE_SWITCH_STATEMENT, 117, 6),
]);
}

test_alwaysExhaustive_sealedClass_implementedByEnum_3at2() async {
await assertErrorsInCode(r'''
sealed class A {}
Expand Down
4 changes: 4 additions & 0 deletions pkg/analyzer/test/verify_diagnostics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ class DocumentationValidator {
'FfiCode.FIELD_INITIALIZER_IN_STRUCT',
// This is not reported after 2.12, and the examples don't compile after 3.0.
'FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER',
// See https://github.com/dart-lang/sdk/issues/54416.
'FfiCode.NATIVE_FIELD_NOT_STATIC',
'FfiCode.NATIVE_FIELD_MISSING_TYPE',
'FfiCode.NATIVE_FIELD_INVALID_TYPE',

// This no longer works in 3.0.
'HintCode.DEPRECATED_COLON_FOR_DEFAULT_VALUE',
Expand Down
153 changes: 153 additions & 0 deletions pkg/analyzer/tool/diagnostics/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -14059,6 +14059,159 @@ Replace the value with a string:
name: example
{% endprettify %}

### native_field_invalid_type

_'{0}' is an unsupported type for native fields. Native fields only support
pointers or numeric and compound types._

#### Description

The analyzer produces this diagnostic when an `@Native`-annotated field
has a type not supported for native fields.

Array fields are unsupported because there currently is no size
annotation for native fields. It is possible to represent global array
variables as pointers though, as they have an identical representation in
memory.

Handles are unsupported because there is no way to transparently load and
store Dart object into pointers.

For more information about FFI, see [C interop using dart:ffi][ffi].

#### Example

The following code produces this diagnostic because the field `f` uses an
unsupported type, `Array`:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

@Native()
Array<Int> [!f!];
{% endprettify %}

#### Common fixes

For array fields, use a pointer instead:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

@Native()
Pointer<Int> f;
{% endprettify %}

### native_field_missing_type

_The native type of this field could not be inferred and must be specified in
the annotation._

#### Description

The analyzer produces this diagnostic when an `@Native`-annotated field
requires a type hint on the annotation to infer the native type.

Dart types like `int` and `double` have multiple possible native
representations. Since the native type needs to be known at compile time
to generate the correct load and stores when accessing the field, an
explicit type must be given.

#### Example

The following code produces this diagnostic because the field `f` has
the type `int` (for which multiple native representations exist), but no
explicit type parameter on the `Native` annotation:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

@Native()
int [!f!];
{% endprettify %}

#### Common fixes

To fix this diagnostic, find out the correct native representation from
the native declaration of the field. Then, add the corresponding type to
the annotation. For instance, if `f` was declared as an `uint8_t` in C,
the Dart field should be declared as:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

@Native<Uint8>()
int f;
{% endprettify %}

For more information about FFI, see [C interop using dart:ffi][ffi].

### native_field_not_static

_Native fields must be static._

#### Description

The analyzer produces this diagnostic when an instance field in a class
has been annotated with `@Native`.
Native fields refer to global variables in C, C++ or other native
languages, whereas instance fields in Dart are specific to an instance of
that class. Hence, native fields must be static.

For more information about FFI, see [C interop using dart:ffi][ffi].

#### Example

The following code produces this diagnostic because the field `f` in the
class `C` is `@Native`, but not `static`:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

class C {
@Native<Int>()
external int [!f!];
}
{% endprettify %}

#### Common fixes

Either make the field static:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

class C {
@Native<Int>()
external static int f;
}
{% endprettify %}

Or move it out of a class, in which case no explicit `static` modifier is
required:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

class C {
}

@Native<Int>()
external int f;
{% endprettify %}

If you meant to annotate an instance field that should be part of a
struct, omit the `@Native` annotation:

{% prettify dart tag=pre+code %}
import 'dart:ffi';

class C extends Struct {
@Int()
external int f;
}
{% endprettify %}

### new_with_undefined_constructor_default

_The class '{0}' doesn't have an unnamed constructor._
Expand Down
14 changes: 8 additions & 6 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4157,7 +4157,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

var returnType = _expectedReturnType(function, _coreTypes.iterableClass);
var syncIterable = _emitInterfaceType(
InterfaceType(_syncIterableClass, Nullability.legacy, [returnType]),
InterfaceType(
_syncIterableClass, Nullability.nonNullable, [returnType]),
emitNullability: false);
return js.call('new #.new(#)', [syncIterable, gen]);
}
Expand All @@ -4174,7 +4175,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

var returnType = _expectedReturnType(function, _coreTypes.streamClass);
var asyncStarImpl = _emitInterfaceType(
InterfaceType(_asyncStarImplClass, Nullability.legacy, [returnType]),
InterfaceType(
_asyncStarImplClass, Nullability.nonNullable, [returnType]),
emitNullability: false);
return js.call('new #.new(#).stream', [asyncStarImpl, gen]);
}
Expand Down Expand Up @@ -7016,7 +7018,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

var type = ctorClass.typeParameters.isEmpty
? _coreTypes.nonNullableRawType(ctorClass)
: InterfaceType(ctorClass, Nullability.legacy, args.types);
: InterfaceType(ctorClass, Nullability.nonNullable, args.types);

if (isFromEnvironmentInvocation(_coreTypes, node)) {
var value = _constants.evaluate(node);
Expand Down Expand Up @@ -7079,7 +7081,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
}
identity ??= _typeRep.isPrimitive(typeArgs[0]);
var c = identity ? _identityHashMapImplClass : _linkedHashMapImplClass;
return _emitClassRef(InterfaceType(c, Nullability.legacy, typeArgs));
return _emitClassRef(InterfaceType(c, Nullability.nonNullable, typeArgs));
}

js_ast.Expression _emitSetImplType(InterfaceType type, {bool? identity}) {
Expand All @@ -7089,7 +7091,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
}
identity ??= _typeRep.isPrimitive(typeArgs[0]);
var c = identity ? _identityHashSetImplClass : _linkedHashSetImplClass;
return _emitClassRef(InterfaceType(c, Nullability.legacy, typeArgs));
return _emitClassRef(InterfaceType(c, Nullability.nonNullable, typeArgs));
}

js_ast.Expression _emitObjectLiteral(Arguments node, Member ctor) {
Expand Down Expand Up @@ -7425,7 +7427,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
// TODO(markzipan): remove const check when we use front-end const eval
if (!node.isConst) {
var setType = _emitClassRef(InterfaceType(
_linkedHashSetClass, Nullability.legacy, [node.typeArgument]));
_linkedHashSetClass, Nullability.nonNullable, [node.typeArgument]));
if (node.expressions.isEmpty) {
return js.call('#.new()', [setType]);
}
Expand Down
Loading

0 comments on commit ed415d9

Please sign in to comment.