Skip to content

Commit 52db6b9

Browse files
committed
InferBorrowKind cleanup
`adjust_upvar_deref` and friends are implemented so that they reuse existing region so new region vars don't have to be generated. Since now we don't have to generate region vars in `InferBorrowKind`, creating a new capture info would be cheap and we can just use `determine_capture_info`. syn is updated so that let_else syntax can be used in fn with `#[instrument]` attribute. `restrict_repr_packed_field_ref_capture` is changed to take place by value since cloning is needed anyway.
1 parent 48258ff commit 52db6b9

File tree

1 file changed

+52
-177
lines changed

1 file changed

+52
-177
lines changed

compiler/rustc_typeck/src/check/upvar.rs

+52-177
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
207207
assert_eq!(body_owner_def_id.to_def_id(), closure_def_id);
208208
let mut delegate = InferBorrowKind {
209209
fcx: self,
210-
closure_def_id,
210+
closure_def_id: local_def_id,
211211
capture_information: Default::default(),
212212
fake_reads: Default::default(),
213213
};
@@ -1648,7 +1648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16481648
fn restrict_repr_packed_field_ref_capture<'tcx>(
16491649
tcx: TyCtxt<'tcx>,
16501650
param_env: ty::ParamEnv<'tcx>,
1651-
place: &Place<'tcx>,
1651+
mut place: Place<'tcx>,
16521652
mut curr_borrow_kind: ty::UpvarCapture,
16531653
) -> (Place<'tcx>, ty::UpvarCapture) {
16541654
let pos = place.projections.iter().enumerate().position(|(i, p)| {
@@ -1681,8 +1681,6 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
16811681
}
16821682
});
16831683

1684-
let mut place = place.clone();
1685-
16861684
if let Some(pos) = pos {
16871685
truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_borrow_kind, pos);
16881686
}
@@ -1729,7 +1727,7 @@ struct InferBorrowKind<'a, 'tcx> {
17291727
fcx: &'a FnCtxt<'a, 'tcx>,
17301728

17311729
// The def-id of the closure whose kind and upvar accesses are being inferred.
1732-
closure_def_id: DefId,
1730+
closure_def_id: LocalDefId,
17331731

17341732
/// For each Place that is captured by the closure, we track the minimal kind of
17351733
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
@@ -1762,170 +1760,51 @@ struct InferBorrowKind<'a, 'tcx> {
17621760
}
17631761

17641762
impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
1765-
#[instrument(skip(self), level = "debug")]
1766-
fn adjust_upvar_borrow_kind_for_consume(
1767-
&mut self,
1768-
place_with_id: &PlaceWithHirId<'tcx>,
1769-
diag_expr_id: hir::HirId,
1770-
) {
1771-
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else {
1772-
return;
1773-
};
1774-
1775-
debug!(?upvar_id);
1776-
1777-
let capture_info = ty::CaptureInfo {
1778-
capture_kind_expr_id: Some(diag_expr_id),
1779-
path_expr_id: Some(diag_expr_id),
1780-
capture_kind: ty::UpvarCapture::ByValue,
1781-
};
1782-
1783-
let curr_info = self.capture_information[&place_with_id.place];
1784-
let updated_info = determine_capture_info(curr_info, capture_info);
1785-
1786-
self.capture_information[&place_with_id.place] = updated_info;
1787-
}
1788-
1789-
/// Indicates that `place_with_id` is being directly mutated (e.g., assigned
1790-
/// to). If the place is based on a by-ref upvar, this implies that
1791-
/// the upvar must be borrowed using an `&mut` borrow.
1792-
#[instrument(skip(self), level = "debug")]
1793-
fn adjust_upvar_borrow_kind_for_mut(
1794-
&mut self,
1795-
place_with_id: &PlaceWithHirId<'tcx>,
1796-
diag_expr_id: hir::HirId,
1797-
) {
1798-
if let PlaceBase::Upvar(_) = place_with_id.place.base {
1799-
// Raw pointers don't inherit mutability
1800-
if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) {
1801-
return;
1763+
fn adjust_capture_info(&mut self, place: Place<'tcx>, capture_info: ty::CaptureInfo) {
1764+
match self.capture_information.get_mut(&place) {
1765+
Some(curr_info) => {
1766+
*curr_info = determine_capture_info(*curr_info, capture_info);
18021767
}
1803-
self.adjust_upvar_deref(place_with_id, diag_expr_id, ty::MutBorrow);
1804-
}
1805-
}
1806-
1807-
#[instrument(skip(self), level = "debug")]
1808-
fn adjust_upvar_borrow_kind_for_unique(
1809-
&mut self,
1810-
place_with_id: &PlaceWithHirId<'tcx>,
1811-
diag_expr_id: hir::HirId,
1812-
) {
1813-
if let PlaceBase::Upvar(_) = place_with_id.place.base {
1814-
if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) {
1815-
// Raw pointers don't inherit mutability.
1816-
return;
1768+
None => {
1769+
debug!("Capturing new place {:?}, capture_info={:?}", place, capture_info);
1770+
self.capture_information.insert(place, capture_info);
18171771
}
1818-
// for a borrowed pointer to be unique, its base must be unique
1819-
self.adjust_upvar_deref(place_with_id, diag_expr_id, ty::UniqueImmBorrow);
1820-
}
1821-
}
1822-
1823-
fn adjust_upvar_deref(
1824-
&mut self,
1825-
place_with_id: &PlaceWithHirId<'tcx>,
1826-
diag_expr_id: hir::HirId,
1827-
borrow_kind: ty::BorrowKind,
1828-
) {
1829-
assert!(match borrow_kind {
1830-
ty::MutBorrow => true,
1831-
ty::UniqueImmBorrow => true,
1832-
1833-
// imm borrows never require adjusting any kinds, so we don't wind up here
1834-
ty::ImmBorrow => false,
1835-
});
1836-
1837-
// if this is an implicit deref of an
1838-
// upvar, then we need to modify the
1839-
// borrow_kind of the upvar to make sure it
1840-
// is inferred to mutable if necessary
1841-
self.adjust_upvar_borrow_kind(place_with_id, diag_expr_id, borrow_kind);
1842-
}
1843-
1844-
/// We infer the borrow_kind with which to borrow upvars in a stack closure.
1845-
/// The borrow_kind basically follows a lattice of `imm < unique-imm < mut`,
1846-
/// moving from left to right as needed (but never right to left).
1847-
/// Here the argument `mutbl` is the borrow_kind that is required by
1848-
/// some particular use.
1849-
#[instrument(skip(self), level = "debug")]
1850-
fn adjust_upvar_borrow_kind(
1851-
&mut self,
1852-
place_with_id: &PlaceWithHirId<'tcx>,
1853-
diag_expr_id: hir::HirId,
1854-
kind: ty::BorrowKind,
1855-
) {
1856-
let curr_capture_info = self.capture_information[&place_with_id.place];
1857-
1858-
debug!(?curr_capture_info);
1859-
1860-
if let ty::UpvarCapture::ByValue = curr_capture_info.capture_kind {
1861-
// It's already captured by value, we don't need to do anything here
1862-
return;
1863-
} else if let ty::UpvarCapture::ByRef(_) = curr_capture_info.capture_kind {
1864-
let capture_info = ty::CaptureInfo {
1865-
capture_kind_expr_id: Some(diag_expr_id),
1866-
path_expr_id: Some(diag_expr_id),
1867-
capture_kind: ty::UpvarCapture::ByRef(kind),
1868-
};
1869-
let updated_info = determine_capture_info(curr_capture_info, capture_info);
1870-
self.capture_information[&place_with_id.place] = updated_info;
1871-
};
1872-
}
1873-
1874-
#[instrument(skip(self, diag_expr_id), level = "debug")]
1875-
fn init_capture_info_for_place(
1876-
&mut self,
1877-
place_with_id: &PlaceWithHirId<'tcx>,
1878-
diag_expr_id: hir::HirId,
1879-
) {
1880-
if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
1881-
assert_eq!(self.closure_def_id.expect_local(), upvar_id.closure_expr_id);
1882-
1883-
// Initialize to ImmBorrow
1884-
// We will escalate the CaptureKind based on any uses we see or in `process_collected_capture_information`.
1885-
let capture_kind = ty::UpvarCapture::ByRef(ty::ImmBorrow);
1886-
1887-
let expr_id = Some(diag_expr_id);
1888-
let capture_info = ty::CaptureInfo {
1889-
capture_kind_expr_id: expr_id,
1890-
path_expr_id: expr_id,
1891-
capture_kind,
1892-
};
1893-
1894-
debug!("Capturing new place {:?}, capture_info={:?}", place_with_id, capture_info);
1895-
1896-
self.capture_information.insert(place_with_id.place.clone(), capture_info);
1897-
} else {
1898-
debug!("Not upvar");
18991772
}
19001773
}
19011774
}
19021775

19031776
impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
19041777
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId) {
1905-
if let PlaceBase::Upvar(_) = place.base {
1906-
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
1907-
// such as deref of a raw pointer.
1908-
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
1909-
1910-
let (place, _) = restrict_capture_precision(place, dummy_capture_kind);
1911-
1912-
let (place, _) = restrict_repr_packed_field_ref_capture(
1913-
self.fcx.tcx,
1914-
self.fcx.param_env,
1915-
&place,
1916-
dummy_capture_kind,
1917-
);
1918-
self.fake_reads.push((place, cause, diag_expr_id));
1919-
}
1778+
let PlaceBase::Upvar(_) = place.base else { return };
1779+
1780+
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
1781+
// such as deref of a raw pointer.
1782+
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
1783+
1784+
let (place, _) = restrict_capture_precision(place, dummy_capture_kind);
1785+
1786+
let (place, _) = restrict_repr_packed_field_ref_capture(
1787+
self.fcx.tcx,
1788+
self.fcx.param_env,
1789+
place,
1790+
dummy_capture_kind,
1791+
);
1792+
self.fake_reads.push((place, cause, diag_expr_id));
19201793
}
19211794

19221795
#[instrument(skip(self), level = "debug")]
19231796
fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
1924-
if !self.capture_information.contains_key(&place_with_id.place) {
1925-
self.init_capture_info_for_place(place_with_id, diag_expr_id);
1926-
}
1797+
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
1798+
assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
19271799

1928-
self.adjust_upvar_borrow_kind_for_consume(place_with_id, diag_expr_id);
1800+
self.adjust_capture_info(
1801+
place_with_id.place.clone(),
1802+
ty::CaptureInfo {
1803+
capture_kind_expr_id: Some(diag_expr_id),
1804+
path_expr_id: Some(diag_expr_id),
1805+
capture_kind: ty::UpvarCapture::ByValue,
1806+
},
1807+
);
19291808
}
19301809

19311810
#[instrument(skip(self), level = "debug")]
@@ -1935,39 +1814,35 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
19351814
diag_expr_id: hir::HirId,
19361815
bk: ty::BorrowKind,
19371816
) {
1817+
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
1818+
assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
1819+
19381820
// The region here will get discarded/ignored
1939-
let dummy_capture_kind = ty::UpvarCapture::ByRef(bk);
1821+
let capture_kind = ty::UpvarCapture::ByRef(bk);
19401822

19411823
// We only want repr packed restriction to be applied to reading references into a packed
19421824
// struct, and not when the data is being moved. Therefore we call this method here instead
19431825
// of in `restrict_capture_precision`.
1944-
let (place, updated_kind) = restrict_repr_packed_field_ref_capture(
1826+
let (place, mut capture_kind) = restrict_repr_packed_field_ref_capture(
19451827
self.fcx.tcx,
19461828
self.fcx.param_env,
1947-
&place_with_id.place,
1948-
dummy_capture_kind,
1829+
place_with_id.place.clone(),
1830+
capture_kind,
19491831
);
19501832

1951-
let place_with_id = PlaceWithHirId { place, ..*place_with_id };
1952-
1953-
if !self.capture_information.contains_key(&place_with_id.place) {
1954-
self.init_capture_info_for_place(&place_with_id, diag_expr_id);
1833+
// Raw pointers don't inherit mutability
1834+
if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) {
1835+
capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
19551836
}
19561837

1957-
match updated_kind {
1958-
ty::UpvarCapture::ByRef(kind) => match kind {
1959-
ty::ImmBorrow => {}
1960-
ty::UniqueImmBorrow => {
1961-
self.adjust_upvar_borrow_kind_for_unique(&place_with_id, diag_expr_id);
1962-
}
1963-
ty::MutBorrow => {
1964-
self.adjust_upvar_borrow_kind_for_mut(&place_with_id, diag_expr_id);
1965-
}
1838+
self.adjust_capture_info(
1839+
place,
1840+
ty::CaptureInfo {
1841+
capture_kind_expr_id: Some(diag_expr_id),
1842+
path_expr_id: Some(diag_expr_id),
1843+
capture_kind,
19661844
},
1967-
1968-
// Just truncating the place will never cause capture kind to be updated to ByValue
1969-
ty::UpvarCapture::ByValue => unreachable!(),
1970-
}
1845+
);
19711846
}
19721847

19731848
#[instrument(skip(self), level = "debug")]

0 commit comments

Comments
 (0)