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:
bors 2023-07-14 19:26:19 +00:00
commit 3b55d2385a
56 changed files with 416 additions and 223 deletions

View File

@ -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,
);
}

View File

@ -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,46 +1084,45 @@ 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 body = hir_map.body(body_id);
let mut v = BindingFinder {
span: err_label_span,
hir_id: None,
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 {
span: err_label_span,
hir_id: None,
};
v.visit_body(body);
v.hir_id
} else {
None
};
v.visit_body(body);
v.hir_id
} else {
None
};
if let Some(hir_id) = hir_id
&& let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
{
let (changing, span, sugg) = match local.ty {
Some(ty) => ("changing", ty.span, message),
None => (
"specifying",
local.pat.span.shrink_to_hi(),
format!(": {message}"),
),
};
err.span_suggestion_verbose(
span,
format!("consider {changing} this binding's type"),
sugg,
Applicability::HasPlaceholders,
);
} else {
err.span_label(
err_label_span,
format!(
"consider changing this binding's type to be: `{message}`"
),
);
}
{
let (changing, span, sugg) = match local.ty {
Some(ty) => ("changing", ty.span, message),
None => (
"specifying",
local.pat.span.shrink_to_hi(),
format!(": {message}"),
),
};
err.span_suggestion_verbose(
span,
format!("consider {changing} this binding's type"),
sugg,
Applicability::HasPlaceholders,
);
} else {
err.span_label(
err_label_span,
format!(
"consider changing this binding's type to be: `{message}`"
),
);
}
}
None => {}
}

View File

@ -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

View File

@ -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),
);
}

View File

@ -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) {

View File

@ -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()

View File

@ -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(),
};

View File

@ -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(),
};

View File

@ -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"

View File

@ -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()
}
}
}

View File

@ -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> {

View File

@ -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)]

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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) }
}
}

View File

@ -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);

View File

@ -1 +1 @@
743333f3dd90721461c09387ec73d09c080d5f5f
33a2c2487ac5d9927830ea4c1844335c6b9f77db

View File

@ -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.
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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 = {

View File

@ -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]);

View File

@ -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 ();

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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};

View File

@ -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);

View File

@ -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()
}

View File

@ -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

View File

@ -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))]

View File

@ -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.

View File

@ -1,5 +1,3 @@
// gets masked by optimizations
//@compile-flags: -Zmir-opt-level=0
#![feature(rustc_attrs)]
#![allow(unused_attributes)]

View File

@ -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.

View File

@ -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.

View File

@ -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(())
}

View File

@ -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<_>, _>>()?)
}

View File

@ -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

View 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 {}

View File

@ -1,3 +1,4 @@
//@run-rustfix
pub struct DataStruct();
pub struct HelperStruct<'n> {

View File

@ -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

View 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
};
}

View 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`.

View 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
};
}

View 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`.

View File

@ -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.

View 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`
}
};
}

View 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`.

View 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
}
};
}

View File

@ -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`.

View File

@ -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"]