If it outputs anything, then it compiles, so it is not a case that currently leads to a compilation error.
If you take a case that doesn't compile, e.g.
let x = NoisyDrop(4).as_ref();
uses_noisy_drop(x);
then this could be changed from "error: creates a temporary which is freed while still in use" to dropping at the end of the scope.
Having said that, I suspect such non-breaking solution may end up being purely theoretical, because it ties drop semantics and borrow checking together, and that may be a pain to implement, and inelegant from language semantics perspective. Unless there exists a simple heuristic that detects these cases without full borrow checking…
Tying drop semantics to borrow checking doesn't sound like a good idea. For example the borrow checker does not work on pointers.
let d = Droppable::new();
let r: &Droppable = &d;
let ptr: *const Droppable = r;
// borrow checker sees no more use of d and r; is d dropped?
let is_this_ub: &Droppable = unsafe { &*ptr };
That code is currently valid, because of let d. If you've changed it to something that depends on the lifetime of the pointer, like:
let ptr = CString::new("uaf").as_ptr();
then it is already a terrible footgun precisely because the borrow checker doesn't see it. Overall it would be nice to do something about this footgun, but I don't think this case of extending lifetimes of temporaries can do it.
let x: &str = &String::from("hello");
let ptr: *const u8 = x.as_ptr();
// x is never used again, so is the temporary dropped?
let is_this_ub = unsafe { &*ptr };
Changing the behaviour to drop the temporary when the borrow ends would lead to new UB.
The affected code would need to have a (useless) unused variable, and would warn by default, unless the variable name starts with an underscore. If I found code like this in a real-world project, I'd suspect that it is already broken. For example, someone might accidentally end up with code like the following, expecting the binding to keep the MutexGuard alive. (It doesn't.)
let _lock = mutex.lock().as_ref().unwrap();
// code that assumes `mutex` is still locked
Currently, this compiles but does not work as intended. With RFC 66 implemented, it would.
Since bindings like this are currently useless, warn by default, should be very rare, and this change might fix existing code rather than break it, I think there are some arguments to be made for this as an acceptable breaking change. But I know that's a very high bar to clear, with good reason.
But this is the opposite — not about shortening lifetime, but about extending it. And of course it can't affect drop order of any code that compiles today.
My point is that if you are going to extend the lifetime of temporaries to enable
let x: &str = new_string().as_ref();
then you must extend them to behave like
let x: &str = &new_string();
Otherwise, there would be a nasty surprise when someone converts &new_string() to new_string().as_ref() and gets UB. That is, I believe it should either be
extended all the way for new_string().as_ref() to behave like &new_string(), or
not at all to avoid the trap that slightly different code will trigger a new UB condition.