Skip to content

Commit

Permalink
Extract helper, fix comment on DerefPure
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Mar 25, 2024
1 parent 5fdc755 commit fc1d7d2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 15 deletions.
17 changes: 3 additions & 14 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2020,20 +2020,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Check if the pattern has any `ref mut` bindings, which would require
// `DerefMut` to be emitted in MIR building instead of just `Deref`.
let mut needs_mut = false;
inner.walk(|pat| {
if let hir::PatKind::Binding(_, id, _, _) = pat.kind
&& let Some(ty::BindByReference(ty::Mutability::Mut)) =
self.typeck_results.borrow().pat_binding_modes().get(id)
{
needs_mut = true;
// No need to continue recursing
false
} else {
true
}
});
if needs_mut {
// We do this *after* checking the inner pattern, since we want to make
// sure to apply any match-ergonomics adjustments.
if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) {
self.register_bound(
expected,
tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_middle/src/ty/typeck_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,31 @@ impl<'tcx> TypeckResults<'tcx> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
}

/// Does the pattern recursively contain a `ref mut` binding in it?
///
/// This is used to determined whether a `deref` pattern should emit a `Deref`
/// or `DerefMut` call for its pattern scrutinee.
///
/// This is computed from the typeck results since we want to make
/// sure to apply any match-ergonomics adjustments, which we cannot
/// determine from the HIR alone.
pub fn pat_has_ref_mut_binding(&self, pat: &'tcx hir::Pat<'tcx>) -> bool {
let mut has_ref_mut = false;
pat.walk(|pat| {
if let hir::PatKind::Binding(_, id, _, _) = pat.kind
&& let Some(ty::BindByReference(ty::Mutability::Mut)) =
self.pat_binding_modes().get(id)
{
has_ref_mut = true;
// No need to continue recursing
false
} else {
true
}
});
has_ref_mut
}

/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
/// by the closure.
pub fn closure_min_captures_flattened(
Expand Down
10 changes: 9 additions & 1 deletion library/core/src/ops/deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,15 @@ impl<T: ?Sized> DerefMut for &mut T {
}
}

/// UwU
/// Perma-unstable marker trait. Indicates that the type has a well-behaved [`Deref`]
/// (and, if applicable, [`DerefMut`]) implementation. This is relied on for soundness
/// of deref patterns.
///
/// FIXME(deref_patterns): The precise semantics are undecided; the rough idea is that
/// successive calls to `deref`/`deref_mut` without intermediate mutation should be
/// idempotent, in the sense that they return the same value as far as pattern-matching
/// is concerned. Calls to `deref`/`deref_mut`` must leave the pointer itself likewise
/// unchanged.
#[unstable(feature = "deref_pure_trait", issue = "87121")]
#[cfg_attr(not(bootstrap), lang = "deref_pure")]
pub unsafe trait DerefPure {}
Expand Down

0 comments on commit fc1d7d2

Please sign in to comment.