mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #110458 - matthiaskrgr:rollup-1xcxmgc, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #104055 (Migrate diagnostics in `rustc_borrowck`) - #110257 (fix false positives for `unused_parens` around unary and binary operations) - #110313 (allow `repr(align = x)` on inherent methods) - #110337 (Correct default value for default-linker-libraries) - #110386 (Clean up traversal macros) - #110394 (Various minor Idx-related tweaks) - #110425 (Encode def span for `ConstParam`) - #110434 (Check freeze with right param-env in `deduced_param_attrs`) - #110455 (tests: adapt for LLVM change 5b386b864c7619897c51a1da97d78f1cf6f3eff6) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
31656e7295
@ -461,8 +461,8 @@ pub trait LayoutCalculator {
|
||||
let all_indices = variants.indices();
|
||||
let needs_disc =
|
||||
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
|
||||
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
|
||||
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
|
||||
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
|
||||
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
|
||||
|
||||
let count = niche_variants.size_hint().1.unwrap() as u128;
|
||||
|
||||
@ -560,8 +560,7 @@ pub trait LayoutCalculator {
|
||||
tag: niche_scalar,
|
||||
tag_encoding: TagEncoding::Niche {
|
||||
untagged_variant: largest_variant_index,
|
||||
niche_variants: (VariantIdx::new(*niche_variants.start())
|
||||
..=VariantIdx::new(*niche_variants.end())),
|
||||
niche_variants,
|
||||
niche_start,
|
||||
},
|
||||
tag_field: 0,
|
||||
|
@ -11,7 +11,7 @@ use bitflags::bitflags;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::StableOrd;
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::HashStable_Generic;
|
||||
#[cfg(feature = "nightly")]
|
||||
|
@ -9,14 +9,14 @@ rustc_index::newtype_index! {
|
||||
///
|
||||
/// [`DefId`]: rustc_span::def_id::DefId
|
||||
#[debug_format = "NodeId({})"]
|
||||
pub struct NodeId {}
|
||||
pub struct NodeId {
|
||||
/// The [`NodeId`] used to represent the root of the crate.
|
||||
const CRATE_NODE_ID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
|
||||
|
||||
/// The [`NodeId`] used to represent the root of the crate.
|
||||
pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
|
||||
|
||||
/// When parsing and at the beginning of doing expansions, we initially give all AST nodes
|
||||
/// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them
|
||||
/// to have small, positive IDs.
|
||||
|
@ -56,18 +56,6 @@ borrowck_returned_lifetime_short =
|
||||
borrowck_used_impl_require_static =
|
||||
the used `impl` has a `'static` requirement
|
||||
|
||||
borrowck_capture_kind_label =
|
||||
capture is {$kind_desc} because of use here
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_generator =
|
||||
borrow occurs due to use of {$place} in closure in generator
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_closure =
|
||||
borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_borrow_by_use_place =
|
||||
borrow occurs due to use of {$place}
|
||||
|
||||
borrowck_borrow_due_to_use_generator =
|
||||
borrow occurs due to use in generator
|
||||
|
||||
@ -101,12 +89,63 @@ borrowck_capture_mut =
|
||||
borrowck_capture_move =
|
||||
capture is moved because of use here
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_generator =
|
||||
{$is_single_var ->
|
||||
*[true] borrow occurs
|
||||
[false] borrows occur
|
||||
} due to use of {$place} in generator
|
||||
|
||||
borrowck_var_borrow_by_use_place_in_closure =
|
||||
{$is_single_var ->
|
||||
*[true] borrow occurs
|
||||
[false] borrows occur
|
||||
} due to use of {$place} in closure
|
||||
|
||||
borrowck_var_borrow_by_use_in_generator =
|
||||
borrow occurs due to use in generator
|
||||
|
||||
borrowck_var_borrow_by_use_in_closure =
|
||||
borrow occurs due to use in closure
|
||||
|
||||
borrowck_var_move_by_use_place_in_generator =
|
||||
move occurs due to use of {$place} in generator
|
||||
|
||||
borrowck_var_move_by_use_place_in_closure =
|
||||
move occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_move_by_use_in_generator =
|
||||
move occurs due to use in generator
|
||||
|
||||
borrowck_var_move_by_use_in_closure =
|
||||
move occurs due to use in closure
|
||||
|
||||
borrowck_partial_var_move_by_use_in_generator =
|
||||
variable {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to use in generator
|
||||
|
||||
borrowck_partial_var_move_by_use_in_closure =
|
||||
variable {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to use in closure
|
||||
|
||||
borrowck_var_first_borrow_by_use_place_in_generator =
|
||||
first borrow occurs due to use of {$place} in generator
|
||||
|
||||
borrowck_var_first_borrow_by_use_place_in_closure =
|
||||
first borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_second_borrow_by_use_place_in_generator =
|
||||
second borrow occurs due to use of {$place} in generator
|
||||
|
||||
borrowck_var_second_borrow_by_use_place_in_closure =
|
||||
second borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_var_mutable_borrow_by_use_place_in_closure =
|
||||
mutable borrow occurs due to use of {$place} in closure
|
||||
|
||||
borrowck_cannot_move_when_borrowed =
|
||||
cannot move out of {$place ->
|
||||
[value] value
|
||||
@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param =
|
||||
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
*[other] this generic parameter must be used with a generic {$kind} parameter
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_call =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to this {$is_loop_message ->
|
||||
[true] call, in previous iteration of loop
|
||||
*[false] call
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_usage_in_operator =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to usage in {$is_loop_message ->
|
||||
[true] operator, in previous iteration of loop
|
||||
*[false] operator
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_implicit_into_iter_call =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to this implicit call to {$is_loop_message ->
|
||||
[true] `.into_iter()`, in previous iteration of loop
|
||||
*[false] `.into_iter()`
|
||||
}
|
||||
|
||||
borrowck_moved_due_to_method_call =
|
||||
{$place_name} {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} due to this method {$is_loop_message ->
|
||||
[true] call, in previous iteration of loop
|
||||
*[false] call
|
||||
}
|
||||
|
||||
borrowck_value_moved_here =
|
||||
value {$is_partial ->
|
||||
[true] partially moved
|
||||
*[false] moved
|
||||
} {$is_move_msg ->
|
||||
[true] into closure here
|
||||
*[false] here
|
||||
}{$is_loop_message ->
|
||||
[true] , in previous iteration of loop
|
||||
*[false] {""}
|
||||
}
|
||||
|
||||
borrowck_consider_borrow_type_contents =
|
||||
help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
|
||||
|
||||
borrowck_moved_a_fn_once_in_call =
|
||||
this value implements `FnOnce`, which causes it to be moved when called
|
||||
|
||||
borrowck_calling_operator_moves_lhs =
|
||||
calling this operator moves the left-hand side
|
||||
|
||||
borrowck_func_take_self_moved_place =
|
||||
`{$func}` takes ownership of the receiver `self`, which moves {$place_name}
|
||||
|
||||
borrowck_suggest_iterate_over_slice =
|
||||
consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
|
||||
|
||||
borrowck_suggest_create_freash_reborrow =
|
||||
consider reborrowing the `Pin` instead of moving it
|
||||
|
||||
borrowck_value_capture_here =
|
||||
value captured {$is_within ->
|
||||
[true] here by generator
|
||||
*[false] here
|
||||
}
|
||||
|
||||
borrowck_move_out_place_here =
|
||||
{$place} is moved here
|
||||
|
||||
borrowck_closure_invoked_twice =
|
||||
closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
|
||||
|
||||
borrowck_closure_moved_twice =
|
||||
closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
|
||||
|
||||
borrowck_ty_no_impl_copy =
|
||||
{$is_partial_move ->
|
||||
[true] partial move
|
||||
*[false] move
|
||||
} occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
|
||||
|
@ -30,8 +30,8 @@ use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
|
||||
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
|
||||
use crate::diagnostics::find_all_local_uses;
|
||||
use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
|
||||
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
|
||||
use crate::{
|
||||
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
||||
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
|
||||
@ -183,13 +183,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
|
||||
let move_span = move_spans.args_or_use();
|
||||
|
||||
let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
|
||||
let is_move_msg = move_spans.for_closure();
|
||||
|
||||
let loop_message = if location == move_out.source || move_site.traversed_back_edge {
|
||||
", in previous iteration of loop"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let is_loop_message = location == move_out.source || move_site.traversed_back_edge;
|
||||
|
||||
if location == move_out.source {
|
||||
is_loop_move = true;
|
||||
@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
let msg_opt = CapturedMessageOpt {
|
||||
is_partial_move,
|
||||
is_loop_message,
|
||||
is_move_msg,
|
||||
is_loop_move,
|
||||
maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
|
||||
.is_empty(),
|
||||
};
|
||||
self.explain_captures(
|
||||
&mut err,
|
||||
span,
|
||||
move_span,
|
||||
move_spans,
|
||||
*moved_place,
|
||||
partially_str,
|
||||
loop_message,
|
||||
move_msg,
|
||||
is_loop_move,
|
||||
maybe_reinitialized_locations.is_empty(),
|
||||
msg_opt,
|
||||
);
|
||||
}
|
||||
seen_spans.insert(move_span);
|
||||
@ -282,12 +282,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
if needs_note {
|
||||
let span = if let Some(local) = place.as_local() {
|
||||
Some(self.body.local_decls[local].source_info.span)
|
||||
if let Some(local) = place.as_local() {
|
||||
let span = self.body.local_decls[local].source_info.span;
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move,
|
||||
ty,
|
||||
place: ¬e_msg,
|
||||
span,
|
||||
});
|
||||
} else {
|
||||
None
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
|
||||
is_partial_move,
|
||||
ty,
|
||||
place: ¬e_msg,
|
||||
});
|
||||
};
|
||||
self.note_type_does_not_implement_copy(&mut err, ¬e_msg, ty, span, partial_str);
|
||||
}
|
||||
|
||||
if let UseSpans::FnSelfUse {
|
||||
@ -827,11 +836,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
|
||||
|
||||
move_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("move occurs due to use{}", move_spans.describe()),
|
||||
"moved",
|
||||
);
|
||||
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => MoveUseInGenerator { var_span },
|
||||
None => MoveUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
self.explain_why_borrow_contains_point(location, borrow, None)
|
||||
.add_explanation_to_diagnostic(
|
||||
@ -868,13 +879,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_span,
|
||||
&self.describe_any_place(borrow.borrowed_place.as_ref()),
|
||||
);
|
||||
borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
|
||||
borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
let place = &borrow.borrowed_place;
|
||||
let desc_place = self.describe_any_place(place.as_ref());
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
|
||||
None => BorrowUsePlaceClosure { place: desc_place, var_span },
|
||||
Some(_) => {
|
||||
BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true }
|
||||
}
|
||||
None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
|
||||
}
|
||||
});
|
||||
|
||||
@ -988,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
immutable_section_description,
|
||||
"mutably borrow",
|
||||
);
|
||||
borrow_spans.var_span_label(
|
||||
borrow_spans.var_subdiag(
|
||||
None,
|
||||
&mut err,
|
||||
format!(
|
||||
"borrow occurs due to use of {}{}",
|
||||
desc_place,
|
||||
borrow_spans.describe(),
|
||||
),
|
||||
"immutable",
|
||||
Some(BorrowKind::Unique),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceGenerator {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: true,
|
||||
},
|
||||
None => BorrowUsePlaceClosure {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return err;
|
||||
} else {
|
||||
first_borrow_desc = "immutable ";
|
||||
@ -1070,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
if issued_spans == borrow_spans {
|
||||
borrow_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),),
|
||||
gen_borrow_kind.describe_mutability(),
|
||||
);
|
||||
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceGenerator {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: false,
|
||||
},
|
||||
None => {
|
||||
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let borrow_place = &issued_borrow.borrowed_place;
|
||||
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
|
||||
issued_spans.var_span_label(
|
||||
issued_spans.var_subdiag(
|
||||
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
|
||||
&mut err,
|
||||
format!(
|
||||
"first borrow occurs due to use of {}{}",
|
||||
borrow_place_desc,
|
||||
issued_spans.describe(),
|
||||
),
|
||||
issued_borrow.kind.describe_mutability(),
|
||||
Some(issued_borrow.kind),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
let borrow_place = &issued_borrow.borrowed_place;
|
||||
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
|
||||
match kind {
|
||||
Some(_) => {
|
||||
FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span }
|
||||
}
|
||||
None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
borrow_spans.var_span_label(
|
||||
borrow_spans.var_subdiag(
|
||||
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
|
||||
&mut err,
|
||||
format!(
|
||||
"second borrow occurs due to use of {}{}",
|
||||
desc_place,
|
||||
borrow_spans.describe(),
|
||||
),
|
||||
gen_borrow_kind.describe_mutability(),
|
||||
Some(gen_borrow_kind),
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span },
|
||||
None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -1731,9 +1770,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
|
||||
|
||||
let within = if borrow_spans.for_generator() { " by generator" } else { "" };
|
||||
|
||||
borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
|
||||
borrow_spans.args_subdiag(&mut err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::Capture {
|
||||
is_within: borrow_spans.for_generator(),
|
||||
args_span,
|
||||
}
|
||||
});
|
||||
|
||||
explanation.add_explanation_to_diagnostic(
|
||||
self.infcx.tcx,
|
||||
@ -1947,9 +1989,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
None,
|
||||
);
|
||||
|
||||
let within = if borrow_spans.for_generator() { " by generator" } else { "" };
|
||||
|
||||
borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
|
||||
borrow_spans.args_subdiag(&mut err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::Capture {
|
||||
is_within: borrow_spans.for_generator(),
|
||||
args_span,
|
||||
}
|
||||
});
|
||||
|
||||
err
|
||||
}
|
||||
@ -2382,11 +2427,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
section,
|
||||
"assign",
|
||||
);
|
||||
loan_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("borrow occurs due to use{}", loan_spans.describe()),
|
||||
loan.kind.describe_mutability(),
|
||||
);
|
||||
|
||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUseInGenerator { var_span },
|
||||
None => BorrowUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
self.buffer_error(err);
|
||||
|
||||
@ -2396,11 +2444,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
|
||||
|
||||
loan_spans.var_span_label(
|
||||
&mut err,
|
||||
format!("borrow occurs due to use{}", loan_spans.describe()),
|
||||
loan.kind.describe_mutability(),
|
||||
);
|
||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUseInGenerator { var_span },
|
||||
None => BorrowUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
|
||||
self.infcx.tcx,
|
||||
|
@ -1,5 +1,9 @@
|
||||
//! Borrow checker diagnostics.
|
||||
|
||||
use crate::session_diagnostics::{
|
||||
CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
|
||||
CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.span_note(
|
||||
*span,
|
||||
&format!(
|
||||
"closure cannot be invoked more than once because it moves the \
|
||||
variable `{}` out of its environment",
|
||||
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
|
||||
),
|
||||
diag.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
OnClosureNote::InvokedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(
|
||||
self.infcx.tcx,
|
||||
hir_place,
|
||||
),
|
||||
span: *span,
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.span_note(
|
||||
*span,
|
||||
&format!(
|
||||
"closure cannot be moved more than once as it is not `Copy` due to \
|
||||
moving the variable `{}` out of its environment",
|
||||
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
|
||||
),
|
||||
diag.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
OnClosureNote::MovedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||
span: *span,
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a note that a type does not implement `Copy`
|
||||
pub(super) fn note_type_does_not_implement_copy(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
place_desc: &str,
|
||||
ty: Ty<'tcx>,
|
||||
span: Option<Span>,
|
||||
move_prefix: &str,
|
||||
) {
|
||||
let message = format!(
|
||||
"{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait",
|
||||
);
|
||||
if let Some(span) = span {
|
||||
err.span_label(span, message);
|
||||
} else {
|
||||
err.note(&message);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn borrowed_content_source(
|
||||
&self,
|
||||
deref_base: PlaceRef<'tcx>,
|
||||
@ -582,9 +568,13 @@ impl UseSpans<'_> {
|
||||
}
|
||||
|
||||
/// Add a span label to the arguments of the closure, if it exists.
|
||||
pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
|
||||
pub(super) fn args_subdiag(
|
||||
self,
|
||||
err: &mut Diagnostic,
|
||||
f: impl FnOnce(Span) -> CaptureArgLabel,
|
||||
) {
|
||||
if let UseSpans::ClosureUse { args_span, .. } = self {
|
||||
err.span_label(args_span, message);
|
||||
err.subdiagnostic(f(args_span));
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,8 +585,8 @@ impl UseSpans<'_> {
|
||||
err: &mut Diagnostic,
|
||||
action: crate::InitializationRequiringAction,
|
||||
) {
|
||||
use crate::session_diagnostics::CaptureVarPathUseCause::*;
|
||||
use crate::InitializationRequiringAction::*;
|
||||
use CaptureVarPathUseCause::*;
|
||||
if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
|
||||
match generator_kind {
|
||||
Some(_) => {
|
||||
@ -619,34 +609,14 @@ impl UseSpans<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a span label to the use of the captured variable, if it exists.
|
||||
pub(super) fn var_span_label(
|
||||
self,
|
||||
err: &mut Diagnostic,
|
||||
message: impl Into<String>,
|
||||
kind_desc: impl Into<String>,
|
||||
) {
|
||||
if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
|
||||
if capture_kind_span == path_span {
|
||||
err.span_label(capture_kind_span, message);
|
||||
} else {
|
||||
let capture_kind_label =
|
||||
format!("capture is {} because of use here", kind_desc.into());
|
||||
let path_label = message;
|
||||
err.span_label(capture_kind_span, capture_kind_label);
|
||||
err.span_label(path_span, path_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a subdiagnostic to the use of the captured variable, if it exists.
|
||||
pub(super) fn var_subdiag(
|
||||
self,
|
||||
handler: Option<&rustc_errors::Handler>,
|
||||
err: &mut Diagnostic,
|
||||
kind: Option<rustc_middle::mir::BorrowKind>,
|
||||
f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause,
|
||||
f: impl FnOnce(Option<GeneratorKind>, Span) -> CaptureVarCause,
|
||||
) {
|
||||
use crate::session_diagnostics::CaptureVarKind::*;
|
||||
if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self {
|
||||
if capture_kind_span != path_span {
|
||||
err.subdiagnostic(match kind {
|
||||
@ -654,17 +624,21 @@ impl UseSpans<'_> {
|
||||
rustc_middle::mir::BorrowKind::Shared
|
||||
| rustc_middle::mir::BorrowKind::Shallow
|
||||
| rustc_middle::mir::BorrowKind::Unique => {
|
||||
Immute { kind_span: capture_kind_span }
|
||||
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
||||
}
|
||||
|
||||
rustc_middle::mir::BorrowKind::Mut { .. } => {
|
||||
Mut { kind_span: capture_kind_span }
|
||||
CaptureVarKind::Mut { kind_span: capture_kind_span }
|
||||
}
|
||||
},
|
||||
None => Move { kind_span: capture_kind_span },
|
||||
None => CaptureVarKind::Move { kind_span: capture_kind_span },
|
||||
});
|
||||
};
|
||||
err.subdiagnostic(f(generator_kind, path_span));
|
||||
let diag = f(generator_kind, path_span);
|
||||
match handler {
|
||||
Some(hd) => err.eager_subdiagnostic(hd, diag),
|
||||
None => err.subdiagnostic(diag),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,20 +658,6 @@ impl UseSpans<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describe the span associated with a use of a place.
|
||||
pub(super) fn describe(&self) -> &str {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { generator_kind, .. } => {
|
||||
if generator_kind.is_some() {
|
||||
" in generator"
|
||||
} else {
|
||||
" in closure"
|
||||
}
|
||||
}
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn or_else<F>(self, if_other: F) -> Self
|
||||
where
|
||||
F: FnOnce() -> Self,
|
||||
@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
///helper struct for explain_captures()
|
||||
struct CapturedMessageOpt {
|
||||
is_partial_move: bool,
|
||||
is_loop_message: bool,
|
||||
is_move_msg: bool,
|
||||
is_loop_move: bool,
|
||||
maybe_reinitialized_locations_is_empty: bool,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// Finds the spans associated to a move or copy of move_place at location.
|
||||
pub(super) fn move_spans(
|
||||
@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_span: Span,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
moved_place: Place<'tcx>,
|
||||
partially_str: &str,
|
||||
loop_message: &str,
|
||||
move_msg: &str,
|
||||
is_loop_move: bool,
|
||||
maybe_reinitialized_locations_is_empty: bool,
|
||||
msg_opt: CapturedMessageOpt,
|
||||
) {
|
||||
let CapturedMessageOpt {
|
||||
is_partial_move: is_partial,
|
||||
is_loop_message,
|
||||
is_move_msg,
|
||||
is_loop_move,
|
||||
maybe_reinitialized_locations_is_empty,
|
||||
} = msg_opt;
|
||||
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
|
||||
let place_name = self
|
||||
.describe_place(moved_place.as_ref())
|
||||
@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
CallKind::FnCall { fn_trait_id, .. }
|
||||
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
|
||||
{
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::Call {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to this call{loop_message}",
|
||||
),
|
||||
);
|
||||
err.span_note(
|
||||
var_span,
|
||||
"this value implements `FnOnce`, which causes it to be moved when called",
|
||||
);
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
|
||||
}
|
||||
CallKind::Operator { self_arg, .. } => {
|
||||
let self_arg = self_arg.unwrap();
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::OperatorUse {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to usage in operator{loop_message}",
|
||||
),
|
||||
);
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
if self.fn_self_span_reported.insert(fn_span) {
|
||||
err.span_note(
|
||||
self_arg.span,
|
||||
"calling this operator moves the left-hand side",
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
|
||||
span: self_arg.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
|
||||
@ -1086,23 +1054,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
_ => false,
|
||||
};
|
||||
if suggest {
|
||||
err.span_suggestion_verbose(
|
||||
move_span.shrink_to_lo(),
|
||||
&format!(
|
||||
"consider iterating over a slice of the `{ty}`'s content to \
|
||||
avoid moving into the `for` loop",
|
||||
),
|
||||
"&",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
|
||||
ty,
|
||||
span: move_span.shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}",
|
||||
),
|
||||
);
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
// If the moved place was a `&mut` ref, then we can
|
||||
// suggest to reborrow it where it was moved, so it
|
||||
// will still be valid by the time we get to the usage.
|
||||
@ -1125,13 +1088,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_label(
|
||||
err.subdiagnostic(CaptureReasonLabel::MethodCall {
|
||||
fn_call_span,
|
||||
&format!(
|
||||
"{place_name} {partially_str}moved due to this method call{loop_message}",
|
||||
),
|
||||
);
|
||||
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
// Erase and shadow everything that could be passed to the new infcx.
|
||||
let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
|
||||
@ -1147,12 +1109,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
)
|
||||
&& infcx.can_eq(self.param_env, ty, self_ty)
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
fn_call_span.shrink_to_lo(),
|
||||
"consider reborrowing the `Pin` instead of moving it",
|
||||
"as_mut().".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.eager_subdiagnostic(
|
||||
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
|
||||
CaptureReasonSuggest::FreshReborrow {
|
||||
span: fn_call_span.shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
if let Some(clone_trait) = tcx.lang_items().clone_trait()
|
||||
&& let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
|
||||
@ -1177,10 +1138,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// error messages.
|
||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
||||
let func = tcx.def_path_str(method_did);
|
||||
err.span_note(
|
||||
self_arg.span,
|
||||
&format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
|
||||
func,
|
||||
place_name,
|
||||
span: self_arg.span,
|
||||
});
|
||||
}
|
||||
let parent_did = tcx.parent(method_did);
|
||||
let parent_self_ty =
|
||||
@ -1194,30 +1156,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
|
||||
});
|
||||
if is_option_or_result && maybe_reinitialized_locations_is_empty {
|
||||
err.span_label(
|
||||
var_span,
|
||||
"help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
|
||||
);
|
||||
err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
|
||||
}
|
||||
}
|
||||
// Other desugarings takes &self, which cannot cause a move
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
if move_span != span || !loop_message.is_empty() {
|
||||
err.span_label(
|
||||
if move_span != span || is_loop_message {
|
||||
err.subdiagnostic(CaptureReasonLabel::MovedHere {
|
||||
move_span,
|
||||
format!("value {partially_str}moved{move_msg} here{loop_message}"),
|
||||
);
|
||||
is_partial,
|
||||
is_move_msg,
|
||||
is_loop_message,
|
||||
});
|
||||
}
|
||||
// If the move error occurs due to a loop, don't show
|
||||
// another message for the same span
|
||||
if loop_message.is_empty() {
|
||||
move_spans.var_span_label(
|
||||
err,
|
||||
format!("variable {partially_str}moved due to use{}", move_spans.describe()),
|
||||
"moved",
|
||||
);
|
||||
if !is_loop_message {
|
||||
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
|
||||
Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial },
|
||||
None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{
|
||||
};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use crate::diagnostics::CapturedMessageOpt;
|
||||
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
|
||||
use crate::prefixes::PrefixSet;
|
||||
use crate::MirBorrowckCtxt;
|
||||
@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
};
|
||||
let msg_opt = CapturedMessageOpt {
|
||||
is_partial_move: false,
|
||||
is_loop_message: false,
|
||||
is_move_msg: false,
|
||||
is_loop_move: false,
|
||||
maybe_reinitialized_locations_is_empty: true,
|
||||
};
|
||||
if let Some(use_spans) = use_spans {
|
||||
self.explain_captures(
|
||||
&mut err, span, span, use_spans, move_place, "", "", "", false, true,
|
||||
);
|
||||
self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt);
|
||||
}
|
||||
err
|
||||
}
|
||||
@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
None => "value".to_string(),
|
||||
};
|
||||
|
||||
self.note_type_does_not_implement_copy(
|
||||
err,
|
||||
&place_desc,
|
||||
place_ty,
|
||||
Some(span),
|
||||
"",
|
||||
);
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: place_ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
} else {
|
||||
binds_to.sort();
|
||||
binds_to.dedup();
|
||||
@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
Some(desc) => format!("`{desc}`"),
|
||||
None => "value".to_string(),
|
||||
};
|
||||
self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: place_ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
|
||||
use_spans.args_span_label(err, format!("{place_desc} is moved here"));
|
||||
use_spans.args_subdiag(err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
|
||||
place: place_desc,
|
||||
args_span,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if binds_to.len() == 1 {
|
||||
self.note_type_does_not_implement_copy(
|
||||
err,
|
||||
&format!("`{}`", self.local_names[*local].unwrap()),
|
||||
bind_to.ty,
|
||||
Some(binding_span),
|
||||
"",
|
||||
);
|
||||
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: bind_to.ty,
|
||||
place: &place_desc,
|
||||
span: binding_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,14 +231,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
if suggest {
|
||||
borrow_spans.var_span_label(
|
||||
&mut err,
|
||||
format!(
|
||||
"mutable borrow occurs due to use of {} in closure",
|
||||
self.describe_any_place(access_place.as_ref()),
|
||||
),
|
||||
"mutable",
|
||||
);
|
||||
borrow_spans.var_subdiag(
|
||||
None,
|
||||
&mut err,
|
||||
Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
|
||||
|_kind, var_span| {
|
||||
let place = self.describe_any_place(access_place.as_ref());
|
||||
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
|
||||
place,
|
||||
var_span,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
borrow_span
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use crate::region_infer::RegionInferenceContext;
|
||||
use crate::Upvar;
|
||||
use rustc_index::vec::{Idx, IndexSlice};
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
argument_index: usize,
|
||||
) -> (Option<Symbol>, Span) {
|
||||
let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
|
||||
let argument_local = Local::new(implicit_inputs + argument_index + 1);
|
||||
let argument_local = Local::from_usize(implicit_inputs + argument_index + 1);
|
||||
debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}");
|
||||
|
||||
let argument_name = local_names[argument_local];
|
||||
|
@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable};
|
||||
use crate::BorrowIndex;
|
||||
use polonius_engine::AllFacts as PoloniusFacts;
|
||||
use polonius_engine::Atom;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir::Local;
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::MovePathIndex;
|
||||
@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts {
|
||||
|
||||
impl Atom for BorrowIndex {
|
||||
fn index(self) -> usize {
|
||||
Idx::index(self)
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl Atom for LocationIndex {
|
||||
fn index(self) -> usize {
|
||||
Idx::index(self)
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::mir::{BasicBlock, Body, Location};
|
||||
|
||||
/// Maps between a MIR Location, which identifies a particular
|
||||
@ -50,19 +50,19 @@ impl LocationTable {
|
||||
}
|
||||
|
||||
pub fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
|
||||
(0..self.num_points).map(LocationIndex::new)
|
||||
(0..self.num_points).map(LocationIndex::from_usize)
|
||||
}
|
||||
|
||||
pub fn start_index(&self, location: Location) -> LocationIndex {
|
||||
let Location { block, statement_index } = location;
|
||||
let start_index = self.statements_before_block[block];
|
||||
LocationIndex::new(start_index + statement_index * 2)
|
||||
LocationIndex::from_usize(start_index + statement_index * 2)
|
||||
}
|
||||
|
||||
pub fn mid_index(&self, location: Location) -> LocationIndex {
|
||||
let Location { block, statement_index } = location;
|
||||
let start_index = self.statements_before_block[block];
|
||||
LocationIndex::new(start_index + statement_index * 2 + 1)
|
||||
LocationIndex::from_usize(start_index + statement_index * 2 + 1)
|
||||
}
|
||||
|
||||
pub fn to_location(&self, index: LocationIndex) -> RichLocation {
|
||||
|
@ -7,8 +7,8 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
||||
Promoted,
|
||||
Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
|
||||
START_BLOCK,
|
||||
};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
@ -94,8 +94,8 @@ fn populate_polonius_move_facts(
|
||||
}
|
||||
}
|
||||
|
||||
let fn_entry_start = location_table
|
||||
.start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 });
|
||||
let fn_entry_start =
|
||||
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
|
||||
|
||||
// initialized_at
|
||||
for init in move_data.inits.iter() {
|
||||
|
@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause {
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureVarKind {
|
||||
#[label(borrowck_capture_immute)]
|
||||
Immute {
|
||||
Immut {
|
||||
#[primary_span]
|
||||
kind_span: Span,
|
||||
},
|
||||
@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind {
|
||||
pub(crate) enum CaptureVarCause {
|
||||
#[label(borrowck_var_borrow_by_use_place_in_generator)]
|
||||
BorrowUsePlaceGenerator {
|
||||
is_single_var: bool,
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_place_in_closure)]
|
||||
BorrowUsePlaceClosure {
|
||||
is_single_var: bool,
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_in_generator)]
|
||||
BorrowUseInGenerator {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_borrow_by_use_in_closure)]
|
||||
BorrowUseInClosure {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_move_by_use_in_generator)]
|
||||
MoveUseInGenerator {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_move_by_use_in_closure)]
|
||||
MoveUseInClosure {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_first_borrow_by_use_place_in_generator)]
|
||||
FirstBorrowUsePlaceGenerator {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_first_borrow_by_use_place_in_closure)]
|
||||
FirstBorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_second_borrow_by_use_place_in_generator)]
|
||||
SecondBorrowUsePlaceGenerator {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_second_borrow_by_use_place_in_closure)]
|
||||
SecondBorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_var_mutable_borrow_by_use_place_in_closure)]
|
||||
MutableBorrowUsePlaceClosure {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[label(borrowck_partial_var_move_by_use_in_generator)]
|
||||
PartialMoveUseInGenerator {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
is_partial: bool,
|
||||
},
|
||||
#[label(borrowck_partial_var_move_by_use_in_closure)]
|
||||
PartialMoveUseInClosure {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
is_partial: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
||||
#[label]
|
||||
pub param_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonLabel<'a> {
|
||||
#[label(borrowck_moved_due_to_call)]
|
||||
Call {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_moved_due_to_usage_in_operator)]
|
||||
OperatorUse {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_moved_due_to_implicit_into_iter_call)]
|
||||
ImplicitCall {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_moved_due_to_method_call)]
|
||||
MethodCall {
|
||||
#[primary_span]
|
||||
fn_call_span: Span,
|
||||
place_name: &'a str,
|
||||
is_partial: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_value_moved_here)]
|
||||
MovedHere {
|
||||
#[primary_span]
|
||||
move_span: Span,
|
||||
is_partial: bool,
|
||||
is_move_msg: bool,
|
||||
is_loop_message: bool,
|
||||
},
|
||||
#[label(borrowck_consider_borrow_type_contents)]
|
||||
BorrowContent {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonNote {
|
||||
#[note(borrowck_moved_a_fn_once_in_call)]
|
||||
FnOnceMoveInCall {
|
||||
#[primary_span]
|
||||
var_span: Span,
|
||||
},
|
||||
#[note(borrowck_calling_operator_moves_lhs)]
|
||||
LhsMoveByOperator {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_func_take_self_moved_place)]
|
||||
FuncTakeSelf {
|
||||
func: String,
|
||||
place_name: String,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureReasonSuggest<'tcx> {
|
||||
#[suggestion(
|
||||
borrowck_suggest_iterate_over_slice,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "&",
|
||||
style = "verbose"
|
||||
)]
|
||||
IterateSlice {
|
||||
ty: Ty<'tcx>,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[suggestion(
|
||||
borrowck_suggest_create_freash_reborrow,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "as_mut().",
|
||||
style = "verbose"
|
||||
)]
|
||||
FreshReborrow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum CaptureArgLabel {
|
||||
#[label(borrowck_value_capture_here)]
|
||||
Capture {
|
||||
is_within: bool,
|
||||
#[primary_span]
|
||||
args_span: Span,
|
||||
},
|
||||
#[label(borrowck_move_out_place_here)]
|
||||
MoveOutPlace {
|
||||
place: String,
|
||||
#[primary_span]
|
||||
args_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum OnClosureNote<'a> {
|
||||
#[note(borrowck_closure_invoked_twice)]
|
||||
InvokedTwice {
|
||||
place_name: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_closure_moved_twice)]
|
||||
MovedTwice {
|
||||
place_name: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum TypeNoCopy<'a, 'tcx> {
|
||||
#[label(borrowck_ty_no_impl_copy)]
|
||||
Label {
|
||||
is_partial_move: bool,
|
||||
ty: Ty<'tcx>,
|
||||
place: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_ty_no_impl_copy)]
|
||||
Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
||||
//! contain revealed `impl Trait` values).
|
||||
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// In MIR, argument N is stored in local N+1.
|
||||
let local = Local::new(argument_index + 1);
|
||||
let local = Local::from_usize(argument_index + 1);
|
||||
|
||||
let mir_input_ty = body.local_decls[local].ty;
|
||||
|
||||
|
@ -19,7 +19,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::BodyOwnerKind;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
|
||||
@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
/// Returns an iterator over all the RegionVids corresponding to
|
||||
/// universally quantified free regions.
|
||||
pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
|
||||
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
|
||||
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
|
||||
}
|
||||
|
||||
/// Returns `true` if `r` is classified as an local region.
|
||||
|
@ -12,7 +12,6 @@ use crate::MemFlags;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
@ -369,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
if self.fn_abi.c_variadic {
|
||||
// The `VaList` "spoofed" argument is just after all the real arguments.
|
||||
let va_list_arg_idx = self.fn_abi.args.len();
|
||||
match self.locals[mir::Local::new(1 + va_list_arg_idx)] {
|
||||
match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] {
|
||||
LocalRef::Place(va_list) => {
|
||||
bx.va_end(va_list.llval);
|
||||
}
|
||||
|
@ -211,18 +211,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let variant_index_relative = u32::try_from(variant_index_relative)
|
||||
.expect("we checked that this fits into a u32");
|
||||
// Then computing the absolute variant idx should not overflow any more.
|
||||
let variant_index = variants_start
|
||||
.checked_add(variant_index_relative)
|
||||
.expect("overflow computing absolute variant idx");
|
||||
let variants_len = op
|
||||
let variant_index = VariantIdx::from_u32(
|
||||
variants_start
|
||||
.checked_add(variant_index_relative)
|
||||
.expect("overflow computing absolute variant idx"),
|
||||
);
|
||||
let variants = op
|
||||
.layout
|
||||
.ty
|
||||
.ty_adt_def()
|
||||
.expect("tagged layout for non adt")
|
||||
.variants()
|
||||
.len();
|
||||
assert!(usize::try_from(variant_index).unwrap() < variants_len);
|
||||
VariantIdx::from_u32(variant_index)
|
||||
.variants();
|
||||
assert!(variant_index < variants.next_index());
|
||||
variant_index
|
||||
} else {
|
||||
untagged_variant
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::ObligationCause;
|
||||
|
||||
@ -875,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
variant.fields.len() == 1
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[FieldIdx::from_u32(0)];
|
||||
let sole_field = &variant.single_field();
|
||||
|
||||
let field_is_local = sole_field.did.is_local();
|
||||
let field_is_accessible =
|
||||
|
@ -4,7 +4,7 @@ use rustc_hir as hir;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_target::abi::{FieldIdx, Pointer, VariantIdx};
|
||||
use rustc_target::abi::{Pointer, VariantIdx};
|
||||
|
||||
use super::FnCtxt;
|
||||
|
||||
@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
}
|
||||
|
||||
if def.variant(data_idx).fields.len() == 1 {
|
||||
return def.variant(data_idx).fields[FieldIdx::from_u32(0)].ty(tcx, substs);
|
||||
return def.variant(data_idx).single_field().ty(tcx, substs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@ use rustc_middle::traits::{
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
|
||||
use crate::errors::{
|
||||
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
|
||||
@ -114,7 +113,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[FieldIdx::from_u32(0)];
|
||||
let sole_field = &variant.single_field();
|
||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||
if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
|
||||
let variant_path =
|
||||
|
@ -569,36 +569,50 @@ trait UnusedDelimLint {
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
|
||||
let lhs_needs_parens = {
|
||||
// Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
|
||||
{
|
||||
let mut innermost = inner;
|
||||
loop {
|
||||
innermost = match &innermost.kind {
|
||||
ExprKind::Binary(_, lhs, _rhs) => lhs,
|
||||
ExprKind::Binary(_op, lhs, _rhs) => lhs,
|
||||
ExprKind::Call(fn_, _params) => fn_,
|
||||
ExprKind::Cast(expr, _ty) => expr,
|
||||
ExprKind::Type(expr, _ty) => expr,
|
||||
ExprKind::Index(base, _subscript) => base,
|
||||
_ => break false,
|
||||
_ => break,
|
||||
};
|
||||
if !classify::expr_requires_semi_to_be_stmt(innermost) {
|
||||
break true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
lhs_needs_parens
|
||||
|| (followed_by_block
|
||||
&& match &inner.kind {
|
||||
ExprKind::Ret(_)
|
||||
| ExprKind::Break(..)
|
||||
| ExprKind::Yield(..)
|
||||
| ExprKind::Yeet(..) => true,
|
||||
ExprKind::Range(_lhs, Some(rhs), _limits) => {
|
||||
matches!(rhs.kind, ExprKind::Block(..))
|
||||
}
|
||||
_ => parser::contains_exterior_struct_lit(&inner),
|
||||
})
|
||||
// Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`.
|
||||
if !followed_by_block {
|
||||
return false;
|
||||
}
|
||||
let mut innermost = inner;
|
||||
loop {
|
||||
innermost = match &innermost.kind {
|
||||
ExprKind::Unary(_op, expr) => expr,
|
||||
ExprKind::Binary(_op, _lhs, rhs) => rhs,
|
||||
ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
|
||||
ExprKind::Assign(_lhs, rhs, _span) => rhs,
|
||||
|
||||
ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,
|
||||
|
||||
ExprKind::Break(_label, None) => return false,
|
||||
ExprKind::Break(_label, Some(break_expr)) => {
|
||||
return matches!(break_expr.kind, ExprKind::Block(..));
|
||||
}
|
||||
|
||||
ExprKind::Range(_lhs, Some(rhs), _limits) => {
|
||||
return matches!(rhs.kind, ExprKind::Block(..));
|
||||
}
|
||||
|
||||
_ => return parser::contains_exterior_struct_lit(&inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_unused_delims_expr(
|
||||
|
@ -823,6 +823,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::TyParam
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Fn
|
||||
| DefKind::Const
|
||||
| DefKind::Static(_)
|
||||
@ -837,8 +838,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::Closure
|
||||
| DefKind::Generator => true,
|
||||
DefKind::ConstParam
|
||||
| DefKind::ExternCrate
|
||||
DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::ImplTraitPlaceholder
|
||||
|
@ -392,10 +392,8 @@ pub type QueryOutlivesConstraint<'tcx> =
|
||||
(ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
|
||||
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
for <'tcx> {
|
||||
crate::infer::canonical::Certainty,
|
||||
crate::infer::canonical::CanonicalTyVarKind,
|
||||
}
|
||||
crate::infer::canonical::Certainty,
|
||||
crate::infer::canonical::CanonicalTyVarKind,
|
||||
}
|
||||
|
||||
impl<'tcx> CanonicalVarValues<'tcx> {
|
||||
|
@ -43,34 +43,26 @@ macro_rules! span_bug {
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! CloneLiftImpls {
|
||||
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
|
||||
($($ty:ty,)+) => {
|
||||
$(
|
||||
impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
|
||||
impl<'tcx> $crate::ty::Lift<'tcx> for $ty {
|
||||
type Lifted = Self;
|
||||
fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option<Self> {
|
||||
fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
|
||||
($($ty:ty,)+) => {
|
||||
CloneLiftImpls! {
|
||||
for <'tcx> {
|
||||
$($ty,)+
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Used for types that are `Copy` and which **do not care arena
|
||||
/// allocated data** (i.e., don't need to be folded).
|
||||
#[macro_export]
|
||||
macro_rules! TrivialTypeTraversalImpls {
|
||||
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
|
||||
($($ty:ty,)+) => {
|
||||
$(
|
||||
impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty {
|
||||
fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<$tcx>>>(
|
||||
impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty {
|
||||
fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_: &mut F,
|
||||
) -> ::std::result::Result<Self, F::Error> {
|
||||
@ -78,7 +70,7 @@ macro_rules! TrivialTypeTraversalImpls {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<$tcx>>>(
|
||||
fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_: &mut F,
|
||||
) -> Self {
|
||||
@ -86,9 +78,9 @@ macro_rules! TrivialTypeTraversalImpls {
|
||||
}
|
||||
}
|
||||
|
||||
impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty {
|
||||
impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty {
|
||||
#[inline]
|
||||
fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<$tcx>>>(
|
||||
fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
_: &mut F)
|
||||
-> ::std::ops::ControlFlow<F::BreakTy>
|
||||
@ -98,14 +90,6 @@ macro_rules! TrivialTypeTraversalImpls {
|
||||
}
|
||||
)+
|
||||
};
|
||||
|
||||
($($ty:ty,)+) => {
|
||||
TrivialTypeTraversalImpls! {
|
||||
for<'tcx> {
|
||||
$($ty,)+
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -714,9 +714,7 @@ pub enum BindingForm<'tcx> {
|
||||
}
|
||||
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
for<'tcx> {
|
||||
BindingForm<'tcx>,
|
||||
}
|
||||
BindingForm<'tcx>,
|
||||
}
|
||||
|
||||
mod binding_form_impl {
|
||||
|
@ -25,9 +25,7 @@ TrivialTypeTraversalAndLiftImpls! {
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! {
|
||||
for <'tcx> {
|
||||
ConstValue<'tcx>,
|
||||
}
|
||||
ConstValue<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
|
||||
|
@ -1329,9 +1329,12 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
|
||||
// This is the impl for `&'a InternalSubsts<'a>`.
|
||||
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
|
||||
|
||||
CloneLiftImpls! { for<'tcx> {
|
||||
Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
|
||||
} }
|
||||
CloneLiftImpls! {
|
||||
Constness,
|
||||
traits::WellFormedLoc,
|
||||
ImplPolarity,
|
||||
crate::mir::ReturnConstraint,
|
||||
}
|
||||
|
||||
macro_rules! sty_debug_print {
|
||||
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
|
||||
|
@ -1963,6 +1963,16 @@ impl VariantDef {
|
||||
pub fn ctor_def_id(&self) -> Option<DefId> {
|
||||
self.ctor.map(|(_, def_id)| def_id)
|
||||
}
|
||||
|
||||
/// Returns the one field in this variant.
|
||||
///
|
||||
/// `panic!`s if there are no fields or multiple fields.
|
||||
#[inline]
|
||||
pub fn single_field(&self) -> &FieldDef {
|
||||
assert!(self.fields.len() == 1);
|
||||
|
||||
&self.fields[FieldIdx::from_u32(0)]
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for VariantDef {
|
||||
|
@ -276,9 +276,7 @@ TrivialTypeTraversalAndLiftImpls! {
|
||||
}
|
||||
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
for<'tcx> {
|
||||
ty::ValTree<'tcx>,
|
||||
}
|
||||
ty::ValTree<'tcx>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
|
||||
use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt};
|
||||
use rustc_session::config::OptLevel;
|
||||
|
||||
/// A visitor that determines which arguments have been mutated. We can't use the mutability field
|
||||
@ -198,11 +198,12 @@ pub fn deduced_param_attrs<'tcx>(
|
||||
// see [1].
|
||||
//
|
||||
// [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
|
||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||
let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
|
||||
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|
||||
|(arg_index, local_decl)| DeducedParamAttrs {
|
||||
read_only: !deduce_read_only.mutable_args.contains(arg_index)
|
||||
&& local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
|
||||
&& local_decl.ty.is_freeze(tcx, param_env),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -627,9 +627,9 @@ passes_attr_application_struct_enum_union =
|
||||
attribute should be applied to a struct, enum, or union
|
||||
.label = not a struct, enum, or union
|
||||
|
||||
passes_attr_application_struct_enum_function_union =
|
||||
attribute should be applied to a struct, enum, function, or union
|
||||
.label = not a struct, enum, function, or union
|
||||
passes_attr_application_struct_enum_function_method_union =
|
||||
attribute should be applied to a struct, enum, function, associated function, or union
|
||||
.label = not a struct, enum, function, associated function, or union
|
||||
|
||||
passes_transparent_incompatible =
|
||||
transparent {$target} cannot have other repr hints
|
||||
|
@ -1728,7 +1728,9 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
}
|
||||
sym::align => {
|
||||
if let (Target::Fn, false) = (target, self.tcx.features().fn_align) {
|
||||
if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
|
||||
(target, self.tcx.features().fn_align)
|
||||
{
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::fn_align,
|
||||
@ -1739,10 +1741,14 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
|
||||
match target {
|
||||
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
|
||||
Target::Struct
|
||||
| Target::Union
|
||||
| Target::Enum
|
||||
| Target::Fn
|
||||
| Target::Method(_) => continue,
|
||||
_ => {
|
||||
self.tcx.sess.emit_err(
|
||||
errors::AttrApplication::StructEnumFunctionUnion {
|
||||
errors::AttrApplication::StructEnumFunctionMethodUnion {
|
||||
hint_span: hint.span(),
|
||||
span,
|
||||
},
|
||||
|
@ -1355,8 +1355,8 @@ pub enum AttrApplication {
|
||||
#[label]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
|
||||
StructEnumFunctionUnion {
|
||||
#[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")]
|
||||
StructEnumFunctionMethodUnion {
|
||||
#[primary_span]
|
||||
hint_span: Span,
|
||||
#[label]
|
||||
|
@ -24,10 +24,7 @@ impl<K: DepKind> DepGraphQuery<K> {
|
||||
|
||||
pub fn push(&mut self, index: DepNodeIndex, node: DepNode<K>, edges: &[DepNodeIndex]) {
|
||||
let source = self.graph.add_node(node);
|
||||
if index.index() >= self.dep_index_to_index.len() {
|
||||
self.dep_index_to_index.resize(index.index() + 1, None);
|
||||
}
|
||||
self.dep_index_to_index[index] = Some(source);
|
||||
self.dep_index_to_index.insert(index, source);
|
||||
self.indices.insert(node, source);
|
||||
|
||||
for &target in edges.iter() {
|
||||
|
@ -11,12 +11,13 @@
|
||||
use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
|
||||
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
|
||||
use crate::solve::{CanonicalResponse, QueryResult, Response};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||
use rustc_middle::ty::{self, GenericArgKind};
|
||||
use rustc_middle::ty::{self, BoundVar, GenericArgKind};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
@ -139,25 +140,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
//
|
||||
// We therefore instantiate the existential variable in the canonical response with the
|
||||
// inference variable of the input right away, which is more performant.
|
||||
let mut opt_values = vec![None; response.variables.len()];
|
||||
let mut opt_values = IndexVec::from_elem_n(None, response.variables.len());
|
||||
for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
|
||||
match result_value.unpack() {
|
||||
GenericArgKind::Type(t) => {
|
||||
if let &ty::Bound(debruijn, b) = t.kind() {
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b.var.index()] = Some(*original_value);
|
||||
opt_values[b.var] = Some(*original_value);
|
||||
}
|
||||
}
|
||||
GenericArgKind::Lifetime(r) => {
|
||||
if let ty::ReLateBound(debruijn, br) = *r {
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[br.var.index()] = Some(*original_value);
|
||||
opt_values[br.var] = Some(*original_value);
|
||||
}
|
||||
}
|
||||
GenericArgKind::Const(c) => {
|
||||
if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
|
||||
assert_eq!(debrujin, ty::INNERMOST);
|
||||
opt_values[b.index()] = Some(*original_value);
|
||||
opt_values[b] = Some(*original_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -180,7 +181,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
// more placeholders then they should be able to. However the inference variables have
|
||||
// to "come from somewhere", so by equating them with the original values of the caller
|
||||
// later on, we pull them down into their correct universe again.
|
||||
if let Some(v) = opt_values[index] {
|
||||
if let Some(v) = opt_values[BoundVar::from_usize(index)] {
|
||||
v
|
||||
} else {
|
||||
self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
|
||||
|
@ -33,144 +33,3 @@ macro_rules! TrivialTypeTraversalImpls {
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! EnumTypeTraversalImpl {
|
||||
(impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
|
||||
$($variants:tt)*
|
||||
} $(where $($wc:tt)*)*) => {
|
||||
impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s
|
||||
$(where $($wc)*)*
|
||||
{
|
||||
fn try_fold_with<V: $crate::fold::FallibleTypeFolder<$tcx>>(
|
||||
self,
|
||||
folder: &mut V,
|
||||
) -> ::std::result::Result<Self, V::Error> {
|
||||
EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
|
||||
$($variants:tt)*
|
||||
} $(where $($wc:tt)*)*) => {
|
||||
impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s
|
||||
$(where $($wc)*)*
|
||||
{
|
||||
fn visit_with<V: $crate::visit::TypeVisitor<$tcx>>(
|
||||
&self,
|
||||
visitor: &mut V,
|
||||
) -> ::std::ops::ControlFlow<V::BreakTy> {
|
||||
EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
|
||||
Ok(match $this {
|
||||
$($output)*
|
||||
})
|
||||
};
|
||||
|
||||
(@FoldVariants($this:expr, $folder:expr)
|
||||
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
|
||||
output( $($output:tt)*) ) => {
|
||||
EnumTypeTraversalImpl!(
|
||||
@FoldVariants($this, $folder)
|
||||
input($($input)*)
|
||||
output(
|
||||
$variant ( $($variant_arg),* ) => {
|
||||
$variant (
|
||||
$($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
|
||||
)
|
||||
}
|
||||
$($output)*
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
(@FoldVariants($this:expr, $folder:expr)
|
||||
input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
|
||||
output( $($output:tt)*) ) => {
|
||||
EnumTypeTraversalImpl!(
|
||||
@FoldVariants($this, $folder)
|
||||
input($($input)*)
|
||||
output(
|
||||
$variant { $($variant_arg),* } => {
|
||||
$variant {
|
||||
$($variant_arg: $crate::fold::TypeFoldable::fold_with(
|
||||
$variant_arg, $folder
|
||||
)?),* }
|
||||
}
|
||||
$($output)*
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
(@FoldVariants($this:expr, $folder:expr)
|
||||
input( ($variant:path), $($input:tt)*)
|
||||
output( $($output:tt)*) ) => {
|
||||
EnumTypeTraversalImpl!(
|
||||
@FoldVariants($this, $folder)
|
||||
input($($input)*)
|
||||
output(
|
||||
$variant => { $variant }
|
||||
$($output)*
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
(@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
|
||||
match $this {
|
||||
$($output)*
|
||||
}
|
||||
};
|
||||
|
||||
(@VisitVariants($this:expr, $visitor:expr)
|
||||
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
|
||||
output( $($output:tt)*) ) => {
|
||||
EnumTypeTraversalImpl!(
|
||||
@VisitVariants($this, $visitor)
|
||||
input($($input)*)
|
||||
output(
|
||||
$variant ( $($variant_arg),* ) => {
|
||||
$($crate::visit::TypeVisitable::visit_with(
|
||||
$variant_arg, $visitor
|
||||
)?;)*
|
||||
::std::ops::ControlFlow::Continue(())
|
||||
}
|
||||
$($output)*
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
(@VisitVariants($this:expr, $visitor:expr)
|
||||
input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
|
||||
output( $($output:tt)*) ) => {
|
||||
EnumTypeTraversalImpl!(
|
||||
@VisitVariants($this, $visitor)
|
||||
input($($input)*)
|
||||
output(
|
||||
$variant { $($variant_arg),* } => {
|
||||
$($crate::visit::TypeVisitable::visit_with(
|
||||
$variant_arg, $visitor
|
||||
)?;)*
|
||||
::std::ops::ControlFlow::Continue(())
|
||||
}
|
||||
$($output)*
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
(@VisitVariants($this:expr, $visitor:expr)
|
||||
input( ($variant:path), $($input:tt)*)
|
||||
output( $($output:tt)*) ) => {
|
||||
EnumTypeTraversalImpl!(
|
||||
@VisitVariants($this, $visitor)
|
||||
input($($input)*)
|
||||
output(
|
||||
$variant => { ::std::ops::ControlFlow::Continue(()) }
|
||||
$($output)*
|
||||
)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -70,30 +70,40 @@ impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>>
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T> TypeFoldable<I> for Option<T> {
|
||||
(Some)(a),
|
||||
(None),
|
||||
} where I: Interner, T: TypeFoldable<I>
|
||||
}
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T> TypeVisitable<I> for Option<T> {
|
||||
(Some)(a),
|
||||
(None),
|
||||
} where I: Interner, T: TypeVisitable<I>
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
Some(v) => Some(v.try_fold_with(folder)?),
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T, E> TypeFoldable<I> for Result<T, E> {
|
||||
(Ok)(a),
|
||||
(Err)(a),
|
||||
} where I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>,
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match self {
|
||||
Some(v) => v.visit_with(visitor),
|
||||
None => ControlFlow::Continue(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T, E> TypeVisitable<I> for Result<T, E> {
|
||||
(Ok)(a),
|
||||
(Err)(a),
|
||||
} where I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>,
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
Ok(v) => Ok(v.try_fold_with(folder)?),
|
||||
Err(e) => Err(e.try_fold_with(folder)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match self {
|
||||
Ok(v) => v.visit_with(visitor),
|
||||
Err(e) => e.visit_with(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Rc<T> {
|
||||
|
@ -84,8 +84,8 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`.
|
||||
This flag controls whether or not the linker includes its default libraries.
|
||||
It takes one of the following values:
|
||||
|
||||
* `y`, `yes`, `on`, `true` or no value: include default libraries (the default).
|
||||
* `n`, `no`, `off` or `false`: exclude default libraries.
|
||||
* `y`, `yes`, `on`, `true`: include default libraries.
|
||||
* `n`, `no`, `off` or `false` or no value: exclude default libraries (the default).
|
||||
|
||||
For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
|
||||
the linker.
|
||||
|
@ -7,3 +7,43 @@
|
||||
#[no_mangle]
|
||||
#[repr(align(16))]
|
||||
pub fn fn_align() {}
|
||||
|
||||
pub struct A;
|
||||
|
||||
impl A {
|
||||
// CHECK: align 16
|
||||
#[no_mangle]
|
||||
#[repr(align(16))]
|
||||
pub fn method_align(self) {}
|
||||
|
||||
// CHECK: align 16
|
||||
#[no_mangle]
|
||||
#[repr(align(16))]
|
||||
pub fn associated_fn() {}
|
||||
}
|
||||
|
||||
trait T: Sized {
|
||||
fn trait_fn() {}
|
||||
|
||||
// CHECK: align 32
|
||||
#[repr(align(32))]
|
||||
fn trait_method(self) {}
|
||||
}
|
||||
|
||||
impl T for A {
|
||||
// CHECK: align 16
|
||||
#[no_mangle]
|
||||
#[repr(align(16))]
|
||||
fn trait_fn() {}
|
||||
|
||||
// CHECK: align 16
|
||||
#[no_mangle]
|
||||
#[repr(align(16))]
|
||||
fn trait_method(self) {}
|
||||
}
|
||||
|
||||
impl T for () {}
|
||||
|
||||
pub fn foo() {
|
||||
().trait_method();
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ thread_local!(static A: Cell<u32> = const { Cell::new(1) });
|
||||
// CHECK-LABEL: @get
|
||||
#[no_mangle]
|
||||
fn get() -> u32 {
|
||||
// CHECK: %0 = load i32, {{.*}}[[TLS]]{{.*}}
|
||||
// CHECK-NEXT: ret i32 %0
|
||||
// CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}}
|
||||
// CHECK-NEXT: ret i32 [[RET_0]]
|
||||
A.with(|a| a.get())
|
||||
}
|
||||
|
||||
@ -36,8 +36,8 @@ fn set(v: u32) {
|
||||
// CHECK-LABEL: @get_aux
|
||||
#[no_mangle]
|
||||
fn get_aux() -> u64 {
|
||||
// CHECK: %0 = load i64, {{.*}}[[TLS_AUX]]
|
||||
// CHECK-NEXT: ret i64 %0
|
||||
// CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]]
|
||||
// CHECK-NEXT: ret i64 [[RET_1]]
|
||||
aux::A.with(|a| a.get())
|
||||
}
|
||||
|
||||
|
5
tests/ui/attributes/invalid-repr.rs
Normal file
5
tests/ui/attributes/invalid-repr.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[repr(align(16))]
|
||||
//~^ ERROR attribute should be applied to a struct, enum, function, associated function, or union
|
||||
pub type Foo = i32;
|
||||
|
||||
fn main() {}
|
12
tests/ui/attributes/invalid-repr.stderr
Normal file
12
tests/ui/attributes/invalid-repr.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union
|
||||
--> $DIR/invalid-repr.rs:1:8
|
||||
|
|
||||
LL | #[repr(align(16))]
|
||||
| ^^^^^^^^^
|
||||
LL |
|
||||
LL | pub type Foo = i32;
|
||||
| ------------------- not a struct, enum, function, associated function, or union
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0517`.
|
19
tests/ui/codegen/freeze-on-polymorphic-projection.rs
Normal file
19
tests/ui/codegen/freeze-on-polymorphic-projection.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// build-pass
|
||||
// compile-flags: -Copt-level=1 --crate-type=lib
|
||||
|
||||
#![feature(specialization)]
|
||||
//~^ WARN the feature `specialization` is incomplete
|
||||
|
||||
pub unsafe trait Storage {
|
||||
type Handle;
|
||||
}
|
||||
|
||||
pub unsafe trait MultipleStorage: Storage {}
|
||||
|
||||
default unsafe impl<S> Storage for S where S: MultipleStorage {}
|
||||
|
||||
// Make sure that we call is_freeze on `(S::Handle,)` in the param-env of `ice`,
|
||||
// instead of in an empty, reveal-all param-env.
|
||||
pub fn ice<S: Storage>(boxed: (S::Handle,)) -> (S::Handle,) {
|
||||
boxed
|
||||
}
|
12
tests/ui/codegen/freeze-on-polymorphic-projection.stderr
Normal file
12
tests/ui/codegen/freeze-on-polymorphic-projection.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/freeze-on-polymorphic-projection.rs:4:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -0,0 +1 @@
|
||||
pub fn test<const N: usize, T>() {}
|
@ -0,0 +1,8 @@
|
||||
// aux-build: foreign-generic-mismatch-with-const-arg.rs
|
||||
|
||||
extern crate foreign_generic_mismatch_with_const_arg;
|
||||
|
||||
fn main() {
|
||||
foreign_generic_mismatch_with_const_arg::test::<1>();
|
||||
//~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/foreign-generic-mismatch-with-const-arg.rs:6:46
|
||||
|
|
||||
LL | foreign_generic_mismatch_with_const_arg::test::<1>();
|
||||
| ^^^^ - supplied 1 generic argument
|
||||
| |
|
||||
| expected 2 generic arguments
|
||||
|
|
||||
note: function defined here, with 2 generic parameters: `N`, `T`
|
||||
--> $DIR/auxiliary/foreign-generic-mismatch-with-const-arg.rs:1:8
|
||||
|
|
||||
LL | pub fn test<const N: usize, T>() {}
|
||||
| ^^^^ -------------- -
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | foreign_generic_mismatch_with_const_arg::test::<1, T>();
|
||||
| +++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
@ -21,17 +21,32 @@ fn lint_on_top_level() {
|
||||
let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern
|
||||
}
|
||||
|
||||
fn _no_lint_attr() {
|
||||
fn no_lint_attr() {
|
||||
let _x = #[allow(dead_code)] (1 + 2);
|
||||
}
|
||||
|
||||
fn _no_lint_yeet() -> Result<(), ()> {
|
||||
fn no_lint_yeet() -> Result<(), ()> {
|
||||
#[allow(unreachable_code)]
|
||||
if (do yeet) {}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn no_lint_ops() {
|
||||
#![allow(unreachable_code, irrefutable_let_patterns)]
|
||||
if ((..{}) == ..{}) {}
|
||||
if (!return) {}
|
||||
loop { match (() = () = () = break {}) {} }
|
||||
while let () = (*&mut false |= true && return) {}
|
||||
}
|
||||
|
||||
fn lint_break_if_not_followed_by_block() {
|
||||
#![allow(unreachable_code)]
|
||||
loop { if break {} } //~ ERROR unnecessary parentheses
|
||||
loop { if break ({ println!("hello") }) {} } //~ ERROR unnecessary parentheses
|
||||
loop { if (break { println!("hello") }) {} }
|
||||
}
|
||||
|
||||
// Don't lint in these cases (#64106).
|
||||
fn or_patterns_no_lint() {
|
||||
match Box::new(0) {
|
||||
|
@ -21,17 +21,32 @@ fn lint_on_top_level() {
|
||||
let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
|
||||
}
|
||||
|
||||
fn _no_lint_attr() {
|
||||
fn no_lint_attr() {
|
||||
let _x = #[allow(dead_code)] (1 + 2);
|
||||
}
|
||||
|
||||
fn _no_lint_yeet() -> Result<(), ()> {
|
||||
fn no_lint_yeet() -> Result<(), ()> {
|
||||
#[allow(unreachable_code)]
|
||||
if (do yeet) {}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn no_lint_ops() {
|
||||
#![allow(unreachable_code, irrefutable_let_patterns)]
|
||||
if ((..{}) == ..{}) {}
|
||||
if (!return) {}
|
||||
loop { match (() = () = () = break {}) {} }
|
||||
while let () = (*&mut false |= true && return) {}
|
||||
}
|
||||
|
||||
fn lint_break_if_not_followed_by_block() {
|
||||
#![allow(unreachable_code)]
|
||||
loop { if (break) {} } //~ ERROR unnecessary parentheses
|
||||
loop { if (break ({ println!("hello") })) {} } //~ ERROR unnecessary parentheses
|
||||
loop { if (break { println!("hello") }) {} }
|
||||
}
|
||||
|
||||
// Don't lint in these cases (#64106).
|
||||
fn or_patterns_no_lint() {
|
||||
match Box::new(0) {
|
||||
|
@ -75,8 +75,32 @@ LL - let _ = |(a): u8| 0;
|
||||
LL + let _ = |a: u8| 0;
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:45:15
|
||||
|
|
||||
LL | loop { if (break) {} }
|
||||
| ^ ^
|
||||
|
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - loop { if (break) {} }
|
||||
LL + loop { if break {} }
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:46:15
|
||||
|
|
||||
LL | loop { if (break ({ println!("hello") })) {} }
|
||||
| ^ ^
|
||||
|
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - loop { if (break ({ println!("hello") })) {} }
|
||||
LL + loop { if break ({ println!("hello") }) {} }
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:56:12
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:71:12
|
||||
|
|
||||
LL | if let (0 | 1) = 0 {}
|
||||
| ^ ^
|
||||
@ -88,7 +112,7 @@ LL + if let 0 | 1 = 0 {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:57:13
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:72:13
|
||||
|
|
||||
LL | if let ((0 | 1),) = (0,) {}
|
||||
| ^ ^
|
||||
@ -100,7 +124,7 @@ LL + if let (0 | 1,) = (0,) {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:58:13
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:73:13
|
||||
|
|
||||
LL | if let [(0 | 1)] = [0] {}
|
||||
| ^ ^
|
||||
@ -112,7 +136,7 @@ LL + if let [0 | 1] = [0] {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:59:16
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:74:16
|
||||
|
|
||||
LL | if let 0 | (1 | 2) = 0 {}
|
||||
| ^ ^
|
||||
@ -124,7 +148,7 @@ LL + if let 0 | 1 | 2 = 0 {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:61:15
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:76:15
|
||||
|
|
||||
LL | if let TS((0 | 1)) = TS(0) {}
|
||||
| ^ ^
|
||||
@ -136,7 +160,7 @@ LL + if let TS(0 | 1) = TS(0) {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:63:20
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:78:20
|
||||
|
|
||||
LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
|
||||
| ^ ^
|
||||
@ -148,7 +172,7 @@ LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:73:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:88:9
|
||||
|
|
||||
LL | (_) => {}
|
||||
| ^ ^
|
||||
@ -160,7 +184,7 @@ LL + _ => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:74:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:89:9
|
||||
|
|
||||
LL | (y) => {}
|
||||
| ^ ^
|
||||
@ -172,7 +196,7 @@ LL + y => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:75:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:90:9
|
||||
|
|
||||
LL | (ref r) => {}
|
||||
| ^ ^
|
||||
@ -184,7 +208,7 @@ LL + ref r => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:76:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:91:9
|
||||
|
|
||||
LL | (e @ 1...2) => {}
|
||||
| ^ ^
|
||||
@ -196,7 +220,7 @@ LL + e @ 1...2 => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:82:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:97:9
|
||||
|
|
||||
LL | (e @ &(1...2)) => {}
|
||||
| ^ ^
|
||||
@ -208,7 +232,7 @@ LL + e @ &(1...2) => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:83:10
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:98:10
|
||||
|
|
||||
LL | &(_) => {}
|
||||
| ^ ^
|
||||
@ -220,7 +244,7 @@ LL + &_ => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:94:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:109:9
|
||||
|
|
||||
LL | (_) => {}
|
||||
| ^ ^
|
||||
@ -232,7 +256,7 @@ LL + _ => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:95:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:110:9
|
||||
|
|
||||
LL | (y) => {}
|
||||
| ^ ^
|
||||
@ -244,7 +268,7 @@ LL + y => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:96:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:111:9
|
||||
|
|
||||
LL | (ref r) => {}
|
||||
| ^ ^
|
||||
@ -256,7 +280,7 @@ LL + ref r => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:97:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:112:9
|
||||
|
|
||||
LL | (e @ 1..=2) => {}
|
||||
| ^ ^
|
||||
@ -268,7 +292,7 @@ LL + e @ 1..=2 => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:103:9
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:118:9
|
||||
|
|
||||
LL | (e @ &(1..=2)) => {}
|
||||
| ^ ^
|
||||
@ -280,7 +304,7 @@ LL + e @ &(1..=2) => {}
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around pattern
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:104:10
|
||||
--> $DIR/issue-54538-unused-parens-lint.rs:119:10
|
||||
|
|
||||
LL | &(_) => {}
|
||||
| ^ ^
|
||||
@ -291,5 +315,5 @@ LL - &(_) => {}
|
||||
LL + &_ => {}
|
||||
|
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user