Skip to content
Merged
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
5 changes: 4 additions & 1 deletion bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@
# toolchain or changing LLVM locally, you probably want to leave this enabled.
#
# Set this to `true` to download if CI llvm available otherwise it builds
# from `src/llvm-project`.
# from `src/llvm-project`. If you set it to `true`, it's safe and time-saving to run
# `git submodule deinit src/llvm-project` to avoid git updating the llvm-project submodule
# when building compiler locally.
#
#
# Set this to `"if-unchanged"` to download only if the llvm-project has not
# been modified. You can also use this if you are unsure whether you're on a
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1929,7 +1929,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// ControlFlow::Break(residual) =>
/// #[allow(unreachable_code)]
/// // If there is an enclosing `try {...}`:
/// break 'catch_target Try::from_residual(residual),
/// break 'catch_target Residual::into_try_type(residual),
/// // Otherwise:
/// return Try::from_residual(residual),
/// }
Expand Down Expand Up @@ -1979,7 +1979,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
let from_residual_expr = self.wrap_in_try_constructor(
hir::LangItem::TryTraitFromResidual,
if self.catch_scope.is_some() {
hir::LangItem::ResidualIntoTryType
} else {
hir::LangItem::TryTraitFromResidual
},
try_span,
self.arena.alloc(residual_expr),
unstable_span,
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
impl_trait_defs: Vec::new(),
impl_trait_bounds: Vec::new(),
allow_contracts: [sym::contracts_internals].into(),
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
allow_try_trait: [
sym::try_trait_v2,
sym::try_trait_v2_residual,
sym::yeet_desugar_details,
]
.into(),
allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
allow_gen_future: if tcx.features().async_fn_track_caller() {
[sym::gen_future, sym::closure_track_caller].into()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ language_item_table! {
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
ResidualIntoTryType, sym::into_try_type, into_try_type_fn, Target::Fn, GenericRequirement::None;

CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);

Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_hir_typeck/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_middle::bug;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, Symbol, sym};
use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
use rustc_target::asm::{
InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo,
};
Expand All @@ -27,6 +27,7 @@ enum NonAsmTypeReason<'tcx> {
InvalidElement(DefId, Ty<'tcx>),
NotSizedPtr(Ty<'tcx>),
EmptySIMDArray(Ty<'tcx>),
Tainted(ErrorGuaranteed),
}

impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
Expand Down Expand Up @@ -93,6 +94,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
}
ty::Adt(adt, args) if adt.repr().simd() => {
if !adt.is_struct() {
let guar = self.fcx.dcx().span_delayed_bug(
span,
format!("repr(simd) should only be used on structs, got {}", adt.descr()),
);
return Err(NonAsmTypeReason::Tainted(guar));
}

let fields = &adt.non_enum_variant().fields;
if fields.is_empty() {
return Err(NonAsmTypeReason::EmptySIMDArray(ty));
Expand Down Expand Up @@ -234,6 +243,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let msg = format!("use of empty SIMD vector `{ty}`");
self.fcx.dcx().struct_span_err(expr.span, msg).emit();
}
NonAsmTypeReason::Tainted(_error_guard) => {
// An error has already been reported.
}
}
return None;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ pub(crate) fn run_in_thread_pool_with_globals<
let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || {
// Ensure there was no errors collecting all active jobs.
// We need the complete map to ensure we find a cycle to break.
QueryCtxt::new(tcx).collect_active_jobs().expect("failed to collect active queries in deadlock handler")
QueryCtxt::new(tcx).collect_active_jobs(false).expect("failed to collect active queries in deadlock handler")
});
break_query_cycles(query_map, &registry);
})
Expand Down
36 changes: 21 additions & 15 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,25 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> {
tls::with_related_context(self.tcx, |icx| icx.query)
}

/// Returns a query map representing active query jobs.
/// It returns an incomplete map as an error if it fails
/// to take locks.
/// Returns a map of currently active query jobs.
///
/// If `require_complete` is `true`, this function locks all shards of the
/// query results to produce a complete map, which always returns `Ok`.
/// Otherwise, it may return an incomplete map as an error if any shard
/// lock cannot be acquired.
///
/// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
/// especially when called from within a deadlock handler, unless a
/// complete map is needed and no deadlock is possible at this call site.
fn collect_active_jobs(
self,
require_complete: bool,
) -> Result<QueryMap<QueryStackDeferred<'tcx>>, QueryMap<QueryStackDeferred<'tcx>>> {
let mut jobs = QueryMap::default();
let mut complete = true;

for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
if collect(self.tcx, &mut jobs).is_none() {
for collect in super::COLLECT_ACTIVE_JOBS.iter() {
if collect(self.tcx, &mut jobs, require_complete).is_none() {
complete = false;
}
}
Expand Down Expand Up @@ -163,11 +171,7 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> {
}

fn depth_limit_error(self, job: QueryJobId) {
// FIXME: `collect_active_jobs` expects no locks to be held, which doesn't hold for this call.
let query_map = match self.collect_active_jobs() {
Ok(query_map) => query_map,
Err(query_map) => query_map,
};
let query_map = self.collect_active_jobs(true).expect("failed to collect active queries");
let (info, depth) = job.find_dep_kind_root(query_map);

let suggested_limit = match self.recursion_limit() {
Expand Down Expand Up @@ -731,19 +735,21 @@ macro_rules! define_queries {
}
}

pub(crate) fn try_collect_active_jobs<'tcx>(
pub(crate) fn collect_active_jobs<'tcx>(
tcx: TyCtxt<'tcx>,
qmap: &mut QueryMap<QueryStackDeferred<'tcx>>,
require_complete: bool,
) -> Option<()> {
let make_query = |tcx, key| {
let kind = rustc_middle::dep_graph::dep_kinds::$name;
let name = stringify!($name);
$crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
};
let res = tcx.query_system.states.$name.try_collect_active_jobs(
let res = tcx.query_system.states.$name.collect_active_jobs(
tcx,
make_query,
qmap,
require_complete,
);
// this can be called during unwinding, and the function has a `try_`-prefix, so
// don't `unwrap()` here, just manually check for `None` and do best-effort error
Expand Down Expand Up @@ -814,10 +820,10 @@ macro_rules! define_queries {

// These arrays are used for iteration and can't be indexed by `DepKind`.

const TRY_COLLECT_ACTIVE_JOBS: &[
for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>) -> Option<()>
const COLLECT_ACTIVE_JOBS: &[
for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>, bool) -> Option<()>
] =
&[$(query_impl::$name::try_collect_active_jobs),*];
&[$(query_impl::$name::collect_active_jobs),*];

const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_system/src/query/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
let mut count_total = 0;

// Make use of a partial query map if we fail to take locks collecting active queries.
let query_map = match qcx.collect_active_jobs() {
let query_map = match qcx.collect_active_jobs(false) {
Ok(query_map) => query_map,
Err(query_map) => query_map,
};
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_query_system/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ pub trait QueryContext: HasDepContext {
/// Get the query information from the TLS context.
fn current_query_job(self) -> Option<QueryJobId>;

fn collect_active_jobs(self) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;
fn collect_active_jobs(
self,
require_complete: bool,
) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;

fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra;

Expand Down
27 changes: 20 additions & 7 deletions compiler/rustc_query_system/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ use std::fmt::Debug;
use std::hash::Hash;
use std::mem;

use hashbrown::HashTable;
use hashbrown::hash_table::Entry;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::LockGuard;
use rustc_data_structures::{outline, sync};
use rustc_errors::{Diag, FatalError, StashKey};
use rustc_span::{DUMMY_SP, Span};
Expand Down Expand Up @@ -63,22 +65,33 @@ where
self.active.lock_shards().all(|shard| shard.is_empty())
}

pub fn try_collect_active_jobs<Qcx: Copy>(
pub fn collect_active_jobs<Qcx: Copy>(
&self,
qcx: Qcx,
make_query: fn(Qcx, K) -> QueryStackFrame<I>,
jobs: &mut QueryMap<I>,
require_complete: bool,
) -> Option<()> {
let mut active = Vec::new();

// We use try_lock_shards here since we are called from the
// deadlock handler, and this shouldn't be locked.
for shard in self.active.try_lock_shards() {
for (k, v) in shard?.iter() {
let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<I>)>>| {
for (k, v) in iter.iter() {
if let QueryResult::Started(ref job) = *v {
active.push((*k, (*job).clone()));
active.push((*k, job.clone()));
}
}
};

if require_complete {
for shard in self.active.lock_shards() {
collect(shard);
}
} else {
// We use try_lock_shards here since we are called from the
// deadlock handler, and this shouldn't be locked.
for shard in self.active.try_lock_shards() {
collect(shard?);
}
}

// Call `make_query` while we're not holding a `self.active` lock as `make_query` may call
Expand Down Expand Up @@ -271,7 +284,7 @@ where
{
// Ensure there was no errors collecting all active jobs.
// We need the complete map to ensure we find a cycle to break.
let query_map = qcx.collect_active_jobs().ok().expect("failed to collect active queries");
let query_map = qcx.collect_active_jobs(false).ok().expect("failed to collect active queries");

let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span);
(mk_cycle(query, qcx, error.lift(qcx)), None)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,7 @@ symbols! {
into_async_iter_into_iter,
into_future,
into_iter,
into_try_type,
intra_doc_pointers,
intrinsics,
intrinsics_unaligned_volatile_load,
Expand Down Expand Up @@ -2280,6 +2281,7 @@ symbols! {
try_from_fn,
try_into,
try_trait_v2,
try_trait_v2_residual,
try_update,
tt,
tuple,
Expand Down
19 changes: 16 additions & 3 deletions library/core/src/ops/try_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,24 @@ where
/// and in the other direction,
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
pub const trait Residual<O> {
#[rustc_const_unstable(feature = "const_try_residual", issue = "91285")]
pub const trait Residual<O>: Sized {
/// The "return" type of this meta-function.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
type TryType: Try<Output = O, Residual = Self>;
type TryType: [const] Try<Output = O, Residual = Self>;
}

/// Used in `try {}` blocks so the type produced in the `?` desugaring
/// depends on the residual type `R` and the output type of the block `O`,
/// but importantly not on the contextual type the way it would be if
/// we called `<_ as FromResidual>::from_residual(r)` directly.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
// needs to be `pub` to avoid `private type` errors
#[expect(unreachable_pub)]
#[inline] // FIXME: force would be nice, but fails -- see #148915
#[lang = "into_try_type"]
pub fn residual_into_try_type<R: Residual<O>, O>(r: R) -> <R as Residual<O>>::TryType {
FromResidual::from_residual(r)
}

#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/pal/unix/kernel_copy/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn copy_specialization() -> Result<()> {
"inner Take allowed reading beyond end of file, some bytes should be left"
);

let mut sink = sink.into_inner()?;
let mut sink = sink.into_inner().map_err(io::Error::from)?;
sink.seek(SeekFrom::Start(0))?;
let mut copied = Vec::new();
sink.read_to_end(&mut copied)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn option_traits(_1: Option<u32>) -> Option<u32> {
}

bb3: {
_0 = <Option<u32> as FromResidual<Option<Infallible>>>::from_residual(const Option::<Infallible>::None) -> [return: bb4, unwind unreachable];
_0 = ops::try_trait::residual_into_try_type::<Option<Infallible>, u32>(const Option::<Infallible>::None) -> [return: bb4, unwind unreachable];
}

bb4: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn option_traits(_1: Option<u32>) -> Option<u32> {
}

bb3: {
_0 = <Option<u32> as FromResidual<Option<Infallible>>>::from_residual(const Option::<Infallible>::None) -> [return: bb4, unwind continue];
_0 = ops::try_trait::residual_into_try_type::<Option<Infallible>, u32>(const Option::<Infallible>::None) -> [return: bb4, unwind continue];
}

bb4: {
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/asm/invalid-repr-simd-on-enum-148634.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ needs-asm-support
#![feature(repr_simd)]

use std::arch::asm;

#[repr(simd)]
//~^ ERROR attribute should be applied to a struct
//~| ERROR unsupported representation for zero-variant enum
enum Es {}

fn main() {
unsafe {
let mut x: Es;
asm!("{}", out(reg) x);
}
}
22 changes: 22 additions & 0 deletions tests/ui/asm/invalid-repr-simd-on-enum-148634.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0517]: attribute should be applied to a struct
--> $DIR/invalid-repr-simd-on-enum-148634.rs:6:8
|
LL | #[repr(simd)]
| ^^^^
...
LL | enum Es {}
| ---------- not a struct

error[E0084]: unsupported representation for zero-variant enum
--> $DIR/invalid-repr-simd-on-enum-148634.rs:6:8
|
LL | #[repr(simd)]
| ^^^^
...
LL | enum Es {}
| ------- zero-variant enum

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0084, E0517.
For more information about an error, try `rustc --explain E0084`.
2 changes: 1 addition & 1 deletion tests/ui/try-block/try-block-bad-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

pub fn main() {
let res: Result<u32, std::array::TryFromSliceError> = try {
Err("")?; //~ ERROR `?` couldn't convert the error
Err("")?; //~ ERROR mismatched types
5
};

Expand Down
Loading
Loading