From e94cf57c3eb9dd54b14dcd40419a2f35cd83db57 Mon Sep 17 00:00:00 2001 From: Dhruv Jauhar Date: Fri, 22 Jan 2021 21:24:54 -0500 Subject: [PATCH 1/2] 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 + From 5e983d7b3f03e9243d905e0579f32be00170c9af Mon Sep 17 00:00:00 2001 From: Dhruv Jauhar Date: Thu, 28 Jan 2021 23:22:49 -0500 Subject: [PATCH 2/2] Add a test for syntax like: ..t.s --- .../run_pass/fru_syntax.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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 index 426eddec6ff8f..e89cf4550c154 100644 --- 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 @@ -8,22 +8,38 @@ //~| NOTE: `#[warn(incomplete_features)]` on by default //~| NOTE: see issue #53488 +#[derive(Clone)] struct S { a: String, b: String, } +struct T { + a: String, + s: S, +} + fn main() { let a = String::new(); let b = String::new(); + let c = String::new(); let s = S {a, b}; + let t = T { + a: c, + s: s.clone() + }; let c = || { let s2 = S { - a: format!("New a"), + a: format!("New s2"), ..s }; + let s3 = S { + a: format!("New s3"), + ..t.s + }; println!("{} {}", s2.a, s2.b); + println!("{} {} {}", s3.a, s3.b, t.a); }; c();