@@ -517,6 +517,30 @@ macro_rules! r#try {
517517#[ cfg_attr( not( test) , rustc_diagnostic_item = "write_macro" ) ]
518518#[ allow_internal_unstable( autoref) ]
519519macro_rules! write {
520+ // Retrocompat workaround to support two phased borrows:
521+ // when `$dst` is made of chaining `.field` (or `.idx`) accesses to a local,
522+ // it is guaranteed to be a *place* and thus there is no question of
523+ // late-dropping anything inside it.
524+ //
525+ // Whilst this won't cover *all* the possible syntaxes for places (it
526+ // won't handle places with `[…]`-indexing inside them (see
527+ // https://github.com/rust-lang/rust/pull/100202#pullrequestreview-1064499226)
528+ // qualified paths to `static mut`s, nor macro invocations), it ought to
529+ // cover the vast majority of uses in practice, especially regarding
530+ // retro-compatibility.
531+ (
532+ $dst_place: ident $( . $field_or_idx: tt) * ,
533+ $( $arg: tt) *
534+ ) => ( {
535+ let result =
536+ $dst_place $( . $field_or_idx ) *
537+ . write_fmt( $crate:: format_args!( $( $arg) * ) )
538+ ;
539+ result
540+ } ) ;
541+
542+ // default case: early-dropped `format_args!($($args)*)` while keeping
543+ // `$dst` late-dropped.
520544 ( $dst: expr, $( $arg: tt) * ) => {
521545 match $crate:: ops:: autoref:: autoref_mut!( $dst) {
522546 mut _dst => {
@@ -560,6 +584,18 @@ macro_rules! writeln {
560584 ( $dst: expr $( , ) ?) => {
561585 $crate:: write!( $dst, "\n " )
562586 } ;
587+
588+ (
589+ $dst_place: ident $( . $field_or_idx: tt) * ,
590+ $( $arg: tt) *
591+ ) => ( {
592+ let result =
593+ $dst_place $( . $field_or_idx) *
594+ . write_fmt( $crate:: format_args_nl!( $( $arg) * ) )
595+ ;
596+ result
597+ } ) ;
598+
563599 ( $dst: expr, $( $arg: tt) * ) => {
564600 match $crate:: ops:: autoref:: autoref_mut!( $dst) {
565601 mut _dst => {
0 commit comments