haxe icon indicating copy to clipboard operation
haxe copied to clipboard

[nullsafety] field access false positive with multiple guards

Open Gama11 opened this issue 6 years ago • 3 comments

Shouldn't this compile with loose null safety? Neither a1 nor a2 can be null here due to the previous checks:

@:nullSafety
class Main {
	static function main() {}

	public static function equals<T>(a1:Null<Array<T>>, a2:Null<Array<T>>):Bool {
		if (a1 == null && a2 == null) return true;
		if (a1 == null && a2 != null) return false;
		if (a1 != null && a2 == null) return false;
		if (a1.length != a2.length) return false;
		// ...
		return true;
	}
}
source/Main.hx:9: characters 7-16 : Null safety: Cannot access "length" of a nullable value.
source/Main.hx:9: characters 20-29 : Null safety: Cannot access "length" of a nullable value.

Gama11 avatar Feb 19 '19 21:02 Gama11

That's a nice test case :)

nadako avatar Feb 19 '19 22:02 nadako

After a1 == null && a2 == null you need to know that one of exprs is not-null and this seems overcomplicated to implement. I just checked and Kotlin/Dart/TS doesn't track such thing and show similar errors, so i think this can be closed as non-planned.

RblSb avatar Apr 23 '25 00:04 RblSb

It is such a nice test case though... I can see how the logic would work:

	public static function equals<T>(a1:Null<Array<T>>, a2:Null<Array<T>>):Bool {
		if (a1 == null && a2 == null)
			return true;
		/*
			post:
				a1 != null || a2 != null
		*/
		if (a1 == null && a2 != null)
			return false;
		/*
			post:
				a1 != null || a2 == null
			combined with previous post:
				(a1 != null || a2 != null) && (a1 != null && a2 == null)
			simplified:
				a1 != null && (a2 != null || a2 == null)
			right part is tautology, so just:
				a1 != null
		*/
		if (a1 != null /* this is actually redundant */ && a2 == null)
			return false;
		/*
			post:
				a1 == null || a2 != null
			combined with previous post:
				a1 != null && (a1 == null || a2 != null)
			expanded:
				a1 != null && a1 == null || a1 != null && a2 != null
			left part is tautology, so just:
				a1 != null && a2 != null
		*/
		if (a1.length != a2.length)
			return false;
		return true;
	}

I understand that we don't really have a framework to support this, but it sure would be nice if we did. I'd like to keep this open in case I randomly decide to implement something like this at some point.

Simn avatar Apr 23 '25 04:04 Simn