Try to explain borrow for tail expr temporary drop order change in 2024
This commit is contained in:
parent
4a099b29cd
commit
c55eefe8bc
9 changed files with 81 additions and 42 deletions
|
@ -213,8 +213,9 @@ borrowck_suggest_create_fresh_reborrow =
|
||||||
borrowck_suggest_iterate_over_slice =
|
borrowck_suggest_iterate_over_slice =
|
||||||
consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
|
consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
|
||||||
|
|
||||||
borrowck_tail_expr_drop_order = a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
|
borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024
|
||||||
.label = consider using a `let` binding to create a longer lived value; or replacing the `{"{"} .. {"}"}` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe {"{"} .. {"}"}`
|
.label = this temporary value will be dropped at the end of the block
|
||||||
|
.note = consider using a `let` binding to ensure the value will live long enough
|
||||||
|
|
||||||
borrowck_ty_no_impl_copy =
|
borrowck_ty_no_impl_copy =
|
||||||
{$is_partial_move ->
|
{$is_partial_move ->
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
|
|
||||||
use rustc_errors::{Applicability, Diag};
|
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||||
|
@ -61,10 +61,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||||
pub(crate) fn is_explained(&self) -> bool {
|
pub(crate) fn is_explained(&self) -> bool {
|
||||||
!matches!(self, BorrowExplanation::Unexplained)
|
!matches!(self, BorrowExplanation::Unexplained)
|
||||||
}
|
}
|
||||||
pub(crate) fn add_explanation_to_diagnostic(
|
pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
|
||||||
&self,
|
&self,
|
||||||
cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
|
cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_, G>,
|
||||||
borrow_desc: &str,
|
borrow_desc: &str,
|
||||||
borrow_span: Option<Span>,
|
borrow_span: Option<Span>,
|
||||||
multiple_borrow_span: Option<(Span, Span)>,
|
multiple_borrow_span: Option<(Span, Span)>,
|
||||||
|
@ -346,10 +346,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_object_lifetime_default_note(
|
fn add_object_lifetime_default_note<G: EmissionGuarantee>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_, G>,
|
||||||
unsize_ty: Ty<'tcx>,
|
unsize_ty: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
if let ty::Adt(def, args) = unsize_ty.kind() {
|
if let ty::Adt(def, args) = unsize_ty.kind() {
|
||||||
|
@ -403,9 +403,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_lifetime_bound_suggestion_to_diagnostic(
|
fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_, G>,
|
||||||
category: &ConstraintCategory<'tcx>,
|
category: &ConstraintCategory<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
region_name: &RegionName,
|
region_name: &RegionName,
|
||||||
|
@ -432,14 +432,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_rewrite_if_let(
|
fn suggest_rewrite_if_let<G: EmissionGuarantee>(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
expr: &hir::Expr<'_>,
|
expr: &hir::Expr<'_>,
|
||||||
pat: &str,
|
pat: &str,
|
||||||
init: &hir::Expr<'_>,
|
init: &hir::Expr<'_>,
|
||||||
conseq: &hir::Expr<'_>,
|
conseq: &hir::Expr<'_>,
|
||||||
alt: Option<&hir::Expr<'_>>,
|
alt: Option<&hir::Expr<'_>>,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_, G>,
|
||||||
) {
|
) {
|
||||||
let source_map = tcx.sess.source_map();
|
let source_map = tcx.sess.source_map();
|
||||||
err.span_note(
|
err.span_note(
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::collections::BTreeMap;
|
||||||
|
|
||||||
use rustc_abi::{FieldIdx, VariantIdx};
|
use rustc_abi::{FieldIdx, VariantIdx};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::{Applicability, Diag, MultiSpan};
|
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan};
|
||||||
use rustc_hir::def::{CtorKind, Namespace};
|
use rustc_hir::def::{CtorKind, Namespace};
|
||||||
use rustc_hir::{self as hir, CoroutineKind, LangItem};
|
use rustc_hir::{self as hir, CoroutineKind, LangItem};
|
||||||
use rustc_index::IndexSlice;
|
use rustc_index::IndexSlice;
|
||||||
|
@ -626,9 +626,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
|
|
||||||
/// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
|
/// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
|
||||||
/// implicitly introduce an "outlives `'static`" constraint.
|
/// implicitly introduce an "outlives `'static`" constraint.
|
||||||
fn add_placeholder_from_predicate_note(
|
fn add_placeholder_from_predicate_note<G: EmissionGuarantee>(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_, G>,
|
||||||
path: &[OutlivesConstraint<'tcx>],
|
path: &[OutlivesConstraint<'tcx>],
|
||||||
) {
|
) {
|
||||||
let predicate_span = path.iter().find_map(|constraint| {
|
let predicate_span = path.iter().find_map(|constraint| {
|
||||||
|
@ -651,9 +651,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
|
|
||||||
/// Add a label to region errors and borrow explanations when outlives constraints arise from
|
/// Add a label to region errors and borrow explanations when outlives constraints arise from
|
||||||
/// proving a type implements `Sized` or `Copy`.
|
/// proving a type implements `Sized` or `Copy`.
|
||||||
fn add_sized_or_copy_bound_info(
|
fn add_sized_or_copy_bound_info<G: EmissionGuarantee>(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_, G>,
|
||||||
blamed_category: ConstraintCategory<'tcx>,
|
blamed_category: ConstraintCategory<'tcx>,
|
||||||
path: &[OutlivesConstraint<'tcx>],
|
path: &[OutlivesConstraint<'tcx>],
|
||||||
) {
|
) {
|
||||||
|
@ -1042,6 +1042,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
kind,
|
kind,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
normal_ret
|
normal_ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::fmt::{self, Display};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use rustc_data_structures::fx::IndexEntry;
|
use rustc_data_structures::fx::IndexEntry;
|
||||||
use rustc_errors::Diag;
|
use rustc_errors::{Diag, EmissionGuarantee};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_middle::ty::print::RegionHighlightMode;
|
use rustc_middle::ty::print::RegionHighlightMode;
|
||||||
|
@ -108,7 +108,7 @@ impl RegionName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_>) {
|
pub(crate) fn highlight_region_name<G: EmissionGuarantee>(&self, diag: &mut Diag<'_, G>) {
|
||||||
match &self.source {
|
match &self.source {
|
||||||
RegionNameSource::NamedLateParamRegion(span)
|
RegionNameSource::NamedLateParamRegion(span)
|
||||||
| RegionNameSource::NamedEarlyParamRegion(span) => {
|
| RegionNameSource::NamedEarlyParamRegion(span) => {
|
||||||
|
|
|
@ -24,6 +24,7 @@ use std::ops::{ControlFlow, Deref};
|
||||||
use rustc_abi::FieldIdx;
|
use rustc_abi::FieldIdx;
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::graph::dominators::Dominators;
|
use rustc_data_structures::graph::dominators::Dominators;
|
||||||
|
use rustc_errors::LintDiagnostic;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::CRATE_HIR_ID;
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
@ -1192,17 +1193,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
||||||
|borrow_index| borrows_in_scope.contains(borrow_index),
|
|borrow_index| borrows_in_scope.contains(borrow_index),
|
||||||
|this, _borrow_index, borrow| {
|
|this, _borrow_index, borrow| {
|
||||||
if matches!(borrow.kind, BorrowKind::Fake(_)) {
|
if matches!(borrow.kind, BorrowKind::Fake(_)) {
|
||||||
return Control::Continue;
|
return ControlFlow::Continue(());
|
||||||
}
|
}
|
||||||
let borrowed = this.retrieve_borrow_spans(borrow).var_or_use_path_span();
|
let borrowed = this.retrieve_borrow_spans(borrow).var_or_use_path_span();
|
||||||
this.infcx.tcx.emit_node_span_lint(
|
let explain = this.explain_why_borrow_contains_point(
|
||||||
|
location,
|
||||||
|
borrow,
|
||||||
|
Some((WriteKind::StorageDeadOrDrop, place)),
|
||||||
|
);
|
||||||
|
this.infcx.tcx.node_span_lint(
|
||||||
TAIL_EXPR_DROP_ORDER,
|
TAIL_EXPR_DROP_ORDER,
|
||||||
CRATE_HIR_ID,
|
CRATE_HIR_ID,
|
||||||
place_span,
|
borrowed,
|
||||||
session_diagnostics::TailExprDropOrder { borrowed },
|
|diag| {
|
||||||
|
session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
|
||||||
|
explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
// We may stop at the first case
|
// We may stop at the first case
|
||||||
Control::Break
|
ControlFlow::Break(())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
|
||||||
|
|
||||||
bb7: {
|
bb7: {
|
||||||
backward incompatible drop(_2);
|
backward incompatible drop(_2);
|
||||||
|
backward incompatible drop(_4);
|
||||||
backward incompatible drop(_5);
|
backward incompatible drop(_5);
|
||||||
goto -> bb21;
|
goto -> bb21;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
|
||||||
|
|
||||||
bb7: {
|
bb7: {
|
||||||
backward incompatible drop(_2);
|
backward incompatible drop(_2);
|
||||||
|
backward incompatible drop(_4);
|
||||||
backward incompatible drop(_5);
|
backward incompatible drop(_5);
|
||||||
goto -> bb21;
|
goto -> bb21;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,20 @@
|
||||||
|
|
||||||
fn should_lint_with_potential_borrowck_err() {
|
fn should_lint_with_potential_borrowck_err() {
|
||||||
let _ = { String::new().as_str() }.len();
|
let _ = { String::new().as_str() }.len();
|
||||||
//~^ ERROR: a temporary value will be dropped here
|
//~^ ERROR: relative drop order changing
|
||||||
//~| WARN: this changes meaning in Rust 2024
|
//~| WARN: this changes meaning in Rust 2024
|
||||||
//~| NOTE: consider using a `let` binding
|
//~| NOTE: this temporary value will be dropped at the end of the block
|
||||||
|
//~| borrow later used by call
|
||||||
//~| NOTE: for more information, see
|
//~| NOTE: for more information, see
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_lint_with_unsafe_block() {
|
fn should_lint_with_unsafe_block() {
|
||||||
fn f(_: usize) {}
|
fn f(_: usize) {}
|
||||||
f(unsafe { String::new().as_str() }.len());
|
f(unsafe { String::new().as_str() }.len());
|
||||||
//~^ ERROR: a temporary value will be dropped here
|
//~^ ERROR: relative drop order changing
|
||||||
//~| WARN: this changes meaning in Rust 2024
|
//~| WARN: this changes meaning in Rust 2024
|
||||||
//~| NOTE: consider using a `let` binding
|
//~| NOTE: this temporary value will be dropped at the end of the block
|
||||||
|
//~| borrow later used by call
|
||||||
//~| NOTE: for more information, see
|
//~| NOTE: for more information, see
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,11 +29,23 @@ fn should_lint_with_big_block() {
|
||||||
fn f<T>(_: T) {}
|
fn f<T>(_: T) {}
|
||||||
f({
|
f({
|
||||||
&mut || 0
|
&mut || 0
|
||||||
//~^ ERROR: a temporary value will be dropped here
|
//~^ ERROR: relative drop order changing
|
||||||
//~| WARN: this changes meaning in Rust 2024
|
//~| WARN: this changes meaning in Rust 2024
|
||||||
//~| NOTE: consider using a `let` binding
|
//~| NOTE: this temporary value will be dropped at the end of the block
|
||||||
|
//~| borrow later used here
|
||||||
//~| NOTE: for more information, see
|
//~| NOTE: for more information, see
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn another_temp_that_is_copy_in_arg() {
|
||||||
|
fn f() {}
|
||||||
|
fn g(_: &()) {}
|
||||||
|
g({ &f() });
|
||||||
|
//~^ ERROR: relative drop order changing
|
||||||
|
//~| WARN: this changes meaning in Rust 2024
|
||||||
|
//~| NOTE: this temporary value will be dropped at the end of the block
|
||||||
|
//~| borrow later used by call
|
||||||
|
//~| NOTE: for more information, see
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
|
error: relative drop order changing in Rust 2024
|
||||||
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:36
|
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:15
|
||||||
|
|
|
|
||||||
LL | let _ = { String::new().as_str() }.len();
|
LL | let _ = { String::new().as_str() }.len();
|
||||||
| ------------- ^
|
| ^^^^^^^^^^^^^ --- borrow later used by call
|
||||||
| |
|
| |
|
||||||
| consider using a `let` binding to create a longer lived value; or replacing the `{ .. }` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe { .. }`
|
| this temporary value will be dropped at the end of the block
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||||
|
@ -14,27 +14,39 @@ note: the lint level is defined here
|
||||||
LL | #![deny(tail_expr_drop_order)]
|
LL | #![deny(tail_expr_drop_order)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
|
error: relative drop order changing in Rust 2024
|
||||||
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:18:37
|
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:19:16
|
||||||
|
|
|
|
||||||
LL | f(unsafe { String::new().as_str() }.len());
|
LL | f(unsafe { String::new().as_str() }.len());
|
||||||
| ------------- ^
|
| ^^^^^^^^^^^^^ --- borrow later used by call
|
||||||
| |
|
| |
|
||||||
| consider using a `let` binding to create a longer lived value; or replacing the `{ .. }` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe { .. }`
|
| this temporary value will be dropped at the end of the block
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||||
|
|
||||||
error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
|
error: relative drop order changing in Rust 2024
|
||||||
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:29:17
|
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:31:9
|
||||||
|
|
|
|
||||||
LL | &mut || 0
|
LL | &mut || 0
|
||||||
| --------^
|
| ^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| consider using a `let` binding to create a longer lived value; or replacing the `{ .. }` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe { .. }`
|
| this temporary value will be dropped at the end of the block
|
||||||
|
| borrow later used here
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: relative drop order changing in Rust 2024
|
||||||
|
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:43:9
|
||||||
|
|
|
||||||
|
LL | g({ &f() });
|
||||||
|
| - ^^^^ this temporary value will be dropped at the end of the block
|
||||||
|
| |
|
||||||
|
| borrow later used by call
|
||||||
|
|
|
||||||
|
= warning: this changes meaning in Rust 2024
|
||||||
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue