From e94cf57c3eb9dd54b14dcd40419a2f35cd83db57 Mon Sep 17 00:00:00 2001 From: Dhruv Jauhar Date: Fri, 22 Jan 2021 21:24:54 -0500 Subject: [PATCH] Make functional record update/struct update syntax works inside closures when feature capture_disjoint_fields is enabled --- .../src/build/expr/as_place.rs | 2 +- .../rustc_mir_build/src/build/expr/into.rs | 13 +++++--- .../run_pass/fru_syntax.rs | 30 +++++++++++++++++++ .../run_pass/fru_syntax.stderr | 11 +++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index cf2e4e8916d0a..3e8d4631464f0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -303,7 +303,7 @@ impl<'tcx> PlaceBuilder<'tcx> { self.base } - fn field(self, f: Field, ty: Ty<'tcx>) -> Self { + crate fn field(self, f: Field, ty: Ty<'tcx>) -> Self { self.project(PlaceElem::Field(f, ty)) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 09281799041ee..0f9d0db750cf8 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -302,7 +302,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let field_names = this.hir.all_fields(adt_def, variant_index); let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base { - let base = unpack!(block = this.as_place(block, base)); + let place_builder = unpack!(block = this.as_place_builder(block, base)); // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that @@ -312,9 +312,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .zip(field_types.into_iter()) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), - None => this.consume_by_copy_or_move( - this.hir.tcx().mk_place_field(base, n, ty), - ), + None => { + let place_builder = place_builder.clone(); + this.consume_by_copy_or_move( + place_builder + .field(n, ty) + .into_place(this.hir.tcx(), this.hir.typeck_results()), + ) + }, }) .collect() } else { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs new file mode 100644 index 0000000000000..426eddec6ff8f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs @@ -0,0 +1,30 @@ +// run-pass + +// Test that functional record update/struct update syntax works inside +// a closure when the feature `capture_disjoint_fields` is enabled. + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 + +struct S { + a: String, + b: String, +} + +fn main() { + let a = String::new(); + let b = String::new(); + let s = S {a, b}; + + let c = || { + let s2 = S { + a: format!("New a"), + ..s + }; + println!("{} {}", s2.a, s2.b); + }; + + c(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr new file mode 100644 index 0000000000000..7ed73abba8608 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr @@ -0,0 +1,11 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/fru_syntax.rs:6:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: 1 warning emitted +