Auto merge of #147662 - Zalathar:rollup-j8ci0f2, r=Zalathar
Rollup of 12 pull requests Successful merges: - rust-lang/rust#146277 (Enable `u64` limbs in `core::num::bignum`) - rust-lang/rust#146976 (constify basic Clone impls) - rust-lang/rust#147249 (Do two passes of `handle_opaque_type_uses_next`) - rust-lang/rust#147266 (fix 2 search graph bugs) - rust-lang/rust#147497 (`proc_macro` cleanups (3/N)) - rust-lang/rust#147546 (Suppress unused_parens for labeled break) - rust-lang/rust#147548 (Fix ICE for never pattern as closure parameters) - rust-lang/rust#147594 (std: implement `pal::os::exit` for VEXos) - rust-lang/rust#147596 (Adjust the Arm targets in CI to reflect latest changes) - rust-lang/rust#147607 (GVN: Invalidate derefs at loop headers) - rust-lang/rust#147620 (Avoid redundant UB check in RangeFrom slice indexing) - rust-lang/rust#147647 (Hide vendoring and copyright in GHA group) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e100792918
37 changed files with 611 additions and 151 deletions
|
|
@ -155,13 +155,6 @@ fn add_hidden_type<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn get_hidden_type<'tcx>(
|
||||
hidden_types: &DefinitionSiteHiddenTypes<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> Option<EarlyBinder<'tcx, OpaqueHiddenType<'tcx>>> {
|
||||
hidden_types.0.get(&def_id).map(|ty| EarlyBinder::bind(*ty))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DefiningUse<'tcx> {
|
||||
/// The opaque type using non NLL vars. This uses the actual
|
||||
|
|
@ -508,7 +501,8 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
|
|||
let tcx = infcx.tcx;
|
||||
let mut errors = Vec::new();
|
||||
for &(key, hidden_type) in opaque_types {
|
||||
let Some(expected) = get_hidden_type(hidden_types, key.def_id) else {
|
||||
let Some(expected) = hidden_types.0.get(&key.def_id).map(|ty| EarlyBinder::bind(*ty))
|
||||
else {
|
||||
if !tcx.use_typing_mode_borrowck() {
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
|
||||
&& alias_ty.def_id == key.def_id.to_def_id()
|
||||
|
|
|
|||
|
|
@ -1817,12 +1817,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let element_ty = if !args.is_empty() {
|
||||
// This shouldn't happen unless there's another error
|
||||
// (e.g., never patterns in inappropriate contexts).
|
||||
if self.diverges.get() != Diverges::Maybe {
|
||||
self.dcx()
|
||||
.struct_span_err(expr.span, "unexpected divergence state in checking array")
|
||||
.delay_as_bug();
|
||||
}
|
||||
|
||||
let coerce_to = expected
|
||||
.to_option(self)
|
||||
.and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index())
|
||||
.unwrap_or_else(|| self.next_ty_var(expr.span));
|
||||
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
|
||||
assert_eq!(self.diverges.get(), Diverges::Maybe);
|
||||
|
||||
for e in args {
|
||||
let e_ty = self.check_expr_with_hint(e, coerce_to);
|
||||
let cause = self.misc(e.span);
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
|
|||
/// the diverges flag is set to something other than `Maybe`.
|
||||
pub(super) diverges: Cell<Diverges>,
|
||||
|
||||
/// If one of the function arguments is a never pattern, this counts as diverging code. This
|
||||
/// affect typechecking of the function body.
|
||||
/// If one of the function arguments is a never pattern, this counts as diverging code.
|
||||
/// This affect typechecking of the function body.
|
||||
pub(super) function_diverges_because_of_empty_arguments: Cell<Diverges>,
|
||||
|
||||
/// Whether the currently checked node is the whole body of the function.
|
||||
|
|
|
|||
|
|
@ -219,6 +219,12 @@ fn typeck_with_inspect<'tcx>(
|
|||
// the future.
|
||||
fcx.check_repeat_exprs();
|
||||
|
||||
// We need to handle opaque types before emitting ambiguity errors as applying
|
||||
// defining uses may guide type inference.
|
||||
if fcx.next_trait_solver() {
|
||||
fcx.try_handle_opaque_type_uses_next();
|
||||
}
|
||||
|
||||
fcx.type_inference_fallback();
|
||||
|
||||
// Even though coercion casts provide type hints, we check casts after fallback for
|
||||
|
|
|
|||
|
|
@ -22,35 +22,50 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
/// inference variables.
|
||||
///
|
||||
/// It then uses these defining uses to guide inference for all other uses.
|
||||
///
|
||||
/// Unlike `handle_opaque_type_uses_next`, this does not report errors.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(super) fn try_handle_opaque_type_uses_next(&mut self) {
|
||||
// We clone the opaques instead of stealing them here as we still need
|
||||
// to use them after fallback.
|
||||
let opaque_types: Vec<_> = self.infcx.clone_opaque_types();
|
||||
|
||||
self.compute_definition_site_hidden_types(opaque_types, false);
|
||||
}
|
||||
|
||||
/// This takes all the opaque type uses during HIR typeck. It first computes
|
||||
/// the concrete hidden type by iterating over all defining uses.
|
||||
///
|
||||
/// A use during HIR typeck is defining if all non-lifetime arguments are
|
||||
/// unique generic parameters and the hidden type does not reference any
|
||||
/// inference variables.
|
||||
///
|
||||
/// It then uses these defining uses to guide inference for all other uses.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(super) fn handle_opaque_type_uses_next(&mut self) {
|
||||
// We clone the opaques instead of stealing them here as they are still used for
|
||||
// normalization in the next generation trait solver.
|
||||
let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types();
|
||||
let opaque_types: Vec<_> = self.infcx.clone_opaque_types();
|
||||
let num_entries = self.inner.borrow_mut().opaque_types().num_entries();
|
||||
let prev = self.checked_opaque_types_storage_entries.replace(Some(num_entries));
|
||||
debug_assert_eq!(prev, None);
|
||||
for entry in &mut opaque_types {
|
||||
*entry = self.resolve_vars_if_possible(*entry);
|
||||
}
|
||||
debug!(?opaque_types);
|
||||
|
||||
self.compute_definition_site_hidden_types(&opaque_types);
|
||||
self.apply_definition_site_hidden_types(&opaque_types);
|
||||
self.compute_definition_site_hidden_types(opaque_types, true);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum UsageKind<'tcx> {
|
||||
None,
|
||||
NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
|
||||
UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
|
||||
HasDefiningUse,
|
||||
HasDefiningUse(OpaqueHiddenType<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> UsageKind<'tcx> {
|
||||
fn merge(&mut self, other: UsageKind<'tcx>) {
|
||||
match (&*self, &other) {
|
||||
(UsageKind::HasDefiningUse, _) | (_, UsageKind::None) => unreachable!(),
|
||||
(UsageKind::HasDefiningUse(_), _) | (_, UsageKind::None) => unreachable!(),
|
||||
(UsageKind::None, _) => *self = other,
|
||||
// When mergining non-defining uses, prefer earlier ones. This means
|
||||
// the error happens as early as possible.
|
||||
|
|
@ -64,7 +79,7 @@ impl<'tcx> UsageKind<'tcx> {
|
|||
// intended to be defining.
|
||||
(
|
||||
UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
|
||||
UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse,
|
||||
UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse(_),
|
||||
) => *self = other,
|
||||
}
|
||||
}
|
||||
|
|
@ -73,8 +88,14 @@ impl<'tcx> UsageKind<'tcx> {
|
|||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
fn compute_definition_site_hidden_types(
|
||||
&mut self,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
|
||||
mut opaque_types: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
|
||||
error_on_missing_defining_use: bool,
|
||||
) {
|
||||
for entry in opaque_types.iter_mut() {
|
||||
*entry = self.resolve_vars_if_possible(*entry);
|
||||
}
|
||||
debug!(?opaque_types);
|
||||
|
||||
let tcx = self.tcx;
|
||||
let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
|
||||
else {
|
||||
|
|
@ -88,19 +109,47 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
_ => unreachable!("not opaque or generator: {def_id:?}"),
|
||||
}
|
||||
|
||||
// We do actually need to check this the second pass (we can't just
|
||||
// store this), because we can go from `UnconstrainedHiddenType` to
|
||||
// `HasDefiningUse` (because of fallback)
|
||||
let mut usage_kind = UsageKind::None;
|
||||
for &(opaque_type_key, hidden_type) in opaque_types {
|
||||
for &(opaque_type_key, hidden_type) in &opaque_types {
|
||||
if opaque_type_key.def_id != def_id {
|
||||
continue;
|
||||
}
|
||||
|
||||
usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
|
||||
if let UsageKind::HasDefiningUse = usage_kind {
|
||||
|
||||
if let UsageKind::HasDefiningUse(..) = usage_kind {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let UsageKind::HasDefiningUse(ty) = usage_kind {
|
||||
for &(opaque_type_key, hidden_type) in &opaque_types {
|
||||
if opaque_type_key.def_id != def_id {
|
||||
continue;
|
||||
}
|
||||
|
||||
let expected = EarlyBinder::bind(ty.ty).instantiate(tcx, opaque_type_key.args);
|
||||
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
|
||||
}
|
||||
|
||||
// Being explicit here: it may be possible that we in a
|
||||
// previous call to this function we did an insert, but this
|
||||
// should be just fine, since they all get equated anyways and
|
||||
// we shouldn't ever go from `HasDefiningUse` to anyway else.
|
||||
let _ = self.typeck_results.borrow_mut().hidden_types.insert(def_id, ty);
|
||||
}
|
||||
|
||||
// If we're in `fn try_handle_opaque_type_uses_next` then do not
|
||||
// report any errors.
|
||||
if !error_on_missing_defining_use {
|
||||
continue;
|
||||
}
|
||||
|
||||
let guar = match usage_kind {
|
||||
UsageKind::HasDefiningUse(_) => continue,
|
||||
UsageKind::None => {
|
||||
if let Some(guar) = self.tainted_by_errors() {
|
||||
guar
|
||||
|
|
@ -137,7 +186,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
.emit()
|
||||
}
|
||||
}
|
||||
UsageKind::HasDefiningUse => continue,
|
||||
};
|
||||
|
||||
self.typeck_results
|
||||
|
|
@ -148,8 +196,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self), ret)]
|
||||
fn consider_opaque_type_use(
|
||||
&mut self,
|
||||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
hidden_type: OpaqueHiddenType<'tcx>,
|
||||
) -> UsageKind<'tcx> {
|
||||
|
|
@ -161,11 +210,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
) {
|
||||
match err {
|
||||
NonDefiningUseReason::Tainted(guar) => {
|
||||
self.typeck_results.borrow_mut().hidden_types.insert(
|
||||
opaque_type_key.def_id,
|
||||
OpaqueHiddenType::new_error(self.tcx, guar),
|
||||
);
|
||||
return UsageKind::HasDefiningUse;
|
||||
return UsageKind::HasDefiningUse(OpaqueHiddenType::new_error(self.tcx, guar));
|
||||
}
|
||||
_ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
|
||||
};
|
||||
|
|
@ -193,27 +238,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
self.tcx,
|
||||
DefiningScopeKind::HirTypeck,
|
||||
);
|
||||
|
||||
let prev = self
|
||||
.typeck_results
|
||||
.borrow_mut()
|
||||
.hidden_types
|
||||
.insert(opaque_type_key.def_id, hidden_type);
|
||||
assert!(prev.is_none());
|
||||
UsageKind::HasDefiningUse
|
||||
}
|
||||
|
||||
fn apply_definition_site_hidden_types(
|
||||
&mut self,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
for &(key, hidden_type) in opaque_types {
|
||||
let expected = *self.typeck_results.borrow_mut().hidden_types.get(&key.def_id).unwrap();
|
||||
|
||||
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
|
||||
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
|
||||
}
|
||||
UsageKind::HasDefiningUse(hidden_type)
|
||||
}
|
||||
|
||||
/// We may in theory add further uses of an opaque after cloning the opaque
|
||||
|
|
|
|||
|
|
@ -914,7 +914,16 @@ trait UnusedDelimLint {
|
|||
(value, UnusedDelimsCtx::ReturnValue, false, Some(left), None, true)
|
||||
}
|
||||
|
||||
Break(_, Some(ref value)) => {
|
||||
Break(label, Some(ref value)) => {
|
||||
// Don't lint on `break 'label ({...})` - the parens are necessary
|
||||
// to disambiguate from `break 'label {...}` which would be a syntax error.
|
||||
// This avoids conflicts with the `break_with_label_and_loop` lint.
|
||||
if label.is_some()
|
||||
&& matches!(value.kind, ast::ExprKind::Paren(ref inner)
|
||||
if matches!(inner.kind, ast::ExprKind::Block(..)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
(value, UnusedDelimsCtx::BreakValue, false, None, None, true)
|
||||
}
|
||||
|
||||
|
|
|
|||
29
compiler/rustc_middle/src/mir/loops.rs
Normal file
29
compiler/rustc_middle/src/mir/loops.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use rustc_index::bit_set::DenseBitSet;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Compute the set of loop headers in the given body. A loop header is usually defined as a block
|
||||
/// which dominates one of its predecessors. This definition is only correct for reducible CFGs.
|
||||
/// However, computing dominators is expensive, so we approximate according to the post-order
|
||||
/// traversal order. A loop header for us is a block which is visited after its predecessor in
|
||||
/// post-order. This is ok as we mostly need a heuristic.
|
||||
pub fn maybe_loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
|
||||
let mut maybe_loop_headers = DenseBitSet::new_empty(body.basic_blocks.len());
|
||||
let mut visited = DenseBitSet::new_empty(body.basic_blocks.len());
|
||||
for (bb, bbdata) in traversal::postorder(body) {
|
||||
// Post-order means we visit successors before the block for acyclic CFGs.
|
||||
// If the successor is not visited yet, consider it a loop header.
|
||||
for succ in bbdata.terminator().successors() {
|
||||
if !visited.contains(succ) {
|
||||
maybe_loop_headers.insert(succ);
|
||||
}
|
||||
}
|
||||
|
||||
// Only mark `bb` as visited after we checked the successors, in case we have a self-loop.
|
||||
// bb1: goto -> bb1;
|
||||
let _new = visited.insert(bb);
|
||||
debug_assert!(_new);
|
||||
}
|
||||
|
||||
maybe_loop_headers
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ mod statement;
|
|||
mod syntax;
|
||||
mod terminator;
|
||||
|
||||
pub mod loops;
|
||||
pub mod traversal;
|
||||
pub mod visit;
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
|
|||
let ssa = SsaLocals::new(tcx, body, typing_env);
|
||||
// Clone dominators because we need them while mutating the body.
|
||||
let dominators = body.basic_blocks.dominators().clone();
|
||||
let maybe_loop_headers = loops::maybe_loop_headers(body);
|
||||
|
||||
let arena = DroplessArena::default();
|
||||
let mut state =
|
||||
|
|
@ -141,6 +142,11 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
|
|||
|
||||
let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
|
||||
for bb in reverse_postorder {
|
||||
// N.B. With loops, reverse postorder cannot produce a valid topological order.
|
||||
// A statement or terminator from inside the loop, that is not processed yet, may have performed an indirect write.
|
||||
if maybe_loop_headers.contains(bb) {
|
||||
state.invalidate_derefs();
|
||||
}
|
||||
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
|
||||
state.visit_basic_block_data(bb, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
|
|||
body,
|
||||
arena,
|
||||
map: Map::new(tcx, body, Some(MAX_PLACES)),
|
||||
maybe_loop_headers: maybe_loop_headers(body),
|
||||
maybe_loop_headers: loops::maybe_loop_headers(body),
|
||||
opportunities: Vec::new(),
|
||||
};
|
||||
|
||||
|
|
@ -830,29 +830,3 @@ enum Update {
|
|||
Incr,
|
||||
Decr,
|
||||
}
|
||||
|
||||
/// Compute the set of loop headers in the given body. A loop header is usually defined as a block
|
||||
/// which dominates one of its predecessors. This definition is only correct for reducible CFGs.
|
||||
/// However, computing dominators is expensive, so we approximate according to the post-order
|
||||
/// traversal order. A loop header for us is a block which is visited after its predecessor in
|
||||
/// post-order. This is ok as we mostly need a heuristic.
|
||||
fn maybe_loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
|
||||
let mut maybe_loop_headers = DenseBitSet::new_empty(body.basic_blocks.len());
|
||||
let mut visited = DenseBitSet::new_empty(body.basic_blocks.len());
|
||||
for (bb, bbdata) in traversal::postorder(body) {
|
||||
// Post-order means we visit successors before the block for acyclic CFGs.
|
||||
// If the successor is not visited yet, consider it a loop header.
|
||||
for succ in bbdata.terminator().successors() {
|
||||
if !visited.contains(succ) {
|
||||
maybe_loop_headers.insert(succ);
|
||||
}
|
||||
}
|
||||
|
||||
// Only mark `bb` as visited after we checked the successors, in case we have a self-loop.
|
||||
// bb1: goto -> bb1;
|
||||
let _new = visited.insert(bb);
|
||||
debug_assert!(_new);
|
||||
}
|
||||
|
||||
maybe_loop_headers
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,19 +99,23 @@ where
|
|||
response_no_constraints(cx, input, Certainty::overflow(false))
|
||||
}
|
||||
|
||||
fn is_ambiguous_result(result: QueryResult<I>) -> bool {
|
||||
result.is_ok_and(|response| {
|
||||
has_no_inference_or_external_constraints(response)
|
||||
fn is_ambiguous_result(result: QueryResult<I>) -> Option<Certainty> {
|
||||
result.ok().and_then(|response| {
|
||||
if has_no_inference_or_external_constraints(response)
|
||||
&& matches!(response.value.certainty, Certainty::Maybe { .. })
|
||||
{
|
||||
Some(response.value.certainty)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn propagate_ambiguity(
|
||||
cx: I,
|
||||
for_input: CanonicalInput<I>,
|
||||
from_result: QueryResult<I>,
|
||||
certainty: Certainty,
|
||||
) -> QueryResult<I> {
|
||||
let certainty = from_result.unwrap().value.certainty;
|
||||
response_no_constraints(cx, for_input, certainty)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::inherent::*;
|
|||
use crate::ir_print::IrPrint;
|
||||
use crate::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
|
||||
use crate::relate::Relate;
|
||||
use crate::solve::{CanonicalInput, ExternalConstraintsData, QueryResult, inspect};
|
||||
use crate::solve::{CanonicalInput, Certainty, ExternalConstraintsData, QueryResult, inspect};
|
||||
use crate::visit::{Flags, TypeVisitable};
|
||||
use crate::{self as ty, CanonicalParamEnvCacheEntry, search_graph};
|
||||
|
||||
|
|
@ -550,6 +550,7 @@ impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
|
|||
impl<I: Interner> search_graph::Cx for I {
|
||||
type Input = CanonicalInput<I>;
|
||||
type Result = QueryResult<I>;
|
||||
type AmbiguityInfo = Certainty;
|
||||
|
||||
type DepNodeIndex = I::DepNodeIndex;
|
||||
type Tracked<T: Debug + Clone> = I::Tracked<T>;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ pub use global_cache::GlobalCache;
|
|||
pub trait Cx: Copy {
|
||||
type Input: Debug + Eq + Hash + Copy;
|
||||
type Result: Debug + Eq + Hash + Copy;
|
||||
type AmbiguityInfo: Debug + Eq + Hash + Copy;
|
||||
|
||||
type DepNodeIndex;
|
||||
type Tracked<T: Debug + Clone>: Debug;
|
||||
|
|
@ -96,11 +97,13 @@ pub trait Delegate: Sized {
|
|||
input: <Self::Cx as Cx>::Input,
|
||||
) -> <Self::Cx as Cx>::Result;
|
||||
|
||||
fn is_ambiguous_result(result: <Self::Cx as Cx>::Result) -> bool;
|
||||
fn is_ambiguous_result(
|
||||
result: <Self::Cx as Cx>::Result,
|
||||
) -> Option<<Self::Cx as Cx>::AmbiguityInfo>;
|
||||
fn propagate_ambiguity(
|
||||
cx: Self::Cx,
|
||||
for_input: <Self::Cx as Cx>::Input,
|
||||
from_result: <Self::Cx as Cx>::Result,
|
||||
ambiguity_info: <Self::Cx as Cx>::AmbiguityInfo,
|
||||
) -> <Self::Cx as Cx>::Result;
|
||||
|
||||
fn compute_goal(
|
||||
|
|
@ -913,9 +916,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
/// heads from the stack. This may not necessarily mean that we've actually
|
||||
/// reached a fixpoint for that cycle head, which impacts the way we rebase
|
||||
/// provisional cache entries.
|
||||
enum RebaseReason {
|
||||
enum RebaseReason<X: Cx> {
|
||||
NoCycleUsages,
|
||||
Ambiguity,
|
||||
Ambiguity(X::AmbiguityInfo),
|
||||
Overflow,
|
||||
/// We've actually reached a fixpoint.
|
||||
///
|
||||
|
|
@ -951,7 +954,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
|||
&mut self,
|
||||
cx: X,
|
||||
stack_entry: &StackEntry<X>,
|
||||
rebase_reason: RebaseReason,
|
||||
rebase_reason: RebaseReason<X>,
|
||||
) {
|
||||
let popped_head_index = self.stack.next_index();
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
|
|
@ -969,10 +972,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
|||
return true;
|
||||
};
|
||||
|
||||
let Some(new_highest_head_index) = heads.opt_highest_cycle_head_index() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// We're rebasing an entry `e` over a head `p`. This head
|
||||
// has a number of own heads `h` it depends on.
|
||||
//
|
||||
|
|
@ -1033,8 +1032,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
|||
// is not actually equal to the final provisional result. We
|
||||
// need to discard the provisional cache entry in this case.
|
||||
RebaseReason::NoCycleUsages => return false,
|
||||
RebaseReason::Ambiguity => {
|
||||
*result = D::propagate_ambiguity(cx, input, *result);
|
||||
RebaseReason::Ambiguity(info) => {
|
||||
*result = D::propagate_ambiguity(cx, input, info);
|
||||
}
|
||||
RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input),
|
||||
RebaseReason::ReachedFixpoint(None) => {}
|
||||
|
|
@ -1046,6 +1045,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
|||
};
|
||||
}
|
||||
|
||||
let Some(new_highest_head_index) = heads.opt_highest_cycle_head_index() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// We now care about the path from the next highest cycle head to the
|
||||
// provisional cache entry.
|
||||
*path_from_head = path_from_head.extend(Self::cycle_path_kind(
|
||||
|
|
@ -1268,6 +1271,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
|||
}
|
||||
|
||||
/// Whether we've reached a fixpoint when evaluating a cycle head.
|
||||
#[instrument(level = "trace", skip(self, stack_entry), ret)]
|
||||
fn reached_fixpoint(
|
||||
&mut self,
|
||||
stack_entry: &StackEntry<X>,
|
||||
|
|
@ -1355,8 +1359,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
|||
// As we only get to this branch if we haven't yet reached a fixpoint,
|
||||
// we also taint all provisional cache entries which depend on the
|
||||
// current goal.
|
||||
if D::is_ambiguous_result(result) {
|
||||
self.rebase_provisional_cache_entries(cx, &stack_entry, RebaseReason::Ambiguity);
|
||||
if let Some(info) = D::is_ambiguous_result(result) {
|
||||
self.rebase_provisional_cache_entries(
|
||||
cx,
|
||||
&stack_entry,
|
||||
RebaseReason::Ambiguity(info),
|
||||
);
|
||||
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -575,7 +575,8 @@ mod impls {
|
|||
($($t:ty)*) => {
|
||||
$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Clone for $t {
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl const Clone for $t {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
|
@ -593,7 +594,8 @@ mod impls {
|
|||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl Clone for ! {
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl const Clone for ! {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
|
@ -601,7 +603,8 @@ mod impls {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: PointeeSized> Clone for *const T {
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl<T: PointeeSized> const Clone for *const T {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
|
@ -609,7 +612,8 @@ mod impls {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: PointeeSized> Clone for *mut T {
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl<T: PointeeSized> const Clone for *mut T {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
|
@ -618,7 +622,8 @@ mod impls {
|
|||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: PointeeSized> Clone for &T {
|
||||
#[rustc_const_unstable(feature = "const_clone", issue = "142757")]
|
||||
impl<T: PointeeSized> const Clone for &T {
|
||||
#[inline(always)]
|
||||
#[rustc_diagnostic_item = "noop_method_clone"]
|
||||
fn clone(&self) -> Self {
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ impl_full_ops! {
|
|||
u8: add(intrinsics::u8_add_with_overflow), mul/div(u16);
|
||||
u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
|
||||
u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
|
||||
// See RFC #521 for enabling this.
|
||||
// u64: add(intrinsics::u64_add_with_overflow), mul/div(u128);
|
||||
u64: add(intrinsics::u64_add_with_overflow), mul/div(u128);
|
||||
}
|
||||
|
||||
/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
|
||||
|
|
|
|||
|
|
@ -564,7 +564,10 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
|
|||
slice_index_fail(self.start, slice.len(), slice.len())
|
||||
}
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { &*self.get_unchecked(slice) }
|
||||
unsafe {
|
||||
let new_len = crate::intrinsics::unchecked_sub(slice.len(), self.start);
|
||||
&*get_offset_len_noubcheck(slice, self.start, new_len)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -573,7 +576,10 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
|
|||
slice_index_fail(self.start, slice.len(), slice.len())
|
||||
}
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { &mut *self.get_unchecked_mut(slice) }
|
||||
unsafe {
|
||||
let new_len = crate::intrinsics::unchecked_sub(slice.len(), self.start);
|
||||
&mut *get_offset_len_mut_noubcheck(slice, self.start, new_len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ macro_rules! define_client_handles {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for $oty {
|
||||
impl<S> Decode<'_, '_, S> for $oty {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
$oty {
|
||||
handle: handle::Handle::decode(r, s),
|
||||
|
|
@ -82,7 +82,7 @@ macro_rules! define_client_handles {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for $ity {
|
||||
impl<S> Decode<'_, '_, S> for $ity {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
$ity {
|
||||
handle: handle::Handle::decode(r, s),
|
||||
|
|
@ -276,7 +276,7 @@ fn maybe_install_panic_hook(force_show_panics: bool) {
|
|||
/// Client-side helper for handling client panics, entering the bridge,
|
||||
/// deserializing input and serializing output.
|
||||
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
|
||||
fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
||||
fn run_client<A: for<'a, 's> Decode<'a, 's, ()>, R: Encode<()>>(
|
||||
config: BridgeConfig<'_>,
|
||||
f: impl FnOnce(A) -> R,
|
||||
) -> Buffer {
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ mod symbol;
|
|||
|
||||
use buffer::Buffer;
|
||||
pub use rpc::PanicMessage;
|
||||
use rpc::{DecodeMut, Encode, Reader, Writer};
|
||||
use rpc::{Decode, Encode, Reader, Writer};
|
||||
|
||||
/// Configuration for establishing an active connection between a server and a
|
||||
/// client. The server creates the bridge config (`run_server` in `server.rs`),
|
||||
|
|
@ -168,7 +168,7 @@ impl !Sync for BridgeConfig<'_> {}
|
|||
#[forbid(unsafe_code)]
|
||||
#[allow(non_camel_case_types)]
|
||||
mod api_tags {
|
||||
use super::rpc::{DecodeMut, Encode, Reader, Writer};
|
||||
use super::rpc::{Decode, Encode, Reader, Writer};
|
||||
|
||||
macro_rules! declare_tags {
|
||||
($($name:ident {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub(super) trait Encode<S>: Sized {
|
|||
|
||||
pub(super) type Reader<'a> = &'a [u8];
|
||||
|
||||
pub(super) trait DecodeMut<'a, 's, S>: Sized {
|
||||
pub(super) trait Decode<'a, 's, S>: Sized {
|
||||
fn decode(r: &mut Reader<'a>, s: &'s mut S) -> Self;
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ macro_rules! rpc_encode_decode {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for $ty {
|
||||
impl<S> Decode<'_, '_, S> for $ty {
|
||||
fn decode(r: &mut Reader<'_>, _: &mut S) -> Self {
|
||||
const N: usize = size_of::<$ty>();
|
||||
|
||||
|
|
@ -43,12 +43,12 @@ macro_rules! rpc_encode_decode {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S>
|
||||
impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S>
|
||||
for $name $(<$($T),+>)?
|
||||
{
|
||||
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
|
||||
$name {
|
||||
$($field: DecodeMut::decode(r, s)),*
|
||||
$($field: Decode::decode(r, s)),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,23 +58,18 @@ macro_rules! rpc_encode_decode {
|
|||
fn encode(self, w: &mut Writer, s: &mut S) {
|
||||
// HACK(eddyb): `Tag` enum duplicated between the
|
||||
// two impls as there's no other place to stash it.
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod tag {
|
||||
#[repr(u8)] enum Tag { $($variant),* }
|
||||
|
||||
$(pub(crate) const $variant: u8 = Tag::$variant as u8;)*
|
||||
}
|
||||
#[repr(u8)] enum Tag { $($variant),* }
|
||||
|
||||
match self {
|
||||
$($name::$variant $(($field))* => {
|
||||
tag::$variant.encode(w, s);
|
||||
(Tag::$variant as u8).encode(w, s);
|
||||
$($field.encode(w, s);)*
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S>
|
||||
impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S>
|
||||
for $name $(<$($T),+>)?
|
||||
{
|
||||
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
|
||||
|
|
@ -89,7 +84,7 @@ macro_rules! rpc_encode_decode {
|
|||
|
||||
match u8::decode(r, s) {
|
||||
$(tag::$variant => {
|
||||
$(let $field = DecodeMut::decode(r, s);)*
|
||||
$(let $field = Decode::decode(r, s);)*
|
||||
$name::$variant $(($field))*
|
||||
})*
|
||||
_ => unreachable!(),
|
||||
|
|
@ -103,7 +98,7 @@ impl<S> Encode<S> for () {
|
|||
fn encode(self, _: &mut Writer, _: &mut S) {}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for () {
|
||||
impl<S> Decode<'_, '_, S> for () {
|
||||
fn decode(_: &mut Reader<'_>, _: &mut S) -> Self {}
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +108,7 @@ impl<S> Encode<S> for u8 {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for u8 {
|
||||
impl<S> Decode<'_, '_, S> for u8 {
|
||||
fn decode(r: &mut Reader<'_>, _: &mut S) -> Self {
|
||||
let x = r[0];
|
||||
*r = &r[1..];
|
||||
|
|
@ -130,7 +125,7 @@ impl<S> Encode<S> for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for bool {
|
||||
impl<S> Decode<'_, '_, S> for bool {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
match u8::decode(r, s) {
|
||||
0 => false,
|
||||
|
|
@ -146,7 +141,7 @@ impl<S> Encode<S> for char {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for char {
|
||||
impl<S> Decode<'_, '_, S> for char {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
char::from_u32(u32::decode(r, s)).unwrap()
|
||||
}
|
||||
|
|
@ -158,7 +153,7 @@ impl<S> Encode<S> for NonZero<u32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for NonZero<u32> {
|
||||
impl<S> Decode<'_, '_, S> for NonZero<u32> {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
Self::new(u32::decode(r, s)).unwrap()
|
||||
}
|
||||
|
|
@ -171,11 +166,11 @@ impl<S, A: Encode<S>, B: Encode<S>> Encode<S> for (A, B) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S>
|
||||
impl<'a, S, A: for<'s> Decode<'a, 's, S>, B: for<'s> Decode<'a, 's, S>> Decode<'a, '_, S>
|
||||
for (A, B)
|
||||
{
|
||||
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
|
||||
(DecodeMut::decode(r, s), DecodeMut::decode(r, s))
|
||||
(Decode::decode(r, s), Decode::decode(r, s))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +181,7 @@ impl<S> Encode<S> for &[u8] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S> DecodeMut<'a, '_, S> for &'a [u8] {
|
||||
impl<'a, S> Decode<'a, '_, S> for &'a [u8] {
|
||||
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
|
||||
let len = usize::decode(r, s);
|
||||
let xs = &r[..len];
|
||||
|
|
@ -201,7 +196,7 @@ impl<S> Encode<S> for &str {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S> DecodeMut<'a, '_, S> for &'a str {
|
||||
impl<'a, S> Decode<'a, '_, S> for &'a str {
|
||||
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
|
||||
str::from_utf8(<&[u8]>::decode(r, s)).unwrap()
|
||||
}
|
||||
|
|
@ -213,7 +208,7 @@ impl<S> Encode<S> for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for String {
|
||||
impl<S> Decode<'_, '_, S> for String {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
<&str>::decode(r, s).to_string()
|
||||
}
|
||||
|
|
@ -228,7 +223,7 @@ impl<S, T: Encode<S>> Encode<S> for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S, T: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> for Vec<T> {
|
||||
impl<'a, S, T: for<'s> Decode<'a, 's, S>> Decode<'a, '_, S> for Vec<T> {
|
||||
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
|
||||
let len = usize::decode(r, s);
|
||||
let mut vec = Vec::with_capacity(len);
|
||||
|
|
@ -288,7 +283,7 @@ impl<S> Encode<S> for PanicMessage {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for PanicMessage {
|
||||
impl<S> Decode<'_, '_, S> for PanicMessage {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
match Option::<String>::decode(r, s) {
|
||||
Some(s) => PanicMessage::String(s),
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ macro_rules! define_reify_functions {
|
|||
>(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty {
|
||||
// FIXME(eddyb) describe the `F` type (e.g. via `type_name::<F>`) once panic
|
||||
// formatting becomes possible in `const fn`.
|
||||
assert!(size_of::<F>() == 0, "selfless_reify: closure must be zero-sized");
|
||||
const { assert!(size_of::<F>() == 0, "selfless_reify: closure must be zero-sized"); }
|
||||
|
||||
$(extern $abi)? fn wrapper<
|
||||
$($($param,)*)?
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ macro_rules! define_server_handles {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Types> DecodeMut<'_, '_, HandleStore<MarkedTypes<S>>>
|
||||
impl<S: Types> Decode<'_, '_, HandleStore<MarkedTypes<S>>>
|
||||
for Marked<S::$oty, client::$oty>
|
||||
{
|
||||
fn decode(r: &mut Reader<'_>, s: &mut HandleStore<MarkedTypes<S>>) -> Self {
|
||||
|
|
@ -40,7 +40,7 @@ macro_rules! define_server_handles {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'s, S: Types> DecodeMut<'_, 's, HandleStore<MarkedTypes<S>>>
|
||||
impl<'s, S: Types> Decode<'_, 's, HandleStore<MarkedTypes<S>>>
|
||||
for &'s Marked<S::$oty, client::$oty>
|
||||
{
|
||||
fn decode(r: &mut Reader<'_>, s: &'s mut HandleStore<MarkedTypes<S>>) -> Self {
|
||||
|
|
@ -48,7 +48,7 @@ macro_rules! define_server_handles {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'s, S: Types> DecodeMut<'_, 's, HandleStore<MarkedTypes<S>>>
|
||||
impl<'s, S: Types> Decode<'_, 's, HandleStore<MarkedTypes<S>>>
|
||||
for &'s mut Marked<S::$oty, client::$oty>
|
||||
{
|
||||
fn decode(
|
||||
|
|
@ -67,7 +67,7 @@ macro_rules! define_server_handles {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Types> DecodeMut<'_, '_, HandleStore<MarkedTypes<S>>>
|
||||
impl<S: Types> Decode<'_, '_, HandleStore<MarkedTypes<S>>>
|
||||
for Marked<S::$ity, client::$ity>
|
||||
{
|
||||
fn decode(r: &mut Reader<'_>, s: &mut HandleStore<MarkedTypes<S>>) -> Self {
|
||||
|
|
@ -355,7 +355,7 @@ pub trait MessagePipe<T>: Sized {
|
|||
fn run_server<
|
||||
S: Server,
|
||||
I: Encode<HandleStore<MarkedTypes<S>>>,
|
||||
O: for<'a, 's> DecodeMut<'a, 's, HandleStore<MarkedTypes<S>>>,
|
||||
O: for<'a, 's> Decode<'a, 's, HandleStore<MarkedTypes<S>>>,
|
||||
>(
|
||||
strategy: &impl ExecutionStrategy,
|
||||
handle_counters: &'static client::HandleCounters,
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl<S> Encode<S> for Symbol {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: server::Server> DecodeMut<'_, '_, server::HandleStore<server::MarkedTypes<S>>>
|
||||
impl<S: server::Server> Decode<'_, '_, server::HandleStore<server::MarkedTypes<S>>>
|
||||
for Marked<S::Symbol, Symbol>
|
||||
{
|
||||
fn decode(r: &mut Reader<'_>, s: &mut server::HandleStore<server::MarkedTypes<S>>) -> Self {
|
||||
|
|
@ -118,7 +118,7 @@ impl<S: server::Server> Encode<server::HandleStore<server::MarkedTypes<S>>>
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> DecodeMut<'_, '_, S> for Symbol {
|
||||
impl<S> Decode<'_, '_, S> for Symbol {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
Symbol::new(<&str>::decode(r, s))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#[path = "../unsupported/os.rs"]
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
|
|
|
|||
19
library/std/src/sys/pal/vexos/os.rs
Normal file
19
library/std/src/sys/pal/vexos/os.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#[expect(dead_code)]
|
||||
#[path = "../unsupported/os.rs"]
|
||||
mod unsupported_os;
|
||||
pub use unsupported_os::{
|
||||
JoinPathsError, SplitPaths, chdir, current_exe, errno, error_string, getcwd, getpid, home_dir,
|
||||
join_paths, split_paths, temp_dir,
|
||||
};
|
||||
|
||||
pub use super::unsupported;
|
||||
|
||||
pub fn exit(_code: i32) -> ! {
|
||||
unsafe {
|
||||
vex_sdk::vexSystemExitRequest();
|
||||
|
||||
loop {
|
||||
vex_sdk::vexTasksRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -274,6 +274,8 @@ impl Step for GenerateCopyright {
|
|||
cache_dir
|
||||
};
|
||||
|
||||
let _guard = builder.group("generate-copyright");
|
||||
|
||||
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
|
||||
cmd.env("CARGO_MANIFESTS", &cargo_manifests);
|
||||
cmd.env("LICENSE_METADATA", &license_metadata);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ impl Step for Vendor {
|
|||
/// This function runs `cargo vendor` and ensures all required submodules
|
||||
/// are initialized before vendoring begins.
|
||||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
builder.info(&format!("Vendoring sources to {:?}", self.root_dir));
|
||||
let _guard = builder.group(&format!("Vendoring sources to {:?}", self.root_dir));
|
||||
|
||||
let mut cmd = command(&builder.initial_cargo);
|
||||
cmd.arg("vendor");
|
||||
|
|
|
|||
|
|
@ -111,12 +111,12 @@ ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
|
|||
ENV TARGETS=$TARGETS,riscv32imafc-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,riscv64gc-unknown-none-elf
|
||||
ENV TARGETS=$TARGETS,armebv7r-none-eabi
|
||||
ENV TARGETS=$TARGETS,armebv7r-none-eabihf
|
||||
ENV TARGETS=$TARGETS,armv7r-none-eabi
|
||||
ENV TARGETS=$TARGETS,armv7r-none-eabihf
|
||||
ENV TARGETS=$TARGETS,armv8r-none-eabihf
|
||||
ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf
|
||||
ENV TARGETS=$TARGETS,armv7a-none-eabi
|
||||
ENV TARGETS=$TARGETS,armv7a-none-eabihf
|
||||
|
||||
ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" \
|
||||
CFLAGS_arm_unknown_linux_musleabi="-march=armv6 -marm" \
|
||||
|
|
@ -130,7 +130,9 @@ ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft
|
|||
CC_armv7a_none_eabi=arm-none-eabi-gcc \
|
||||
CC_armv7a_none_eabihf=arm-none-eabi-gcc \
|
||||
CFLAGS_armv7a_none_eabi=-march=armv7-a \
|
||||
CFLAGS_armv7a_none_eabihf=-march=armv7-a+vfpv3 \
|
||||
CFLAGS_armv7a_none_eabihf=-march=armv7-a+fp \
|
||||
CC_armv8r_none_eabihf=arm-none-eabi-gcc \
|
||||
CFLAGS_armv8r_none_eabihf="-march=armv8-r+fp.sp -mfpu=fp-armv8" \
|
||||
CC_aarch64_unknown_none_softfloat=aarch64-none-elf-gcc \
|
||||
CFLAGS_aarch64_unknown_none_softfloat=-mstrict-align -march=armv8-a+nofp+nosimd \
|
||||
CC_aarch64_unknown_none=aarch64-none-elf-gcc \
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ static TARGETS: &[&str] = &[
|
|||
"armv7-unknown-linux-gnueabi",
|
||||
"armv7-unknown-linux-gnueabihf",
|
||||
"armv7a-none-eabi",
|
||||
"armv7a-none-eabihf",
|
||||
"thumbv7neon-unknown-linux-gnueabihf",
|
||||
"armv7-unknown-linux-musleabi",
|
||||
"armv7-unknown-linux-musleabihf",
|
||||
|
|
|
|||
115
tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff
Normal file
115
tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
- // MIR for `loop_deref_mut` before GVN
|
||||
+ // MIR for `loop_deref_mut` after GVN
|
||||
|
||||
fn loop_deref_mut(_1: &mut Value) -> Value {
|
||||
debug val => _1;
|
||||
let mut _0: Value;
|
||||
let _2: &Value;
|
||||
let _3: &Value;
|
||||
let mut _4: &Value;
|
||||
let mut _6: !;
|
||||
let mut _8: isize;
|
||||
let mut _9: !;
|
||||
let mut _10: ();
|
||||
let mut _12: i32;
|
||||
let _13: ();
|
||||
let mut _14: bool;
|
||||
let mut _15: !;
|
||||
let mut _16: Value;
|
||||
scope 1 {
|
||||
debug val_alias => _2;
|
||||
let mut _5: bool;
|
||||
scope 2 {
|
||||
debug stop => _5;
|
||||
let _7: i32;
|
||||
scope 3 {
|
||||
debug v => _7;
|
||||
let _11: Value;
|
||||
scope 4 {
|
||||
debug v => _11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
- StorageLive(_3);
|
||||
+ nop;
|
||||
StorageLive(_4);
|
||||
_4 = &(*_1);
|
||||
_3 = get::<Value>(move _4) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_2 = &(*_3);
|
||||
StorageDead(_4);
|
||||
- StorageDead(_3);
|
||||
+ nop;
|
||||
StorageLive(_5);
|
||||
_5 = const false;
|
||||
- _8 = discriminant((*_2));
|
||||
+ _8 = discriminant((*_3));
|
||||
switchInt(move _8) -> [0: bb3, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- StorageLive(_7);
|
||||
- _7 = copy (((*_2) as V0).0: i32);
|
||||
+ nop;
|
||||
+ _7 = copy (((*_3) as V0).0: i32);
|
||||
StorageLive(_9);
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_11);
|
||||
StorageLive(_12);
|
||||
_12 = copy _7;
|
||||
- _11 = Value::V0(move _12);
|
||||
+ _11 = Value::V0(copy _7);
|
||||
StorageDead(_12);
|
||||
StorageLive(_13);
|
||||
StorageLive(_14);
|
||||
_14 = copy _5;
|
||||
switchInt(move _14) -> [0: bb6, otherwise: bb5];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_0 = move _11;
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
- StorageDead(_7);
|
||||
+ nop;
|
||||
StorageDead(_5);
|
||||
StorageDead(_2);
|
||||
return;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_13 = const ();
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
_5 = const true;
|
||||
StorageLive(_16);
|
||||
- _16 = Value::V1;
|
||||
- (*_1) = move _16;
|
||||
+ _16 = const Value::V1;
|
||||
+ (*_1) = const Value::V1;
|
||||
StorageDead(_16);
|
||||
_10 = const ();
|
||||
StorageDead(_11);
|
||||
goto -> bb4;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 __ __ __ __ │ ....░░░░
|
||||
}
|
||||
|
||||
39
tests/mir-opt/gvn_loop.rs
Normal file
39
tests/mir-opt/gvn_loop.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//@ test-mir-pass: GVN
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(core_intrinsics, rustc_attrs)]
|
||||
|
||||
pub enum Value {
|
||||
V0(i32),
|
||||
V1,
|
||||
}
|
||||
|
||||
// Check that we do not use the dereferenced value of `val_alias` when returning.
|
||||
|
||||
// EMIT_MIR gvn_loop.loop_deref_mut.GVN.diff
|
||||
fn loop_deref_mut(val: &mut Value) -> Value {
|
||||
// CHECK-LABEL: fn loop_deref_mut(
|
||||
// CHECK: [[VAL_REF:_.*]] = get::<Value>(
|
||||
// CHECK: [[V:_.*]] = copy (((*[[VAL_REF]]) as V0).0: i32);
|
||||
// CEHCK-NOT: copy (*[[VAL_REF]]);
|
||||
// CHECK: [[RET:_*]] = Value::V0(copy [[V]]);
|
||||
// CEHCK-NOT: copy (*[[VAL_REF]]);
|
||||
// CHECK: _0 = move [[RET]]
|
||||
let val_alias: &Value = get(val);
|
||||
let mut stop = false;
|
||||
let Value::V0(v) = *val_alias else { unsafe { core::intrinsics::unreachable() } };
|
||||
loop {
|
||||
let v = Value::V0(v);
|
||||
if stop {
|
||||
return v;
|
||||
}
|
||||
stop = true;
|
||||
*val = Value::V1;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[rustc_nounwind]
|
||||
fn get<T>(v: &T) -> &T {
|
||||
v
|
||||
}
|
||||
22
tests/ui/lint/unused/break-label-with-parens-147542.rs
Normal file
22
tests/ui/lint/unused/break-label-with-parens-147542.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//@ check-pass
|
||||
|
||||
// Regression test for #147542
|
||||
// Ensures that we don't suggest removing parens in a break with label and loop
|
||||
// when the parens are necessary for correct parsing.
|
||||
|
||||
#![warn(unused_parens)]
|
||||
#![warn(break_with_label_and_loop)]
|
||||
|
||||
fn xyz() -> usize {
|
||||
'foo: {
|
||||
// parens bellow are necessary break of break with label and loop
|
||||
break 'foo ({
|
||||
println!("Hello!");
|
||||
123
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
xyz();
|
||||
}
|
||||
34
tests/ui/mir/gvn-loop-miscompile.rs
Normal file
34
tests/ui/mir/gvn-loop-miscompile.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//@ compile-flags: -O
|
||||
//@ run-pass
|
||||
|
||||
pub enum Value {
|
||||
V0(i32),
|
||||
V1,
|
||||
}
|
||||
|
||||
fn set_discriminant(val: &mut Value) -> Value {
|
||||
let val_alias: &Value = get(val);
|
||||
let mut stop = false;
|
||||
let Value::V0(v) = *val_alias else {
|
||||
unreachable!();
|
||||
};
|
||||
loop {
|
||||
let v = Value::V0(v);
|
||||
if stop {
|
||||
return v;
|
||||
}
|
||||
stop = true;
|
||||
*val = Value::V1;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut v = Value::V0(1);
|
||||
let v = set_discriminant(&mut v);
|
||||
assert!(matches!(v, Value::V0(1)));
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn get<T>(v: &T) -> &T {
|
||||
v
|
||||
}
|
||||
24
tests/ui/never_type/never-pattern-as-closure-param-141592.rs
Normal file
24
tests/ui/never_type/never-pattern-as-closure-param-141592.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#![feature(never_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
enum Never {}
|
||||
|
||||
fn example(x: Never) -> [i32; 1] {
|
||||
let ! = x;
|
||||
[1]
|
||||
}
|
||||
|
||||
fn function_param_never(!: Never) -> [i32; 1] {
|
||||
[1]
|
||||
}
|
||||
|
||||
fn generic_never<T>(!: T) -> [i32; 1] //~ ERROR mismatched types
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
[1]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = "12".lines().map(|!| [1]); //~ ERROR mismatched types
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
error: mismatched types
|
||||
--> $DIR/never-pattern-as-closure-param-141592.rs:15:21
|
||||
|
|
||||
LL | fn generic_never<T>(!: T) -> [i32; 1]
|
||||
| ^ a never pattern must be used on an uninhabited type
|
||||
|
|
||||
= note: the matched value is of type `T`
|
||||
|
||||
error: mismatched types
|
||||
--> $DIR/never-pattern-as-closure-param-141592.rs:23:31
|
||||
|
|
||||
LL | let _ = "12".lines().map(|!| [1]);
|
||||
| ^ a never pattern must be used on an uninhabited type
|
||||
|
|
||||
= note: the matched value is of type `str`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
#![feature(rustc_attrs)]
|
||||
#![rustc_no_implicit_bounds]
|
||||
|
||||
// A regression test making sure that when forcing dependent
|
||||
// provisional cache entries to ambiguous, we use the `MaybeCause`
|
||||
// of the cycle head. We ended up trying to use the current result
|
||||
// of the provisional cache entry, which is incorrect and caused an
|
||||
// ICE when trying to unwrap it.
|
||||
|
||||
struct Root<T>(T);
|
||||
struct Head<T>(T);
|
||||
struct Error<T>(T);
|
||||
struct NotImplemented<T>(T);
|
||||
|
||||
#[rustc_coinductive]
|
||||
trait Trait {}
|
||||
impl<T> Trait for Root<T>
|
||||
where
|
||||
Head<T>: Trait,
|
||||
{}
|
||||
|
||||
impl<T> Trait for Head<T>
|
||||
where
|
||||
Root<T>: Trait,
|
||||
T: Trait, // ambiguous
|
||||
{}
|
||||
|
||||
impl<T> Trait for Head<T>
|
||||
where
|
||||
Error<T>: Trait,
|
||||
NotImplemented<T>: Trait,
|
||||
{}
|
||||
|
||||
impl<T> Trait for Error<T>
|
||||
where
|
||||
Head<T>: Trait,
|
||||
NotImplemented<T>: Trait,
|
||||
{}
|
||||
|
||||
fn impls_trait<T: Trait>() {}
|
||||
fn main() {
|
||||
impls_trait::<Root<_>>() //~ ERROR type annotations needed
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
error[E0283]: type annotations needed
|
||||
--> $DIR/forced_ambiguity-use-head-maybe-cause.rs:43:19
|
||||
|
|
||||
LL | impls_trait::<Root<_>>()
|
||||
| ^^^^^^^ cannot infer type for struct `Head<_>`
|
||||
|
|
||||
= note: cannot satisfy `Head<_>: Trait`
|
||||
= help: the trait `Trait` is implemented for `Head<T>`
|
||||
note: required for `Root<_>` to implement `Trait`
|
||||
--> $DIR/forced_ambiguity-use-head-maybe-cause.rs:18:9
|
||||
|
|
||||
LL | impl<T> Trait for Root<T>
|
||||
| ^^^^^ ^^^^^^^
|
||||
LL | where
|
||||
LL | Head<T>: Trait,
|
||||
| ----- unsatisfied trait bound introduced here
|
||||
= note: 8 redundant requirements hidden
|
||||
= note: required for `Root<_>` to implement `Trait`
|
||||
note: required by a bound in `impls_trait`
|
||||
--> $DIR/forced_ambiguity-use-head-maybe-cause.rs:41:19
|
||||
|
|
||||
LL | fn impls_trait<T: Trait>() {}
|
||||
| ^^^^^ required by this bound in `impls_trait`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
// Regression test for trait-system-refactor-initiative#240. Hidden types should
|
||||
// equate *before* inference var fallback, otherwise we can get mismatched types.
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct FileSystem;
|
||||
impl FileSystem {
|
||||
fn build<T>(self, commands: T) -> Option<impl Sized> {
|
||||
match false {
|
||||
true => Some(commands),
|
||||
false => {
|
||||
drop(match self.build::<_>(commands) {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
});
|
||||
panic!()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build2<T, U>() -> impl Sized {
|
||||
if false {
|
||||
build2::<U, T>()
|
||||
} else {
|
||||
loop {}
|
||||
};
|
||||
1u32
|
||||
}
|
||||
|
||||
fn build3<'a>() -> impl Sized + use<'a> {
|
||||
if false {
|
||||
build3()
|
||||
} else {
|
||||
loop {}
|
||||
};
|
||||
1u32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue