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:
commit
47aee31b2a
16 changed files with 107 additions and 86 deletions
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
13
src/test/ui/async-await/issues/issue-95307.rs
Normal file
13
src/test/ui/async-await/issues/issue-95307.rs
Normal 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() {}
|
30
src/test/ui/async-await/issues/issue-95307.stderr
Normal file
30
src/test/ui/async-await/issues/issue-95307.stderr
Normal 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`.
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue