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::{
|
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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
|
||||||
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 block in body.basic_blocks() {
|
||||||
for statement in &block.statements {
|
for statement in &block.statements {
|
||||||
use mir::StatementKind::{StorageDead, StorageLive};
|
use mir::StatementKind::{StorageDead, StorageLive};
|
||||||
if let StorageLive(l) | StorageDead(l) = statement.kind {
|
if let StorageLive(l) | StorageDead(l) = statement.kind {
|
||||||
always_live_locals.0.remove(l);
|
always_live_locals.remove(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
always_live_locals
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -327,16 +327,13 @@ 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,
|
span.shrink_to_lo(),
|
||||||
"you are looking for the module in `std`, \
|
"you are looking for the module in `std`, not the primitive type",
|
||||||
not the primitive type",
|
"std::".to_string(),
|
||||||
format!("std::{}", snippet),
|
|
||||||
Applicability::MachineApplicable,
|
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 \
|
||||||
|
@ -344,9 +341,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
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",
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
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
|
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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue