mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-14 04:56:49 +00:00
Rollup merge of #81291 - sexxi-goose:fix-struct-update-functional-record-update-syntax-error, r=nikomatsakis
Support FRU pattern with `[feature(capture_disjoint_fields)]` In case of a functional record update syntax for creating a structure, `ExprUseVisitor` to only detect the precise use of some of the field in the `..x` part of the syntax. However, when we start building MIR, we 1. First, build the place for `x` 2. and then, add precise field projections so that only some parts of `x` end up getting read. When `capture_disjoint_fields` is enabled, and FRU is used within a closure `x` won't be completely captured, and therefore the first step will fail. This PR updates `mir_build` to create a place builder in the first step and then create place from the builder only after applying the field projection. Closes https://github.com/rust-lang/project-rfc-2229/issues/32 r? ``````@nikomatsakis``````
This commit is contained in:
commit
7fa991fb85
@ -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))
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,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
|
||||
@ -306,9 +306,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 {
|
||||
|
@ -0,0 +1,46 @@
|
||||
// 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 <https://github.com/rust-lang/rust/issues/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 s2"),
|
||||
..s
|
||||
};
|
||||
let s3 = S {
|
||||
a: format!("New s3"),
|
||||
..t.s
|
||||
};
|
||||
println!("{} {}", s2.a, s2.b);
|
||||
println!("{} {} {}", s3.a, s3.b, t.a);
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
@ -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 <https://github.com/rust-lang/rust/issues/53488> for more information
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
Loading…
Reference in New Issue
Block a user