mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:21:18 +00:00
[cfe] Add type checks on tearing off instance members
Closes #46784. Bug: https://github.com/dart-lang/sdk/issues/46784 Change-Id: I7637618be0686bbffe6eb18a19049ec5da6059aa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208881 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
c66ae0027b
commit
f77f8e5871
|
@ -4790,7 +4790,8 @@ class InferenceVisitor
|
||||||
checkReturn =
|
checkReturn =
|
||||||
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
|
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
|
||||||
interfaceMember.enclosingClass!,
|
interfaceMember.enclosingClass!,
|
||||||
interfaceMember.function.returnType);
|
interfaceMember.function
|
||||||
|
.computeFunctionType(inferrer.library.nonNullable));
|
||||||
} else if (interfaceMember is Field) {
|
} else if (interfaceMember is Field) {
|
||||||
checkReturn =
|
checkReturn =
|
||||||
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
|
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
|
||||||
|
|
|
@ -65,7 +65,7 @@ static method test() → dynamic {
|
||||||
core::List<core::String*>* list1 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(a.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list1 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(a.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
core::List<core::String*>* list2 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1 == null ?{(core::String*) →* core::String*} null : #t1.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list2 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1 == null ?{(core::String*) →* core::String*} null : #t1.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
self::B<core::String*>* b = new self::B::•<core::String*>();
|
self::B<core::String*>* b = new self::B::•<core::String*>();
|
||||||
core::List<core::String*>* list3 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list3 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*} as{TypeError,CovarianceCheck} (core::String*) →* core::String*){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
core::List<core::String*>* list4 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2 == null ?{(core::String*) →* core::String*} null : #t2.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list4 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2 == null ?{(core::String*) →* core::String*} null : #t2.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
self::C* c = new self::C::•();
|
self::C* c = new self::C::•();
|
||||||
core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}{<T extends core::Object* = dynamic>(T*) →* T*}<core::String*>){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}{<T extends core::Object* = dynamic>(T*) →* T*}<core::String*>){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
|
|
|
@ -65,7 +65,7 @@ static method test() → dynamic {
|
||||||
core::List<core::String*>* list1 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(a.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list1 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(a.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
core::List<core::String*>* list2 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1 == null ?{(core::String*) →* core::String*} null : #t1.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list2 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1 == null ?{(core::String*) →* core::String*} null : #t1.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
self::B<core::String*>* b = new self::B::•<core::String*>();
|
self::B<core::String*>* b = new self::B::•<core::String*>();
|
||||||
core::List<core::String*>* list3 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list3 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*} as{TypeError,CovarianceCheck} (core::String*) →* core::String*){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
core::List<core::String*>* list4 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2 == null ?{(core::String*) →* core::String*} null : #t2.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list4 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2 == null ?{(core::String*) →* core::String*} null : #t2.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
self::C* c = new self::C::•();
|
self::C* c = new self::C::•();
|
||||||
core::List<core::String*>* list5 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(c.{self::C::call}{<T extends core::Object* = dynamic>(T*) →* T*}<core::String*>){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
core::List<core::String*>* list5 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(c.{self::C::call}{<T extends core::Object* = dynamic>(T*) →* T*}<core::String*>){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) 2021, 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.
|
||||||
|
|
||||||
|
class A<X extends num> {
|
||||||
|
void f<Y extends X>(Y y) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectThrows(void Function() f) {
|
||||||
|
try {
|
||||||
|
f();
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw "Expected an exception to be thrown!";
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
A<num> a = new A<int>();
|
||||||
|
expectThrows(() {
|
||||||
|
void Function<Y extends num>(Y) f = a.f;
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
class A<X extends num> {
|
||||||
|
void f<Y extends X>(Y y) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectThrows(void Function() f) {}
|
||||||
|
main() {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
class A<X extends num> {
|
||||||
|
void f<Y extends X>(Y y) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectThrows(void Function() f) {}
|
||||||
|
main() {}
|
|
@ -0,0 +1,25 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
|
||||||
|
class A<X extends core::num> extends core::Object {
|
||||||
|
synthetic constructor •() → self::A<self::A::X>
|
||||||
|
: super core::Object::•()
|
||||||
|
;
|
||||||
|
method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void {}
|
||||||
|
}
|
||||||
|
static method expectThrows(() → void f) → dynamic {
|
||||||
|
try {
|
||||||
|
f(){() → void};
|
||||||
|
}
|
||||||
|
on core::Object catch(final core::Object e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw "Expected an exception to be thrown!";
|
||||||
|
}
|
||||||
|
static method main() → dynamic {
|
||||||
|
self::A<core::num> a = new self::A::•<core::int>();
|
||||||
|
self::expectThrows(() → void {
|
||||||
|
<Y extends core::num>(Y) → void f = a.{self::A::f}{<generic-covariant-impl Y extends core::num>(Y) → void} as{TypeError,CovarianceCheck,ForNonNullableByDefault} <generic-covariant-impl Y extends core::num>(Y) → void;
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
|
||||||
|
class A<X extends core::num> extends core::Object {
|
||||||
|
synthetic constructor •() → self::A<self::A::X>
|
||||||
|
;
|
||||||
|
method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void
|
||||||
|
;
|
||||||
|
}
|
||||||
|
static method expectThrows(() → void f) → dynamic
|
||||||
|
;
|
||||||
|
static method main() → dynamic
|
||||||
|
;
|
|
@ -0,0 +1,25 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
|
||||||
|
class A<X extends core::num> extends core::Object {
|
||||||
|
synthetic constructor •() → self::A<self::A::X>
|
||||||
|
: super core::Object::•()
|
||||||
|
;
|
||||||
|
method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void {}
|
||||||
|
}
|
||||||
|
static method expectThrows(() → void f) → dynamic {
|
||||||
|
try {
|
||||||
|
f(){() → void};
|
||||||
|
}
|
||||||
|
on core::Object catch(final core::Object e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw "Expected an exception to be thrown!";
|
||||||
|
}
|
||||||
|
static method main() → dynamic {
|
||||||
|
self::A<core::num> a = new self::A::•<core::int>();
|
||||||
|
self::expectThrows(() → void {
|
||||||
|
<Y extends core::num>(Y) → void f = a.{self::A::f}{<generic-covariant-impl Y extends core::num>(Y) → void} as{TypeError,CovarianceCheck,ForNonNullableByDefault} <generic-covariant-impl Y extends core::num>(Y) → void;
|
||||||
|
});
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ class C<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
F<num> g1(C<num> c) {
|
F<num> g1(C<num> c) {
|
||||||
return c.f1;
|
return c. /*@ checkReturn=(num*) ->* void*/ f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void g2(C<int> c, Object x) {
|
void g2(C<int> c, Object x) {
|
||||||
|
@ -24,7 +24,7 @@ void g2(C<int> c, Object x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
G<List<num>, num> g3(C<num> c) {
|
G<List<num>, num> g3(C<num> c) {
|
||||||
return c.f2;
|
return c. /*@ checkReturn=(List<num*>*) ->* num**/ f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test() {
|
void test() {
|
||||||
|
|
|
@ -23,14 +23,14 @@ class C<T extends core::Object* = dynamic> extends core::Object {
|
||||||
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
|
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
|
||||||
}
|
}
|
||||||
static method g1(self::C<core::num*>* c) → (core::num*) →* void {
|
static method g1(self::C<core::num*>* c) → (core::num*) →* void {
|
||||||
return c.{self::C::f1}{(core::num*) →* void};
|
return c.{self::C::f1}{(core::num*) →* void} as{TypeError,CovarianceCheck} (core::num*) →* void;
|
||||||
}
|
}
|
||||||
static method g2(self::C<core::int*>* c, core::Object* x) → void {
|
static method g2(self::C<core::int*>* c, core::Object* x) → void {
|
||||||
(core::Object*) →* void f = self::g1(c) as (core::Object*) →* void;
|
(core::Object*) →* void f = self::g1(c) as (core::Object*) →* void;
|
||||||
f(x){(core::Object*) →* void};
|
f(x){(core::Object*) →* void};
|
||||||
}
|
}
|
||||||
static method g3(self::C<core::num*>* c) → (core::List<core::num*>*) →* core::num* {
|
static method g3(self::C<core::num*>* c) → (core::List<core::num*>*) →* core::num* {
|
||||||
return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*};
|
return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*} as{TypeError,CovarianceCheck} (core::List<core::num*>*) →* core::num*;
|
||||||
}
|
}
|
||||||
static method test() → void {
|
static method test() → void {
|
||||||
(core::num*) →* void x = self::g1(new self::C::•<core::int*>());
|
(core::num*) →* void x = self::g1(new self::C::•<core::int*>());
|
||||||
|
|
|
@ -23,14 +23,14 @@ class C<T extends core::Object* = dynamic> extends core::Object {
|
||||||
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
|
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
|
||||||
}
|
}
|
||||||
static method g1(self::C<core::num*>* c) → (core::num*) →* void {
|
static method g1(self::C<core::num*>* c) → (core::num*) →* void {
|
||||||
return c.{self::C::f1}{(core::num*) →* void};
|
return c.{self::C::f1}{(core::num*) →* void} as{TypeError,CovarianceCheck} (core::num*) →* void;
|
||||||
}
|
}
|
||||||
static method g2(self::C<core::int*>* c, core::Object* x) → void {
|
static method g2(self::C<core::int*>* c, core::Object* x) → void {
|
||||||
(core::Object*) →* void f = self::g1(c) as (core::Object*) →* void;
|
(core::Object*) →* void f = self::g1(c) as (core::Object*) →* void;
|
||||||
f(x){(core::Object*) →* void};
|
f(x){(core::Object*) →* void};
|
||||||
}
|
}
|
||||||
static method g3(self::C<core::num*>* c) → (core::List<core::num*>*) →* core::num* {
|
static method g3(self::C<core::num*>* c) → (core::List<core::num*>*) →* core::num* {
|
||||||
return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*};
|
return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*} as{TypeError,CovarianceCheck} (core::List<core::num*>*) →* core::num*;
|
||||||
}
|
}
|
||||||
static method test() → void {
|
static method test() → void {
|
||||||
(core::num*) →* void x = self::g1(new self::C::•<core::int*>());
|
(core::num*) →* void x = self::g1(new self::C::•<core::int*>());
|
||||||
|
|
|
@ -109,7 +109,9 @@ bool containsFreeTypeVariables(DartType type) {
|
||||||
/// mapping to be used for replacing other types to use the new type parameters.
|
/// mapping to be used for replacing other types to use the new type parameters.
|
||||||
FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
|
FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
|
||||||
List<TypeParameter> freshParameters = new List<TypeParameter>.generate(
|
List<TypeParameter> freshParameters = new List<TypeParameter>.generate(
|
||||||
typeParameters.length, (i) => new TypeParameter(typeParameters[i].name),
|
typeParameters.length,
|
||||||
|
(i) => new TypeParameter(typeParameters[i].name)
|
||||||
|
..flags = typeParameters[i].flags,
|
||||||
growable: true);
|
growable: true);
|
||||||
List<DartType> freshTypeArguments =
|
List<DartType> freshTypeArguments =
|
||||||
new List<DartType>.generate(typeParameters.length, (int i) {
|
new List<DartType>.generate(typeParameters.length, (int i) {
|
||||||
|
@ -138,8 +140,10 @@ FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
|
||||||
class FreshTypeParameters {
|
class FreshTypeParameters {
|
||||||
/// The newly created type parameters.
|
/// The newly created type parameters.
|
||||||
final List<TypeParameter> freshTypeParameters;
|
final List<TypeParameter> freshTypeParameters;
|
||||||
|
|
||||||
/// List of [TypeParameterType]s for [TypeParameter].
|
/// List of [TypeParameterType]s for [TypeParameter].
|
||||||
final List<DartType> freshTypeArguments;
|
final List<DartType> freshTypeArguments;
|
||||||
|
|
||||||
/// Substitution from the original type parameters to [freshTypeArguments].
|
/// Substitution from the original type parameters to [freshTypeArguments].
|
||||||
final Substitution substitution;
|
final Substitution substitution;
|
||||||
|
|
||||||
|
@ -389,7 +393,7 @@ class _InnerTypeSubstitutor extends _TypeSubstitutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeParameter freshTypeParameter(TypeParameter node) {
|
TypeParameter freshTypeParameter(TypeParameter node) {
|
||||||
TypeParameter fresh = new TypeParameter(node.name);
|
TypeParameter fresh = new TypeParameter(node.name)..flags = node.flags;
|
||||||
TypeParameterType typeParameterType = substitution[node] =
|
TypeParameterType typeParameterType = substitution[node] =
|
||||||
new TypeParameterType.forAlphaRenaming(node, fresh);
|
new TypeParameterType.forAlphaRenaming(node, fresh);
|
||||||
fresh.bound = visit(node.bound);
|
fresh.bound = visit(node.bound);
|
||||||
|
|
Loading…
Reference in a new issue