Auto merge of #113703 - matthiaskrgr:rollup-19uhwuh, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #113599 (Use maybe_body_owned_by for multiple suggestions) - #113662 (Rename VecDeque's `rotate_left` and `rotate_right` parameters) - #113681 (rustdoc-json: Add test for private supertrait.) - #113682 (trait system refactor ping: also apply to nested modules of `solve`) - #113685 (Print artifact sizes in `opt-dist`) - #113688 (llvm-wrapper: update for LLVM API change) - #113692 (tests: adapt for removal of -opaque-pointers in LLVM 17) - #113698 (Make it clearer that we're just checking for an RPITIT) - #113699 (update Miri) Failed merges: - #113625 (Structurally normalize in selection) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3b55d2385a
@ -363,21 +363,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
let hir = self.infcx.tcx.hir();
|
||||
if let Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, body_id),
|
||||
..
|
||||
})) = hir.find(self.mir_hir_id())
|
||||
&& let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
|
||||
{
|
||||
if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) {
|
||||
let expr = hir.body(body_id).value;
|
||||
let place = &self.move_data.move_paths[mpi].place;
|
||||
let span = place.as_local()
|
||||
.map(|local| self.body.local_decls[local].source_info.span);
|
||||
let mut finder = ExpressionFinder {
|
||||
expr_span: move_span,
|
||||
expr: None,
|
||||
pat: None,
|
||||
parent_pat: None,
|
||||
};
|
||||
let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span);
|
||||
let mut finder =
|
||||
ExpressionFinder { expr_span: move_span, expr: None, pat: None, parent_pat: None };
|
||||
finder.visit_expr(expr);
|
||||
if let Some(span) = span && let Some(expr) = finder.expr {
|
||||
for (_, expr) in hir.parent_iter(expr.hir_id) {
|
||||
@ -461,7 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
} = move_spans {
|
||||
// We already suggest cloning for these cases in `explain_captures`.
|
||||
} else {
|
||||
self.suggest_cloning(err, ty, move_span);
|
||||
self.suggest_cloning(err, ty, expr, move_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -736,9 +727,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
true
|
||||
}
|
||||
|
||||
fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
|
||||
fn suggest_cloning(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let suggestion =
|
||||
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
format!(": {}.clone()", symbol)
|
||||
} else {
|
||||
".clone()".to_owned()
|
||||
};
|
||||
if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
|
||||
&& self.infcx
|
||||
.type_implements_trait(
|
||||
@ -751,7 +754,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
"consider cloning the value if the performance cost is acceptable",
|
||||
".clone()",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{
|
||||
@ -646,14 +645,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
let hir_map = self.infcx.tcx.hir();
|
||||
let def_id = self.body.source.def_id();
|
||||
let hir_id = hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap());
|
||||
let node = hir_map.find(hir_id);
|
||||
let Some(hir::Node::Item(item)) = node else {
|
||||
return;
|
||||
};
|
||||
let hir::ItemKind::Fn(.., body_id) = item.kind else {
|
||||
return;
|
||||
};
|
||||
let Some(local_def_id) = def_id.as_local() else { return };
|
||||
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
|
||||
let body = self.infcx.tcx.hir().body(body_id);
|
||||
|
||||
let mut v = V { assign_span: span, err, ty, suggested: false };
|
||||
@ -790,23 +783,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
// In the future, attempt in all path but initially for RHS of for_loop
|
||||
fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic) {
|
||||
use hir::{
|
||||
BodyId, Expr,
|
||||
Expr,
|
||||
ExprKind::{Block, Call, DropTemps, Match, MethodCall},
|
||||
HirId, ImplItem, ImplItemKind, Item, ItemKind,
|
||||
};
|
||||
|
||||
fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
|
||||
match hir_map.find(id) {
|
||||
Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. }))
|
||||
| Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => {
|
||||
Some(*body_id)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
let hir_map = self.infcx.tcx.hir();
|
||||
let mir_body_hir_id = self.mir_hir_id();
|
||||
if let Some(fn_body_id) = maybe_body_id_of_fn(hir_map, mir_body_hir_id) {
|
||||
if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) {
|
||||
if let Block(
|
||||
hir::Block {
|
||||
expr:
|
||||
@ -840,7 +822,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
..
|
||||
},
|
||||
_,
|
||||
) = hir_map.body(fn_body_id).value.kind
|
||||
) = hir_map.body(body_id).value.kind
|
||||
{
|
||||
let opt_suggestions = self
|
||||
.infcx
|
||||
@ -1102,10 +1084,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
let hir_map = self.infcx.tcx.hir();
|
||||
let def_id = self.body.source.def_id();
|
||||
let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
|
||||
let node = hir_map.find(hir_id);
|
||||
let hir_id = if let Some(hir::Node::Item(item)) = node
|
||||
&& let hir::ItemKind::Fn(.., body_id) = item.kind
|
||||
let hir_id = if let Some(local_def_id) = def_id.as_local() &&
|
||||
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
|
||||
{
|
||||
let body = hir_map.body(body_id);
|
||||
let mut v = BindingFinder {
|
||||
@ -1117,6 +1097,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
|
||||
{
|
||||
|
@ -123,7 +123,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let all_candidate_names: Vec<_> = all_candidates()
|
||||
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
|
||||
.filter_map(|item| {
|
||||
if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
|
||||
if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type {
|
||||
Some(item.name)
|
||||
} else {
|
||||
None
|
||||
@ -164,7 +164,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
self.tcx().associated_items(*trait_def_id).in_definition_order()
|
||||
})
|
||||
.filter_map(|item| {
|
||||
if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
|
||||
if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type {
|
||||
Some(item.name)
|
||||
} else {
|
||||
None
|
||||
|
@ -173,7 +173,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
tcx.associated_items(pred.def_id())
|
||||
.in_definition_order()
|
||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.filter(|item| item.opt_rpitit_info.is_none())
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
.map(|item| item.def_id),
|
||||
);
|
||||
}
|
||||
|
@ -1322,7 +1322,7 @@ fn compare_number_of_generics<'tcx>(
|
||||
// has mismatched type or const generic arguments, then the method that it's
|
||||
// inheriting the generics from will also have mismatched arguments, and
|
||||
// we'll report an error for that instead. Delay a bug for safety, though.
|
||||
if trait_.opt_rpitit_info.is_some() {
|
||||
if trait_.is_impl_trait_in_trait() {
|
||||
return Err(tcx.sess.delay_span_bug(
|
||||
rustc_span::DUMMY_SP,
|
||||
"errors comparing numbers of generics of trait/impl functions were not emitted",
|
||||
@ -2116,7 +2116,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
|
||||
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
|
||||
// associated type.
|
||||
let impl_ty_span = if impl_ty.opt_rpitit_info.is_some() {
|
||||
let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
|
||||
tcx.def_span(impl_ty_def_id)
|
||||
} else {
|
||||
match tcx.hir().get_by_def_id(impl_ty_def_id) {
|
||||
|
@ -188,7 +188,7 @@ fn missing_items_err(
|
||||
full_impl_span: Span,
|
||||
) {
|
||||
let missing_items =
|
||||
missing_items.iter().filter(|trait_item| trait_item.opt_rpitit_info.is_none());
|
||||
missing_items.iter().filter(|trait_item| !trait_item.is_impl_trait_in_trait());
|
||||
|
||||
let missing_items_msg = missing_items
|
||||
.clone()
|
||||
|
@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
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::symbol::sym;
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::ObligationCause;
|
||||
@ -997,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.collect();
|
||||
|
||||
let suggestions_for = |variant: &_, ctor_kind, field_name| {
|
||||
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!("{ident}: "),
|
||||
None => String::new(),
|
||||
};
|
||||
@ -1240,39 +1240,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_get_struct_pattern_shorthand_field(
|
||||
&self,
|
||||
expr: &hir::Expr<'_>,
|
||||
) -> Option<Symbol> {
|
||||
let hir = self.tcx.hir();
|
||||
let local = match expr {
|
||||
hir::Expr {
|
||||
kind:
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path {
|
||||
res: hir::def::Res::Local(_),
|
||||
segments: [hir::PathSegment { ident, .. }],
|
||||
..
|
||||
},
|
||||
)),
|
||||
..
|
||||
} => Some(ident),
|
||||
_ => None,
|
||||
}?;
|
||||
|
||||
match hir.find_parent(expr.hir_id)? {
|
||||
Node::ExprField(field) => {
|
||||
if field.ident.name == local.name && field.is_shorthand {
|
||||
return Some(local.name);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
|
||||
pub(crate) fn maybe_get_block_expr(
|
||||
&self,
|
||||
@ -1467,7 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
));
|
||||
}
|
||||
|
||||
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!("{ident}: "),
|
||||
None => String::new(),
|
||||
};
|
||||
@ -1661,7 +1628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
)
|
||||
};
|
||||
|
||||
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!("{ident}: "),
|
||||
None => String::new(),
|
||||
};
|
||||
|
@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
|
||||
};
|
||||
let struct_pat_shorthand_field =
|
||||
self.maybe_get_struct_pattern_shorthand_field(expr);
|
||||
self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr);
|
||||
if let Some(name) = struct_pat_shorthand_field {
|
||||
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
|
||||
}
|
||||
@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!(": {}.clone()", ident),
|
||||
None => ".clone()".to_string()
|
||||
};
|
||||
@ -1247,7 +1247,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
Some(ident) => format!(": {}.is_some()", ident),
|
||||
None => ".is_some()".to_string(),
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
|
||||
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp
|
||||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
|
||||
|
@ -1136,7 +1136,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
|
||||
// the default projection predicates in default trait methods
|
||||
// with RPITITs.
|
||||
ty::AssocItemContainer::TraitContainer => {
|
||||
assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some()
|
||||
assoc_item.defaultness(tcx).has_value() || assoc_item.is_impl_trait_in_trait()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1103,6 +1103,33 @@ impl<'hir> Map<'hir> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option<Symbol> {
|
||||
let local = match expr {
|
||||
Expr {
|
||||
kind:
|
||||
ExprKind::Path(QPath::Resolved(
|
||||
None,
|
||||
Path {
|
||||
res: def::Res::Local(_), segments: [PathSegment { ident, .. }], ..
|
||||
},
|
||||
)),
|
||||
..
|
||||
} => Some(ident),
|
||||
_ => None,
|
||||
}?;
|
||||
|
||||
match self.find_parent(expr.hir_id)? {
|
||||
Node::ExprField(field) => {
|
||||
if field.ident.name == local.name && field.is_shorthand {
|
||||
return Some(local.name);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> intravisit::Map<'hir> for Map<'hir> {
|
||||
|
@ -96,6 +96,10 @@ impl AssocItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_impl_trait_in_trait(&self) -> bool {
|
||||
self.opt_rpitit_info.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
|
||||
|
@ -276,7 +276,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||
}
|
||||
|
||||
// Avoid accessing the HIR for the synthesized associated type generated for RPITITs.
|
||||
if self.tcx.opt_rpitit_info(id.to_def_id()).is_some() {
|
||||
if self.tcx.is_impl_trait_in_trait(id.to_def_id()) {
|
||||
self.live_symbols.insert(id);
|
||||
continue;
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ fn suggest_restriction<'tcx>(
|
||||
) {
|
||||
if hir_generics.where_clause_span.from_expansion()
|
||||
|| hir_generics.where_clause_span.desugaring_kind().is_some()
|
||||
|| projection.is_some_and(|projection| tcx.opt_rpitit_info(projection.def_id).is_some())
|
||||
|| projection.is_some_and(|projection| tcx.is_impl_trait_in_trait(projection.def_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ fn object_safety_violation_for_assoc_item(
|
||||
ty::AssocKind::Type => {
|
||||
if !tcx.features().generic_associated_types_extended
|
||||
&& !tcx.generics_of(item.def_id).params.is_empty()
|
||||
&& item.opt_rpitit_info.is_none()
|
||||
&& !item.is_impl_trait_in_trait()
|
||||
{
|
||||
Some(ObjectSafetyViolation::GAT(item.name, item.ident(tcx).span))
|
||||
} else {
|
||||
|
@ -2283,21 +2283,21 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
unsafe { slice::from_raw_parts_mut(ptr.add(self.head), self.len) }
|
||||
}
|
||||
|
||||
/// Rotates the double-ended queue `mid` places to the left.
|
||||
/// Rotates the double-ended queue `n` places to the left.
|
||||
///
|
||||
/// Equivalently,
|
||||
/// - Rotates item `mid` into the first position.
|
||||
/// - Pops the first `mid` items and pushes them to the end.
|
||||
/// - Rotates `len() - mid` places to the right.
|
||||
/// - Rotates item `n` into the first position.
|
||||
/// - Pops the first `n` items and pushes them to the end.
|
||||
/// - Rotates `len() - n` places to the right.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `mid` is greater than `len()`. Note that `mid == len()`
|
||||
/// If `n` is greater than `len()`. Note that `n == len()`
|
||||
/// does _not_ panic and is a no-op rotation.
|
||||
///
|
||||
/// # Complexity
|
||||
///
|
||||
/// Takes `*O*(min(mid, len() - mid))` time and no extra space.
|
||||
/// Takes `*O*(min(n, len() - n))` time and no extra space.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2316,31 +2316,31 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
/// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
/// ```
|
||||
#[stable(feature = "vecdeque_rotate", since = "1.36.0")]
|
||||
pub fn rotate_left(&mut self, mid: usize) {
|
||||
assert!(mid <= self.len());
|
||||
let k = self.len - mid;
|
||||
if mid <= k {
|
||||
unsafe { self.rotate_left_inner(mid) }
|
||||
pub fn rotate_left(&mut self, n: usize) {
|
||||
assert!(n <= self.len());
|
||||
let k = self.len - n;
|
||||
if n <= k {
|
||||
unsafe { self.rotate_left_inner(n) }
|
||||
} else {
|
||||
unsafe { self.rotate_right_inner(k) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotates the double-ended queue `k` places to the right.
|
||||
/// Rotates the double-ended queue `n` places to the right.
|
||||
///
|
||||
/// Equivalently,
|
||||
/// - Rotates the first item into position `k`.
|
||||
/// - Pops the last `k` items and pushes them to the front.
|
||||
/// - Rotates `len() - k` places to the left.
|
||||
/// - Rotates the first item into position `n`.
|
||||
/// - Pops the last `n` items and pushes them to the front.
|
||||
/// - Rotates `len() - n` places to the left.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `k` is greater than `len()`. Note that `k == len()`
|
||||
/// If `n` is greater than `len()`. Note that `n == len()`
|
||||
/// does _not_ panic and is a no-op rotation.
|
||||
///
|
||||
/// # Complexity
|
||||
///
|
||||
/// Takes `*O*(min(k, len() - k))` time and no extra space.
|
||||
/// Takes `*O*(min(n, len() - n))` time and no extra space.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2359,13 +2359,13 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
/// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
/// ```
|
||||
#[stable(feature = "vecdeque_rotate", since = "1.36.0")]
|
||||
pub fn rotate_right(&mut self, k: usize) {
|
||||
assert!(k <= self.len());
|
||||
let mid = self.len - k;
|
||||
if k <= mid {
|
||||
unsafe { self.rotate_right_inner(k) }
|
||||
pub fn rotate_right(&mut self, n: usize) {
|
||||
assert!(n <= self.len());
|
||||
let k = self.len - n;
|
||||
if n <= k {
|
||||
unsafe { self.rotate_right_inner(n) }
|
||||
} else {
|
||||
unsafe { self.rotate_left_inner(mid) }
|
||||
unsafe { self.rotate_left_inner(k) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,14 +351,14 @@ fn test_rotate_left_right() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "assertion failed: mid <= self.len()"]
|
||||
#[should_panic = "assertion failed: n <= self.len()"]
|
||||
fn test_rotate_left_panic() {
|
||||
let mut tester: VecDeque<_> = (1..=10).collect();
|
||||
tester.rotate_left(tester.len() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "assertion failed: k <= self.len()"]
|
||||
#[should_panic = "assertion failed: n <= self.len()"]
|
||||
fn test_rotate_right_panic() {
|
||||
let mut tester: VecDeque<_> = (1..=10).collect();
|
||||
tester.rotate_right(tester.len() + 1);
|
||||
|
@ -1 +1 @@
|
||||
743333f3dd90721461c09387ec73d09c080d5f5f
|
||||
33a2c2487ac5d9927830ea4c1844335c6b9f77db
|
||||
|
@ -74,7 +74,7 @@ pub struct FrameState {
|
||||
|
||||
impl VisitTags for FrameState {
|
||||
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
|
||||
// `protected_tags` are fine to GC.
|
||||
// `protected_tags` are already recorded by `GlobalStateInner`.
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,9 +108,12 @@ pub struct GlobalStateInner {
|
||||
}
|
||||
|
||||
impl VisitTags for GlobalStateInner {
|
||||
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
|
||||
// The only candidate is base_ptr_tags, and that does not need visiting since we don't ever
|
||||
// GC the bottommost tag.
|
||||
fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
|
||||
for &tag in self.protected_tags.keys() {
|
||||
visit(tag);
|
||||
}
|
||||
// The only other candidate is base_ptr_tags, and that does not need visiting since we don't ever
|
||||
// GC the bottommost/root tag.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,19 +43,20 @@
|
||||
// Needed for rustdoc from bootstrap (with `-Znormalize-docs`).
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
extern crate either; // the one from rustc
|
||||
|
||||
extern crate rustc_apfloat;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_errors;
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_hir;
|
||||
extern crate rustc_index;
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_target;
|
||||
extern crate either; // the one from rustc
|
||||
|
||||
// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
|
||||
// files.
|
||||
|
@ -1097,9 +1097,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
ptr: Pointer<Self::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
match ptr.provenance {
|
||||
Provenance::Concrete { alloc_id, tag } => {
|
||||
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
|
||||
}
|
||||
Provenance::Concrete { alloc_id, tag } =>
|
||||
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
|
||||
Provenance::Wildcard => {
|
||||
// No need to do anything for wildcard pointers as
|
||||
// their provenances have already been previously exposed.
|
||||
|
@ -1,6 +1,5 @@
|
||||
// Make sure we find these even with many checks disabled.
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
|
||||
fn main() {
|
||||
let p = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// should find the bug even without these, but gets masked by optimizations
|
||||
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0
|
||||
// should find the bug even without these
|
||||
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
|
||||
|
||||
struct SliceWithHead(u8, [u8]);
|
||||
|
||||
|
@ -1,6 +1,3 @@
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
|
||||
fn main() {
|
||||
// This pointer *could* be NULL so we cannot load from it, not even at ZST
|
||||
let ptr = (&0u8 as *const u8).wrapping_sub(0x800) as *const ();
|
||||
|
@ -1,6 +1,3 @@
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
|
||||
fn main() {
|
||||
// This pointer *could* be NULL so we cannot load from it, not even at ZST.
|
||||
// Not using the () type here, as writes of that type do not even have MIR generated.
|
||||
|
@ -1,6 +1,3 @@
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
|
||||
#[allow(deref_nullptr)]
|
||||
fn main() {
|
||||
let x: () = unsafe { *std::ptr::null() }; //~ ERROR: dereferencing pointer failed: null pointer is a dangling pointer
|
||||
|
@ -1,6 +1,3 @@
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
|
||||
#[allow(deref_nullptr)]
|
||||
fn main() {
|
||||
// Not using the () type here, as writes of that type do not even have MIR generated.
|
||||
|
@ -1,5 +1,5 @@
|
||||
// This should fail even without validation, but some MIR opts mask the error
|
||||
//@compile-flags: -Zmiri-disable-validation -Zmir-opt-level=0
|
||||
// This should fail even without validation
|
||||
//@compile-flags: -Zmiri-disable-validation
|
||||
|
||||
unsafe fn make_ref<'a>(x: *mut i32) -> &'a mut i32 {
|
||||
&mut *x
|
||||
|
@ -1,5 +1,5 @@
|
||||
// This should fail even without validation, but some MIR opts mask the error
|
||||
//@compile-flags: -Zmiri-disable-validation -Zmir-opt-level=0 -Zmiri-permissive-provenance
|
||||
// This should fail even without validation
|
||||
//@compile-flags: -Zmiri-disable-validation -Zmiri-permissive-provenance
|
||||
|
||||
static mut LEAK: usize = 0;
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows
|
||||
|
||||
// Note: mir-opt-level set to 0 to prevent the read of stack_var in thread 1
|
||||
// from being optimized away and preventing the detection of the data-race.
|
||||
//@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows
|
||||
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
|
@ -1,7 +1,5 @@
|
||||
//! Make sure we detect erroneous constants post-monomorphization even when they are unused.
|
||||
//! (https://github.com/rust-lang/miri/issues/1382)
|
||||
// Inlining changes the error location
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
#![feature(never_type)]
|
||||
|
||||
struct PrintName<T>(T);
|
||||
|
@ -5,9 +5,9 @@ pub struct S(i32);
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn main() {
|
||||
// FIXME: the span is not great (probably caused by custom MIR)
|
||||
mir! { //~ERROR: uninitialized
|
||||
mir! {
|
||||
let unit: ();
|
||||
let _observe: i32;
|
||||
{
|
||||
let non_copy = S(42);
|
||||
// This could change `non_copy` in-place
|
||||
@ -15,7 +15,7 @@ fn main() {
|
||||
}
|
||||
after_call = {
|
||||
// So now we must not be allowed to observe non-copy again.
|
||||
let _observe = non_copy.0;
|
||||
_observe = non_copy.0; //~ERROR: uninitialized
|
||||
Return()
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,13 @@
|
||||
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||
--> $DIR/arg_inplace_observe_after.rs:LL:CC
|
||||
|
|
||||
LL | / mir! {
|
||||
LL | | let unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | _observe = non_copy.0;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at RUSTLIB/core/src/intrinsics/mir.rs:LL:CC
|
||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
= note: inside `main` at $DIR/arg_inplace_observe_after.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// should find the bug even without, but gets masked by optimizations
|
||||
//@compile-flags: -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
|
||||
//@compile-flags: -Zmiri-disable-stacked-borrows -Cdebug-assertions=no
|
||||
//@normalize-stderr-test: "but found [0-9]+" -> "but found $$ALIGN"
|
||||
|
||||
#[repr(align(256))]
|
||||
|
@ -1,6 +1,5 @@
|
||||
// This should fail even without validation
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0 -Zmiri-disable-validation -Cdebug-assertions=no
|
||||
//@compile-flags: -Zmiri-disable-validation -Cdebug-assertions=no
|
||||
|
||||
fn main() {
|
||||
// Try many times as this might work by chance.
|
||||
|
@ -1,5 +1,3 @@
|
||||
// gets masked by optimizations
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(unused_attributes)]
|
||||
|
||||
|
@ -1,6 +1,3 @@
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
|
||||
fn main() {
|
||||
// Not using the () type here, as writes of that type do not even have MIR generated.
|
||||
// Also not assigning directly as that's array initialization, not assignment.
|
||||
|
@ -1,6 +1,3 @@
|
||||
// Some optimizations remove ZST accesses, thus masking this UB.
|
||||
//@compile-flags: -Zmir-opt-level=0
|
||||
|
||||
fn main() {
|
||||
// Not using the () type here, as writes of that type do not even have MIR generated.
|
||||
// Also not assigning directly as that's array initialization, not assignment.
|
||||
|
@ -7,7 +7,9 @@ use crate::tests::run_tests;
|
||||
use crate::timer::Timer;
|
||||
use crate::training::{gather_llvm_bolt_profiles, gather_llvm_profiles, gather_rustc_profiles};
|
||||
use crate::utils::io::reset_directory;
|
||||
use crate::utils::{clear_llvm_files, format_env_variables, print_free_disk_space};
|
||||
use crate::utils::{
|
||||
clear_llvm_files, format_env_variables, print_binary_sizes, print_free_disk_space,
|
||||
};
|
||||
|
||||
mod environment;
|
||||
mod exec;
|
||||
@ -170,6 +172,8 @@ fn main() -> anyhow::Result<()> {
|
||||
log::info!("Timer results\n{}", timer.format_stats());
|
||||
|
||||
print_free_disk_space()?;
|
||||
result.context("Optimized build pipeline has failed")?;
|
||||
print_binary_sizes(env.as_ref())?;
|
||||
|
||||
result.context("Optimized build pipeline has failed")
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::Context;
|
||||
use camino::Utf8Path;
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use fs_extra::dir::CopyOptions;
|
||||
use std::fs::File;
|
||||
|
||||
@ -46,3 +46,17 @@ pub fn unpack_archive(path: &Utf8Path, dest_dir: &Utf8Path) -> anyhow::Result<()
|
||||
archive.unpack(dest_dir.as_std_path())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns paths in the given `dir` (non-recursively), optionally with the given `suffix`.
|
||||
/// The `suffix` should contain the leading dot.
|
||||
pub fn get_files_from_dir(
|
||||
dir: &Utf8Path,
|
||||
suffix: Option<&str>,
|
||||
) -> anyhow::Result<Vec<Utf8PathBuf>> {
|
||||
let path = format!("{dir}/*{}", suffix.unwrap_or(""));
|
||||
|
||||
Ok(glob::glob(&path)?
|
||||
.into_iter()
|
||||
.map(|p| p.map(|p| Utf8PathBuf::from_path_buf(p).unwrap()))
|
||||
.collect::<Result<Vec<_>, _>>()?)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
pub mod io;
|
||||
|
||||
use crate::environment::Environment;
|
||||
use crate::utils::io::delete_directory;
|
||||
use humansize::BINARY;
|
||||
use crate::utils::io::{delete_directory, get_files_from_dir};
|
||||
use humansize::{format_size, BINARY};
|
||||
use sysinfo::{DiskExt, RefreshKind, System, SystemExt};
|
||||
|
||||
pub fn format_env_variables() -> String {
|
||||
@ -25,6 +25,28 @@ pub fn print_free_disk_space() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_binary_sizes(env: &dyn Environment) -> anyhow::Result<()> {
|
||||
use std::fmt::Write;
|
||||
|
||||
let root = env.build_artifacts().join("stage2");
|
||||
|
||||
let mut files = get_files_from_dir(&root.join("bin"), None)?;
|
||||
files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?);
|
||||
files.sort_unstable();
|
||||
|
||||
let mut output = String::new();
|
||||
for file in files {
|
||||
let size = std::fs::metadata(file.as_std_path())?.len();
|
||||
let size_formatted = format_size(size, BINARY);
|
||||
let name = format!("{}:", file.file_name().unwrap());
|
||||
writeln!(output, "{name:<50}{size_formatted:>10}")?;
|
||||
}
|
||||
|
||||
log::info!("Rustc artifact size\n{output}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear_llvm_files(env: &dyn Environment) -> anyhow::Result<()> {
|
||||
// Bootstrap currently doesn't support rebuilding LLVM when PGO options
|
||||
// change (or any other llvm-related options); so just clear out the relevant
|
||||
|
15
tests/rustdoc-json/traits/private_supertrait.rs
Normal file
15
tests/rustdoc-json/traits/private_supertrait.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
|
||||
|
||||
// @!has "$.index[*][?(@.name == 'sealed')]"
|
||||
mod sealed {
|
||||
// @set sealed_id = "$.index[*][?(@.name=='Sealed')].id"
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
// @count "$.index[*][?(@.name=='Trait')].inner.trait.bounds[*]" 1
|
||||
// @is "$.index[*][?(@.name=='Trait')].inner.trait.bounds[0].trait_bound.trait.id" $sealed_id
|
||||
pub trait Trait: sealed::Sealed {}
|
@ -1,3 +1,4 @@
|
||||
//@run-rustfix
|
||||
pub struct DataStruct();
|
||||
|
||||
pub struct HelperStruct<'n> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0382]: borrow of moved value: `helpers`
|
||||
--> $DIR/copy-suggestion-region-vid.rs:12:43
|
||||
--> $DIR/copy-suggestion-region-vid.rs:13:43
|
||||
|
|
||||
LL | let helpers = [vec![], vec![]];
|
||||
| ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait
|
||||
@ -8,6 +8,11 @@ LL | HelperStruct { helpers, is_empty: helpers[0].is_empty() }
|
||||
| ------- ^^^^^^^^^^ value borrowed here after move
|
||||
| |
|
||||
| value moved here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | HelperStruct { helpers: helpers.clone(), is_empty: helpers[0].is_empty() }
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
31
tests/ui/borrowck/issue-85765-closure.rs
Normal file
31
tests/ui/borrowck/issue-85765-closure.rs
Normal file
@ -0,0 +1,31 @@
|
||||
fn main() {
|
||||
let _ = || {
|
||||
let mut test = Vec::new();
|
||||
let rofl: &Vec<Vec<i32>> = &mut test;
|
||||
//~^ HELP consider changing this binding's type
|
||||
rofl.push(Vec::new());
|
||||
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
|
||||
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
let mut mutvar = 42;
|
||||
let r = &mutvar;
|
||||
//~^ HELP consider changing this to be a mutable reference
|
||||
*r = 0;
|
||||
//~^ ERROR cannot assign to `*r`, which is behind a `&` reference
|
||||
//~| NOTE `r` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
#[rustfmt::skip]
|
||||
let x: &usize = &mut{0};
|
||||
//~^ HELP consider changing this binding's type
|
||||
*x = 1;
|
||||
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
|
||||
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
#[rustfmt::skip]
|
||||
let y: &usize = &mut(0);
|
||||
//~^ HELP consider changing this binding's type
|
||||
*y = 1;
|
||||
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
|
||||
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
|
||||
};
|
||||
}
|
48
tests/ui/borrowck/issue-85765-closure.stderr
Normal file
48
tests/ui/borrowck/issue-85765-closure.stderr
Normal file
@ -0,0 +1,48 @@
|
||||
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-85765-closure.rs:6:9
|
||||
|
|
||||
LL | rofl.push(Vec::new());
|
||||
| ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
|
||||
help: consider changing this binding's type
|
||||
|
|
||||
LL | let rofl: &mut Vec<Vec<i32>> = &mut test;
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
|
||||
--> $DIR/issue-85765-closure.rs:13:9
|
||||
|
|
||||
LL | *r = 0;
|
||||
| ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written
|
||||
|
|
||||
help: consider changing this to be a mutable reference
|
||||
|
|
||||
LL | let r = &mut mutvar;
|
||||
| +++
|
||||
|
||||
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
|
||||
--> $DIR/issue-85765-closure.rs:20:9
|
||||
|
|
||||
LL | *x = 1;
|
||||
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
|
||||
|
|
||||
help: consider changing this binding's type
|
||||
|
|
||||
LL | let x: &mut usize = &mut{0};
|
||||
| ~~~~~~~~~~
|
||||
|
||||
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
|
||||
--> $DIR/issue-85765-closure.rs:27:9
|
||||
|
|
||||
LL | *y = 1;
|
||||
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
|
||||
|
|
||||
help: consider changing this binding's type
|
||||
|
|
||||
LL | let y: &mut usize = &mut(0);
|
||||
| ~~~~~~~~~~
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0594, E0596.
|
||||
For more information about an error, try `rustc --explain E0594`.
|
8
tests/ui/btreemap/btreemap-index-mut-2.rs
Normal file
8
tests/ui/btreemap/btreemap-index-mut-2.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn main() {
|
||||
let _ = || {
|
||||
let mut map = BTreeMap::<u32, u32>::new();
|
||||
map[&0] = 1; //~ ERROR cannot assign
|
||||
};
|
||||
}
|
19
tests/ui/btreemap/btreemap-index-mut-2.stderr
Normal file
19
tests/ui/btreemap/btreemap-index-mut-2.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0594]: cannot assign to data in an index of `BTreeMap<u32, u32>`
|
||||
--> $DIR/btreemap-index-mut-2.rs:6:9
|
||||
|
|
||||
LL | map[&0] = 1;
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `BTreeMap<u32, u32>`
|
||||
help: to modify a `BTreeMap<u32, u32>`, use `.get_mut()`, `.insert()` or the entry API
|
||||
|
|
||||
LL | map.insert(&0, 1);
|
||||
| ~~~~~~~~ ~ +
|
||||
LL | map.get_mut(&0).map(|val| { *val = 1; });
|
||||
| ~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ ++++
|
||||
LL | let val = map.entry(&0).or_insert(1);
|
||||
| +++++++++ ~~~~~~~ ~~~~~~~~~~~~ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0594`.
|
@ -3,6 +3,8 @@
|
||||
|
||||
// (opaque-pointers flag is called force-opaque-pointers in LLVM 13...)
|
||||
// min-llvm-version: 14.0
|
||||
// (the ability to disable opaque pointers has been removed in LLVM 17)
|
||||
// ignore-llvm-version: 17 - 99
|
||||
|
||||
// This test can be removed once non-opaque pointers are gone from LLVM, maybe.
|
||||
|
||||
|
12
tests/ui/liveness/liveness-move-call-arg-2.rs
Normal file
12
tests/ui/liveness/liveness-move-call-arg-2.rs
Normal file
@ -0,0 +1,12 @@
|
||||
fn take(_x: Box<isize>) {}
|
||||
|
||||
|
||||
fn main() {
|
||||
let _ = || {
|
||||
let x: Box<isize> = Box::new(25);
|
||||
|
||||
loop {
|
||||
take(x); //~ ERROR use of moved value: `x`
|
||||
}
|
||||
};
|
||||
}
|
26
tests/ui/liveness/liveness-move-call-arg-2.stderr
Normal file
26
tests/ui/liveness/liveness-move-call-arg-2.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/liveness-move-call-arg-2.rs:9:18
|
||||
|
|
||||
LL | let x: Box<isize> = Box::new(25);
|
||||
| - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
|
||||
LL |
|
||||
LL | loop {
|
||||
| ---- inside of this loop
|
||||
LL | take(x);
|
||||
| ^ value moved here, in previous iteration of loop
|
||||
|
|
||||
note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary
|
||||
--> $DIR/liveness-move-call-arg-2.rs:1:13
|
||||
|
|
||||
LL | fn take(_x: Box<isize>) {}
|
||||
| ---- ^^^^^^^^^^ this parameter takes ownership of the value
|
||||
| |
|
||||
| in this function
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | take(x.clone());
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
19
tests/ui/suggestions/suggest-mut-method-for-loop-closure.rs
Normal file
19
tests/ui/suggestions/suggest-mut-method-for-loop-closure.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use std::collections::HashMap;
|
||||
struct X(usize);
|
||||
struct Y {
|
||||
v: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = || {
|
||||
let mut buzz = HashMap::new();
|
||||
buzz.insert("a", Y { v: 0 });
|
||||
|
||||
for mut t in buzz.values() {
|
||||
//~^ HELP
|
||||
//~| SUGGESTION values_mut()
|
||||
t.v += 1;
|
||||
//~^ ERROR cannot assign
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error[E0594]: cannot assign to `t.v`, which is behind a `&` reference
|
||||
--> $DIR/suggest-mut-method-for-loop-closure.rs:15:13
|
||||
|
|
||||
LL | for mut t in buzz.values() {
|
||||
| -------------
|
||||
| | |
|
||||
| | help: use mutable method: `values_mut()`
|
||||
| this iterator yields `&` references
|
||||
...
|
||||
LL | t.v += 1;
|
||||
| ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0594`.
|
@ -264,7 +264,7 @@ exclude_labels = [
|
||||
[autolabel."WG-trait-system-refactor"]
|
||||
trigger_files = [
|
||||
"compiler/rustc_trait_selection/src/solve",
|
||||
"compiler/rustc_middle/src/traits/solve.rs"
|
||||
"compiler/rustc_middle/src/traits/solve"
|
||||
]
|
||||
|
||||
[notify-zulip."I-prioritize"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user