Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More Lambda inlines #11148

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/typing/nullSafety.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1455,10 +1455,15 @@ class expr_checker mode immediate_execution report =
Check if specified expressions can be passed to a call which expects `types`.
*)
method private check_args callee args types =
let rec expr_with_unsafe_meta e =
match e.eexpr with
| TMeta ((Meta.NullSafety, [(EConst (Ident "Off"), _)], _), e) -> true
| TParenthesis e -> expr_with_unsafe_meta e
| _ -> false in
let rec traverse arg_num args types meta =
match (args, types, meta) with
| (arg :: args, (arg_name, optional, t) :: types, arg_meta :: meta) ->
let unsafe_argument = contains_unsafe_meta arg_meta in
let unsafe_argument = contains_unsafe_meta arg_meta || expr_with_unsafe_meta arg in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need that?
Couldn't you just do if (@:nullSafety(Off) f(v)) ? (which also happens to be at least somewhat readable)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will disable null safety for inlined function code, see:

final f = [1, 2, null, 3].find(item -> {
	item++; // should error
	item == 2;
});

Current change only casts argument type instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😕 this both feels a bit hacky on compiler side and very ugly on haxe side imo

if
not optional && not unsafe_argument
&& not (self#can_pass_expr arg t arg.epos)
Expand Down
43 changes: 26 additions & 17 deletions std/Lambda.hx
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,14 @@ class Lambda {

If `f` is null, the result is unspecified.
**/
public static function exists<A>(it:Iterable<A>, f:(item:A) -> Bool) {
public static inline function exists<A>(it:Iterable<A>, f:(item:A) -> Bool) {
var isExists = false;
for (x in it)
if (f(x))
return true;
return false;
if (f(x)) {
isExists = true;
break;
}
return isExists;
}

/**
Expand All @@ -141,19 +144,22 @@ class Lambda {

If `f` is null, the result is unspecified.
**/
public static function foreach<A>(it:Iterable<A>, f:(item:A) -> Bool) {
public static inline function foreach<A>(it:Iterable<A>, f:(item:A) -> Bool) {
var isAll = true;
for (x in it)
if (!f(x))
return false;
return true;
if (!f(x)) {
isAll = false;
break;
}
return isAll;
}

/**
Calls `f` on all elements of `it`, in order.

If `f` is null, the result is unspecified.
**/
public static function iter<A>(it:Iterable<A>, f:(item:A) -> Void) {
public static inline function iter<A>(it:Iterable<A>, f:(item:A) -> Void) {
for (x in it)
f(x);
}
Expand All @@ -164,7 +170,7 @@ class Lambda {
If `it` is empty, the result is the empty Array even if `f` is null.
Otherwise if `f` is null, the result is unspecified.
**/
public static function filter<A>(it:Iterable<A>, f:(item:A) -> Bool) {
public static inline function filter<A>(it:Iterable<A>, f:(item:A) -> Bool) {
return [for (x in it) if (f(x)) x];
}

Expand All @@ -180,7 +186,7 @@ class Lambda {

If `it` or `f` are null, the result is unspecified.
**/
public static function fold<A, B>(it:Iterable<A>, f:(item:A, result:B) -> B, first:B):B {
public static inline function fold<A, B>(it:Iterable<A>, f:(item:A, result:B) -> B, first:B):B {
for (x in it)
first = f(x, first);
return first;
Expand All @@ -191,7 +197,7 @@ class Lambda {

If `it` or `f` are null, the result is unspecified.
**/
public static function foldi<A, B>(it:Iterable<A>, f:(item:A, result:B, index:Int) -> B, first:B):B {
public static inline function foldi<A, B>(it:Iterable<A>, f:(item:A, result:B, index:Int) -> B, first:B):B {
var i = 0;
for (x in it) {
first = f(x, first, i);
Expand All @@ -206,7 +212,7 @@ class Lambda {

This function traverses all elements.
**/
public static function count<A>(it:Iterable<A>, ?pred:(item:A) -> Bool) {
public static inline function count<A>(it:Iterable<A>, ?pred:(item:A) -> Bool) {
var n = 0;
if (pred == null)
for (_ in it)
Expand Down Expand Up @@ -252,12 +258,15 @@ class Lambda {

If `f` is null, the result is unspecified.
**/
public static function find<T>(it:Iterable<T>, f:(item:T) -> Bool):Null<T> {
public static inline function find<T>(it:Iterable<T>, f:(item:T) -> Bool):Null<T> {
var first:Null<T> = null;
for (v in it) {
if (f(v))
return v;
if (f(@:nullSafety(Off) v)) {
first = v;
break;
}
}
return null;
return first;
}

/**
Expand Down