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::{
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_session::Limit;
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
// 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() {
if !always_live.contains(local) {
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::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
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_target::abi::{Size, VariantIdx};
@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
let param_env = tcx.param_env(def_id);
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)
.into_engine(tcx, body)
.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);
if (C->getBitWidth() > 128) { return false; }
APInt AP;
#if LLVM_VERSION_GE(15, 0)
if (sext) {
AP = C->getValue().sext(128);
} else {
AP = C->getValue().zext(128);
}
#else
if (sext) {
AP = C->getValue().sextOrSelf(128);
} else {
AP = C->getValue().zextOrSelf(128);
}
#endif
*low = AP.getLoBits(64).getZExtValue();
*high = AP.getHiBits(64).getZExtValue();
return true;

View file

@ -109,7 +109,7 @@ where
/// For backward analyses, this is the state that will be propagated to its
/// predecessors (ignoring edge-specific effects).
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)
} else {
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
/// successors (ignoring edge-specific effects).
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)
} else {
self.seek_after(self.body.terminator_loc(block), Effect::Primary)
@ -157,7 +157,7 @@ where
self.seek_to_block_entry(target.block);
} else if let Some(curr_effect) = self.pos.curr_effect_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()
}
@ -173,7 +173,7 @@ where
debug_assert_eq!(target.block, self.pos.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]
self.pos.curr_effect_index.map_or_else(
|| Effect::Before.at_index(0),

View file

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

View file

@ -147,7 +147,7 @@ where
let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), body.basic_blocks());
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");
}
@ -200,7 +200,7 @@ where
let mut dirty_queue: WorkQueue<BasicBlock> =
WorkQueue::with_none(body.basic_blocks().len());
if A::Direction::is_forward() {
if A::Direction::IS_FORWARD {
for (bb, _) in traversal::reverse_postorder(body) {
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
// state at block entry.
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 {
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
_ => "(on end)",
@ -390,7 +390,7 @@ where
let mut afters = diffs.after.into_iter();
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() {
@ -527,7 +527,7 @@ where
_block_data: &mir::BasicBlockData<'tcx>,
_block: BasicBlock,
) {
if A::Direction::is_forward() {
if A::Direction::IS_FORWARD {
self.prev_state.clone_from(state);
}
}
@ -538,7 +538,7 @@ where
_block_data: &mir::BasicBlockData<'tcx>,
_block: BasicBlock,
) {
if A::Direction::is_backward() {
if A::Direction::IS_BACKWARD {
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),
};
let mut pos = if D::is_forward() {
let mut pos = if D::IS_FORWARD {
Effect::Before.at_index(0)
} else {
Effect::Before.at_index(self.body[block].statements.len())
@ -153,7 +153,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
return ret;
}
if D::is_forward() {
if D::IS_FORWARD {
pos = pos.next_in_forward_order();
} else {
pos = pos.next_in_backward_order();

View file

@ -1,6 +1,5 @@
pub use super::*;
use crate::storage::AlwaysLiveLocals;
use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@ -8,11 +7,11 @@ use std::cell::RefCell;
#[derive(Clone)]
pub struct MaybeStorageLive {
always_live_locals: AlwaysLiveLocals,
always_live_locals: BitSet<Local>,
}
impl MaybeStorageLive {
pub fn new(always_live_locals: AlwaysLiveLocals) -> Self {
pub fn new(always_live_locals: BitSet<Local>) -> Self {
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
// as a field in the `LocalDecl` for each `Local`.
#[derive(Debug, Clone)]
pub struct AlwaysLiveLocals(BitSet<Local>);
pub fn always_live_locals(body: &mir::Body<'_>) -> BitSet<Local> {
let mut always_live_locals = BitSet::new_filled(body.local_decls.len());
impl AlwaysLiveLocals {
pub fn new(body: &mir::Body<'_>) -> Self {
let mut always_live_locals = AlwaysLiveLocals(BitSet::new_filled(body.local_decls.len()));
for block in body.basic_blocks() {
for statement in &block.statements {
use mir::StatementKind::{StorageDead, StorageLive};
if let StorageLive(l) | StorageDead(l) = statement.kind {
always_live_locals.0.remove(l);
}
for block in body.basic_blocks() {
for statement in &block.statements {
use mir::StatementKind::{StorageDead, StorageLive};
if let StorageLive(l) | StorageDead(l) = statement.kind {
always_live_locals.remove(l);
}
}
always_live_locals
}
pub fn into_inner(self) -> BitSet<Local> {
self.0
}
}
impl std::ops::Deref for AlwaysLiveLocals {
type Target = BitSet<Local>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
always_live_locals
}

View file

@ -228,7 +228,7 @@ struct TransformVisitor<'tcx> {
suspension_points: Vec<SuspensionPoint<'tcx>>,
// 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
new_ret_local: Local,
@ -450,7 +450,7 @@ struct LivenessInfo {
fn locals_live_across_suspend_points<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
always_live_locals: &storage::AlwaysLiveLocals,
always_live_locals: &BitSet<Local>,
movable: bool,
) -> LivenessInfo {
let body_ref: &Body<'_> = &body;
@ -615,7 +615,7 @@ impl ops::Deref for GeneratorSavedLocals {
fn compute_storage_conflicts<'mir, 'tcx>(
body: &'mir Body<'tcx>,
saved_locals: &GeneratorSavedLocals,
always_live_locals: storage::AlwaysLiveLocals,
always_live_locals: BitSet<Local>,
requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
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
// 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);
// 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 =
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,
) -> ErrorGuaranteed {
let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
if let (true, Ok(snippet)) = (
self.tcx()
.resolutions(())
.confused_type_with_std_module
.keys()
.any(|full_span| full_span.contains(span)),
self.tcx().sess.source_map().span_to_snippet(span),
) {
if self
.tcx()
.resolutions(())
.confused_type_with_std_module
.keys()
.any(|full_span| full_span.contains(span))
{
err.span_suggestion(
span,
span.shrink_to_lo(),
"you are looking for the module in `std`, not the primitive type",
format!("std::{}", snippet),
"std::".to_string(),
Applicability::MachineApplicable,
);
} 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 Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
err.span_suggestion(
*span,
"you are looking for the module in `std`, \
not the primitive type",
format!("std::{}", snippet),
Applicability::MachineApplicable,
);
}
err.span_suggestion(
span.shrink_to_lo(),
"you are looking for the module in `std`, not the primitive type",
"std::".to_string(),
Applicability::MachineApplicable,
);
}
if let ty::RawPtr(_) = &actual.kind() {
err.note(
"try using `<*const T>::as_ref()` to get a reference to the \
type behind the pointer: https://doc.rust-lang.org/std/\
primitive.pointer.html#method.as_ref",
type behind the pointer: https://doc.rust-lang.org/std/\
primitive.pointer.html#method.as_ref",
);
err.note(
"using `<*const T>::as_ref()` on a pointer \
which is unaligned or points to invalid \
or uninitialized memory is undefined behavior",
"using `<*const T>::as_ref()` on a pointer which is unaligned or points \
to invalid 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
|
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
--> $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
|
LL | std::str::from_utf8(bytes)
| ~~~~~~~~~~~~~~~~~~~
| +++++
error: aborting due to 2 previous errors