Skip to content

Commit f77f8e5

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
authored andcommitted
[cfe] Add type checks on tearing off instance members
Closes #46784. Bug: #46784 Change-Id: I7637618be0686bbffe6eb18a19049ec5da6059aa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208881 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Dmitry Stefantsov <[email protected]>
1 parent c66ae00 commit f77f8e5

13 files changed

+115
-11
lines changed

pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4790,7 +4790,8 @@ class InferenceVisitor
47904790
checkReturn =
47914791
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
47924792
interfaceMember.enclosingClass!,
4793-
interfaceMember.function.returnType);
4793+
interfaceMember.function
4794+
.computeFunctionType(inferrer.library.nonNullable));
47944795
} else if (interfaceMember is Field) {
47954796
checkReturn =
47964797
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(

pkg/front_end/testcases/general/bug33298.dart.weak.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static method test() → dynamic {
6565
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*>*};
6666
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*>*};
6767
self::B<core::String*>* b = new self::B::•<core::String*>();
68-
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*>*};
68+
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*>*};
6969
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*>*};
7070
self::C* c = new self::C::•();
7171
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*>*};

pkg/front_end/testcases/general/bug33298.dart.weak.transformed.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static method test() → dynamic {
6565
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*>*};
6666
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*>*};
6767
self::B<core::String*>* b = new self::B::•<core::String*>();
68-
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*>*};
68+
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*>*};
6969
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*>*};
7070
self::C* c = new self::C::•();
7171
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*>*};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
class A<X extends num> {
6+
void f<Y extends X>(Y y) {}
7+
}
8+
9+
expectThrows(void Function() f) {
10+
try {
11+
f();
12+
} catch (e) {
13+
return;
14+
}
15+
throw "Expected an exception to be thrown!";
16+
}
17+
18+
main() {
19+
A<num> a = new A<int>();
20+
expectThrows(() {
21+
void Function<Y extends num>(Y) f = a.f;
22+
});
23+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class A<X extends num> {
2+
void f<Y extends X>(Y y) {}
3+
}
4+
5+
expectThrows(void Function() f) {}
6+
main() {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class A<X extends num> {
2+
void f<Y extends X>(Y y) {}
3+
}
4+
5+
expectThrows(void Function() f) {}
6+
main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
class A<X extends core::num> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::X>
7+
: super core::Object::•()
8+
;
9+
method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void {}
10+
}
11+
static method expectThrows(() → void f) → dynamic {
12+
try {
13+
f(){() → void};
14+
}
15+
on core::Object catch(final core::Object e) {
16+
return;
17+
}
18+
throw "Expected an exception to be thrown!";
19+
}
20+
static method main() → dynamic {
21+
self::A<core::num> a = new self::A::•<core::int>();
22+
self::expectThrows(() → void {
23+
<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;
24+
});
25+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
class A<X extends core::num> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::X>
7+
;
8+
method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void
9+
;
10+
}
11+
static method expectThrows(() → void f) → dynamic
12+
;
13+
static method main() → dynamic
14+
;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
class A<X extends core::num> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::X>
7+
: super core::Object::•()
8+
;
9+
method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void {}
10+
}
11+
static method expectThrows(() → void f) → dynamic {
12+
try {
13+
f(){() → void};
14+
}
15+
on core::Object catch(final core::Object e) {
16+
return;
17+
}
18+
throw "Expected an exception to be thrown!";
19+
}
20+
static method main() → dynamic {
21+
self::A<core::num> a = new self::A::•<core::int>();
22+
self::expectThrows(() → void {
23+
<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;
24+
});
25+
}

pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class C<T> {
1515
}
1616

1717
F<num> g1(C<num> c) {
18-
return c.f1;
18+
return c. /*@ checkReturn=(num*) ->* void*/ f1;
1919
}
2020

2121
void g2(C<int> c, Object x) {
@@ -24,7 +24,7 @@ void g2(C<int> c, Object x) {
2424
}
2525

2626
G<List<num>, num> g3(C<num> c) {
27-
return c.f2;
27+
return c. /*@ checkReturn=(List<num*>*) ->* num**/ f2;
2828
}
2929

3030
void test() {

0 commit comments

Comments
 (0)