Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// we'll use this to check whether it was originally from an overloaded
// operator.
match self.move_data.rev_lookup.find(deref_base) {
LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
LookupResult::Exact(mpi) | LookupResult::Parent { mpi, .. } => {
debug!("borrowed_content_source: mpi={:?}", mpi);

for i in &self.move_data.init_path_map[mpi] {
Expand Down Expand Up @@ -580,7 +580,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
}
}
// Base is a `static` so won't be from an overloaded operator
_ => (),
LookupResult::None => (),
};

// If we didn't find an overloaded deref or index, then assume it's a
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {

match self.move_data.rev_lookup.find(match_place.as_ref()) {
// Error with the match place
LookupResult::Parent(_) => {
LookupResult::Parent { .. } | LookupResult::None => {
for ge in &mut *grouped_errors {
if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge
&& match_span == *span
Expand Down Expand Up @@ -218,7 +218,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
}
// Error with the pattern
LookupResult::Exact(_) => {
let LookupResult::Parent(Some(mpi)) =
let LookupResult::Parent { mpi, .. } =
self.move_data.rev_lookup.find(move_from.as_ref())
else {
// move_from should be a projection from match_place.
Expand Down
56 changes: 32 additions & 24 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2075,15 +2075,42 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
// This code covers scenarios 1, 2, and 3.

debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
let (prefix, mpi) = self.move_path_closest_to(place_span.0);
if maybe_uninits.contains(mpi) {

let uninit_mpi = match self.move_data.rev_lookup.find(place_span.0) {
// Index projections arbitrarily overlap sibling move paths, so we need to check all descendents of the parent
// Subslice and ConstantIndex projections of slices also overlap siblings,
// but the parent slice will never have a move path
// Subslice projections of arrays are specifically checked in `check_if_subslice_element_is_moved`
LookupResult::Parent { mpi, next_elem: ProjectionKind::Index(..) } => self
.move_data
.find_in_move_path_or_its_descendants(mpi, |mpi| maybe_uninits.contains(mpi)),

LookupResult::Exact(mpi)
| LookupResult::Parent {
mpi,
next_elem:
ProjectionKind::Deref
| ProjectionKind::Field(..)
| ProjectionKind::ConstantIndex { .. }
| ProjectionKind::Subslice { .. }
| ProjectionKind::Downcast(..)
| ProjectionKind::OpaqueCast(..)
| ProjectionKind::UnwrapUnsafeBinder(..),
} => maybe_uninits.contains(mpi).then_some(mpi),

LookupResult::None => bug!("should have move path for every Local"),
};

if let Some(mpi) = uninit_mpi {
self.report_use_of_moved_or_uninitialized(
location,
desired_action,
(prefix, place_span.0, place_span.1),
(self.move_data.move_paths[mpi].place.as_ref(), place_span.0, place_span.1),
mpi,
);
} // Only query longest prefix with a MovePath, not further
}

// Only query longest prefix with a MovePath, not further
// ancestors; dataflow recurs on children when parents
// move (to support partial (re)inits).
//
Expand Down Expand Up @@ -2205,32 +2232,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
}
}

/// Currently MoveData does not store entries for all places in
/// the input MIR. For example it will currently filter out
/// places that are Copy; thus we do not track places of shared
/// reference type. This routine will walk up a place along its
/// prefixes, searching for a foundational place that *is*
/// tracked in the MoveData.
///
/// An Err result includes a tag indicated why the search failed.
/// Currently this can only occur if the place is built off of a
/// static variable, as we do not track those in the MoveData.
fn move_path_closest_to(&mut self, place: PlaceRef<'tcx>) -> (PlaceRef<'tcx>, MovePathIndex) {
match self.move_data.rev_lookup.find(place) {
LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
(self.move_data.move_paths[mpi].place.as_ref(), mpi)
}
LookupResult::Parent(None) => panic!("should have move path for every Local"),
}
}

fn move_path_for_place(&mut self, place: PlaceRef<'tcx>) -> Option<MovePathIndex> {
// If returns None, then there is no move path corresponding
// to a direct owner of `place` (which means there is nothing
// that borrowck tracks for its analysis).

match self.move_data.rev_lookup.find(place) {
LookupResult::Parent(_) => None,
LookupResult::Parent { .. } | LookupResult::None => None,
LookupResult::Exact(mpi) => Some(mpi),
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
match context {
PlaceContext::NonMutatingUse(_)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
let (LookupResult::Exact(path) | LookupResult::Parent(Some(path))) =
let (LookupResult::Exact(path) | LookupResult::Parent { mpi: path, .. }) =
self.move_data.rev_lookup.find(place.as_ref())
else {
// There's no path access to emit.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ unsafe fn configure_llvm(sess: &EarlySession) {
}
}

if wants_wasm_eh(&sess.target) {
if get_version() < (24, 0, 0) && wants_wasm_eh(&sess.target) {
add("-wasm-enable-eh", false);
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2190,7 +2190,7 @@ impl<'tcx> Ty<'tcx> {
def.flags().contains(AdtFlags::IS_MAYBE_DANGLING)
|| def.flags().contains(AdtFlags::IS_MANUALLY_DROP)
}
ty::Coroutine(..) | ty::CoroutineClosure(..) => true,
ty::Coroutine(..) => true,
_ => false,
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub fn on_lookup_result_bits<'tcx, F>(
F: FnMut(MovePathIndex),
{
match lookup_result {
LookupResult::Parent(..) => {
LookupResult::Parent { .. } | LookupResult::None => {
// access to untracked value - do not touch children
}
LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child),
Expand Down
21 changes: 14 additions & 7 deletions compiler/rustc_mir_dataflow/src/move_paths/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,11 +344,18 @@ pub enum LookupResult {
/// This exact thing has a move path. E.g. we looked up `x` or `x.m` and it has been moved.
Exact(MovePathIndex),

/// - If the field is `None`, neither the exact thing nor any ancestor of it has a move path.
/// E.g. we looked up `x.m` and neither it nor `x` have a move path.
/// - If the field is `Some`, the exact thing has no move path, but an ancestor does. E.g. we
/// looked up `x.m` which has no move path but `x` has one. Not possible for locals.
Parent(Option<MovePathIndex>),
/// The exact thing has no move path, but an ancestor does.
/// E.g. we looked up `x.m` which has no move path but `x` has one. Not possible for locals.
Parent {
mpi: MovePathIndex,

/// The projection in the place immediately projecting from the parent move path.
next_elem: ProjectionKind,
},

/// Neither the exact thing nor any ancestor of it has a move path.
/// E.g. we looked up `x.m` and neither it nor `x` have a move path.
None,
}

impl<'tcx> MovePathLookup<'tcx> {
Expand All @@ -359,7 +366,7 @@ impl<'tcx> MovePathLookup<'tcx> {
pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult {
// Look first in the locals (roots).
let Some(mut result) = self.find_local(place.local) else {
return LookupResult::Parent(None);
return LookupResult::None;
};

// Look for a projection through the found local.
Expand All @@ -372,7 +379,7 @@ impl<'tcx> MovePathLookup<'tcx> {
};

let Some(&subpath) = subpath else {
return LookupResult::Parent(Some(result));
return LookupResult::Parent { mpi: result, next_elem: elem.kind() };
};
result = subpath;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/rustc_peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ where
}
}

LookupResult::Parent(..) => {
LookupResult::Parent { .. } | LookupResult::None => {
tcx.dcx().emit_err(PeekArgumentUntracked { span: call.span });
}
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir_transform/src/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
}
});
}
LookupResult::Parent(None) => {}
LookupResult::Parent(Some(parent)) => {
LookupResult::None => {}
LookupResult::Parent { mpi: parent, .. } => {
if self.body.local_decls[place.local].is_deref_temp() {
continue;
}
Expand Down Expand Up @@ -387,8 +387,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
drop,
)
}
LookupResult::Parent(None) => {}
LookupResult::Parent(Some(_)) => {
LookupResult::None => {}
LookupResult::Parent { .. } => {
if !replace {
self.tcx.dcx().span_bug(
terminator.source_info.span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> {
}
MovePathIndexAtBlock::Unknown => {
if let TerminatorKind::Drop { place, .. } = &terminator.kind
&& let LookupResult::Exact(idx) | LookupResult::Parent(Some(idx)) =
&& let LookupResult::Exact(idx) | LookupResult::Parent { mpi: idx, .. } =
self.move_data.rev_lookup.find(place.as_ref())
{
// Since we are working with MIRs at a very early stage, observing a `drop`
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
ast::UseTreeKind::Simple(Some(ident)) => {
if ident.name == kw::Underscore
&& !matches!(
self.r.current_owner.import_res[&id].type_ns,
self.r.current_owner.import_res.get(&id).and_then(|res| res.type_ns),
Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
)
{
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3082,16 +3082,16 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {

/// Invoked when the node with dfn `dfn` does not get a successful
/// result. This will clear out any provisional cache entries
/// that were added since `dfn` was created. This is because the
/// provisional entries are things which must assume that the
/// things on the stack at the time of their creation succeeded --
/// since the failing node is presently at the top of the stack,
/// these provisional entries must either depend on it or some
/// ancestor of it.
/// originating from nodes visited before this node (`from_dfn < dfn`).
/// This is because the provisional entries are things which must
/// assume that the things on the stack at the time of their creation
/// succeeded -- since the failing node is presently at the top of
/// the stack, these provisional entries must either depend on it or
/// some ancestor of it.
fn on_failure(&self, dfn: usize) {
debug!(?dfn, "on_failure");
self.map.borrow_mut().retain(|key, eval| {
if !eval.from_dfn >= dfn {
if eval.from_dfn < dfn {
debug!("on_failure: removing {:?}", key);
false
} else {
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_type_ir/src/ty_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ pub enum TyKind<I: Interner> {
/// `ClosureArgs` for more details.
Closure(I::ClosureId, I::GenericArgs),

/// The anonymous type of a closure. Used to represent the type of `async |a| a`.
/// The anonymous type of an async closure. Used to represent the type of `async |a| a`.
///
/// This type itself is not a coroutine, it just represents a closure that returns one.
///
/// Coroutine-closure args contain both the - potentially instantiated - generic
/// parameters of its parent and some synthetic parameters. See the documentation
Expand Down
71 changes: 48 additions & 23 deletions tests/assembly-llvm/simd-intrinsic-select.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// ignore-tidy-file-linelength
//@ add-minicore
//@ revisions: x86-avx2 x86-avx512 aarch64
//@ revisions: x86-avx2 x86-avx-512-llvm23 x86-avx-512 aarch64
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
//@ [x86-avx2] needs-llvm-components: x86
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx512] needs-llvm-components: x86
//@ [x86-avx-512-llvm23] max-llvm-major-version: 23
//@ [x86-avx-512-llvm23] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx-512-llvm23] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx-512-llvm23] needs-llvm-components: x86
//@ [x86-avx-512] min-llvm-version: 24
//@ [x86-avx-512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
//@ [x86-avx-512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
//@ [x86-avx-512] needs-llvm-components: x86
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
//@ [aarch64] needs-llvm-components: aarch64
//@ assembly-output: emit-asm
Expand Down Expand Up @@ -34,9 +40,13 @@ pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16
// x86-avx2-NOT: vpsllw
// x86-avx2: vpblendvb xmm0, xmm2, xmm1, xmm0
//
// x86-avx512-NOT: vpsllw
// x86-avx512: vpmovb2m k1, xmm0
// x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1
// x86-avx-512-llvm23-NOT: vpsllw
// x86-avx-512-llvm23: vpmovb2m k1, xmm0
// x86-avx-512-llvm23-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1
//
// x86-avx-512-NOT: vpsllw
// x86-avx-512: vpmovb2m k1, xmm0
// x86-avx-512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1
//
// aarch64-NOT: shl
// aarch64: cmlt v0.16b, v0.16b, #0
Expand All @@ -50,9 +60,12 @@ pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4
// x86-avx2-NOT: vpslld
// x86-avx2: vblendvps xmm0, xmm2, xmm1, xmm0
//
// x86-avx512-NOT: vpslld
// x86-avx512: vpmovd2m k1, xmm0
// x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1
// x86-avx-512-llvm23-NOT: vpslld
// x86-avx-512-llvm23: vpmovd2m k1, xmm0
// x86-avx-512-llvm23-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1
//
// x86-avx-512-NOT: vpslld
// x86-avx-512: vblendvps xmm0, xmm2, xmm1, xmm0
//
// aarch64-NOT: shl
// aarch64: cmlt v0.4s, v0.4s, #0
Expand All @@ -66,9 +79,12 @@ pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2
// x86-avx2-NOT: vpsllq
// x86-avx2: vblendvpd xmm0, xmm2, xmm1, xmm0
//
// x86-avx512-NOT: vpsllq
// x86-avx512: vpmovq2m k1, xmm0
// x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1
// x86-avx-512-llvm23-NOT: vpsllq
// x86-avx-512-llvm23: vpmovq2m k1, xmm0
// x86-avx-512-llvm23-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1
//
// x86-avx-512-NOT: vpsllq
// x86-avx-512: vblendvpd xmm0, xmm2, xmm1, xmm0
//
// aarch64-NOT: shl
// aarch64: cmlt v0.2d, v0.2d, #0
Expand All @@ -77,29 +93,38 @@ pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2
}

// x86-avx2-LABEL: select_f64x4
// x86-avx512-LABEL: select_f64x4
// x86-avx-512-llvm23-LABEL: select_f64x4
// x86-avx-512-LABEL: select_f64x4
#[no_mangle]
#[cfg(any(x86_avx2, x86_avx512))]
#[cfg(any(x86_avx2, x86_avx_512, x86_avx_512_llvm23))]
pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 {
// The parameter is a 256 bit vector which in the C abi is only valid for avx targets.
//
// x86-avx2-NOT: vpsllq
// x86-avx2: vblendvpd ymm0, ymm2, ymm1, ymm0
//
// x86-avx512-NOT: vpsllq
// x86-avx512: vpmovq2m k1, ymm0
// x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1
// x86-avx-512-llvm23-NOT: vpsllq
// x86-avx-512-llvm23: vpmovq2m k1, ymm0
// x86-avx-512-llvm23-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1
//
// x86-avx-512-NOT: vpsllq
// x86-avx-512: vblendvpd ymm0, ymm2, ymm1, ymm0
simd_select(mask, a, b)
}

// x86-avx512-LABEL: select_f64x8
// x86-avx-512-llvm23-LABEL: select_f64x8
// x86-avx-512-LABEL: select_f64x8
#[no_mangle]
#[cfg(x86_avx512)]
#[cfg(any(x86_avx_512, x86_avx_512_llvm23))]
pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 {
// The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets.
//
// x86-avx512-NOT: vpsllq
// x86-avx512: vpmovq2m k1, zmm0
// x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1
// x86-avx-512-llvm23-NOT: vpsllq
// x86-avx-512-llvm23: vpmovq2m k1, zmm0
// x86-avx-512-llvm23-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1
//
// x86-avx-512-NOT: vpsllq
// x86-avx-512: vpmovq2m k1, zmm0
// x86-avx-512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1
simd_select(mask, a, b)
}
Loading
Loading