1
Fork 0

Auto merge of #97849 - matthiaskrgr:rollup-1yodhvw, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #97829 (Add regresion test for #95307)
 - #97831 (Remove `AlwaysLiveLocals` wrapper struct)
 - #97832 (Change `Direction::{is_forward,is_backward}` functions into constants)
 - #97840 (RustWrapper: adapt to APInt API changes in LLVM 15)
 - #97845 (Use more targeted suggestion when confusing i8 with std::i8)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-06-08 00:26:37 +00:00
commit 47aee31b2a
16 changed files with 107 additions and 86 deletions

View file

@ -15,7 +15,7 @@ use rustc_middle::ty::layout::{
use rustc_middle::ty::{ use rustc_middle::ty::{
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
}; };
use rustc_mir_dataflow::storage::AlwaysLiveLocals; use rustc_mir_dataflow::storage::always_live_locals;
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
use rustc_session::Limit; use rustc_session::Limit;
use rustc_span::{Pos, Span}; use rustc_span::{Pos, Span};
@ -715,7 +715,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Now mark those locals as dead that we do not want to initialize // Now mark those locals as dead that we do not want to initialize
// Mark locals that use `Storage*` annotations as dead on function entry. // Mark locals that use `Storage*` annotations as dead on function entry.
let always_live = AlwaysLiveLocals::new(self.body()); let always_live = always_live_locals(self.body());
for local in locals.indices() { for local in locals.indices() {
if !always_live.contains(local) { if !always_live.contains(local) {
locals[local].value = LocalValue::Dead; locals[local].value = LocalValue::Dead;

View file

@ -14,7 +14,7 @@ use rustc_middle::mir::{
use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::AlwaysLiveLocals; use rustc_mir_dataflow::storage::always_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_mir_dataflow::{Analysis, ResultsCursor};
use rustc_target::abi::{Size, VariantIdx}; use rustc_target::abi::{Size, VariantIdx};
@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
let param_env = tcx.param_env(def_id); let param_env = tcx.param_env(def_id);
let mir_phase = self.mir_phase; let mir_phase = self.mir_phase;
let always_live_locals = AlwaysLiveLocals::new(body); let always_live_locals = always_live_locals(body);
let storage_liveness = MaybeStorageLive::new(always_live_locals) let storage_liveness = MaybeStorageLive::new(always_live_locals)
.into_engine(tcx, body) .into_engine(tcx, body)
.iterate_to_fixpoint() .iterate_to_fixpoint()

View file

@ -1542,11 +1542,19 @@ extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *hig
auto C = unwrap<llvm::ConstantInt>(CV); auto C = unwrap<llvm::ConstantInt>(CV);
if (C->getBitWidth() > 128) { return false; } if (C->getBitWidth() > 128) { return false; }
APInt AP; APInt AP;
#if LLVM_VERSION_GE(15, 0)
if (sext) {
AP = C->getValue().sext(128);
} else {
AP = C->getValue().zext(128);
}
#else
if (sext) { if (sext) {
AP = C->getValue().sextOrSelf(128); AP = C->getValue().sextOrSelf(128);
} else { } else {
AP = C->getValue().zextOrSelf(128); AP = C->getValue().zextOrSelf(128);
} }
#endif
*low = AP.getLoBits(64).getZExtValue(); *low = AP.getLoBits(64).getZExtValue();
*high = AP.getHiBits(64).getZExtValue(); *high = AP.getHiBits(64).getZExtValue();
return true; return true;

View file

@ -109,7 +109,7 @@ where
/// For backward analyses, this is the state that will be propagated to its /// For backward analyses, this is the state that will be propagated to its
/// predecessors (ignoring edge-specific effects). /// predecessors (ignoring edge-specific effects).
pub fn seek_to_block_start(&mut self, block: BasicBlock) { pub fn seek_to_block_start(&mut self, block: BasicBlock) {
if A::Direction::is_forward() { if A::Direction::IS_FORWARD {
self.seek_to_block_entry(block) self.seek_to_block_entry(block)
} else { } else {
self.seek_after(Location { block, statement_index: 0 }, Effect::Primary) self.seek_after(Location { block, statement_index: 0 }, Effect::Primary)
@ -123,7 +123,7 @@ where
/// For forward analyses, this is the state that will be propagated to its /// For forward analyses, this is the state that will be propagated to its
/// successors (ignoring edge-specific effects). /// successors (ignoring edge-specific effects).
pub fn seek_to_block_end(&mut self, block: BasicBlock) { pub fn seek_to_block_end(&mut self, block: BasicBlock) {
if A::Direction::is_backward() { if A::Direction::IS_BACKWARD {
self.seek_to_block_entry(block) self.seek_to_block_entry(block)
} else { } else {
self.seek_after(self.body.terminator_loc(block), Effect::Primary) self.seek_after(self.body.terminator_loc(block), Effect::Primary)
@ -157,7 +157,7 @@ where
self.seek_to_block_entry(target.block); self.seek_to_block_entry(target.block);
} else if let Some(curr_effect) = self.pos.curr_effect_index { } else if let Some(curr_effect) = self.pos.curr_effect_index {
let mut ord = curr_effect.statement_index.cmp(&target.statement_index); let mut ord = curr_effect.statement_index.cmp(&target.statement_index);
if A::Direction::is_backward() { if A::Direction::IS_BACKWARD {
ord = ord.reverse() ord = ord.reverse()
} }
@ -173,7 +173,7 @@ where
debug_assert_eq!(target.block, self.pos.block); debug_assert_eq!(target.block, self.pos.block);
let block_data = &self.body[target.block]; let block_data = &self.body[target.block];
let next_effect = if A::Direction::is_forward() { let next_effect = if A::Direction::IS_FORWARD {
#[rustfmt::skip] #[rustfmt::skip]
self.pos.curr_effect_index.map_or_else( self.pos.curr_effect_index.map_or_else(
|| Effect::Before.at_index(0), || Effect::Before.at_index(0),

View file

@ -9,11 +9,9 @@ use super::{
}; };
pub trait Direction { pub trait Direction {
fn is_forward() -> bool; const IS_FORWARD: bool;
fn is_backward() -> bool { const IS_BACKWARD: bool = !Self::IS_FORWARD;
!Self::is_forward()
}
/// Applies all effects between the given `EffectIndex`s. /// Applies all effects between the given `EffectIndex`s.
/// ///
@ -68,9 +66,7 @@ pub trait Direction {
pub struct Backward; pub struct Backward;
impl Direction for Backward { impl Direction for Backward {
fn is_forward() -> bool { const IS_FORWARD: bool = false;
false
}
fn apply_effects_in_block<'tcx, A>( fn apply_effects_in_block<'tcx, A>(
analysis: &A, analysis: &A,
@ -338,9 +334,7 @@ where
pub struct Forward; pub struct Forward;
impl Direction for Forward { impl Direction for Forward {
fn is_forward() -> bool { const IS_FORWARD: bool = true;
true
}
fn apply_effects_in_block<'tcx, A>( fn apply_effects_in_block<'tcx, A>(
analysis: &A, analysis: &A,

View file

@ -147,7 +147,7 @@ where
let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), body.basic_blocks()); let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), body.basic_blocks());
analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
if A::Direction::is_backward() && entry_sets[mir::START_BLOCK] != bottom_value { if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != bottom_value {
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
} }
@ -200,7 +200,7 @@ where
let mut dirty_queue: WorkQueue<BasicBlock> = let mut dirty_queue: WorkQueue<BasicBlock> =
WorkQueue::with_none(body.basic_blocks().len()); WorkQueue::with_none(body.basic_blocks().len());
if A::Direction::is_forward() { if A::Direction::IS_FORWARD {
for (bb, _) in traversal::reverse_postorder(body) { for (bb, _) in traversal::reverse_postorder(body) {
dirty_queue.insert(bb); dirty_queue.insert(bb);
} }

View file

@ -216,7 +216,7 @@ where
// Write the full dataflow state immediately after the terminator if it differs from the // Write the full dataflow state immediately after the terminator if it differs from the
// state at block entry. // state at block entry.
self.results.seek_to_block_end(block); self.results.seek_to_block_end(block);
if self.results.get() != &block_start_state || A::Direction::is_backward() { if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
let after_terminator_name = match terminator.kind { let after_terminator_name = match terminator.kind {
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)", mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
_ => "(on end)", _ => "(on end)",
@ -390,7 +390,7 @@ where
let mut afters = diffs.after.into_iter(); let mut afters = diffs.after.into_iter();
let next_in_dataflow_order = |it: &mut std::vec::IntoIter<_>| { let next_in_dataflow_order = |it: &mut std::vec::IntoIter<_>| {
if A::Direction::is_forward() { it.next().unwrap() } else { it.next_back().unwrap() } if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
}; };
for (i, statement) in body[block].statements.iter().enumerate() { for (i, statement) in body[block].statements.iter().enumerate() {
@ -527,7 +527,7 @@ where
_block_data: &mir::BasicBlockData<'tcx>, _block_data: &mir::BasicBlockData<'tcx>,
_block: BasicBlock, _block: BasicBlock,
) { ) {
if A::Direction::is_forward() { if A::Direction::IS_FORWARD {
self.prev_state.clone_from(state); self.prev_state.clone_from(state);
} }
} }
@ -538,7 +538,7 @@ where
_block_data: &mir::BasicBlockData<'tcx>, _block_data: &mir::BasicBlockData<'tcx>,
_block: BasicBlock, _block: BasicBlock,
) { ) {
if A::Direction::is_backward() { if A::Direction::IS_BACKWARD {
self.prev_state.clone_from(state); self.prev_state.clone_from(state);
} }
} }

View file

@ -140,7 +140,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
SeekTarget::After(loc) => Effect::Primary.at_index(loc.statement_index), SeekTarget::After(loc) => Effect::Primary.at_index(loc.statement_index),
}; };
let mut pos = if D::is_forward() { let mut pos = if D::IS_FORWARD {
Effect::Before.at_index(0) Effect::Before.at_index(0)
} else { } else {
Effect::Before.at_index(self.body[block].statements.len()) Effect::Before.at_index(self.body[block].statements.len())
@ -153,7 +153,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
return ret; return ret;
} }
if D::is_forward() { if D::IS_FORWARD {
pos = pos.next_in_forward_order(); pos = pos.next_in_forward_order();
} else { } else {
pos = pos.next_in_backward_order(); pos = pos.next_in_backward_order();

View file

@ -1,6 +1,5 @@
pub use super::*; pub use super::*;
use crate::storage::AlwaysLiveLocals;
use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor}; use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*; use rustc_middle::mir::*;
@ -8,11 +7,11 @@ use std::cell::RefCell;
#[derive(Clone)] #[derive(Clone)]
pub struct MaybeStorageLive { pub struct MaybeStorageLive {
always_live_locals: AlwaysLiveLocals, always_live_locals: BitSet<Local>,
} }
impl MaybeStorageLive { impl MaybeStorageLive {
pub fn new(always_live_locals: AlwaysLiveLocals) -> Self { pub fn new(always_live_locals: BitSet<Local>) -> Self {
MaybeStorageLive { always_live_locals } MaybeStorageLive { always_live_locals }
} }
} }

View file

@ -7,35 +7,17 @@ use rustc_middle::mir::{self, Local};
// //
// FIXME: Currently, we need to traverse the entire MIR to compute this. We should instead store it // FIXME: Currently, we need to traverse the entire MIR to compute this. We should instead store it
// as a field in the `LocalDecl` for each `Local`. // as a field in the `LocalDecl` for each `Local`.
#[derive(Debug, Clone)] pub fn always_live_locals(body: &mir::Body<'_>) -> BitSet<Local> {
pub struct AlwaysLiveLocals(BitSet<Local>); let mut always_live_locals = BitSet::new_filled(body.local_decls.len());
impl AlwaysLiveLocals { for block in body.basic_blocks() {
pub fn new(body: &mir::Body<'_>) -> Self { for statement in &block.statements {
let mut always_live_locals = AlwaysLiveLocals(BitSet::new_filled(body.local_decls.len())); use mir::StatementKind::{StorageDead, StorageLive};
if let StorageLive(l) | StorageDead(l) = statement.kind {
for block in body.basic_blocks() { always_live_locals.remove(l);
for statement in &block.statements {
use mir::StatementKind::{StorageDead, StorageLive};
if let StorageLive(l) | StorageDead(l) = statement.kind {
always_live_locals.0.remove(l);
}
} }
} }
always_live_locals
} }
pub fn into_inner(self) -> BitSet<Local> { always_live_locals
self.0
}
}
impl std::ops::Deref for AlwaysLiveLocals {
type Target = BitSet<Local>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
} }

View file

@ -228,7 +228,7 @@ struct TransformVisitor<'tcx> {
suspension_points: Vec<SuspensionPoint<'tcx>>, suspension_points: Vec<SuspensionPoint<'tcx>>,
// The set of locals that have no `StorageLive`/`StorageDead` annotations. // The set of locals that have no `StorageLive`/`StorageDead` annotations.
always_live_locals: storage::AlwaysLiveLocals, always_live_locals: BitSet<Local>,
// The original RETURN_PLACE local // The original RETURN_PLACE local
new_ret_local: Local, new_ret_local: Local,
@ -450,7 +450,7 @@ struct LivenessInfo {
fn locals_live_across_suspend_points<'tcx>( fn locals_live_across_suspend_points<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
always_live_locals: &storage::AlwaysLiveLocals, always_live_locals: &BitSet<Local>,
movable: bool, movable: bool,
) -> LivenessInfo { ) -> LivenessInfo {
let body_ref: &Body<'_> = &body; let body_ref: &Body<'_> = &body;
@ -615,7 +615,7 @@ impl ops::Deref for GeneratorSavedLocals {
fn compute_storage_conflicts<'mir, 'tcx>( fn compute_storage_conflicts<'mir, 'tcx>(
body: &'mir Body<'tcx>, body: &'mir Body<'tcx>,
saved_locals: &GeneratorSavedLocals, saved_locals: &GeneratorSavedLocals,
always_live_locals: storage::AlwaysLiveLocals, always_live_locals: BitSet<Local>,
requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> { ) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
assert_eq!(body.local_decls.len(), saved_locals.domain_size()); assert_eq!(body.local_decls.len(), saved_locals.domain_size());
@ -625,7 +625,7 @@ fn compute_storage_conflicts<'mir, 'tcx>(
// Locals that are always live or ones that need to be stored across // Locals that are always live or ones that need to be stored across
// suspension points are not eligible for overlap. // suspension points are not eligible for overlap.
let mut ineligible_locals = always_live_locals.into_inner(); let mut ineligible_locals = always_live_locals;
ineligible_locals.intersect(&**saved_locals); ineligible_locals.intersect(&**saved_locals);
// Compute the storage conflicts for all eligible locals. // Compute the storage conflicts for all eligible locals.
@ -1300,7 +1300,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
}, },
); );
let always_live_locals = storage::AlwaysLiveLocals::new(&body); let always_live_locals = storage::always_live_locals(&body);
let liveness_info = let liveness_info =
locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);

View file

@ -1577,18 +1577,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
name: Symbol, name: Symbol,
) -> ErrorGuaranteed { ) -> ErrorGuaranteed {
let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type"); let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
if let (true, Ok(snippet)) = ( if self
self.tcx() .tcx()
.resolutions(()) .resolutions(())
.confused_type_with_std_module .confused_type_with_std_module
.keys() .keys()
.any(|full_span| full_span.contains(span)), .any(|full_span| full_span.contains(span))
self.tcx().sess.source_map().span_to_snippet(span), {
) {
err.span_suggestion( err.span_suggestion(
span, span.shrink_to_lo(),
"you are looking for the module in `std`, not the primitive type", "you are looking for the module in `std`, not the primitive type",
format!("std::{}", snippet), "std::".to_string(),
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} else { } else {

View file

@ -327,26 +327,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
} }
if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) { if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) {
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) { err.span_suggestion(
err.span_suggestion( span.shrink_to_lo(),
*span, "you are looking for the module in `std`, not the primitive type",
"you are looking for the module in `std`, \ "std::".to_string(),
not the primitive type", Applicability::MachineApplicable,
format!("std::{}", snippet), );
Applicability::MachineApplicable,
);
}
} }
if let ty::RawPtr(_) = &actual.kind() { if let ty::RawPtr(_) = &actual.kind() {
err.note( err.note(
"try using `<*const T>::as_ref()` to get a reference to the \ "try using `<*const T>::as_ref()` to get a reference to the \
type behind the pointer: https://doc.rust-lang.org/std/\ type behind the pointer: https://doc.rust-lang.org/std/\
primitive.pointer.html#method.as_ref", primitive.pointer.html#method.as_ref",
); );
err.note( err.note(
"using `<*const T>::as_ref()` on a pointer \ "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
which is unaligned or points to invalid \ to invalid or uninitialized memory is undefined behavior",
or uninitialized memory is undefined behavior",
); );
} }

View file

@ -0,0 +1,13 @@
// edition:2018
// Regression test for #95307.
// The ICE occurred on all the editions, specifying edition:2018 to reduce diagnostics.
pub trait C {
async fn new() -> [u8; _];
//~^ ERROR: functions in traits cannot be declared `async`
//~| ERROR: using `_` for array lengths is unstable
//~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
}
fn main() {}

View file

@ -0,0 +1,30 @@
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/issue-95307.rs:7:5
|
LL | async fn new() -> [u8; _];
| -----^^^^^^^^^^^^^^^^^^^^^
| |
| `async` because of this
|
= note: `async` trait functions are not currently supported
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
error[E0658]: using `_` for array lengths is unstable
--> $DIR/issue-95307.rs:7:28
|
LL | async fn new() -> [u8; _];
| ^
|
= note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
error: in expressions, `_` can only be used on the left-hand side of an assignment
--> $DIR/issue-95307.rs:7:28
|
LL | async fn new() -> [u8; _];
| ^ `_` not allowed here
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0658, E0706.
For more information about an error, try `rustc --explain E0658`.

View file

@ -7,7 +7,7 @@ LL | let pi = f32::consts::PI;
help: you are looking for the module in `std`, not the primitive type help: you are looking for the module in `std`, not the primitive type
| |
LL | let pi = std::f32::consts::PI; LL | let pi = std::f32::consts::PI;
| ~~~~~~~~~~~~~~~~ | +++++
error[E0599]: no function or associated item named `from_utf8` found for type `str` in the current scope error[E0599]: no function or associated item named `from_utf8` found for type `str` in the current scope
--> $DIR/suggest-std-when-using-type.rs:5:14 --> $DIR/suggest-std-when-using-type.rs:5:14
@ -18,7 +18,7 @@ LL | str::from_utf8(bytes)
help: you are looking for the module in `std`, not the primitive type help: you are looking for the module in `std`, not the primitive type
| |
LL | std::str::from_utf8(bytes) LL | std::str::from_utf8(bytes)
| ~~~~~~~~~~~~~~~~~~~ | +++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors