Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9eb6a54
sync::mpsc: add miri reproducer of double free
petrosagg Apr 10, 2025
b9e2ac5
sync::mpsc: prevent double free on `Drop`
petrosagg Apr 8, 2025
f35eae7
store the kind of pattern adjustments in `pat_adjustments`
dianne Mar 15, 2025
1c1febc
add new config option: `include`
onur-ozkan Apr 1, 2025
89e3bef
document config extensions
onur-ozkan Mar 25, 2025
4e80659
implement cyclic inclusion handling
onur-ozkan Apr 1, 2025
78cb453
document `include` in `bootstrap.example.toml`
onur-ozkan Apr 1, 2025
3f70f19
apply nit notes
onur-ozkan Apr 1, 2025
8e6f50b
fix path and the ordering logic
onur-ozkan Apr 15, 2025
7dfb457
add FIXME note in `TomlConfig::merge`
onur-ozkan Apr 15, 2025
2907ab5
Move `is_builder_target`, `is_system_llvm` and `is_rust_llvm` from `B…
Kobzol Apr 15, 2025
3c01dfe
Rename `is_builder_target` to `is_host_target`
Kobzol Apr 15, 2025
6d52b51
add comment in `TomlConfig::merge` about the merge order
onur-ozkan Apr 15, 2025
8c50f95
rustdoc: Output target feature information
willglynn Apr 4, 2025
a870bba
Add a warning when combining LLD with external LLVM config
Kobzol Apr 16, 2025
8270478
resolve config include FIXME
onur-ozkan Apr 16, 2025
f9ebd36
add coverage on config include logic
onur-ozkan Apr 16, 2025
cb6c499
lower implicit deref patterns to THIR
dianne Feb 24, 2025
e4b7b3d
pattern typing for immutable implicit deref patterns
dianne Mar 9, 2025
91d0b57
register `DerefMut` bounds for implicit mutable derefs
dianne Mar 9, 2025
d6df469
refactor path pattern checking to get info for peeling
dianne Apr 7, 2025
9196048
refactor struct pattern checking to get info for peeling
dianne Mar 4, 2025
1f40e9a
refactor tuple struct pattern checking to get info for peeling
dianne Mar 4, 2025
923d95c
don't peel ADTs the pattern could match
dianne Mar 9, 2025
977c9ab
respect the tcx's recursion limit when peeling
dianne Mar 10, 2025
ff0d4bc
upvar inference for implicit deref patterns
dianne Mar 14, 2025
4c4b61b
add a feature gate test
dianne Mar 14, 2025
93d13e9
add an unstable book chapter
dianne Mar 14, 2025
3b91b7a
Make cow_of_cow test a teeny bit more explicit
Nadrieril Apr 16, 2025
92ce44f
ignore aix for tests/ui/erros/pic-linker.rs
Apr 16, 2025
4be670f
Warnings-as-errors in `check-builtin-attr-ice.rs`.
nnethercote Apr 9, 2025
400e8e5
Fix attribute printing in an error.
nnethercote Apr 9, 2025
7e1f2f9
Augment some tests involving attributes.
nnethercote Apr 10, 2025
2fef0a3
Replace infallible `name_or_empty` methods with fallible `name` methods.
nnethercote Apr 10, 2025
846c10f
Avoid an `unwrap` in `RustcMirAttrs::set_field`.
nnethercote Apr 15, 2025
6214674
rustdoc/clean: Change terminology of items pertaining to (formal) fn …
fmease Apr 15, 2025
82ff0a0
rustdoc: Properly clean fn params in all contexts
fmease Apr 16, 2025
993acf1
Rollup merge of #138528 - dianne:implicit-deref-patterns, r=Nadrieril
matthiaskrgr Apr 17, 2025
4cc9588
Rollup merge of #138934 - onur-ozkan:extended-config-profiles, r=Kobzol
matthiaskrgr Apr 17, 2025
9efd2af
Rollup merge of #139393 - willglynn:rustdoc_output_target_feature_inf…
matthiaskrgr Apr 17, 2025
96192a9
Rollup merge of #139553 - petrosagg:channel-double-free, r=RalfJung,t…
matthiaskrgr Apr 17, 2025
f6008db
Rollup merge of #139615 - nnethercote:rm-name_or_empty, r=jdonszelmann
matthiaskrgr Apr 17, 2025
1257f67
Rollup merge of #139853 - Kobzol:lld-llvm-config, r=onur-ozkan
matthiaskrgr Apr 17, 2025
e30bda2
Rollup merge of #139913 - fmease:rustdoc-fix-fn-param-handling, r=Gui…
matthiaskrgr Apr 17, 2025
c4cacd2
Rollup merge of #139942 - dalvescb:master, r=jieyouxu
matthiaskrgr Apr 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
upvar inference for implicit deref patterns
  • Loading branch information
dianne committed Apr 16, 2025
commit ff0d4bc743086111c841812ec9925efb075d1243
54 changes: 43 additions & 11 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
// determines whether to borrow *at the level of the deref pattern* rather than
// borrowing the bound place (since that inner place is inside the temporary that
// stores the result of calling `deref()`/`deref_mut()` so can't be captured).
// HACK: this could be a fake pattern corresponding to a deref inserted by match
// ergonomics, in which case `pat.hir_id` will be the id of the subpattern.
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
let mutability =
if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
Expand Down Expand Up @@ -1675,12 +1677,31 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
// Then we see that to get the same result, we must start with
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
for _ in
0..self.cx.typeck_results().pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len())
{
let typeck_results = self.cx.typeck_results();
let adjustments: &[adjustment::PatAdjustment<'tcx>] =
typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
let mut adjusts = adjustments.iter().peekable();
while let Some(adjust) = adjusts.next() {
debug!("applying adjustment to place_with_id={:?}", place_with_id);
place_with_id = self.cat_deref(pat.hir_id, place_with_id)?;
place_with_id = match adjust.kind {
adjustment::PatAdjust::BuiltinDeref => self.cat_deref(pat.hir_id, place_with_id)?,
adjustment::PatAdjust::OverloadedDeref => {
// This adjustment corresponds to an overloaded deref; it borrows the scrutinee to
// call `Deref::deref` or `DerefMut::deref_mut`. Invoke the callback before setting
// `place_with_id` to the temporary storing the result of the deref.
// HACK(dianne): giving the callback a fake deref pattern makes sure it behaves the
// same as it would if this were an explicit deref pattern.
op(&place_with_id, &hir::Pat { kind: PatKind::Deref(pat), ..*pat })?;
let target_ty = match adjusts.peek() {
Some(&&next_adjust) => next_adjust.source,
// At the end of the deref chain, we get `pat`'s scrutinee.
None => self.pat_ty_unadjusted(pat)?,
};
self.pat_deref_temp(pat.hir_id, pat, target_ty)?
}
};
}
drop(typeck_results); // explicitly release borrow of typeck results, just in case.
let place_with_id = place_with_id; // lose mutability
debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);

Expand Down Expand Up @@ -1783,14 +1804,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
self.cat_pattern(subplace, subpat, op)?;
}
PatKind::Deref(subpat) => {
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpat);
let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
let re_erased = self.cx.tcx().lifetimes.re_erased;
let ty = self.pat_ty_adjusted(subpat)?;
let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability);
// A deref pattern generates a temporary.
let base = self.cat_rvalue(pat.hir_id, ty);
let place = self.cat_deref(pat.hir_id, base)?;
let place = self.pat_deref_temp(pat.hir_id, subpat, ty)?;
self.cat_pattern(place, subpat, op)?;
}

Expand Down Expand Up @@ -1843,6 +1858,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
Ok(())
}

/// Represents the place of the temp that stores the scrutinee of a deref pattern's interior.
fn pat_deref_temp(
&self,
hir_id: HirId,
inner: &hir::Pat<'_>,
target_ty: Ty<'tcx>,
) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(inner);
let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
let re_erased = self.cx.tcx().lifetimes.re_erased;
let ty = Ty::new_ref(self.cx.tcx(), re_erased, target_ty, mutability);
// A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ...
let base = self.cat_rvalue(hir_id, ty);
// ... and the inner pattern matches on the place behind that reference.
self.cat_deref(hir_id, base)
}

fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
Expand Down
27 changes: 27 additions & 0 deletions tests/ui/pattern/deref-patterns/closure_capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,38 @@ fn main() {
assert_eq!(b.len(), 3);
f();

let v = vec![1, 2, 3];
let f = || {
// this should count as a borrow of `v` as a whole
let [.., x] = v else { unreachable!() };
assert_eq!(x, 3);
};
assert_eq!(v, [1, 2, 3]);
f();

let mut b = Box::new("aaa".to_string());
let mut f = || {
let deref!(ref mut s) = b else { unreachable!() };
s.push_str("aa");
};
f();
assert_eq!(b.len(), 5);

let mut v = vec![1, 2, 3];
let mut f = || {
// this should count as a mutable borrow of `v` as a whole
let [.., ref mut x] = v else { unreachable!() };
*x = 4;
};
f();
assert_eq!(v, [1, 2, 4]);

let mut v = vec![1, 2, 3];
let mut f = || {
// here, `[.., x]` is adjusted by both an overloaded deref and a builtin deref
let [.., x] = &mut v else { unreachable!() };
*x = 4;
};
f();
assert_eq!(v, [1, 2, 4]);
}