Rollup merge of #81062 - sexxi-goose:precise_capture_diagnostics, r=nikomatsakis
Improve diagnostics for Precise Capture This is just the capture analysis part and borrow checker logging will updated as part of rust-lang/project-rfc-2229#8 Closes rust-lang/project-rfc-2229#22
This commit is contained in:
commit
84ad95be70
@ -712,8 +712,20 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) ->
|
||||
pub struct CaptureInfo<'tcx> {
|
||||
/// Expr Id pointing to use that resulted in selecting the current capture kind
|
||||
///
|
||||
/// Eg:
|
||||
/// ```rust,no_run
|
||||
/// let mut t = (0,1);
|
||||
///
|
||||
/// let c = || {
|
||||
/// println!("{}",t); // L1
|
||||
/// t.1 = 4; // L2
|
||||
/// };
|
||||
/// ```
|
||||
/// `capture_kind_expr_id` will point to the use on L2 and `path_expr_id` will point to the
|
||||
/// use on L1.
|
||||
///
|
||||
/// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is
|
||||
/// possible that we don't see the use of a particular place resulting in expr_id being
|
||||
/// possible that we don't see the use of a particular place resulting in capture_kind_expr_id being
|
||||
/// None. In such case we fallback on uvpars_mentioned for span.
|
||||
///
|
||||
/// Eg:
|
||||
@ -727,7 +739,12 @@ pub struct CaptureInfo<'tcx> {
|
||||
///
|
||||
/// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured,
|
||||
/// but we won't see it being used during capture analysis, since it's essentially a discard.
|
||||
pub expr_id: Option<hir::HirId>,
|
||||
pub capture_kind_expr_id: Option<hir::HirId>,
|
||||
/// Expr Id pointing to use that resulted the corresponding place being captured
|
||||
///
|
||||
/// See `capture_kind_expr_id` for example.
|
||||
///
|
||||
pub path_expr_id: Option<hir::HirId>,
|
||||
|
||||
/// Capture mode that was selected
|
||||
pub capture_kind: UpvarCapture<'tcx>,
|
||||
|
@ -42,7 +42,7 @@ use rustc_infer::infer::UpvarRegion;
|
||||
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, ProjectionKind};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts};
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{MultiSpan, Span, Symbol};
|
||||
|
||||
/// Describe the relationship between the paths of two places
|
||||
/// eg:
|
||||
@ -135,7 +135,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let upvar_id = ty::UpvarId::new(var_hir_id, local_def_id);
|
||||
let capture_kind = self.init_capture_kind(capture_clause, upvar_id, span);
|
||||
let info = ty::CaptureInfo { expr_id: None, capture_kind };
|
||||
let info = ty::CaptureInfo {
|
||||
capture_kind_expr_id: None,
|
||||
path_expr_id: None,
|
||||
capture_kind,
|
||||
};
|
||||
|
||||
capture_information.insert(place, info);
|
||||
}
|
||||
@ -308,8 +312,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let Some(capture_kind) = upvar_capture_map.get(&upvar_id) {
|
||||
// upvar_capture_map only stores the UpvarCapture (CaptureKind),
|
||||
// so we create a fake capture info with no expression.
|
||||
let fake_capture_info =
|
||||
ty::CaptureInfo { expr_id: None, capture_kind: *capture_kind };
|
||||
let fake_capture_info = ty::CaptureInfo {
|
||||
capture_kind_expr_id: None,
|
||||
path_expr_id: None,
|
||||
capture_kind: *capture_kind,
|
||||
};
|
||||
determine_capture_info(fake_capture_info, capture_info).capture_kind
|
||||
} else {
|
||||
capture_info.capture_kind
|
||||
@ -359,20 +366,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
///
|
||||
/// ```
|
||||
/// {
|
||||
/// Place(base: hir_id_s, projections: [], ....) -> (hir_id_L5, ByValue),
|
||||
/// Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> (hir_id_L2, ByRef(MutBorrow))
|
||||
/// Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> (hir_id_L3, ByRef(ImmutBorrow))
|
||||
/// Place(base: hir_id_p, projections: [], ...) -> (hir_id_L4, ByRef(ImmutBorrow))
|
||||
/// Place(base: hir_id_s, projections: [], ....) -> {
|
||||
/// capture_kind_expr: hir_id_L5,
|
||||
/// path_expr_id: hir_id_L5,
|
||||
/// capture_kind: ByValue
|
||||
/// },
|
||||
/// Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> {
|
||||
/// capture_kind_expr: hir_id_L2,
|
||||
/// path_expr_id: hir_id_L2,
|
||||
/// capture_kind: ByValue
|
||||
/// },
|
||||
/// Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> {
|
||||
/// capture_kind_expr: hir_id_L3,
|
||||
/// path_expr_id: hir_id_L3,
|
||||
/// capture_kind: ByValue
|
||||
/// },
|
||||
/// Place(base: hir_id_p, projections: [], ...) -> {
|
||||
/// capture_kind_expr: hir_id_L4,
|
||||
/// path_expr_id: hir_id_L4,
|
||||
/// capture_kind: ByValue
|
||||
/// },
|
||||
/// ```
|
||||
///
|
||||
/// After the min capture analysis, we get:
|
||||
/// ```
|
||||
/// {
|
||||
/// hir_id_s -> [
|
||||
/// Place(base: hir_id_s, projections: [], ....) -> (hir_id_L4, ByValue)
|
||||
/// Place(base: hir_id_s, projections: [], ....) -> {
|
||||
/// capture_kind_expr: hir_id_L5,
|
||||
/// path_expr_id: hir_id_L5,
|
||||
/// capture_kind: ByValue
|
||||
/// },
|
||||
/// ],
|
||||
/// hir_id_p -> [
|
||||
/// Place(base: hir_id_p, projections: [], ...) -> (hir_id_L2, ByRef(MutBorrow)),
|
||||
/// Place(base: hir_id_p, projections: [], ...) -> {
|
||||
/// capture_kind_expr: hir_id_L2,
|
||||
/// path_expr_id: hir_id_L4,
|
||||
/// capture_kind: ByValue
|
||||
/// },
|
||||
/// ],
|
||||
/// ```
|
||||
fn compute_min_captures(
|
||||
@ -425,8 +456,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// current place is ancestor of possible_descendant
|
||||
PlaceAncestryRelation::Ancestor => {
|
||||
descendant_found = true;
|
||||
let backup_path_expr_id = updated_capture_info.path_expr_id;
|
||||
|
||||
updated_capture_info =
|
||||
determine_capture_info(updated_capture_info, possible_descendant.info);
|
||||
|
||||
// we need to keep the ancestor's `path_expr_id`
|
||||
updated_capture_info.path_expr_id = backup_path_expr_id;
|
||||
false
|
||||
}
|
||||
|
||||
@ -441,9 +477,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// current place is descendant of possible_ancestor
|
||||
PlaceAncestryRelation::Descendant => {
|
||||
ancestor_found = true;
|
||||
let backup_path_expr_id = possible_ancestor.info.path_expr_id;
|
||||
possible_ancestor.info =
|
||||
determine_capture_info(possible_ancestor.info, capture_info);
|
||||
|
||||
// we need to keep the ancestor's `path_expr_id`
|
||||
possible_ancestor.info.path_expr_id = backup_path_expr_id;
|
||||
|
||||
// Only one ancestor of the current place will be in the list.
|
||||
break;
|
||||
}
|
||||
@ -518,7 +558,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let capture_str = construct_capture_info_string(self.tcx, place, capture_info);
|
||||
let output_str = format!("Capturing {}", capture_str);
|
||||
|
||||
let span = capture_info.expr_id.map_or(closure_span, |e| self.tcx.hir().span(e));
|
||||
let span =
|
||||
capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e));
|
||||
diag.span_note(span, &output_str);
|
||||
}
|
||||
diag.emit();
|
||||
@ -542,9 +583,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
construct_capture_info_string(self.tcx, place, capture_info);
|
||||
let output_str = format!("Min Capture {}", capture_str);
|
||||
|
||||
let span =
|
||||
capture_info.expr_id.map_or(closure_span, |e| self.tcx.hir().span(e));
|
||||
diag.span_note(span, &output_str);
|
||||
if capture.info.path_expr_id != capture.info.capture_kind_expr_id {
|
||||
let path_span = capture_info
|
||||
.path_expr_id
|
||||
.map_or(closure_span, |e| self.tcx.hir().span(e));
|
||||
let capture_kind_span = capture_info
|
||||
.capture_kind_expr_id
|
||||
.map_or(closure_span, |e| self.tcx.hir().span(e));
|
||||
|
||||
let mut multi_span: MultiSpan =
|
||||
MultiSpan::from_spans(vec![path_span, capture_kind_span]);
|
||||
|
||||
let capture_kind_label =
|
||||
construct_capture_kind_reason_string(self.tcx, place, capture_info);
|
||||
let path_label = construct_path_string(self.tcx, place);
|
||||
|
||||
multi_span.push_span_label(path_span, path_label);
|
||||
multi_span.push_span_label(capture_kind_span, capture_kind_label);
|
||||
|
||||
diag.span_note(multi_span, &output_str);
|
||||
} else {
|
||||
let span = capture_info
|
||||
.path_expr_id
|
||||
.map_or(closure_span, |e| self.tcx.hir().span(e));
|
||||
|
||||
diag.span_note(span, &output_str);
|
||||
};
|
||||
}
|
||||
}
|
||||
diag.emit();
|
||||
@ -642,7 +706,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
);
|
||||
|
||||
let capture_info = ty::CaptureInfo {
|
||||
expr_id: Some(diag_expr_id),
|
||||
capture_kind_expr_id: Some(diag_expr_id),
|
||||
path_expr_id: Some(diag_expr_id),
|
||||
capture_kind: ty::UpvarCapture::ByValue(Some(usage_span)),
|
||||
};
|
||||
|
||||
@ -762,7 +827,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
let new_upvar_borrow = ty::UpvarBorrow { kind, region: curr_upvar_borrow.region };
|
||||
|
||||
let capture_info = ty::CaptureInfo {
|
||||
expr_id: Some(diag_expr_id),
|
||||
capture_kind_expr_id: Some(diag_expr_id),
|
||||
path_expr_id: Some(diag_expr_id),
|
||||
capture_kind: ty::UpvarCapture::ByRef(new_upvar_borrow),
|
||||
};
|
||||
let updated_info = determine_capture_info(curr_capture_info, capture_info);
|
||||
@ -824,7 +890,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||
self.fcx.init_capture_kind(self.capture_clause, upvar_id, self.closure_span);
|
||||
|
||||
let expr_id = Some(diag_expr_id);
|
||||
let capture_info = ty::CaptureInfo { expr_id, capture_kind };
|
||||
let capture_info = ty::CaptureInfo {
|
||||
capture_kind_expr_id: expr_id,
|
||||
path_expr_id: expr_id,
|
||||
capture_kind,
|
||||
};
|
||||
|
||||
debug!("Capturing new place {:?}, capture_info={:?}", place_with_id, capture_info);
|
||||
|
||||
@ -890,11 +960,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_capture_info_string(
|
||||
tcx: TyCtxt<'_>,
|
||||
place: &Place<'tcx>,
|
||||
capture_info: &ty::CaptureInfo<'tcx>,
|
||||
) -> String {
|
||||
fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
|
||||
let variable_name = match place.base {
|
||||
PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(),
|
||||
_ => bug!("Capture_information should only contain upvars"),
|
||||
@ -914,11 +980,42 @@ fn construct_capture_info_string(
|
||||
projections_str.push_str(proj.as_str());
|
||||
}
|
||||
|
||||
format!("{}[{}]", variable_name, projections_str)
|
||||
}
|
||||
|
||||
fn construct_capture_kind_reason_string(
|
||||
tcx: TyCtxt<'_>,
|
||||
place: &Place<'tcx>,
|
||||
capture_info: &ty::CaptureInfo<'tcx>,
|
||||
) -> String {
|
||||
let place_str = construct_place_string(tcx, &place);
|
||||
|
||||
let capture_kind_str = match capture_info.capture_kind {
|
||||
ty::UpvarCapture::ByValue(_) => "ByValue".into(),
|
||||
ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind),
|
||||
};
|
||||
format!("{}[{}] -> {}", variable_name, projections_str, capture_kind_str)
|
||||
|
||||
format!("{} captured as {} here", place_str, capture_kind_str)
|
||||
}
|
||||
|
||||
fn construct_path_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
|
||||
let place_str = construct_place_string(tcx, &place);
|
||||
|
||||
format!("{} used here", place_str)
|
||||
}
|
||||
|
||||
fn construct_capture_info_string(
|
||||
tcx: TyCtxt<'_>,
|
||||
place: &Place<'tcx>,
|
||||
capture_info: &ty::CaptureInfo<'tcx>,
|
||||
) -> String {
|
||||
let place_str = construct_place_string(tcx, &place);
|
||||
|
||||
let capture_kind_str = match capture_info.capture_kind {
|
||||
ty::UpvarCapture::ByValue(_) => "ByValue".into(),
|
||||
ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind),
|
||||
};
|
||||
format!("{} -> {}", place_str, capture_kind_str)
|
||||
}
|
||||
|
||||
fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
|
||||
@ -930,7 +1027,9 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
|
||||
/// (Note: CaptureInfo contains CaptureKind and an expression that led to capture it in that way)
|
||||
///
|
||||
/// If both `CaptureKind`s are considered equivalent, then the CaptureInfo is selected based
|
||||
/// on the `CaptureInfo` containing an associated expression id.
|
||||
/// on the `CaptureInfo` containing an associated `capture_kind_expr_id`.
|
||||
///
|
||||
/// It is the caller's duty to figure out which path_expr_id to use.
|
||||
///
|
||||
/// If both the CaptureKind and Expression are considered to be equivalent,
|
||||
/// then `CaptureInfo` A is preferred. This can be useful in cases where we want to priortize
|
||||
@ -981,7 +1080,7 @@ fn determine_capture_info(
|
||||
};
|
||||
|
||||
if eq_capture_kind {
|
||||
match (capture_info_a.expr_id, capture_info_b.expr_id) {
|
||||
match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) {
|
||||
(Some(_), _) | (None, None) => capture_info_a,
|
||||
(None, Some(_)) => capture_info_b,
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
let min_list_wb = min_list
|
||||
.iter()
|
||||
.map(|captured_place| {
|
||||
let locatable = captured_place.info.expr_id.unwrap_or(
|
||||
let locatable = captured_place.info.path_expr_id.unwrap_or(
|
||||
self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()),
|
||||
);
|
||||
|
||||
|
@ -630,7 +630,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
PlaceBase::Local(*var_hir_id)
|
||||
};
|
||||
let place_with_id = PlaceWithHirId::new(
|
||||
capture_info.expr_id.unwrap_or(closure_expr.hir_id),
|
||||
capture_info.path_expr_id.unwrap_or(closure_expr.hir_id),
|
||||
place.base_ty,
|
||||
place_base,
|
||||
place.projections.clone(),
|
||||
|
@ -0,0 +1,35 @@
|
||||
#![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>
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p = Point { x: 10, y: 10 };
|
||||
let q = Point { x: 10, y: 10 };
|
||||
|
||||
let c = #[rustc_capture_analysis]
|
||||
//~^ ERROR: attributes on expressions are experimental
|
||||
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|
||||
|| {
|
||||
//~^ First Pass analysis includes:
|
||||
//~| Min Capture analysis includes:
|
||||
println!("{:?}", p);
|
||||
//~^ NOTE: Capturing p[] -> ImmBorrow
|
||||
//~| NOTE: Min Capture p[] -> ImmBorrow
|
||||
println!("{:?}", p.x);
|
||||
//~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow
|
||||
|
||||
println!("{:?}", q.x);
|
||||
//~^ NOTE: Capturing q[(0, 0)] -> ImmBorrow
|
||||
println!("{:?}", q);
|
||||
//~^ NOTE: Capturing q[] -> ImmBorrow
|
||||
//~| NOTE: Min Capture q[] -> ImmBorrow
|
||||
};
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/capture-analysis-1.rs:17:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/capture-analysis-1.rs:1: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
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/capture-analysis-1.rs:20:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | println!("{:?}", p);
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing p[] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-1.rs:23:26
|
||||
|
|
||||
LL | println!("{:?}", p);
|
||||
| ^
|
||||
note: Capturing p[(0, 0)] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-1.rs:26:26
|
||||
|
|
||||
LL | println!("{:?}", p.x);
|
||||
| ^^^
|
||||
note: Capturing q[(0, 0)] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-1.rs:29:26
|
||||
|
|
||||
LL | println!("{:?}", q.x);
|
||||
| ^^^
|
||||
note: Capturing q[] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-1.rs:31:26
|
||||
|
|
||||
LL | println!("{:?}", q);
|
||||
| ^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/capture-analysis-1.rs:20:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | println!("{:?}", p);
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture p[] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-1.rs:23:26
|
||||
|
|
||||
LL | println!("{:?}", p);
|
||||
| ^
|
||||
note: Min Capture q[] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-1.rs:31:26
|
||||
|
|
||||
LL | println!("{:?}", q);
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,30 @@
|
||||
#![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>
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Point {
|
||||
x: String,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut p = Point { x: String::new(), y: 10 };
|
||||
|
||||
let c = #[rustc_capture_analysis]
|
||||
//~^ ERROR: attributes on expressions are experimental
|
||||
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|
||||
|| {
|
||||
//~^ First Pass analysis includes:
|
||||
//~| Min Capture analysis includes:
|
||||
let _x = p.x;
|
||||
//~^ NOTE: Capturing p[(0, 0)] -> ByValue
|
||||
//~| NOTE: p[] captured as ByValue here
|
||||
println!("{:?}", p);
|
||||
//~^ NOTE: Capturing p[] -> ImmBorrow
|
||||
//~| NOTE: Min Capture p[] -> ByValue
|
||||
//~| NOTE: p[] used here
|
||||
};
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/capture-analysis-2.rs:16:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/capture-analysis-2.rs:1: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
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/capture-analysis-2.rs:19:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _x = p.x;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing p[(0, 0)] -> ByValue
|
||||
--> $DIR/capture-analysis-2.rs:22:18
|
||||
|
|
||||
LL | let _x = p.x;
|
||||
| ^^^
|
||||
note: Capturing p[] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-2.rs:25:26
|
||||
|
|
||||
LL | println!("{:?}", p);
|
||||
| ^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/capture-analysis-2.rs:19:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _x = p.x;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture p[] -> ByValue
|
||||
--> $DIR/capture-analysis-2.rs:22:18
|
||||
|
|
||||
LL | let _x = p.x;
|
||||
| ^^^ p[] captured as ByValue here
|
||||
...
|
||||
LL | println!("{:?}", p);
|
||||
| ^ p[] used here
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,35 @@
|
||||
#![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>
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Child {
|
||||
c: String,
|
||||
d: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Parent {
|
||||
b: Child,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut a = Parent { b: Child {c: String::new(), d: String::new()} };
|
||||
|
||||
let c = #[rustc_capture_analysis]
|
||||
//~^ ERROR: attributes on expressions are experimental
|
||||
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|
||||
|| {
|
||||
//~^ First Pass analysis includes:
|
||||
//~| Min Capture analysis includes:
|
||||
let _x = a.b.c;
|
||||
//~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue
|
||||
//~| NOTE: a[(0, 0)] captured as ByValue here
|
||||
println!("{:?}", a.b);
|
||||
//~^ NOTE: Capturing a[(0, 0)] -> ImmBorrow
|
||||
//~| NOTE: Min Capture a[(0, 0)] -> ByValue
|
||||
//~| NOTE: a[(0, 0)] used here
|
||||
};
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/capture-analysis-3.rs:21:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/capture-analysis-3.rs:1: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
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/capture-analysis-3.rs:24:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _x = a.b.c;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing a[(0, 0),(0, 0)] -> ByValue
|
||||
--> $DIR/capture-analysis-3.rs:27:18
|
||||
|
|
||||
LL | let _x = a.b.c;
|
||||
| ^^^^^
|
||||
note: Capturing a[(0, 0)] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-3.rs:30:26
|
||||
|
|
||||
LL | println!("{:?}", a.b);
|
||||
| ^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/capture-analysis-3.rs:24:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _x = a.b.c;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture a[(0, 0)] -> ByValue
|
||||
--> $DIR/capture-analysis-3.rs:27:18
|
||||
|
|
||||
LL | let _x = a.b.c;
|
||||
| ^^^^^ a[(0, 0)] captured as ByValue here
|
||||
...
|
||||
LL | println!("{:?}", a.b);
|
||||
| ^^^ a[(0, 0)] used here
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,33 @@
|
||||
#![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>
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Child {
|
||||
c: String,
|
||||
d: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Parent {
|
||||
b: Child,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut a = Parent { b: Child {c: String::new(), d: String::new()} };
|
||||
|
||||
let c = #[rustc_capture_analysis]
|
||||
//~^ ERROR: attributes on expressions are experimental
|
||||
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|
||||
|| {
|
||||
//~^ First Pass analysis includes:
|
||||
//~| Min Capture analysis includes:
|
||||
let _x = a.b;
|
||||
//~^ NOTE: Capturing a[(0, 0)] -> ByValue
|
||||
//~| NOTE: Min Capture a[(0, 0)] -> ByValue
|
||||
println!("{:?}", a.b.c);
|
||||
//~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ImmBorrow
|
||||
};
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/capture-analysis-4.rs:21:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/capture-analysis-4.rs:1: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
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/capture-analysis-4.rs:24:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _x = a.b;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing a[(0, 0)] -> ByValue
|
||||
--> $DIR/capture-analysis-4.rs:27:18
|
||||
|
|
||||
LL | let _x = a.b;
|
||||
| ^^^
|
||||
note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow
|
||||
--> $DIR/capture-analysis-4.rs:30:26
|
||||
|
|
||||
LL | println!("{:?}", a.b.c);
|
||||
| ^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/capture-analysis-4.rs:24:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _x = a.b;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture a[(0, 0)] -> ByValue
|
||||
--> $DIR/capture-analysis-4.rs:27:18
|
||||
|
|
||||
LL | let _x = a.b;
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,52 @@
|
||||
#![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>
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(unused)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct Line {
|
||||
p: Point,
|
||||
q: Point
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct Plane {
|
||||
a: Line,
|
||||
b: Line,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut p = Plane {
|
||||
a: Line {
|
||||
p: Point { x: 1,y: 2 },
|
||||
q: Point { x: 3,y: 4 },
|
||||
},
|
||||
b: Line {
|
||||
p: Point { x: 1,y: 2 },
|
||||
q: Point { x: 3,y: 4 },
|
||||
}
|
||||
};
|
||||
|
||||
let c = #[rustc_capture_analysis]
|
||||
//~^ ERROR: attributes on expressions are experimental
|
||||
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|
||||
|| {
|
||||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
let x = &p.a.p.x;
|
||||
//~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
|
||||
p.b.q.y = 9;
|
||||
//~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow
|
||||
//~| NOTE: p[] captured as MutBorrow here
|
||||
println!("{:?}", p);
|
||||
//~^ NOTE: Capturing p[] -> ImmBorrow
|
||||
//~| NOTE: Min Capture p[] -> MutBorrow
|
||||
//~| NOTE: p[] used here
|
||||
};
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/deep-multilevel-struct.rs:36:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/deep-multilevel-struct.rs:1: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
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/deep-multilevel-struct.rs:39:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let x = &p.a.p.x;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
|
||||
--> $DIR/deep-multilevel-struct.rs:42:18
|
||||
|
|
||||
LL | let x = &p.a.p.x;
|
||||
| ^^^^^^^
|
||||
note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow
|
||||
--> $DIR/deep-multilevel-struct.rs:44:9
|
||||
|
|
||||
LL | p.b.q.y = 9;
|
||||
| ^^^^^^^
|
||||
note: Capturing p[] -> ImmBorrow
|
||||
--> $DIR/deep-multilevel-struct.rs:47:26
|
||||
|
|
||||
LL | println!("{:?}", p);
|
||||
| ^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/deep-multilevel-struct.rs:39:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let x = &p.a.p.x;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture p[] -> MutBorrow
|
||||
--> $DIR/deep-multilevel-struct.rs:44:9
|
||||
|
|
||||
LL | p.b.q.y = 9;
|
||||
| ^^^^^^^ p[] captured as MutBorrow here
|
||||
...
|
||||
LL | println!("{:?}", p);
|
||||
| ^ p[] used here
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,27 @@
|
||||
#![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>
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(unused)]
|
||||
|
||||
fn main() {
|
||||
let mut t = (((1,2),(3,4)),((5,6),(7,8)));
|
||||
|
||||
let c = #[rustc_capture_analysis]
|
||||
//~^ ERROR: attributes on expressions are experimental
|
||||
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|
||||
|| {
|
||||
//~^ ERROR: First Pass analysis includes:
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
let x = &t.0.0.0;
|
||||
//~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
|
||||
t.1.1.1 = 9;
|
||||
//~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow
|
||||
//~| NOTE: t[] captured as MutBorrow here
|
||||
println!("{:?}", t);
|
||||
//~^ NOTE: Min Capture t[] -> MutBorrow
|
||||
//~| NOTE: Capturing t[] -> ImmBorrow
|
||||
//~| NOTE: t[] used here
|
||||
};
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/deep-multilevel-tuple.rs:11:13
|
||||
|
|
||||
LL | let c = #[rustc_capture_analysis]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/deep-multilevel-tuple.rs:1: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
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/deep-multilevel-tuple.rs:14:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let x = &t.0.0.0;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
|
||||
--> $DIR/deep-multilevel-tuple.rs:17:18
|
||||
|
|
||||
LL | let x = &t.0.0.0;
|
||||
| ^^^^^^^
|
||||
note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow
|
||||
--> $DIR/deep-multilevel-tuple.rs:19:9
|
||||
|
|
||||
LL | t.1.1.1 = 9;
|
||||
| ^^^^^^^
|
||||
note: Capturing t[] -> ImmBorrow
|
||||
--> $DIR/deep-multilevel-tuple.rs:22:26
|
||||
|
|
||||
LL | println!("{:?}", t);
|
||||
| ^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/deep-multilevel-tuple.rs:14:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let x = &t.0.0.0;
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture t[] -> MutBorrow
|
||||
--> $DIR/deep-multilevel-tuple.rs:19:9
|
||||
|
|
||||
LL | t.1.1.1 = 9;
|
||||
| ^^^^^^^ t[] captured as MutBorrow here
|
||||
...
|
||||
LL | println!("{:?}", t);
|
||||
| ^ t[] used here
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -32,9 +32,11 @@ fn main() {
|
||||
//~| ERROR: Min Capture analysis includes:
|
||||
p.x += 10;
|
||||
//~^ NOTE: Capturing p[(0, 0)] -> MutBorrow
|
||||
//~| NOTE: Min Capture p[] -> MutBorrow
|
||||
//~| NOTE: p[] captured as MutBorrow here
|
||||
println!("{:?}", p);
|
||||
//~^ NOTE: Capturing p[] -> ImmBorrow
|
||||
//~| NOTE: Min Capture p[] -> MutBorrow
|
||||
//~| NOTE: p[] used here
|
||||
};
|
||||
|
||||
c();
|
||||
|
@ -55,7 +55,10 @@ note: Min Capture p[] -> MutBorrow
|
||||
--> $DIR/simple-struct-min-capture.rs:33:9
|
||||
|
|
||||
LL | p.x += 10;
|
||||
| ^^^
|
||||
| ^^^ p[] captured as MutBorrow here
|
||||
...
|
||||
LL | println!("{:?}", p);
|
||||
| ^ p[] used here
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user