Pattern binding modes +!

AFAIK shared references are marked as "dereferenceable" in LLVM IR, and that attribute implies that the compiler is free to load the value at any time. Quote:

A pointer that is dereferenceable can be loaded from speculatively without a risk of trapping.

Now, the issue is complicated by the fact that ! is supposed to be a zero-sized type, which means that nothing can actually be loaded (i.e. &! should be dereferenceable(0)), but this still makes me nervous to declare that &! is inhabited. That sounds logically inconsistent, which makes it quite likely that either there exists some weird way to cause UB, or that there will be a bug in the compiler based on the inconsistent assumptions.

3 Likes

I think some forms of speculative execution, like loop-invariant code motion may benefit from it. For a contrived example:

fn foo0(n: usize, x: &bool) {
	for _ in 0..n {
		println!("{}", match *x {
			true => "true",
			false => "false",
		});
	}
}

fn foo1(n: usize, x: &bool) {
	let s = match *x {
		true => "true",
		false => "false",
	};

	for _ in 0..n {
		println!("{}", s);
	}
}

If a reference pointing to an invalid value is itself still valid, then it follows that foo0(0, unsafe { mem::transmute<&bool>(&3) }) is not UB, but foo1(0, unsafe { mem::transmute<&bool>(&3) }) is, so foo0 cannot be rewritten into foo1.

I’m not necessarily insisting on having the validity of the referent matter, but it’s not like ignoring it is giving up nothing.

4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.