Check contravariance of property gets that resolve to fields.

Fixes #32501

Change-Id: Ic3c5aca1d12b73e40e63c6cdd8304b95f54e5497
Reviewed-on: https://dart-review.googlesource.com/46002
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry 2018-03-13 10:37:09 +00:00 committed by commit-bot@chromium.org
parent 60a2cfa219
commit 424ae0f5e4
5 changed files with 79 additions and 3 deletions

View file

@ -875,9 +875,12 @@ abstract class TypeInferrerImpl extends TypeInferrer {
}
desugaredGet?.dispatchCategory = callKind;
bool checkReturn = false;
if (callKind == DispatchCategory.interface &&
interfaceMember is Procedure) {
if (callKind == DispatchCategory.interface) {
if (interfaceMember is Procedure) {
checkReturn = interfaceMember.isGenericContravariant;
} else if (interfaceMember is Field) {
checkReturn = interfaceMember.isGenericContravariant;
}
}
var replacedExpression = desugaredGet ?? expression;
if (checkReturn) {

View file

@ -0,0 +1,21 @@
// Copyright (c) 2018, 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.
/*@testedFeatures=checks*/
library test;
typedef void F<T>(T x);
class C<T> {
F<T> /*@genericContravariant=true*/ y;
void f() {
var x = this. /*@callKind=this*/ y;
}
}
void g(C<num> c) {
var x = c. /*@checkReturn=(num) -> void*/ y;
}
void main() {}

View file

@ -0,0 +1,18 @@
library test;
import self as self;
import "dart:core" as core;
typedef F<T extends core::Object> = (T) → void;
class C<T extends core::Object> extends core::Object {
field (self::C::T) → void y = null;
synthetic constructor •() → void
: super core::Object::•()
;
method f() → void {
dynamic x = this.{self::C::y};
}
}
static method g(self::C<core::num> c) → void {
dynamic x = c.y;
}
static method main() → void {}

View file

@ -0,0 +1,16 @@
library test;
import self as self;
import "dart:core" as core;
typedef F<T extends core::Object> = (T) → void;
class C<T extends core::Object> extends core::Object {
field (self::C::T) → void y;
synthetic constructor •() → void
;
method f() → void
;
}
static method g(self::C<core::num> c) → void
;
static method main() → void
;

View file

@ -0,0 +1,18 @@
library test;
import self as self;
import "dart:core" as core;
typedef F<T extends core::Object> = (T) → void;
class C<T extends core::Object> extends core::Object {
generic-contravariant field (self::C::T) → void y = null;
synthetic constructor •() → void
: super core::Object::•()
;
method f() → void {
(self::C::T) → void x = this.{self::C::y};
}
}
static method g(self::C<core::num> c) → void {
(core::num) → void x = c.{self::C::y} as{TypeError} (core::num) → void;
}
static method main() → void {}