Skip to content

Commit d022142

Browse files
Moved more of the capture related types into closure.rs
1 parent 90cbb39 commit d022142

File tree

2 files changed

+173
-172
lines changed

2 files changed

+173
-172
lines changed

compiler/rustc_middle/src/ty/closure.rs

+173-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::hir::place::{Place as HirPlace, PlaceBase as HirPlaceBase};
1+
use crate::hir::place::{
2+
Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
3+
};
24
use crate::ty;
35

46
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@@ -7,7 +9,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
79
use rustc_hir::lang_items::LangItem;
810
use rustc_span::Span;
911

10-
use super::{BorrowKind, CaptureInfo, Ty, TyCtxt};
12+
use super::{Ty, TyCtxt};
13+
14+
use self::BorrowKind::*;
1115

1216
#[derive(
1317
Clone,
@@ -165,3 +169,170 @@ impl CapturedPlace<'tcx> {
165169
}
166170
}
167171
}
172+
173+
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
174+
/// for a particular capture as well as identifying the part of the source code
175+
/// that triggered this capture to occur.
176+
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
177+
pub struct CaptureInfo<'tcx> {
178+
/// Expr Id pointing to use that resulted in selecting the current capture kind
179+
///
180+
/// Eg:
181+
/// ```rust,no_run
182+
/// let mut t = (0,1);
183+
///
184+
/// let c = || {
185+
/// println!("{}",t); // L1
186+
/// t.1 = 4; // L2
187+
/// };
188+
/// ```
189+
/// `capture_kind_expr_id` will point to the use on L2 and `path_expr_id` will point to the
190+
/// use on L1.
191+
///
192+
/// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is
193+
/// possible that we don't see the use of a particular place resulting in capture_kind_expr_id being
194+
/// None. In such case we fallback on uvpars_mentioned for span.
195+
///
196+
/// Eg:
197+
/// ```rust,no_run
198+
/// let x = 5;
199+
///
200+
/// let c = || {
201+
/// let _ = x
202+
/// };
203+
/// ```
204+
///
205+
/// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured,
206+
/// but we won't see it being used during capture analysis, since it's essentially a discard.
207+
pub capture_kind_expr_id: Option<hir::HirId>,
208+
/// Expr Id pointing to use that resulted the corresponding place being captured
209+
///
210+
/// See `capture_kind_expr_id` for example.
211+
///
212+
pub path_expr_id: Option<hir::HirId>,
213+
214+
/// Capture mode that was selected
215+
pub capture_kind: UpvarCapture<'tcx>,
216+
}
217+
218+
pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
219+
let name = match place.base {
220+
HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
221+
_ => bug!("Capture_information should only contain upvars"),
222+
};
223+
let mut curr_string = name;
224+
225+
for (i, proj) in place.projections.iter().enumerate() {
226+
match proj.kind {
227+
HirProjectionKind::Deref => {
228+
curr_string = format!("*{}", curr_string);
229+
}
230+
HirProjectionKind::Field(idx, variant) => match place.ty_before_projection(i).kind() {
231+
ty::Adt(def, ..) => {
232+
curr_string = format!(
233+
"{}.{}",
234+
curr_string,
235+
def.variants[variant].fields[idx as usize].ident.name.as_str()
236+
);
237+
}
238+
ty::Tuple(_) => {
239+
curr_string = format!("{}.{}", curr_string, idx);
240+
}
241+
_ => {
242+
bug!(
243+
"Field projection applied to a type other than Adt or Tuple: {:?}.",
244+
place.ty_before_projection(i).kind()
245+
)
246+
}
247+
},
248+
proj => bug!("{:?} unexpected because it isn't captured", proj),
249+
}
250+
}
251+
252+
curr_string.to_string()
253+
}
254+
255+
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
256+
pub enum BorrowKind {
257+
/// Data must be immutable and is aliasable.
258+
ImmBorrow,
259+
260+
/// Data must be immutable but not aliasable. This kind of borrow
261+
/// cannot currently be expressed by the user and is used only in
262+
/// implicit closure bindings. It is needed when the closure
263+
/// is borrowing or mutating a mutable referent, e.g.:
264+
///
265+
/// ```
266+
/// let x: &mut isize = ...;
267+
/// let y = || *x += 5;
268+
/// ```
269+
///
270+
/// If we were to try to translate this closure into a more explicit
271+
/// form, we'd encounter an error with the code as written:
272+
///
273+
/// ```
274+
/// struct Env { x: & &mut isize }
275+
/// let x: &mut isize = ...;
276+
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
277+
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
278+
/// ```
279+
///
280+
/// This is then illegal because you cannot mutate a `&mut` found
281+
/// in an aliasable location. To solve, you'd have to translate with
282+
/// an `&mut` borrow:
283+
///
284+
/// ```
285+
/// struct Env { x: & &mut isize }
286+
/// let x: &mut isize = ...;
287+
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
288+
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
289+
/// ```
290+
///
291+
/// Now the assignment to `**env.x` is legal, but creating a
292+
/// mutable pointer to `x` is not because `x` is not mutable. We
293+
/// could fix this by declaring `x` as `let mut x`. This is ok in
294+
/// user code, if awkward, but extra weird for closures, since the
295+
/// borrow is hidden.
296+
///
297+
/// So we introduce a "unique imm" borrow -- the referent is
298+
/// immutable, but not aliasable. This solves the problem. For
299+
/// simplicity, we don't give users the way to express this
300+
/// borrow, it's just used when translating closures.
301+
UniqueImmBorrow,
302+
303+
/// Data is mutable and not aliasable.
304+
MutBorrow,
305+
}
306+
307+
impl BorrowKind {
308+
pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
309+
match m {
310+
hir::Mutability::Mut => MutBorrow,
311+
hir::Mutability::Not => ImmBorrow,
312+
}
313+
}
314+
315+
/// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow
316+
/// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
317+
/// mutability that is stronger than necessary so that it at least *would permit* the borrow in
318+
/// question.
319+
pub fn to_mutbl_lossy(self) -> hir::Mutability {
320+
match self {
321+
MutBorrow => hir::Mutability::Mut,
322+
ImmBorrow => hir::Mutability::Not,
323+
324+
// We have no type corresponding to a unique imm borrow, so
325+
// use `&mut`. It gives all the capabilities of an `&uniq`
326+
// and hence is a safe "over approximation".
327+
UniqueImmBorrow => hir::Mutability::Mut,
328+
}
329+
}
330+
331+
pub fn to_user_str(&self) -> &'static str {
332+
match *self {
333+
MutBorrow => "mutable",
334+
ImmBorrow => "immutable",
335+
UniqueImmBorrow => "uniquely immutable",
336+
}
337+
}
338+
}

compiler/rustc_middle/src/ty/mod.rs

-170
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ pub use closure::*;
2020
pub use generics::*;
2121

2222
use crate::hir::exports::ExportMap;
23-
use crate::hir::place::{
24-
Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
25-
};
2623
use crate::ich::StableHashingContext;
2724
use crate::middle::cstore::CrateStoreDyn;
2825
use crate::mir::{Body, GeneratorLayout};
@@ -352,140 +349,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
352349
#[rustc_diagnostic_item = "Ty"]
353350
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
354351

355-
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
356-
pub enum BorrowKind {
357-
/// Data must be immutable and is aliasable.
358-
ImmBorrow,
359-
360-
/// Data must be immutable but not aliasable. This kind of borrow
361-
/// cannot currently be expressed by the user and is used only in
362-
/// implicit closure bindings. It is needed when the closure
363-
/// is borrowing or mutating a mutable referent, e.g.:
364-
///
365-
/// ```
366-
/// let x: &mut isize = ...;
367-
/// let y = || *x += 5;
368-
/// ```
369-
///
370-
/// If we were to try to translate this closure into a more explicit
371-
/// form, we'd encounter an error with the code as written:
372-
///
373-
/// ```
374-
/// struct Env { x: & &mut isize }
375-
/// let x: &mut isize = ...;
376-
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
377-
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
378-
/// ```
379-
///
380-
/// This is then illegal because you cannot mutate a `&mut` found
381-
/// in an aliasable location. To solve, you'd have to translate with
382-
/// an `&mut` borrow:
383-
///
384-
/// ```
385-
/// struct Env { x: & &mut isize }
386-
/// let x: &mut isize = ...;
387-
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
388-
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
389-
/// ```
390-
///
391-
/// Now the assignment to `**env.x` is legal, but creating a
392-
/// mutable pointer to `x` is not because `x` is not mutable. We
393-
/// could fix this by declaring `x` as `let mut x`. This is ok in
394-
/// user code, if awkward, but extra weird for closures, since the
395-
/// borrow is hidden.
396-
///
397-
/// So we introduce a "unique imm" borrow -- the referent is
398-
/// immutable, but not aliasable. This solves the problem. For
399-
/// simplicity, we don't give users the way to express this
400-
/// borrow, it's just used when translating closures.
401-
UniqueImmBorrow,
402-
403-
/// Data is mutable and not aliasable.
404-
MutBorrow,
405-
}
406-
407-
pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
408-
let name = match place.base {
409-
HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
410-
_ => bug!("Capture_information should only contain upvars"),
411-
};
412-
let mut curr_string = name;
413-
414-
for (i, proj) in place.projections.iter().enumerate() {
415-
match proj.kind {
416-
HirProjectionKind::Deref => {
417-
curr_string = format!("*{}", curr_string);
418-
}
419-
HirProjectionKind::Field(idx, variant) => match place.ty_before_projection(i).kind() {
420-
ty::Adt(def, ..) => {
421-
curr_string = format!(
422-
"{}.{}",
423-
curr_string,
424-
def.variants[variant].fields[idx as usize].ident.name.as_str()
425-
);
426-
}
427-
ty::Tuple(_) => {
428-
curr_string = format!("{}.{}", curr_string, idx);
429-
}
430-
_ => {
431-
bug!(
432-
"Field projection applied to a type other than Adt or Tuple: {:?}.",
433-
place.ty_before_projection(i).kind()
434-
)
435-
}
436-
},
437-
proj => bug!("{:?} unexpected because it isn't captured", proj),
438-
}
439-
}
440-
441-
curr_string.to_string()
442-
}
443-
444-
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
445-
/// for a particular capture as well as identifying the part of the source code
446-
/// that triggered this capture to occur.
447-
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
448-
pub struct CaptureInfo<'tcx> {
449-
/// Expr Id pointing to use that resulted in selecting the current capture kind
450-
///
451-
/// Eg:
452-
/// ```rust,no_run
453-
/// let mut t = (0,1);
454-
///
455-
/// let c = || {
456-
/// println!("{}",t); // L1
457-
/// t.1 = 4; // L2
458-
/// };
459-
/// ```
460-
/// `capture_kind_expr_id` will point to the use on L2 and `path_expr_id` will point to the
461-
/// use on L1.
462-
///
463-
/// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is
464-
/// possible that we don't see the use of a particular place resulting in capture_kind_expr_id being
465-
/// None. In such case we fallback on uvpars_mentioned for span.
466-
///
467-
/// Eg:
468-
/// ```rust,no_run
469-
/// let x = 5;
470-
///
471-
/// let c = || {
472-
/// let _ = x
473-
/// };
474-
/// ```
475-
///
476-
/// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured,
477-
/// but we won't see it being used during capture analysis, since it's essentially a discard.
478-
pub capture_kind_expr_id: Option<hir::HirId>,
479-
/// Expr Id pointing to use that resulted the corresponding place being captured
480-
///
481-
/// See `capture_kind_expr_id` for example.
482-
///
483-
pub path_expr_id: Option<hir::HirId>,
484-
485-
/// Capture mode that was selected
486-
pub capture_kind: UpvarCapture<'tcx>,
487-
}
488-
489352
impl ty::EarlyBoundRegion {
490353
/// Does this early bound region have a name? Early bound regions normally
491354
/// always have names except when using anonymous lifetimes (`'_`).
@@ -1655,39 +1518,6 @@ impl<'tcx> FieldDef {
16551518
}
16561519
}
16571520

1658-
impl BorrowKind {
1659-
pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
1660-
match m {
1661-
hir::Mutability::Mut => MutBorrow,
1662-
hir::Mutability::Not => ImmBorrow,
1663-
}
1664-
}
1665-
1666-
/// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow
1667-
/// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
1668-
/// mutability that is stronger than necessary so that it at least *would permit* the borrow in
1669-
/// question.
1670-
pub fn to_mutbl_lossy(self) -> hir::Mutability {
1671-
match self {
1672-
MutBorrow => hir::Mutability::Mut,
1673-
ImmBorrow => hir::Mutability::Not,
1674-
1675-
// We have no type corresponding to a unique imm borrow, so
1676-
// use `&mut`. It gives all the capabilities of an `&uniq`
1677-
// and hence is a safe "over approximation".
1678-
UniqueImmBorrow => hir::Mutability::Mut,
1679-
}
1680-
}
1681-
1682-
pub fn to_user_str(&self) -> &'static str {
1683-
match *self {
1684-
MutBorrow => "mutable",
1685-
ImmBorrow => "immutable",
1686-
UniqueImmBorrow => "uniquely immutable",
1687-
}
1688-
}
1689-
}
1690-
16911521
pub type Attributes<'tcx> = &'tcx [ast::Attribute];
16921522

16931523
#[derive(Debug, PartialEq, Eq)]

0 commit comments

Comments
 (0)