diff --git a/Cargo.lock b/Cargo.lock index d4c1a02c018af..8b3792cef61bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3421,14 +3421,14 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b881c015c729b43105bbd3702a9bdecee28fafaa21126d1d62e454ec011a4b7" +checksum = "eec3905e8201688412f6f4b1f6c86d38b3ee6578f59ba85f41330a3af61e8365" dependencies = [ "anyhow", "rustc_version", "tempfile", - "toml 0.8.23", + "toml 1.1.0+spec-1.1.0", "walkdir", ] @@ -5195,9 +5195,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" dependencies = [ "serde_core", ] @@ -5693,7 +5693,6 @@ version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ - "indexmap", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -5708,13 +5707,28 @@ checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.0.3", + "serde_spanned 1.1.0", "toml_datetime 0.7.3", "toml_parser", "toml_writer", "winnow 0.7.13", ] +[[package]] +name = "toml" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned 1.1.0", + "toml_datetime 1.1.0+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.0", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -5733,6 +5747,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.19.15" @@ -5762,11 +5785,11 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" dependencies = [ - "winnow 0.7.13", + "winnow 1.0.0", ] [[package]] @@ -5777,9 +5800,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.4" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" [[package]] name = "tracing" @@ -6765,6 +6788,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" + [[package]] name = "winsplit" version = "0.1.0" diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index ce2be24adc586..5a0f149fd0550 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -78,7 +78,7 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate, I: Interner /// We can simply cache based on the ty itself, because we use /// `ty::BoundVarIndexKind::Canonical`. - cache: HashMap, + cache: HashMap, ty::Ty>, } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { @@ -316,7 +316,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { (max_universe, self.variables, var_kinds) } - fn inner_fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn inner_fold_ty(&mut self, t: ty::Ty) -> ty::Ty { let kind = match t.kind() { ty::Infer(i) => match i { ty::TyVar(vid) => { @@ -475,7 +475,7 @@ impl, I: Interner> TypeFolder for Canonicaliz Region::new_canonical_bound(self.cx(), var) } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { if !t.flags().intersects(NEEDS_CANONICAL) { t } else if let Some(&ty) = self.cache.get(&t) { diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 1f64f09fe787f..cd42bf8b57b60 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -16,7 +16,7 @@ use rustc_index::IndexVec; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{ - self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, + self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, Ty, TypeFoldable, }; use tracing::instrument; @@ -53,7 +53,7 @@ impl ResponseT for inspect::State { pub(super) fn canonicalize_goal( delegate: &D, goal: Goal, - opaque_types: &[(ty::OpaqueTypeKey, I::Ty)], + opaque_types: &[(ty::OpaqueTypeKey, Ty)], ) -> (Vec, CanonicalInput) where D: SolverDelegate, @@ -264,7 +264,7 @@ fn register_region_constraints( fn register_new_opaque_types( delegate: &D, - opaque_types: &[(ty::OpaqueTypeKey, I::Ty)], + opaque_types: &[(ty::OpaqueTypeKey, Ty)], span: I::Span, ) where D: SolverDelegate, diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index c370fd24a1bb3..69cebb0a3dc64 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -47,7 +47,7 @@ pub enum Conflict { pub fn trait_ref_is_knowable( infcx: &Infcx, trait_ref: ty::TraitRef, - mut lazily_normalize_ty: impl FnMut(I::Ty) -> Result, + mut lazily_normalize_ty: impl FnMut(ty::Ty) -> Result, E>, ) -> Result, E> where Infcx: InferCtxtLike, @@ -115,14 +115,14 @@ impl From for IsFirstInputType { #[derive_where(Debug; I: Interner, T: Debug)] pub enum OrphanCheckErr { - NonLocalInputType(Vec<(I::Ty, IsFirstInputType)>), + NonLocalInputType(Vec<(ty::Ty, IsFirstInputType)>), UncoveredTyParams(UncoveredTyParams), } #[derive_where(Debug; I: Interner, T: Debug)] pub struct UncoveredTyParams { pub uncovered: T, - pub local_ty: Option, + pub local_ty: Option>, } /// Checks whether a trait-ref is potentially implementable by a crate. @@ -222,8 +222,8 @@ pub fn orphan_check_trait_ref( infcx: &Infcx, trait_ref: ty::TraitRef, in_crate: InCrate, - lazily_normalize_ty: impl FnMut(I::Ty) -> Result, -) -> Result>, E> + lazily_normalize_ty: impl FnMut(ty::Ty) -> Result, E>, +) -> Result>>, E> where Infcx: InferCtxtLike, I: Interner, @@ -262,14 +262,14 @@ struct OrphanChecker<'a, Infcx, I: Interner, F> { lazily_normalize_ty: F, /// Ignore orphan check failures and exclusively search for the first local type. search_first_local_ty: bool, - non_local_tys: Vec<(I::Ty, IsFirstInputType)>, + non_local_tys: Vec<(ty::Ty, IsFirstInputType)>, } impl<'a, Infcx, I, F, E> OrphanChecker<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnOnce(I::Ty) -> Result, + F: FnOnce(ty::Ty) -> Result, E>, { fn new(infcx: &'a Infcx, in_crate: InCrate, lazily_normalize_ty: F) -> Self { OrphanChecker { @@ -282,12 +282,15 @@ where } } - fn found_non_local_ty(&mut self, t: I::Ty) -> ControlFlow> { + fn found_non_local_ty(&mut self, t: ty::Ty) -> ControlFlow> { self.non_local_tys.push((t, self.in_self_ty.into())); ControlFlow::Continue(()) } - fn found_uncovered_ty_param(&mut self, ty: I::Ty) -> ControlFlow> { + fn found_uncovered_ty_param( + &mut self, + ty: ty::Ty, + ) -> ControlFlow> { if self.search_first_local_ty { return ControlFlow::Continue(()); } @@ -305,15 +308,15 @@ where enum OrphanCheckEarlyExit { NormalizationFailure(E), - UncoveredTyParam(I::Ty), - LocalTy(I::Ty), + UncoveredTyParam(ty::Ty), + LocalTy(ty::Ty), } impl<'a, Infcx, I, F, E> TypeVisitor for OrphanChecker<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Ty) -> Result, + F: FnMut(ty::Ty) -> Result, E>, { type Result = ControlFlow>; @@ -321,7 +324,7 @@ where ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: ty::Ty) -> Self::Result { let ty = self.infcx.shallow_resolve(ty); let ty = match (self.lazily_normalize_ty)(ty) { Ok(norm_ty) if norm_ty.is_ty_var() => ty, diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 9d5aa8bc124b6..1714ae3dd6b2e 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable}; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Ty, TypeFoldable}; pub trait SolverDelegate: Deref + Sized { type Infcx: InferCtxtLike; @@ -70,7 +70,7 @@ pub trait SolverDelegate: Deref + Sized { def_id: ::DefId, args: ::GenericArgs, param_env: ::ParamEnv, - hidden_ty: ::Ty, + hidden_ty: Ty, goals: &mut Vec::Predicate>>, ); @@ -86,8 +86,8 @@ pub trait SolverDelegate: Deref + Sized { fn is_transmutable( &self, - src: ::Ty, - dst: ::Ty, + src: Ty, + dst: Ty, assume: ::Const, ) -> Result; } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index 83f3bdf01dc83..fe7521c86e9be 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -113,7 +113,7 @@ where } } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { match t.kind() { ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _) if debruijn.as_usize() + 1 diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index c3c57eccd6eff..86bf05bdb57cc 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -1,7 +1,7 @@ use rustc_type_ir::data_structures::DelayedMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, + self as ty, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -19,7 +19,7 @@ where delegate: &'a D, /// We're able to use a cache here as the folder does not have any /// mutable state. - cache: DelayedMap, + cache: DelayedMap, Ty>, } pub fn eager_resolve_vars>( @@ -45,7 +45,7 @@ impl, I: Interner> TypeFolder for EagerResolv self.delegate.cx() } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { match t.kind() { ty::Infer(ty::TyVar(vid)) => { let resolved = self.delegate.opportunistic_resolve_ty_var(vid); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 32b1e93bf98be..f58318b83625d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -46,11 +46,11 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty; + fn self_ty(self) -> ty::Ty; fn trait_ref(self, cx: I) -> ty::TraitRef; - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self; + fn with_replaced_self_ty(self, cx: I, self_ty: ty::Ty) -> Self; fn trait_def_id(self, cx: I) -> I::TraitId; @@ -683,7 +683,7 @@ where // hitting another overflow error something. Add a depth parameter needed later. fn assemble_alias_bound_candidates_recur>( &mut self, - self_ty: I::Ty, + self_ty: ty::Ty, goal: Goal, candidates: &mut Vec>, consider_self_bounds: AliasBoundKind, @@ -1017,13 +1017,13 @@ where struct ReplaceOpaque { cx: I, alias_ty: ty::AliasTy, - self_ty: I::Ty, + self_ty: ty::Ty, } impl TypeFolder for ReplaceOpaque { fn cx(&self) -> I { self.cx } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn fold_ty(&mut self, ty: ty::Ty) -> ty::Ty { if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() { if alias_ty == self.alias_ty { return self.self_ty; @@ -1280,7 +1280,7 @@ where ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: ty::Ty) -> Self::Result { let ty = self.ecx.replace_bound_vars(ty, &mut self.universes); let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { return ControlFlow::Break(Err(NoSolution)); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 433cad188bb6c..cbdf0b0a4cc72 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -21,8 +21,8 @@ use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution}; #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait( ecx: &EvalCtxt<'_, D>, - ty: I::Ty, -) -> Result>, NoSolution> + ty: ty::Ty, +) -> Result>>, NoSolution> where D: SolverDelegate, I: Interner, @@ -108,8 +108,8 @@ where pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait( ecx: &EvalCtxt<'_, D>, sizedness: SizedTraitKind, - ty: I::Ty, -) -> Result>, NoSolution> + ty: ty::Ty, +) -> Result>>, NoSolution> where D: SolverDelegate, I: Interner, @@ -186,8 +186,8 @@ where #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait( ecx: &EvalCtxt<'_, D>, - ty: I::Ty, -) -> Result>, NoSolution> + ty: ty::Ty, +) -> Result>>, NoSolution> where D: SolverDelegate, I: Interner, @@ -268,9 +268,9 @@ where // Returns a binder of the tupled inputs types and output type from a builtin callable type. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable( cx: I, - self_ty: I::Ty, + self_ty: ty::Ty, goal_kind: ty::ClosureKind, -) -> Result>, NoSolution> { +) -> Result, ty::Ty)>>, NoSolution> { match self_ty.kind() { // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnDef(def_id, args) => { @@ -408,13 +408,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { - pub tupled_inputs_ty: I::Ty, + pub tupled_inputs_ty: ty::Ty, /// Type returned by calling the closure /// i.e. `f()`. - pub output_coroutine_ty: I::Ty, + pub output_coroutine_ty: ty::Ty, /// Type returned by `await`ing the output /// i.e. `f().await`. - pub coroutine_return_ty: I::Ty, + pub coroutine_return_ty: ty::Ty, } // Returns a binder of the tupled inputs types, output type, and coroutine type @@ -424,7 +424,7 @@ pub(in crate::solve) struct AsyncCallableRelevantTypes { // know the kind already, we can short-circuit this check. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( cx: I, - self_ty: I::Ty, + self_ty: ty::Ty, goal_kind: ty::ClosureKind, env_region: I::Region, ) -> Result<(ty::Binder>, Vec), NoSolution> { @@ -608,7 +608,7 @@ fn coroutine_closure_to_certain_coroutine( def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, -) -> I::Ty { +) -> ty::Ty { sig.to_coroutine_given_kind_and_upvars( cx, args.parent_args(), @@ -632,7 +632,7 @@ fn coroutine_closure_to_ambiguous_coroutine( def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, -) -> I::Ty { +) -> ty::Ty { let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars); let tupled_upvars_ty = Ty::new_projection( cx, @@ -664,8 +664,8 @@ fn coroutine_closure_to_ambiguous_coroutine( #[instrument(level = "trace", skip(cx), ret)] pub(in crate::solve) fn extract_fn_def_from_const_callable( cx: I, - self_ty: I::Ty, -) -> Result<(ty::Binder, I::DefId, I::GenericArgs), NoSolution> { + self_ty: ty::Ty, +) -> Result<(ty::Binder, ty::Ty)>, I::DefId, I::GenericArgs), NoSolution> { match self_ty.kind() { ty::FnDef(def_id, args) => { let sig = cx.fn_sig(def_id); @@ -742,7 +742,7 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( // the old solver, for as long as that exists. pub(in crate::solve) fn const_conditions_for_destruct( cx: I, - self_ty: I::Ty, + self_ty: ty::Ty, ) -> Result>, NoSolution> { let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct); @@ -927,7 +927,7 @@ where struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate> { ecx: &'a mut EvalCtxt<'b, D>, param_env: I::ParamEnv, - self_ty: I::Ty, + self_ty: ty::Ty, mapping: &'a HashMap>>>, nested: Vec>, } @@ -1013,7 +1013,7 @@ where self.ecx.cx() } - fn try_fold_ty(&mut self, ty: I::Ty) -> Result { + fn try_fold_ty(&mut self, ty: ty::Ty) -> Result, Ambiguous> { if let ty::Alias(ty::Projection, alias_ty) = ty.kind() && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 4b1e4b2de571d..9a0a82acbc931 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -13,7 +13,7 @@ use super::assembly::{Candidate, structural_traits}; use crate::delegate::SolverDelegate; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution, - QueryResult, assembly, + QueryResult, Ty, assembly, }; impl assembly::GoalKind for ty::HostEffectPredicate @@ -21,7 +21,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty { + fn self_ty(self) -> Ty { self.self_ty() } @@ -29,7 +29,7 @@ where self.trait_ref } - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 6841fe1c5124e..d6ed220909732 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -10,7 +10,7 @@ use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind}; use rustc_type_ir::solve::OpaqueTypesJank; use rustc_type_ir::{ - self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder, + self as ty, CanonicalVarValues, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; @@ -781,7 +781,7 @@ where region } - pub(super) fn next_ty_infer(&mut self) -> I::Ty { + pub(super) fn next_ty_infer(&mut self) -> Ty { let ty = self.delegate.next_ty_infer(); self.inspect.add_var_value(ty); ty @@ -829,7 +829,7 @@ where term: I::Term, universe_of_term: ty::UniverseIndex, delegate: &'a D, - cache: HashSet, + cache: HashSet>, } impl, I: Interner> ContainsTermOrNotNameable<'_, D, I> { @@ -846,7 +846,7 @@ where for ContainsTermOrNotNameable<'_, D, I> { type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { if self.cache.contains(&t) { return ControlFlow::Continue(()); } @@ -1072,7 +1072,7 @@ where self.delegate.resolve_vars_if_possible(value) } - pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty { + pub(super) fn shallow_resolve(&self, ty: Ty) -> Ty { self.delegate.shallow_resolve(ty) } @@ -1092,7 +1092,7 @@ where args } - pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { + pub(super) fn register_ty_outlives(&self, ty: Ty, lt: I::Region) { self.delegate.register_ty_outlives(ty, lt, self.origin_span); } @@ -1134,8 +1134,8 @@ where pub(super) fn register_hidden_type_in_storage( &mut self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: I::Ty, - ) -> Option { + hidden_ty: Ty, + ) -> Option> { self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span) } @@ -1144,7 +1144,7 @@ where opaque_def_id: I::DefId, opaque_args: I::GenericArgs, param_env: I::ParamEnv, - hidden_ty: I::Ty, + hidden_ty: Ty, ) { let mut goals = Vec::new(); self.delegate.add_item_bounds_for_hidden_type( @@ -1170,8 +1170,8 @@ where pub(super) fn is_transmutable( &mut self, - src: I::Ty, - dst: I::Ty, + src: Ty, + dst: Ty, assume: I::Const, ) -> Result { self.delegate.is_transmutable(dst, src, assume) @@ -1195,7 +1195,7 @@ where pub(crate) fn opaques_with_sub_unified_hidden_type( &self, - self_ty: I::Ty, + self_ty: Ty, ) -> Vec> { if let ty::Infer(ty::TyVar(vid)) = self_ty.kind() { self.delegate.opaques_with_sub_unified_hidden_type(vid) @@ -1389,7 +1389,7 @@ where ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv, normalization_goal_source: GoalSource, - cache: HashMap, + cache: HashMap, Ty>, } impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I> @@ -1421,7 +1421,7 @@ where self.ecx.cx() } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn fold_ty(&mut self, ty: Ty) -> Ty { match ty.kind() { ty::Alias(..) if !ty.has_escaping_bound_vars() => { let infer_ty = self.ecx.next_ty_infer(); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 58bd7cf663d98..71b28cf1ad277 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -24,7 +24,7 @@ mod trait_goals; use derive_where::derive_where; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner, TyVid, TypingMode}; +use rustc_type_ir::{self as ty, Interner, Ty, TyVid, TypingMode}; use tracing::instrument; pub use self::eval_ctxt::{ @@ -88,7 +88,7 @@ where #[instrument(level = "trace", skip(self))] fn compute_type_outlives_goal( &mut self, - goal: Goal>, + goal: Goal>>, ) -> QueryResult { let ty::OutlivesPredicate(ty, lt) = goal.predicate; self.register_ty_outlives(ty, lt); @@ -205,7 +205,7 @@ where #[instrument(level = "trace", skip(self), ret)] fn compute_const_arg_has_type_goal( &mut self, - goal: Goal, + goal: Goal)>, ) -> QueryResult { let (ct, ty) = goal.predicate; let ct = self.structurally_normalize_const(goal.param_env, ct)?; @@ -315,8 +315,8 @@ where fn structurally_normalize_ty( &mut self, param_env: I::ParamEnv, - ty: I::Ty, - ) -> Result { + ty: Ty, + ) -> Result, NoSolution> { self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty()) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 13f2ad8f82eba..13ed945857db2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -125,7 +125,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty { + fn self_ty(self) -> ty::Ty { self.self_ty() } @@ -133,7 +133,7 @@ where self.alias.trait_ref(cx) } - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: ty::Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 6589a12c4cc2d..82051b2fea4ef 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -29,7 +29,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty { + fn self_ty(self) -> ty::Ty { self.self_ty() } @@ -37,7 +37,7 @@ where self.trait_ref } - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: ty::Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } @@ -929,7 +929,7 @@ where /// ``` fn consider_builtin_dyn_upcast_candidates( &mut self, - goal: Goal, + goal: Goal, ty::Ty)>, a_data: I::BoundExistentialPredicates, a_region: I::Region, b_data: I::BoundExistentialPredicates, @@ -977,7 +977,7 @@ where fn consider_builtin_unsize_to_dyn_candidate( &mut self, - goal: Goal, + goal: Goal, ty::Ty)>, b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Result, NoSolution> { @@ -1018,7 +1018,7 @@ where fn consider_builtin_upcast_to_principal( &mut self, - goal: Goal, + goal: Goal, ty::Ty)>, source: CandidateSource, a_data: I::BoundExistentialPredicates, a_region: I::Region, @@ -1132,9 +1132,9 @@ where /// `#[rustc_deny_explicit_impl]` in this case. fn consider_builtin_array_unsize( &mut self, - goal: Goal, - a_elem_ty: I::Ty, - b_elem_ty: I::Ty, + goal: Goal, ty::Ty)>, + a_elem_ty: ty::Ty, + b_elem_ty: ty::Ty, ) -> Result, NoSolution> { self.eq(goal.param_env, a_elem_ty, b_elem_ty)?; self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) @@ -1156,7 +1156,7 @@ where /// ``` fn consider_builtin_struct_unsize( &mut self, - goal: Goal, + goal: Goal, ty::Ty)>, def: I::AdtDef, a_args: I::GenericArgs, b_args: I::GenericArgs, @@ -1319,8 +1319,8 @@ where goal: Goal>, constituent_tys: impl Fn( &EvalCtxt<'_, D>, - I::Ty, - ) -> Result>, NoSolution>, + ty::Ty, + ) -> Result>>, NoSolution>, ) -> Result, NoSolution> { self.probe_trait_candidate(source).enter(|ecx| { let goals = @@ -1542,7 +1542,10 @@ where self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info) } - fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { + fn try_stall_coroutine( + &mut self, + self_ty: ty::Ty, + ) -> Option, NoSolution>> { if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 0b0f0fd2f4249..6528aa7526b21 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -16,7 +16,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldabl use crate::inherent::*; use crate::lift::Lift; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex}; +use crate::{self as ty, DebruijnIndex, Interner, Ty, UniverseIndex}; /// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` @@ -274,7 +274,7 @@ pub struct ValidateBoundVars { // We only cache types because any complex const will have to step through // a type at some point anyways. We may encounter the same variable at // different levels of binding, so this can't just be `Ty`. - visited: SsoHashSet<(ty::DebruijnIndex, I::Ty)>, + visited: SsoHashSet<(ty::DebruijnIndex, Ty)>, } impl ValidateBoundVars { @@ -297,7 +297,7 @@ impl TypeVisitor for ValidateBoundVars { result } - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { @@ -724,7 +724,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { if !t.has_param() { return t; } @@ -753,7 +753,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } impl<'a, I: Interner> ArgFolder<'a, I> { - fn ty_for_param(&self, p: I::ParamTy, source_ty: I::Ty) -> I::Ty { + fn ty_for_param(&self, p: I::ParamTy, source_ty: Ty) -> Ty { // Look up the type in the args. It really should be in there. let opt_ty = self.args.get(p.index() as usize).map(|arg| arg.kind()); let ty = match opt_ty { @@ -767,7 +767,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn type_param_expected(&self, p: I::ParamTy, ty: I::Ty, kind: ty::GenericArgKind) -> ! { + fn type_param_expected(&self, p: I::ParamTy, ty: Ty, kind: ty::GenericArgKind) -> ! { panic!( "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", p, @@ -780,7 +780,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn type_param_out_of_range(&self, p: I::ParamTy, ty: I::Ty) -> ! { + fn type_param_out_of_range(&self, p: I::ParamTy, ty: Ty) -> ! { panic!( "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", p, @@ -1277,7 +1277,7 @@ impl PlaceholderConst { Self { universe: ui, bound, _tcx: PhantomData } } - pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { + pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> Ty { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. match clause.kind().skip_binder() { diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index eba4c7c6644ac..ef542af7f1f9a 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -2,7 +2,7 @@ use derive_where::derive_where; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::solve::NoSolution; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(TypeFoldable_Generic, TypeVisitable_Generic, GenericTypeVisitable)] @@ -36,15 +36,15 @@ pub enum TypeError { RegionsInsufficientlyPolymorphic(ty::BoundRegion, I::Region), RegionsPlaceholderMismatch, - Sorts(ExpectedFound), - ArgumentSorts(ExpectedFound, usize), + Sorts(ExpectedFound>), + ArgumentSorts(ExpectedFound>, usize), Traits(ExpectedFound), VariadicMismatch(ExpectedFound), /// Instantiating a type variable with the given type would have /// created a cycle (because it appears somewhere within that /// type). - CyclicTy(I::Ty), + CyclicTy(Ty), CyclicConst(I::Const), ProjectionMismatched(ExpectedFound), ExistentialMismatch(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index ed6416a7f55f2..72b58776565b5 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -113,7 +113,7 @@ pub enum TreatParams { /// ยน meaning that if the outermost layers are different, then the whole types are also different. pub fn simplify_type( cx: I, - ty: I::Ty, + ty: ty::Ty, treat_params: TreatParams, ) -> Option> { match ty.kind() { @@ -236,11 +236,16 @@ impl bool { + pub fn types_may_unify(self, lhs: ty::Ty, rhs: ty::Ty) -> bool { self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH) } - pub fn types_may_unify_with_depth(self, lhs: I::Ty, rhs: I::Ty, depth_limit: usize) -> bool { + pub fn types_may_unify_with_depth( + self, + lhs: ty::Ty, + rhs: ty::Ty, + depth_limit: usize, + ) -> bool { self.types_may_unify_inner(lhs, rhs, depth_limit) } @@ -268,7 +273,7 @@ impl bool { + fn types_may_unify_inner(self, lhs: ty::Ty, rhs: ty::Ty, depth: usize) -> bool { if lhs == rhs { return true; } @@ -527,7 +532,7 @@ impl bool { + fn var_and_ty_may_unify(self, var: ty::InferTy, ty: ty::Ty) -> bool { if !ty.is_known_rigid() { return true; } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 7e905da0785f8..6962a7ab1d727 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,6 +1,6 @@ use crate::inherent::*; use crate::visit::Flags; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; bitflags::bitflags! { /// Flags that we track on types. These flags are propagated upwards @@ -430,7 +430,7 @@ impl FlagComputation { } } - fn add_ty(&mut self, ty: I::Ty) { + fn add_ty(&mut self, ty: Ty) { self.add_flags(ty.flags()); self.add_exclusive_binder(ty.outer_exclusive_binder()); } diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index d1a50599e8b9c..ef162b21b660e 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -135,7 +135,7 @@ pub trait TypeFolder: Sized { t.super_fold_with(self) } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { t.super_fold_with(self) } @@ -177,7 +177,7 @@ pub trait FallibleTypeFolder: Sized { t.try_super_fold_with(self) } - fn try_fold_ty(&mut self, t: I::Ty) -> Result { + fn try_fold_ty(&mut self, t: ty::Ty) -> Result, Self::Error> { t.try_super_fold_with(self) } @@ -408,7 +408,7 @@ impl TypeFolder for Shifter { } } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn fold_ty(&mut self, ty: ty::Ty) -> ty::Ty { match ty.kind() { ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty) if debruijn >= self.current_index => @@ -538,7 +538,7 @@ where } } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { if t.has_type_flags( TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, ) { diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index 5d612740fdd84..22a4ebd03b69c 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -3,7 +3,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::GenericTypeVisitable; -use crate::Interner; +use crate::{Interner, Ty}; #[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)] #[derive(GenericTypeVisitable)] @@ -13,7 +13,7 @@ use crate::Interner; )] pub enum GenericArgKind { Lifetime(I::Region), - Type(I::Ty), + Type(Ty), Const(I::Const), } @@ -26,7 +26,7 @@ impl Eq for GenericArgKind {} derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub enum TermKind { - Ty(I::Ty), + Ty(Ty), Const(I::Const), } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index feafcee7bad9e..843d1eb37b7d9 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -6,7 +6,7 @@ use crate::fold::TypeFoldable; use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::{self as ty, Interner, TyVid}; +use crate::{self as ty, Interner, Ty, TyVid}; /// The current typing mode of an inference context. We unfortunately have some /// slightly different typing rules depending on the current context. See the @@ -161,12 +161,9 @@ pub trait InferCtxtLike: Sized { fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid; fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid; - fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; - fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; - fn opportunistic_resolve_float_var( - &self, - vid: ty::FloatVid, - ) -> ::Ty; + fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty; + fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty; + fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty; fn opportunistic_resolve_ct_var( &self, vid: ty::ConstVid, @@ -179,7 +176,7 @@ pub trait InferCtxtLike: Sized { fn is_changed_arg(&self, arg: ::GenericArg) -> bool; fn next_region_infer(&self) -> ::Region; - fn next_ty_infer(&self) -> ::Ty; + fn next_ty_infer(&self) -> Ty; fn next_const_infer(&self) -> ::Const; fn fresh_args_for_item( &self, @@ -209,7 +206,7 @@ pub trait InferCtxtLike: Sized { target_is_expected: bool, target_vid: ty::TyVid, instantiation_variance: ty::Variance, - source_ty: ::Ty, + source_ty: Ty, ) -> RelateResult; fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); @@ -223,10 +220,7 @@ pub trait InferCtxtLike: Sized { fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); - fn shallow_resolve( - &self, - ty: ::Ty, - ) -> ::Ty; + fn shallow_resolve(&self, ty: Ty) -> Ty; fn shallow_resolve_const( &self, ty: ::Const, @@ -254,7 +248,7 @@ pub trait InferCtxtLike: Sized { fn register_ty_outlives( &self, - ty: ::Ty, + ty: Ty, r: ::Region, span: ::Span, ); @@ -263,26 +257,26 @@ pub trait InferCtxtLike: Sized { fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; fn clone_opaque_types_lookup_table( &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, Ty)>; fn clone_duplicate_opaque_types( &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, Ty)>; fn clone_opaque_types_added_since( &self, prev_entries: Self::OpaqueTypeStorageEntries, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, Ty)>; fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec>; fn register_hidden_type_in_storage( &self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, + hidden_ty: Ty, span: ::Span, - ) -> Option<::Ty>; + ) -> Option>; fn add_duplicate_opaque_type( &self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, + hidden_ty: Ty, span: ::Span, ); diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 116fd100bf0a9..45590561d9d08 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -55,7 +55,7 @@ pub trait Ty>: fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self; fn new_projection_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self { - Ty::new_alias( + Self::new_alias( interner, ty::AliasTyKind::Projection, ty::AliasTy::new_from_args(interner, def_id, args), @@ -67,7 +67,7 @@ pub trait Ty>: def_id: I::DefId, args: impl IntoIterator>, ) -> Self { - Ty::new_alias( + Self::new_alias( interner, ty::AliasTyKind::Projection, ty::AliasTy::new(interner, def_id, args), @@ -108,7 +108,7 @@ pub trait Ty>: fn new_slice(interner: I, ty: Self) -> Self; - fn new_tup(interner: I, tys: &[I::Ty]) -> Self; + fn new_tup(interner: I, tys: &[ty::Ty]) -> Self; fn new_tup_from_iter(interner: I, iter: It) -> T::Output where @@ -121,7 +121,7 @@ pub trait Ty>: fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self; - fn new_unsafe_binder(interner: I, ty: ty::Binder) -> Self; + fn new_unsafe_binder(interner: I, ty: ty::Binder>) -> Self; fn tuple_fields(self) -> I::Tys; @@ -158,7 +158,7 @@ pub trait Ty>: self.kind().fn_sig(interner) } - fn discriminant_ty(self, interner: I) -> I::Ty; + fn discriminant_ty(self, interner: I) -> ty::Ty; fn is_known_rigid(self) -> bool { self.kind().is_known_rigid() @@ -198,11 +198,11 @@ pub trait Ty>: } pub trait Tys>: - Copy + Debug + Hash + Eq + SliceLike + TypeFoldable + Default + Copy + Debug + Hash + Eq + SliceLike> + TypeFoldable + Default { fn inputs(self) -> I::FnInputTys; - fn output(self) -> I::Ty; + fn output(self) -> ty::Ty; } pub trait Abi>: Copy + Debug + Hash + Eq { @@ -290,7 +290,7 @@ pub trait Const>: } pub trait ValueConst>: Copy + Debug + Hash + Eq { - fn ty(self) -> I::Ty; + fn ty(self) -> ty::Ty; fn valtree(self) -> I::ValTree; } @@ -310,7 +310,7 @@ pub trait GenericArg>: + IntoKind> + TypeVisitable + Relate - + From + + From> + From + From + From @@ -323,11 +323,11 @@ pub trait GenericArg>: } } - fn as_type(&self) -> Option { + fn as_type(&self) -> Option> { if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None } } - fn expect_ty(&self) -> I::Ty { + fn expect_ty(&self) -> ty::Ty { self.as_type().expect("expected a type") } @@ -359,11 +359,11 @@ pub trait GenericArg>: pub trait Term>: Copy + Debug + Hash + Eq + IntoKind> + TypeFoldable + Relate { - fn as_type(&self) -> Option { + fn as_type(&self) -> Option> { if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None } } - fn expect_ty(&self) -> I::Ty { + fn expect_ty(&self) -> ty::Ty { self.as_type().expect("expected a type, but found a const") } @@ -413,7 +413,7 @@ pub trait GenericArgs>: target: I::GenericArgs, ) -> I::GenericArgs; - fn type_at(self, i: usize) -> I::Ty; + fn type_at(self, i: usize) -> ty::Ty; fn region_at(self, i: usize) -> I::Region; @@ -459,7 +459,7 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom>> + UpcastFrom> - + UpcastFrom> + + UpcastFrom>> + UpcastFrom> + IntoKind>> + Elaboratable @@ -578,7 +578,7 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { /// Returns the type of the struct tail. /// /// Expects the `AdtDef` to be a struct. If it is not, then this will panic. - fn struct_tail_ty(self, interner: I) -> Option>; + fn struct_tail_ty(self, interner: I) -> Option>>; fn is_phantom_data(self) -> bool; @@ -591,13 +591,13 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { ) -> Option>; // FIXME: perhaps use `all_fields` and expose `FieldDef`. - fn all_field_tys(self, interner: I) -> ty::EarlyBinder>; + fn all_field_tys(self, interner: I) -> ty::EarlyBinder>>; fn sizedness_constraint( self, interner: I, sizedness: SizedTraitKind, - ) -> Option>; + ) -> Option>>; fn is_fundamental(self) -> bool; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a0b444024ca79..6c838cf8a48ac 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -31,6 +31,7 @@ pub mod outlives; pub mod relate; pub mod search_graph; pub mod solve; +pub mod sty; pub mod walk; // These modules are not `pub` since they are glob-imported. @@ -78,6 +79,7 @@ pub use predicate_kind::*; pub use region_kind::*; pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy}; use rustc_type_ir_macros::GenericTypeVisitable; +pub use sty::*; pub use ty_info::*; pub use ty_kind::*; pub use upcast::*; @@ -443,8 +445,8 @@ impl fmt::Display for ClosureKind { } pub struct FieldInfo { - pub base: I::Ty, - pub ty: I::Ty, + pub base: Ty, + pub ty: Ty, pub variant: Option, pub variant_idx: VariantIdx, pub name: I::Symbol, diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 300e5c0b46956..cc79d6589e6fb 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -8,7 +8,7 @@ use smallvec::{SmallVec, smallvec}; use crate::data_structures::SsoHashSet; use crate::inherent::*; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, TypeVisitor}; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; #[derive_where(Debug; I: Interner)] pub enum Component { @@ -55,7 +55,7 @@ pub enum Component { /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. pub fn push_outlives_components( cx: I, - ty: I::Ty, + ty: Ty, out: &mut SmallVec<[Component; 4]>, ) { ty.visit_with(&mut OutlivesCollector { cx, out, visited: Default::default() }); @@ -64,14 +64,14 @@ pub fn push_outlives_components( struct OutlivesCollector<'a, I: Interner> { cx: I, out: &'a mut SmallVec<[Component; 4]>, - visited: SsoHashSet, + visited: SsoHashSet>, } impl TypeVisitor for OutlivesCollector<'_, I> { #[cfg(not(feature = "nightly"))] type Result = (); - fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: Ty) -> Self::Result { if !self.visited.insert(ty) { return; } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 113192cc02eb8..f4975f3ad4486 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -101,7 +101,7 @@ impl TraitRef { ) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { TraitRef::new( interner, self.def_id, @@ -110,13 +110,13 @@ impl TraitRef { } #[inline] - pub fn self_ty(&self) -> I::Ty { + pub fn self_ty(&self) -> ty::Ty { self.args.type_at(0) } } impl ty::Binder> { - pub fn self_ty(&self) -> ty::Binder { + pub fn self_ty(&self) -> ty::Binder> { self.map_bound_ref(|tr| tr.self_ty()) } @@ -152,7 +152,7 @@ pub struct TraitPredicate { impl Eq for TraitPredicate {} impl TraitPredicate { - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), polarity: self.polarity, @@ -163,7 +163,7 @@ impl TraitPredicate { self.trait_ref.def_id } - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> ty::Ty { self.trait_ref.self_ty() } } @@ -174,7 +174,7 @@ impl ty::Binder> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder { + pub fn self_ty(self) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.self_ty()) } @@ -307,7 +307,7 @@ impl ty::Binder> { /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). - pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause { + pub fn with_self_ty(&self, cx: I, self_ty: ty::Ty) -> I::Clause { match self.skip_binder() { ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx), ExistentialPredicate::Projection(p) => { @@ -384,7 +384,7 @@ impl ExistentialTraitRef { /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self type. A common choice is `mk_err()` /// or some placeholder type. - pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { + pub fn with_self_ty(self, interner: I, self_ty: ty::Ty) -> TraitRef { // otherwise the escaping vars would be captured by the binder // debug_assert!(!self_ty.has_escaping_bound_vars()); @@ -401,7 +401,7 @@ impl ty::Binder> { /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self type. A common choice is `mk_err()` /// or some placeholder type. - pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder> { + pub fn with_self_ty(&self, cx: I, self_ty: ty::Ty) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty)) } } @@ -459,7 +459,7 @@ impl ExistentialProjection { ExistentialTraitRef::new_from_args(interner, def_id.try_into().unwrap(), args) } - pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { + pub fn with_self_ty(&self, interner: I, self_ty: ty::Ty) -> ProjectionPredicate { // otherwise the escaping regions would be captured by the binders debug_assert!(!self_ty.has_escaping_bound_vars()); @@ -487,7 +487,7 @@ impl ExistentialProjection { } impl ty::Binder> { - pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder> { + pub fn with_self_ty(&self, cx: I, self_ty: ty::Ty) -> ty::Binder> { self.map_bound(|p| p.with_self_ty(cx, self_ty)) } @@ -683,11 +683,11 @@ impl AliasTerm { /// The following methods work only with (trait) associated term projections. impl AliasTerm { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> ty::Ty { self.args.type_at(0) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { AliasTerm::new( interner, self.def_id, @@ -796,11 +796,11 @@ pub struct ProjectionPredicate { impl Eq for ProjectionPredicate {} impl ProjectionPredicate { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> ty::Ty { self.projection_term.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> ProjectionPredicate { Self { projection_term: self.projection_term.with_replaced_self_ty(interner, self_ty), ..self @@ -859,11 +859,11 @@ pub struct NormalizesTo { impl Eq for NormalizesTo {} impl NormalizesTo { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> ty::Ty { self.alias.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> NormalizesTo { Self { alias: self.alias.with_replaced_self_ty(interner, self_ty), ..self } } @@ -896,11 +896,11 @@ pub struct HostEffectPredicate { impl Eq for HostEffectPredicate {} impl HostEffectPredicate { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> ty::Ty { self.trait_ref.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), ..self } } @@ -915,7 +915,7 @@ impl ty::Binder> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder { + pub fn self_ty(self) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.self_ty()) } @@ -936,8 +936,8 @@ impl ty::Binder> { )] pub struct SubtypePredicate { pub a_is_expected: bool, - pub a: I::Ty, - pub b: I::Ty, + pub a: ty::Ty, + pub b: ty::Ty, } impl Eq for SubtypePredicate {} @@ -950,8 +950,8 @@ impl Eq for SubtypePredicate {} derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub struct CoercePredicate { - pub a: I::Ty, - pub b: I::Ty, + pub a: ty::Ty, + pub b: ty::Ty, } impl Eq for CoercePredicate {} diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 445e85a888fca..b6ff27fb238e6 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -5,7 +5,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. @@ -25,7 +25,7 @@ pub enum ClauseKind { RegionOutlives(ty::OutlivesPredicate), /// `where T: 'r` - TypeOutlives(ty::OutlivesPredicate), + TypeOutlives(ty::OutlivesPredicate>), /// `where ::Name == X`, approximately. /// See the `ProjectionPredicate` struct for details. @@ -33,7 +33,7 @@ pub enum ClauseKind { /// Ensures that a const generic argument to a parameter `const N: u8` /// is of type `u8`. - ConstArgHasType(I::Const, I::Ty), + ConstArgHasType(I::Const, Ty), /// No syntax: `T` well-formed. WellFormed(I::Term), diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index d33c6036dadd8..31248bea4cf85 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -44,7 +44,7 @@ pub enum VarianceDiagInfo { Invariant { /// The generic type containing the generic parameter /// that changes the variance (e.g. `*mut T`, `MyStruct`) - ty: I::Ty, + ty: ty::Ty, /// The index of the generic parameter being used /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`) param_index: u32, @@ -75,13 +75,13 @@ pub trait TypeRelation: Sized { fn relate_ty_args( &mut self, - a_ty: I::Ty, - b_ty: I::Ty, + a_ty: ty::Ty, + b_ty: ty::Ty, ty_def_id: I::DefId, a_arg: I::GenericArgs, b_arg: I::GenericArgs, - mk: impl FnOnce(I::GenericArgs) -> I::Ty, - ) -> RelateResult; + mk: impl FnOnce(I::GenericArgs) -> ty::Ty, + ) -> RelateResult>; /// Switch variance for the purpose of relating `a` and `b`. fn relate_with_variance>( @@ -98,7 +98,7 @@ pub trait TypeRelation: Sized { // additional hooks for other types in the future if needed // without making older code, which called `relate`, obsolete. - fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult; + fn tys(&mut self, a: ty::Ty, b: ty::Ty) -> RelateResult>; fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult; @@ -332,9 +332,9 @@ impl Relate for ty::ExistentialTraitRef { #[instrument(level = "trace", skip(relation), ret)] pub fn structurally_relate_tys>( relation: &mut R, - a: I::Ty, - b: I::Ty, -) -> RelateResult { + a: ty::Ty, + b: ty::Ty, +) -> RelateResult> { let cx = relation.cx(); match (a.kind(), b.kind()) { (ty::Infer(_), _) | (_, ty::Infer(_)) => { diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 64b87fac77f94..11fbbf89b9c7b 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -39,15 +39,15 @@ where ); /// Register `AliasRelate` obligation(s) that both types must be related to each other. - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); + fn register_alias_relate_predicate(&mut self, a: ty::Ty, b: ty::Ty); } pub fn super_combine_tys( infcx: &Infcx, relation: &mut R, - a: I::Ty, - b: I::Ty, -) -> RelateResult + a: ty::Ty, + b: ty::Ty, +) -> RelateResult> where Infcx: InferCtxtLike, I: Interner, @@ -226,13 +226,13 @@ where pub fn combine_ty_args( infcx: &Infcx, relation: &mut R, - a_ty: I::Ty, - b_ty: I::Ty, + a_ty: ty::Ty, + b_ty: ty::Ty, variances: I::VariancesOf, a_args: I::GenericArgs, b_args: I::GenericArgs, - mk: impl FnOnce(I::GenericArgs) -> I::Ty, -) -> RelateResult + mk: impl FnOnce(I::GenericArgs) -> ty::Ty, +) -> RelateResult> where Infcx: InferCtxtLike, I: Interner, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 82ee4f75fcb0a..1494d67d3c603 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -5,7 +5,7 @@ use crate::data_structures::DelayedSet; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; use crate::solve::Goal; -use crate::{self as ty, InferCtxtLike, Interner}; +use crate::{self as ty, InferCtxtLike, Interner, Ty}; pub trait RelateExt: InferCtxtLike { fn relate>( @@ -104,7 +104,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { /// constrain `?1` to `u32`. When using the cache entry from the /// first time we've related these types, this only happens when /// later proving the `Subtype(?0, ?1)` goal from the first relation. - cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>, + cache: DelayedSet<(ty::Variance, Ty, Ty)>, } impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I> @@ -142,13 +142,13 @@ where fn relate_ty_args( &mut self, - a_ty: I::Ty, - b_ty: I::Ty, + a_ty: Ty, + b_ty: Ty, def_id: I::DefId, a_args: I::GenericArgs, b_args: I::GenericArgs, - _: impl FnOnce(I::GenericArgs) -> I::Ty, - ) -> RelateResult { + _: impl FnOnce(I::GenericArgs) -> Ty, + ) -> RelateResult> { if self.ambient_variance == ty::Invariant { // Avoid fetching the variance if we are in an invariant // context; no need, and it can induce dependency cycles @@ -178,7 +178,7 @@ where } #[instrument(skip(self), level = "trace")] - fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult { + fn tys(&mut self, a: Ty, b: Ty) -> RelateResult> { if a == b { return Ok(a); } @@ -383,7 +383,7 @@ where self.goals.extend(obligations); } - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { + fn register_alias_relate_predicate(&mut self, a: Ty, b: Ty) { self.register_predicates([ty::Binder::dummy(match self.ambient_variance { ty::Covariant => ty::PredicateKind::AliasRelate( a.into(), diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 72b7df22b30d5..23e6075452b18 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -11,7 +11,7 @@ use rustc_type_ir_macros::{ use crate::lang_items::SolverTraitLangItem; use crate::search_graph::PathKind; -use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast}; +use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Ty, Upcast}; pub type CanonicalInput::Predicate> = ty::CanonicalQueryInput>; @@ -254,7 +254,7 @@ impl Eq for Response {} #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct ExternalConstraintsData { pub region_constraints: Vec>, - pub opaque_types: Vec<(ty::OpaqueTypeKey, I::Ty)>, + pub opaque_types: Vec<(ty::OpaqueTypeKey, Ty)>, pub normalization_nested_goals: NestedNormalizationGoals, } diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs new file mode 100644 index 0000000000000..5b73d372384b8 --- /dev/null +++ b/compiler/rustc_type_ir/src/sty/mod.rs @@ -0,0 +1,3 @@ +/// This type is temporary and exists to cut down the bloat of further PR's +/// moving `struct Ty` from `rustc_middle` to `rustc_type_ir`. +pub type Ty = ::Ty; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 983d8f0820b6b..24d28acc05e98 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -100,7 +100,7 @@ pub enum TyKind { Str, /// An array with the given length. Written as `[T; N]`. - Array(I::Ty, I::Const), + Array(ty::Ty, I::Const), /// A pattern newtype. /// @@ -109,17 +109,17 @@ pub enum TyKind { /// Only `Copy` and `Clone` will automatically get implemented for pattern types. /// Auto-traits treat this as if it were an aggregate with a single nested type. /// Only supports integer range patterns for now. - Pat(I::Ty, I::Pat), + Pat(ty::Ty, I::Pat), /// The pointee of an array slice. Written as `[T]`. - Slice(I::Ty), + Slice(ty::Ty), /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(I::Ty, Mutability), + RawPtr(ty::Ty, Mutability), /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. - Ref(I::Region, I::Ty, Mutability), + Ref(I::Region, ty::Ty, Mutability), /// The anonymous type of a function declaration/definition. /// @@ -469,18 +469,18 @@ impl AliasTy { matches!(self.kind(interner), AliasTyKind::Opaque) } - pub fn to_ty(self, interner: I) -> I::Ty { + pub fn to_ty(self, interner: I) -> ty::Ty { Ty::new_alias(interner, self.kind(interner), self) } } /// The following methods work only with (trait) associated type projections. impl AliasTy { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> ty::Ty { self.args.type_at(0) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { AliasTy::new( interner, self.def_id, @@ -735,7 +735,7 @@ impl fmt::Debug for InferTy { )] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct TypeAndMut { - pub ty: I::Ty, + pub ty: ty::Ty, pub mutbl: Mutability, } @@ -765,7 +765,7 @@ impl FnSig { self.inputs_and_output.inputs() } - pub fn output(self) -> I::Ty { + pub fn output(self) -> ty::Ty { self.inputs_and_output.output() } @@ -783,7 +783,7 @@ impl ty::Binder> { #[inline] #[track_caller] - pub fn input(self, index: usize) -> ty::Binder { + pub fn input(self, index: usize) -> ty::Binder> { self.map_bound(|fn_sig| fn_sig.inputs().get(index).unwrap()) } @@ -792,7 +792,7 @@ impl ty::Binder> { } #[inline] - pub fn output(self) -> ty::Binder { + pub fn output(self) -> ty::Binder> { self.map_bound(|fn_sig| fn_sig.output()) } @@ -856,21 +856,21 @@ impl fmt::Debug for FnSig { } // FIXME: this is a distinct type because we need to define `Encode`/`Decode` -// impls in this crate for `Binder`. +// impls in this crate for `Binder>`. #[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -pub struct UnsafeBinderInner(ty::Binder); +pub struct UnsafeBinderInner(ty::Binder>); impl Eq for UnsafeBinderInner {} -impl From> for UnsafeBinderInner { - fn from(value: ty::Binder) -> Self { +impl From>> for UnsafeBinderInner { + fn from(value: ty::Binder>) -> Self { UnsafeBinderInner(value) } } -impl From> for ty::Binder { +impl From> for ty::Binder> { fn from(value: UnsafeBinderInner) -> Self { value.0 } @@ -883,7 +883,7 @@ impl fmt::Debug for UnsafeBinderInner { } impl Deref for UnsafeBinderInner { - type Target = ty::Binder; + type Target = ty::Binder>; fn deref(&self) -> &Self::Target { &self.0 @@ -894,7 +894,7 @@ impl Deref for UnsafeBinderInner { impl rustc_serialize::Encodable for UnsafeBinderInner where - I::Ty: rustc_serialize::Encodable, + ty::Ty: rustc_serialize::Encodable, I::BoundVarKinds: rustc_serialize::Encodable, { fn encode(&self, e: &mut E) { @@ -907,7 +907,7 @@ where impl rustc_serialize::Decodable for UnsafeBinderInner where - I::Ty: TypeVisitable + rustc_serialize::Decodable, + ty::Ty: TypeVisitable + rustc_serialize::Decodable, I::BoundVarKinds: rustc_serialize::Decodable, { fn decode(decoder: &mut D) -> Self { @@ -937,7 +937,7 @@ impl FnSigTys { self.inputs_and_output.inputs() } - pub fn output(self) -> I::Ty { + pub fn output(self) -> ty::Ty { self.inputs_and_output.output() } } @@ -960,7 +960,7 @@ impl ty::Binder> { #[inline] #[track_caller] - pub fn input(self, index: usize) -> ty::Binder { + pub fn input(self, index: usize) -> ty::Binder> { self.map_bound(|sig_tys| sig_tys.inputs().get(index).unwrap()) } @@ -969,7 +969,7 @@ impl ty::Binder> { } #[inline] - pub fn output(self) -> ty::Binder { + pub fn output(self) -> ty::Binder> { self.map_bound(|sig_tys| sig_tys.output()) } } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index e8f94c8e7cc92..08c303b8de9c8 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -121,13 +121,13 @@ pub struct ClosureArgsParts { /// This is the args of the typeck root. pub parent_args: I::GenericArgsSlice, /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: I::Ty, + pub closure_kind_ty: ty::Ty, /// Captures the closure's signature. This closure signature is "tupled", and /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`. - pub closure_sig_as_fn_ptr_ty: I::Ty, + pub closure_sig_as_fn_ptr_ty: ty::Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: I::Ty, + pub tupled_upvars_ty: ty::Ty, } impl ClosureArgs { @@ -169,14 +169,14 @@ impl ClosureArgs { /// Returns the tuple type representing the upvars for this closure. #[inline] - pub fn tupled_upvars_ty(self) -> I::Ty { + pub fn tupled_upvars_ty(self) -> ty::Ty { self.split().tupled_upvars_ty } /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during /// inference, use `infcx.closure_kind(args)`. - pub fn kind_ty(self) -> I::Ty { + pub fn kind_ty(self) -> ty::Ty { self.split().closure_kind_ty } @@ -185,7 +185,7 @@ impl ClosureArgs { // FIXME(eddyb) this should be unnecessary, as the shallowly resolved // type is known at the time of the creation of `ClosureArgs`, // see `rustc_hir_analysis::check::closure`. - pub fn sig_as_fn_ptr_ty(self) -> I::Ty { + pub fn sig_as_fn_ptr_ty(self) -> ty::Ty { self.split().closure_sig_as_fn_ptr_ty } @@ -223,7 +223,7 @@ pub struct CoroutineClosureArgsParts { /// This is the args of the typeck root. pub parent_args: I::GenericArgsSlice, /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: I::Ty, + pub closure_kind_ty: ty::Ty, /// Represents all of the relevant parts of the coroutine returned by this /// coroutine-closure. This signature parts type will have the general /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where @@ -232,10 +232,10 @@ pub struct CoroutineClosureArgsParts { /// /// Use `coroutine_closure_sig` to break up this type rather than using it /// yourself. - pub signature_parts_ty: I::Ty, + pub signature_parts_ty: ty::Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: I::Ty, + pub tupled_upvars_ty: ty::Ty, /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. /// This allows us to represent the binder of the self-captures of the closure. /// @@ -243,7 +243,7 @@ pub struct CoroutineClosureArgsParts { /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, /// while the `tupled_upvars_ty`, representing the by-move version of the same /// captures, will be `(String,)`. - pub coroutine_captures_by_ref_ty: I::Ty, + pub coroutine_captures_by_ref_ty: ty::Ty, } impl CoroutineClosureArgs { @@ -277,11 +277,11 @@ impl CoroutineClosureArgs { } #[inline] - pub fn tupled_upvars_ty(self) -> I::Ty { + pub fn tupled_upvars_ty(self) -> ty::Ty { self.split().tupled_upvars_ty } - pub fn kind_ty(self) -> I::Ty { + pub fn kind_ty(self) -> ty::Ty { self.split().closure_kind_ty } @@ -289,7 +289,7 @@ impl CoroutineClosureArgs { self.kind_ty().to_opt_closure_kind().unwrap() } - pub fn signature_parts_ty(self) -> I::Ty { + pub fn signature_parts_ty(self) -> ty::Ty { self.split().signature_parts_ty } @@ -314,7 +314,7 @@ impl CoroutineClosureArgs { }) } - pub fn coroutine_captures_by_ref_ty(self) -> I::Ty { + pub fn coroutine_captures_by_ref_ty(self) -> ty::Ty { self.split().coroutine_captures_by_ref_ty } @@ -358,10 +358,10 @@ impl TypeVisitor for HasRegionsBoundAt { #[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct CoroutineClosureSignature { - pub tupled_inputs_ty: I::Ty, - pub resume_ty: I::Ty, - pub yield_ty: I::Ty, - pub return_ty: I::Ty, + pub tupled_inputs_ty: ty::Ty, + pub resume_ty: ty::Ty, + pub yield_ty: ty::Ty, + pub return_ty: ty::Ty, // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types // never actually differ. But we save them rather than recreating them @@ -393,10 +393,10 @@ impl CoroutineClosureSignature { self, cx: I, parent_args: I::GenericArgsSlice, - coroutine_kind_ty: I::Ty, + coroutine_kind_ty: ty::Ty, coroutine_def_id: I::CoroutineId, - tupled_upvars_ty: I::Ty, - ) -> I::Ty { + tupled_upvars_ty: ty::Ty, + ) -> ty::Ty { let coroutine_args = ty::CoroutineArgs::new( cx, ty::CoroutineArgsParts { @@ -424,9 +424,9 @@ impl CoroutineClosureSignature { coroutine_def_id: I::CoroutineId, goal_kind: ty::ClosureKind, env_region: I::Region, - closure_tupled_upvars_ty: I::Ty, - coroutine_captures_by_ref_ty: I::Ty, - ) -> I::Ty { + closure_tupled_upvars_ty: ty::Ty, + coroutine_captures_by_ref_ty: ty::Ty, + ) -> ty::Ty { let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( cx, goal_kind, @@ -457,11 +457,11 @@ impl CoroutineClosureSignature { pub fn tupled_upvars_by_closure_kind( cx: I, kind: ty::ClosureKind, - tupled_inputs_ty: I::Ty, - closure_tupled_upvars_ty: I::Ty, - coroutine_captures_by_ref_ty: I::Ty, + tupled_inputs_ty: ty::Ty, + closure_tupled_upvars_ty: ty::Ty, + coroutine_captures_by_ref_ty: ty::Ty, env_region: I::Region, - ) -> I::Ty { + ) -> ty::Ty { match kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else { @@ -503,7 +503,7 @@ struct FoldEscapingRegions { // Depends on `debruijn` because we may have types with regions of different // debruijn depths depending on the binders we've entered. - cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>, + cache: DelayedMap<(ty::DebruijnIndex, ty::Ty), ty::Ty>, } impl TypeFolder for FoldEscapingRegions { @@ -511,7 +511,7 @@ impl TypeFolder for FoldEscapingRegions { self.interner } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { if !t.has_vars_bound_at_or_above(self.debruijn) { t } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) { @@ -553,9 +553,9 @@ impl TypeFolder for FoldEscapingRegions { #[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct GenSig { - pub resume_ty: I::Ty, - pub yield_ty: I::Ty, - pub return_ty: I::Ty, + pub resume_ty: ty::Ty, + pub yield_ty: ty::Ty, + pub return_ty: ty::Ty, } impl Eq for GenSig {} @@ -581,15 +581,15 @@ pub struct CoroutineArgsParts { /// kind: `i8`/`i16`/`i32`. /// /// For regular coroutines, this field will always just be `()`. - pub kind_ty: I::Ty, + pub kind_ty: ty::Ty, - pub resume_ty: I::Ty, - pub yield_ty: I::Ty, - pub return_ty: I::Ty, + pub resume_ty: ty::Ty, + pub yield_ty: ty::Ty, + pub return_ty: ty::Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: I::Ty, + pub tupled_upvars_ty: ty::Ty, } impl CoroutineArgs { @@ -619,7 +619,7 @@ impl CoroutineArgs { } // Returns the kind of the coroutine. See docs on the `kind_ty` field. - pub fn kind_ty(self) -> I::Ty { + pub fn kind_ty(self) -> ty::Ty { self.split().kind_ty } @@ -638,22 +638,22 @@ impl CoroutineArgs { /// Returns the tuple type representing the upvars for this coroutine. #[inline] - pub fn tupled_upvars_ty(self) -> I::Ty { + pub fn tupled_upvars_ty(self) -> ty::Ty { self.split().tupled_upvars_ty } /// Returns the type representing the resume type of the coroutine. - pub fn resume_ty(self) -> I::Ty { + pub fn resume_ty(self) -> ty::Ty { self.split().resume_ty } /// Returns the type representing the yield type of the coroutine. - pub fn yield_ty(self) -> I::Ty { + pub fn yield_ty(self) -> ty::Ty { self.split().yield_ty } /// Returns the type representing the return type of the coroutine. - pub fn return_ty(self) -> I::Ty { + pub fn return_ty(self) -> ty::Ty { self.split().return_ty } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 6e62e1031a969..1ee4bff6b7a11 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, TypeFlags}; +use crate::{self as ty, Interner, Ty, TypeFlags}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -98,7 +98,7 @@ pub trait TypeVisitor: Sized { t.super_visit_with(self) } - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { t.super_visit_with(self) } @@ -417,7 +417,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { // Note: no `super_visit_with` call. let flags = t.flags(); if flags.intersects(self.flags) { @@ -522,7 +522,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `t` contains some content // bound at `outer_index` or above (because diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 4eeba30228924..9129562efe1d7 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: env: HOST_TARGET: ${{ matrix.host_target }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: install multiarch if: ${{ matrix.multiarch != '' }} run: | @@ -105,7 +105,7 @@ jobs: name: style checks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: ./.github/workflows/setup - name: rustfmt @@ -121,7 +121,7 @@ jobs: name: bootstrap build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # Deliberately skipping `./.github/workflows/setup` as we do our own setup - name: Add cache for cargo id: cache @@ -156,7 +156,7 @@ jobs: name: coverage report runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: ./.github/workflows/setup - name: coverage run: ./miri test --coverage @@ -191,7 +191,7 @@ jobs: pull-requests: write if: ${{ github.event_name == 'schedule' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 256 # get a bit more of the history - name: install josh-sync diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 852ea26ab89e0..ad8b2b09b6ba8 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -171,8 +171,8 @@ MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows ./miri run tests/pass/v ``` Note that you will only get `info`, `warn` or `error` messages if you use a prebuilt compiler. -In order to get `debug` and `trace` level messages, you need to build miri with a locally built -compiler that has `debug=true` set in `bootstrap.toml`. +In order to get `debug` and `trace` level messages, you need to build miri with a [locally built +compiler](#advanced-topic-building-miri-against-a-locally-compiled-rustc) that has `debug=true` set in `bootstrap.toml`. #### Debugging error messages @@ -320,6 +320,33 @@ You can also directly run Miri on a Rust source file: ./x.py run miri --stage 1 --args src/tools/miri/tests/pass/hello.rs ``` +## Advanced topic: Building Miri against a locally compiled rustc + +Very rarely, it can be necessary to work with an out-of-tree Miri but build it against a rustc that +was locally compiled. (Usually, you should instead work on the Miri that's in the Rust tree, as +described in the previous subsection.) + +This requires a fully bootstrapped build: + +```sh +# Build rustc, then build rustc with that rustc. This can take a while. +./x build library --stage 3 +``` + +You also need to set up a linked toolchain with rustup: + +```sh +rustup toolchain link stage2 build/host/stage2 +``` + +Then in the Miri folder, you can set this as the current toolchain and build against it: + +```sh +rustup override set stage2 +# Prevent `./miri` from reseting the toolchain. +export MIRI_AUTO_OPS=no +``` + ## Advanced topic: Syncing with the rustc repo We use the [`josh-sync`](https://github.com/rust-lang/josh-sync) tool to transmit changes between the diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 45be05fcc7f78..977728f63499a 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -230,9 +230,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b881c015c729b43105bbd3702a9bdecee28fafaa21126d1d62e454ec011a4b7" +checksum = "eec3905e8201688412f6f4b1f6c86d38b3ee6578f59ba85f41330a3af61e8365" dependencies = [ "anyhow", "rustc_version", @@ -339,11 +339,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.9" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -392,45 +392,42 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.23" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc" dependencies = [ "indexmap", - "serde", + "serde_core", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_parser", + "toml_writer", + "winnow", ] [[package]] name = "toml_datetime" -version = "0.6.11" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" dependencies = [ - "serde", + "serde_core", ] [[package]] -name = "toml_edit" -version = "0.22.27" +name = "toml_parser" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_write", "winnow", ] [[package]] -name = "toml_write" -version = "0.1.2" +name = "toml_writer" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" [[package]] name = "unicode-ident" @@ -489,12 +486,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.13" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" -dependencies = [ - "memchr", -] +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" [[package]] name = "wit-bindgen" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index e8da7f2ca8a74..568bb29f49f88 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -18,7 +18,7 @@ directories = "6" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.23" -rustc-build-sysroot = "0.5.10" +rustc-build-sysroot = "0.5.12" # Enable some feature flags that dev-dependencies need but dependencies # do not. This makes `./miri install` after `./miri build` faster. diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 6c0bceac7731f..9bacbbcf4597c 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -28,6 +28,7 @@ begingroup "Building Miri" export RUSTFLAGS="-D warnings" export CARGO_INCREMENTAL=0 export CARGO_EXTRA_FLAGS="--locked" +export CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT=true # Determine configuration for installed build (used by test-cargo-miri and `./miri bench`). # We use the default set of features for this. diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 86f6253d4558a..d469502c243f4 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -80,7 +80,7 @@ impl Command { // `toolchain` goes first as it could affect the others if auto_toolchain { - Self::toolchain(vec![])?; + Self::toolchain(None, vec![])?; } if auto_fmt { Self::fmt(vec![])?; @@ -121,15 +121,18 @@ impl Command { Command::Clippy { features, flags } => Self::clippy(features, flags), Command::Bench { target, no_install, save_baseline, load_baseline, benches } => Self::bench(target, no_install, save_baseline, load_baseline, benches), - Command::Toolchain { flags } => Self::toolchain(flags), + Command::Toolchain { commit, flags } => Self::toolchain(commit, flags), Command::Squash => Self::squash(), } } - fn toolchain(flags: Vec) -> Result<()> { + fn toolchain(new_commit: Option, flags: Vec) -> Result<()> { let sh = Shell::new()?; sh.change_dir(miri_dir()?); - let new_commit = sh.read_file("rust-version")?.trim().to_owned(); + let new_commit = match new_commit { + Some(c) => c, + None => sh.read_file("rust-version")?.trim().to_owned(), + }; let current_commit = { let rustc_info = cmd!(sh, "rustc +miri --version -v").read(); if let Ok(rustc_info) = rustc_info { diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index e307014496886..419c128e5b72f 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -138,6 +138,9 @@ pub enum Command { /// The `rust-version` file is used to determine the commit that will be intsalled. /// `rustup-toolchain-install-master` must be installed for this to work. Toolchain { + /// Overwrite the commit to install. + #[arg(long)] + commit: Option, /// Flags that are passed through to `rustup-toolchain-install-master`. #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, @@ -157,8 +160,8 @@ impl Command { | Self::Build { flags, .. } | Self::Check { flags, .. } | Self::Doc { flags, .. } - | Self::Fmt { flags } - | Self::Toolchain { flags } + | Self::Fmt { flags, .. } + | Self::Toolchain { flags, .. } | Self::Clippy { flags, .. } | Self::Run { flags, .. } | Self::Test { flags, .. } => { diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e281dad8ef1ee..85571d95f742d 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -fd0c901b00ee1e08a250039cdb90258603497e20 +116458d0a5ae01cd517cabd2d1aee7f5457018ab diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index d6d6449df32bf..ee74e06815945 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -656,64 +656,10 @@ impl<'tcx> ThreadManager<'tcx> { // We should only switch stacks between steps. self.yield_active_thread = true; } - - /// Get the wait time for the next timeout, or `None` if no timeout is pending. - fn next_callback_wait_time(&self, clock: &MonotonicClock) -> Option { - self.threads - .iter() - .filter_map(|t| { - match &t.state { - ThreadState::Blocked { timeout: Some(timeout), .. } => - Some(timeout.get_wait_time(clock)), - _ => None, - } - }) - .min() - } } impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {} trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { - /// Execute a timeout callback on the callback's thread. - #[inline] - fn run_timeout_callback(&mut self) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let mut found_callback = None; - // Find a blocked thread that has timed out. - for (id, thread) in this.machine.threads.threads.iter_enumerated_mut() { - match &thread.state { - ThreadState::Blocked { timeout: Some(timeout), .. } - if timeout.get_wait_time(&this.machine.monotonic_clock) == Duration::ZERO => - { - let old_state = mem::replace(&mut thread.state, ThreadState::Enabled); - let ThreadState::Blocked { callback, .. } = old_state else { unreachable!() }; - found_callback = Some((id, callback)); - // Run the fallback (after the loop because borrow-checking). - break; - } - _ => {} - } - } - if let Some((thread, callback)) = found_callback { - // This back-and-forth with `set_active_thread` is here because of two - // design decisions: - // 1. Make the caller and not the callback responsible for changing - // thread. - // 2. Make the scheduler the only place that can change the active - // thread. - let old_thread = this.machine.threads.set_active_thread_id(thread); - callback.call(this, UnblockKind::TimedOut)?; - this.machine.threads.set_active_thread_id(old_thread); - } - // found_callback can remain None if the computer's clock - // was shifted after calling the scheduler and before the call - // to get_ready_callback (see issue - // https://github.com/rust-lang/miri/issues/1763). In this case, - // just do nothing, which effectively just returns to the - // scheduler. - interp_ok(()) - } - #[inline] fn run_on_stack_empty(&mut self) -> InterpResult<'tcx, Poll<()>> { let this = self.eval_context_mut(); @@ -790,19 +736,12 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { this.poll_and_unblock(Some(Duration::ZERO))?; } - let thread_manager = &this.machine.threads; - let clock = &this.machine.monotonic_clock; - // We also check timeouts before running any other thread, to ensure that timeouts // "in the past" fire before any other thread can take an action. This ensures that for // `pthread_cond_timedwait`, "an error is returned if [...] the absolute time specified by // abstime has already been passed at the time of the call". // - let potential_sleep_time = thread_manager.next_callback_wait_time(clock); - if potential_sleep_time == Some(Duration::ZERO) { - // The timeout exceeded for some thread so we unblock the thread and execute its timeout callback. - this.run_timeout_callback()?; - } + let potential_sleep_time = this.unblock_expired_timeouts()?; let thread_manager = &mut this.machine.threads; let rng = this.machine.rng.get_mut(); @@ -868,6 +807,71 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { throw_machine_stop!(TerminationInfo::GlobalDeadlock); } } + + /// Poll for I/O events until either an I/O event happened or the timeout expired. + /// The different timeout values are described in [`BlockingIoManager::poll`]. + fn poll_and_unblock(&mut self, timeout: Option) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + + let ready = match this.machine.blocking_io.poll(timeout) { + Ok(ready) => ready, + // We can ignore errors originating from interrupts; that's just a spurious wakeup. + Err(e) if e.kind() == io::ErrorKind::Interrupted => return interp_ok(()), + // For other errors we panic. On Linux and BSD hosts this should only be + // reachable when a system resource error (e.g. ENOMEM or ENOSPC) occurred. + Err(e) => panic!("unexpected error while polling: {e}"), + }; + + ready.into_iter().try_for_each(|thread_id| this.unblock_thread(thread_id, BlockReason::IO)) + } + + /// Find all threads with expired timeouts, unblock them and execute their timeout callbacks. + /// + /// This method returns the minimum duration until the next thread timeout expires. + /// If all ready threads have no timeout set, [`None`] is returned. + fn unblock_expired_timeouts(&mut self) -> InterpResult<'tcx, Option> { + let this = self.eval_context_mut(); + let clock = &this.machine.monotonic_clock; + + let mut min_wait_time = Option::::None; + let mut callbacks = Vec::new(); + + for (id, thread) in this.machine.threads.threads.iter_enumerated_mut() { + match &thread.state { + ThreadState::Blocked { timeout: Some(timeout), .. } => { + let wait_time = timeout.get_wait_time(clock); + if wait_time.is_zero() { + // The timeout expired for this thread. + let old_state = mem::replace(&mut thread.state, ThreadState::Enabled); + let ThreadState::Blocked { callback, .. } = old_state else { + unreachable!() + }; + // Add callback to list to be run after this loop because of borrow-checking. + callbacks.push((id, callback)); + } else { + // Update `min_wait_time` to contain the smallest duration until + // the next timeout expires. + min_wait_time = Some(wait_time.min(min_wait_time.unwrap_or(Duration::MAX))); + } + } + _ => {} + } + } + + for (thread, callback) in callbacks { + // This back-and-forth with `set_active_thread` is here because of two + // design decisions: + // 1. Make the caller and not the callback responsible for changing + // thread. + // 2. Make the scheduler the only place that can change the active + // thread. + let old_thread = this.machine.threads.set_active_thread_id(thread); + callback.call(this, UnblockKind::TimedOut)?; + this.machine.threads.set_active_thread_id(old_thread); + } + + interp_ok(min_wait_time) + } } // Public interface to thread management. @@ -1348,21 +1352,4 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } } - - /// Poll for I/O events until either an I/O event happened or the timeout expired. - /// The different timeout values are described in [`BlockingIoManager::poll`]. - fn poll_and_unblock(&mut self, timeout: Option) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let ready = match this.machine.blocking_io.poll(timeout) { - Ok(ready) => ready, - // We can ignore errors originating from interrupts; that's just a spurious wakeup. - Err(e) if e.kind() == io::ErrorKind::Interrupted => return interp_ok(()), - // For other errors we panic. On Linux and BSD hosts this should only be - // reachable when a system resource error (e.g. ENOMEM or ENOSPC) occurred. - Err(e) => panic!("{e}"), - }; - - ready.into_iter().try_for_each(|thread_id| this.unblock_thread(thread_id, BlockReason::IO)) - } } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index d8224f1878f05..566a775b90108 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -569,7 +569,7 @@ pub struct MiriMachine<'tcx> { pub(crate) user_relevant_crates: Vec, /// Mapping extern static names to their pointer. - extern_statics: FxHashMap, + pub(crate) extern_statics: FxHashMap, /// The random number generator used for resolving non-determinism. /// Needs to be queried by ptr_to_int, hence needs interior mutability. diff --git a/src/tools/miri/src/shims/aarch64.rs b/src/tools/miri/src/shims/aarch64.rs index d06b02a41334f..6a914d5cfa68a 100644 --- a/src/tools/miri/src/shims/aarch64.rs +++ b/src/tools/miri/src/shims/aarch64.rs @@ -4,6 +4,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; +use crate::shims::math::compute_crc32; use crate::*; impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -58,6 +59,93 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_immediate(*res_lane, &dest)?; } } + + // Wrapping pairwise addition. + // + // Concatenates the two input vectors and adds adjacent elements. For input vectors `v` + // and `w` this computes `[v0 + v1, v2 + v3, ..., w0 + w1, w2 + w3, ...]`, using + // wrapping addition for `+`. + // + // Used by `vpadd_{s8, u8, s16, u16, s32, u32}`. + name if name.starts_with("neon.addp.") => { + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; + + let (left, left_len) = this.project_to_simd(left)?; + let (right, right_len) = this.project_to_simd(right)?; + let (dest, dest_len) = this.project_to_simd(dest)?; + + assert_eq!(left_len, right_len); + assert_eq!(left_len, dest_len); + + assert_eq!(left.layout, right.layout); + assert_eq!(left.layout, dest.layout); + + assert!(dest_len.is_multiple_of(2)); + let half_len = dest_len.strict_div(2); + + for lane_idx in 0..dest_len { + // The left and right vectors are concatenated. + let (src, src_pair_idx) = if lane_idx < half_len { + (&left, lane_idx) + } else { + (&right, lane_idx.strict_sub(half_len)) + }; + // Convert "pair index" into "index of first element of the pair". + let i = src_pair_idx.strict_mul(2); + + let lhs = this.read_immediate(&this.project_index(src, i)?)?; + let rhs = this.read_immediate(&this.project_index(src, i.strict_add(1))?)?; + + // Wrapping addition on the element type. + let sum = this.binary_op(BinOp::Add, &lhs, &rhs)?; + + let dst_lane = this.project_index(&dest, lane_idx)?; + this.write_immediate(*sum, &dst_lane)?; + } + } + + // Widening pairwise addition. + // + // Takes a single input vector, and an output vector with half as many lanes and double + // the element width. Takes adjacent pairs of elements, widens both, and then adds them + // together. + // + // Used by `vpaddl_{u8, u16, u32}` and `vpaddlq_{u8, u16, u32}`. + name if name.starts_with("neon.uaddlp.") => { + let [src] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; + + let (src, src_len) = this.project_to_simd(src)?; + let (dest, dest_len) = this.project_to_simd(dest)?; + + // Operates pairwise, so src has twice as many lanes. + assert_eq!(src_len, dest_len.strict_mul(2)); + + let src_elem_size = src.layout.field(this, 0).size; + let dest_elem_size = dest.layout.field(this, 0).size; + + // Widens, so dest elements must be exactly twice as wide. + assert_eq!(dest_elem_size.bytes(), src_elem_size.bytes().strict_mul(2)); + + for dest_idx in 0..dest_len { + let src_idx = dest_idx.strict_mul(2); + + let a_scalar = this.read_scalar(&this.project_index(&src, src_idx)?)?; + let b_scalar = + this.read_scalar(&this.project_index(&src, src_idx.strict_add(1))?)?; + + let a_val = a_scalar.to_uint(src_elem_size)?; + let b_val = b_scalar.to_uint(src_elem_size)?; + + // Use addition on u128 to simulate widening addition for the destination type. + // This cannot wrap since the element type is at most u64. + let sum = a_val.strict_add(b_val); + + let dst_lane = this.project_index(&dest, dest_idx)?; + this.write_scalar(Scalar::from_uint(sum, dest_elem_size), &dst_lane)?; + } + } + // Vector table lookup: each index selects a byte from the 16-byte table, out-of-range -> 0. // Used to implement vtbl1_u8 function. // LLVM does not have a portable shuffle that takes non-const indices @@ -85,6 +173,47 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(val, &this.project_index(&dest, i)?)?; } } + // Used to implement the __crc32{b,h,w,x} and __crc32c{b,h,w,x} functions. + // Polynomial 0x04C11DB7 (standard CRC-32): + // https://developer.arm.com/documentation/ddi0602/latest/Base-Instructions/CRC32B--CRC32H--CRC32W--CRC32X--CRC32-checksum- + // Polynomial 0x1EDC6F41 (CRC-32C / Castagnoli): + // https://developer.arm.com/documentation/ddi0602/latest/Base-Instructions/CRC32CB--CRC32CH--CRC32CW--CRC32CX--CRC32C-checksum- + "crc32b" | "crc32h" | "crc32w" | "crc32x" | "crc32cb" | "crc32ch" | "crc32cw" + | "crc32cx" => { + this.expect_target_feature_for_intrinsic(link_name, "crc")?; + // The polynomial constants below include the leading 1 bit + // (e.g. 0x104C11DB7 instead of 0x04C11DB7) which the ARM docs + // omit but the polynomial division algorithm requires. + let (bit_size, polynomial): (u32, u128) = match unprefixed_name { + "crc32b" => (8, 0x104C11DB7), + "crc32h" => (16, 0x104C11DB7), + "crc32w" => (32, 0x104C11DB7), + "crc32x" => (64, 0x104C11DB7), + "crc32cb" => (8, 0x11EDC6F41), + "crc32ch" => (16, 0x11EDC6F41), + "crc32cw" => (32, 0x11EDC6F41), + "crc32cx" => (64, 0x11EDC6F41), + _ => unreachable!(), + }; + + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; + let left = this.read_scalar(left)?; + let right = this.read_scalar(right)?; + + // The CRC accumulator is always u32. The data argument is u32 for + // b/h/w variants and u64 for the x variant, per the LLVM intrinsic + // definitions (all b/h/w take i32, only x takes i64). + // https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsAArch64.td + // If the higher bits are non-zero, `compute_crc32` will panic. We should probably + // raise a proper error instead, but outside stdarch nobody can trigger this anyway. + let crc = left.to_u32()?; + let data = + if bit_size == 64 { right.to_u64()? } else { u64::from(right.to_u32()?) }; + + let result = compute_crc32(crc, data, bit_size, polynomial); + this.write_scalar(Scalar::from_u32(result), dest)?; + } _ => return interp_ok(EmulateItemResult::NotSupported), } interp_ok(EmulateItemResult::NeedsReturn) diff --git a/src/tools/miri/src/shims/math.rs b/src/tools/miri/src/shims/math.rs index ef185aa2a3e9f..1da7fbbdac0ce 100644 --- a/src/tools/miri/src/shims/math.rs +++ b/src/tools/miri/src/shims/math.rs @@ -245,3 +245,51 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(EmulateItemResult::NeedsReturn) } } + +/// Compute a CRC32 checksum using the given polynomial. +/// +/// `bit_size` is the number of relevant data bits (8, 16, 32, or 64). +/// Only the low `bit_size` bits of `data` are used; higher bits must be zero. +/// `polynomial` includes the leading 1 bit (e.g. `0x11EDC6F41` for CRC32C). +/// +/// Following hardware CRC conventions, `crc` and `data` bits are assumed to be reversed, +/// and output bits will be equally reversed. +pub(crate) fn compute_crc32(crc: u32, data: u64, bit_size: u32, polynomial: u128) -> u32 { + assert!( + bit_size == 64 || data < 1u64.strict_shl(bit_size), + "crc32: `data` is larger than {bit_size} bits" + ); + // Bit-reverse inputs to match hardware CRC conventions. + let crc = u128::from(crc.reverse_bits()); + // Reverse all 64 bits of `data`, then shift right by `64 - bit_size`. This + // discards the (now-reversed) higher bits, leaving only the reversed low + // `bit_size` bits in the lowest positions (with zeros above). + let v = u128::from(data.reverse_bits() >> (64u32.strict_sub(bit_size))); + + // Perform polynomial division modulo 2. + // The algorithm for the division is an adapted version of the + // schoolbook division algorithm used for normal integer or polynomial + // division. In this context, the quotient is not calculated, since + // only the remainder is needed. + // + // The algorithm works as follows: + // 1. Pull down digits until division can be performed. In the context of division + // modulo 2 it means locating the most significant digit of the dividend and shifting + // the divisor such that the position of the divisors most significand digit and the + // dividends most significand digit match. + // 2. Perform a division and determine the remainder. Since it is arithmetic modulo 2, + // this operation is a simple bitwise exclusive or. + // 3. Repeat steps 1. and 2. until the full remainder is calculated. This is the case + // once the degree of the remainder polynomial is smaller than the degree of the + // divisor polynomial. In other words, the number of leading zeros of the remainder + // is larger than the number of leading zeros of the divisor. It is important to + // note that standard arithmetic comparison is not applicable here: + // 0b10011 / 0b11111 = 0b01100 is a valid division, even though the dividend is + // smaller than the divisor. + let mut dividend = (crc << bit_size) ^ (v << 32); + while dividend.leading_zeros() <= polynomial.leading_zeros() { + dividend ^= (polynomial << polynomial.leading_zeros()) >> dividend.leading_zeros(); + } + + u32::try_from(dividend).unwrap().reverse_bits() +} diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index 6a281ddbb7b2f..b302a07cf0c53 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -396,8 +396,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches what codegen does. This does mean that we support some types whose ABI is not // stable, but that's fine -- we are anyway quite conservative in native-lib mode. if let BackendRepr::Scalar(s) = layout.backend_repr { - // Simple sanity-check: this cannot be `repr(C)`. - assert!(!layout.ty.ty_adt_def().is_some_and(|adt| adt.repr().c())); + // Simple sanity-check: this cannot be a `repr(C)` struct or union. (It could be a + // repr(C) enum. Those indeed behave like integers in the ABI.) + assert!(!layout.ty.ty_adt_def().is_some_and(|adt| !adt.is_enum() && adt.repr().c())); return Ok(match s.primitive() { Primitive::Int(Integer::I8, /* signed */ true) => FfiType::i8(), Primitive::Int(Integer::I16, /* signed */ true) => FfiType::i16(), diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index f2e16e75892ec..3651bc171adcd 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -633,6 +633,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = this.getsockname(socket, address, address_len)?; this.write_scalar(result, dest)?; } + "getpeername" => { + let [socket, address, address_len] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32), + link_name, + abi, + args, + )?; + let result = this.getpeername(socket, address, address_len)?; + this.write_scalar(result, dest)?; + } // Time "gettimeofday" => { @@ -727,11 +737,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.read_target_usize(handle)?; let symbol = this.read_pointer(symbol)?; let name = this.read_c_str(symbol)?; - if let Ok(name) = str::from_utf8(name) - && is_dyn_sym(name, &this.tcx.sess.target.os) - { + let Ok(name) = str::from_utf8(name) else { + throw_unsup_format!("dlsym: non UTF-8 symbol name not supported") + }; + if is_dyn_sym(name, &this.tcx.sess.target.os) { let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; + } else if let Some(&ptr) = this.machine.extern_statics.get(&Symbol::intern(name)) { + this.write_pointer(ptr, dest)?; } else { this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/unix/freebsd/sync.rs b/src/tools/miri/src/shims/unix/freebsd/sync.rs index 8cf4464389631..7c46dd549bc0a 100644 --- a/src/tools/miri/src/shims/unix/freebsd/sync.rs +++ b/src/tools/miri/src/shims/unix/freebsd/sync.rs @@ -215,8 +215,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Some(duration) = this.read_timespec(×pec_place)? else { return interp_ok(None) }; let flags_place = this.project_field(ut, FieldIdx::from_u32(1))?; - let flags = this.read_scalar(&flags_place)?.to_u32()?; - let abs_time_flag = flags == abs_time; + let mut flags = this.read_scalar(&flags_place)?.to_u32()?; + + let abs_time_flag = if flags & abs_time != 0 { + flags &= !abs_time; + true + } else { + false + }; + if flags != 0 { + throw_unsup_format!("unsupported `_umtx_time` flags: {:#x}", flags); + } let clock_id_place = this.project_field(ut, FieldIdx::from_u32(2))?; let clock_id = this.read_scalar(&clock_id_place)?; diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 9873af85b989b..5adc5932883ef 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -364,6 +364,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.emit_diagnostic(NonHaltingDiagnostic::FileInProcOpened); } + // We will "subtract" supported flags from this and at the end check that no bits are left. + let mut flag = flag; + let mut options = OpenOptions::new(); let o_rdonly = this.eval_libc_i32("O_RDONLY"); @@ -379,6 +382,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Now we check the access mode let access_mode = flag & 0b11; + flag &= !access_mode; if access_mode == o_rdonly { writable = false; @@ -390,23 +394,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { throw_unsup_format!("unsupported access mode {:#x}", access_mode); } - // We need to check that there aren't unsupported options in `flag`. For this we try to - // reproduce the content of `flag` in the `mirror` variable using only the supported - // options. - let mut mirror = access_mode; let o_append = this.eval_libc_i32("O_APPEND"); if flag & o_append == o_append { + flag &= !o_append; options.append(true); - mirror |= o_append; } let o_trunc = this.eval_libc_i32("O_TRUNC"); if flag & o_trunc == o_trunc { + flag &= !o_trunc; options.truncate(true); - mirror |= o_trunc; } let o_creat = this.eval_libc_i32("O_CREAT"); if flag & o_creat == o_creat { + flag &= !o_creat; // Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but // C integer promotion rules mean that on the ABI level, it gets passed as `u32` // (see https://github.com/rust-lang/rust/issues/71915). @@ -430,11 +431,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - mirror |= o_creat; - let o_excl = this.eval_libc_i32("O_EXCL"); if flag & o_excl == o_excl { - mirror |= o_excl; + flag &= !o_excl; options.create_new(true); } else { options.create(true); @@ -442,9 +441,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let o_cloexec = this.eval_libc_i32("O_CLOEXEC"); if flag & o_cloexec == o_cloexec { + flag &= !o_cloexec; // We do not need to do anything for this flag because `std` already sets it. // (Technically we do not support *not* setting this flag, but we ignore that.) - mirror |= o_cloexec; } if this.tcx.sess.target.os == Os::Linux { let o_tmpfile = this.eval_libc_i32("O_TMPFILE"); @@ -456,6 +455,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let o_nofollow = this.eval_libc_i32("O_NOFOLLOW"); if flag & o_nofollow == o_nofollow { + flag &= !o_nofollow; #[cfg(unix)] { use std::os::unix::fs::OpenOptionsExt; @@ -472,13 +472,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_last_error_and_return_i32(LibcError("ELOOP")); } } - mirror |= o_nofollow; } - // If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`, - // then we throw an error. - if flag != mirror { - throw_unsup_format!("unsupported flags {:#x}", flag & !mirror); + // If `flag` has any bits left set, those are not supported. + if flag != 0 { + throw_unsup_format!("unsupported flags {:#x}", flag); } // Reject if isolation is enabled. diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs index f9b3ca479b799..8f2ab69261ce7 100644 --- a/src/tools/miri/src/shims/unix/socket.rs +++ b/src/tools/miri/src/shims/unix/socket.rs @@ -620,6 +620,48 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(e) => this.set_last_error_and_return_i32(e), } } + + fn getpeername( + &mut self, + socket: &OpTy<'tcx>, + address: &OpTy<'tcx>, + address_len: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let socket = this.read_scalar(socket)?.to_i32()?; + let address_ptr = this.read_pointer(address)?; + let address_len_ptr = this.read_pointer(address_len)?; + + // Get the file handle + let Some(fd) = this.machine.fds.get(socket) else { + return this.set_last_error_and_return_i32(LibcError("EBADF")); + }; + + let Some(socket) = fd.downcast::() else { + // Man page specifies to return ENOTSOCK if `fd` is not a socket. + return this.set_last_error_and_return_i32(LibcError("ENOTSOCK")); + }; + + assert!(this.machine.communicate(), "cannot have `Socket` with isolation enabled!"); + + let state = socket.state.borrow(); + + let SocketState::Connected(stream) = &*state else { + // We can only read the peer address of connected sockets. + return this.set_last_error_and_return_i32(LibcError("ENOTCONN")); + }; + + let address = match stream.peer_addr() { + Ok(address) => address, + Err(e) => return this.set_last_error_and_return_i32(e), + }; + + match this.write_socket_address(&address, address_ptr, address_len_ptr, "getpeername")? { + Ok(_) => interp_ok(Scalar::from_i32(0)), + Err(e) => this.set_last_error_and_return_i32(e), + } + } } impl<'tcx> EvalContextPrivExt<'tcx> for crate::MiriInterpCx<'tcx> {} diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 2d1a153d9262e..16e269c688809 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -451,6 +451,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.SetFilePointerEx(file, distance_to_move, new_file_pointer, move_method)?; this.write_scalar(res, dest)?; } + "MoveFileExW" => { + let [existing_name, new_name, flags] = this.check_shim_sig( + shim_sig!(extern "system" fn(*const _, *const _, u32) -> winapi::BOOL), + link_name, + abi, + args, + )?; + let res = this.MoveFileExW(existing_name, new_name, flags)?; + this.write_scalar(res, dest)?; + } // Allocation "HeapAlloc" => { diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index e5a98e86d6453..1ee93cf911c5a 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -490,6 +490,36 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } + fn MoveFileExW( + &mut self, + existing_name: &OpTy<'tcx>, + new_name: &OpTy<'tcx>, + flags: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let existing_name = this.read_path_from_wide_str(this.read_pointer(existing_name)?)?; + let new_name = this.read_path_from_wide_str(this.read_pointer(new_name)?)?; + + let flags = this.read_scalar(flags)?.to_u32()?; + + // Flag to indicate whether we should replace an existing file. + // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefileexw + let movefile_replace_existing = this.eval_windows_u32("c", "MOVEFILE_REPLACE_EXISTING"); + + if flags != movefile_replace_existing { + throw_unsup_format!("MoveFileExW: Unsupported `dwFlags` value {}", flags); + } + + match std::fs::rename(existing_name, new_name) { + Ok(_) => interp_ok(this.eval_windows("c", "TRUE")), + Err(e) => { + this.set_last_error(e)?; + interp_ok(this.eval_windows("c", "FALSE")) + } + } + } + fn DeleteFileW( &mut self, file_name: &OpTy<'tcx>, // LPCWSTR diff --git a/src/tools/miri/src/shims/x86/sse42.rs b/src/tools/miri/src/shims/x86/sse42.rs index 7c0f9c570e2ef..6b0e6726e8f79 100644 --- a/src/tools/miri/src/shims/x86/sse42.rs +++ b/src/tools/miri/src/shims/x86/sse42.rs @@ -5,6 +5,7 @@ use rustc_span::Symbol; use rustc_target::callconv::FnAbi; use rustc_target::spec::Arch; +use crate::shims::math::compute_crc32; use crate::*; /// A bitmask constant for scrutinizing the immediate byte provided @@ -445,46 +446,19 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // The 64-bit version will only consider the lower 32 bits, // while the upper 32 bits get discarded. #[expect(clippy::as_conversions)] - u128::from((left.to_u64()? as u32).reverse_bits()) + (left.to_u64()? as u32) } else { - u128::from(left.to_u32()?.reverse_bits()) + left.to_u32()? }; - let v = match bit_size { - 8 => u128::from(right.to_u8()?.reverse_bits()), - 16 => u128::from(right.to_u16()?.reverse_bits()), - 32 => u128::from(right.to_u32()?.reverse_bits()), - 64 => u128::from(right.to_u64()?.reverse_bits()), + let data = match bit_size { + 8 => u64::from(right.to_u8()?), + 16 => u64::from(right.to_u16()?), + 32 => u64::from(right.to_u32()?), + 64 => right.to_u64()?, _ => unreachable!(), }; - // Perform polynomial division modulo 2. - // The algorithm for the division is an adapted version of the - // schoolbook division algorithm used for normal integer or polynomial - // division. In this context, the quotient is not calculated, since - // only the remainder is needed. - // - // The algorithm works as follows: - // 1. Pull down digits until division can be performed. In the context of division - // modulo 2 it means locating the most significant digit of the dividend and shifting - // the divisor such that the position of the divisors most significand digit and the - // dividends most significand digit match. - // 2. Perform a division and determine the remainder. Since it is arithmetic modulo 2, - // this operation is a simple bitwise exclusive or. - // 3. Repeat steps 1. and 2. until the full remainder is calculated. This is the case - // once the degree of the remainder polynomial is smaller than the degree of the - // divisor polynomial. In other words, the number of leading zeros of the remainder - // is larger than the number of leading zeros of the divisor. It is important to - // note that standard arithmetic comparison is not applicable here: - // 0b10011 / 0b11111 = 0b01100 is a valid division, even though the dividend is - // smaller than the divisor. - let mut dividend = (crc << bit_size) ^ (v << 32); - const POLYNOMIAL: u128 = 0x11EDC6F41; - while dividend.leading_zeros() <= POLYNOMIAL.leading_zeros() { - dividend ^= - (POLYNOMIAL << POLYNOMIAL.leading_zeros()) >> dividend.leading_zeros(); - } - - let result = u32::try_from(dividend).unwrap().reverse_bits(); + let result = compute_crc32(crc, data, bit_size, 0x11EDC6F41); let result = if bit_size == 64 { Scalar::from_u64(u64::from(result)) } else { diff --git a/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs b/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs index 5c80f6425eaae..b1929e3f27ed2 100644 --- a/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs +++ b/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs @@ -7,7 +7,7 @@ fn main() { let t = thread::spawn(|| unsafe { // Access the environment in another thread without taking the env lock. // This represents some C code that queries the environment. - libc::getenv(b"TZ\0".as_ptr().cast()); //~ERROR: Data race detected + libc::getenv(c"TZ".as_ptr()); //~ERROR: Data race detected }); // Meanwhile, the main thread uses the "safe" Rust env accessor. env::set_var("MY_RUST_VAR", "Ferris"); diff --git a/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.stderr b/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.stderr index 635091cc0173d..b4cd31b4ddaba 100644 --- a/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.stderr +++ b/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `unnamed-ID` at ALLOC --> tests/fail-dep/libc/env-set_var-data-race.rs:LL:CC | -LL | libc::getenv(b"TZ/0".as_ptr().cast()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (2) just happened here +LL | libc::getenv(c"TZ".as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (2) just happened here | help: and (1) occurred earlier here --> tests/fail-dep/libc/env-set_var-data-race.rs:LL:CC @@ -19,7 +19,7 @@ LL | let t = thread::spawn(|| unsafe { | _____________^ LL | | // Access the environment in another thread without taking the env lock. LL | | // This represents some C code that queries the environment. -LL | | libc::getenv(b"TZ/0".as_ptr().cast()); +LL | | libc::getenv(c"TZ".as_ptr()); LL | | }); | |______^ diff --git a/src/tools/miri/tests/fail-dep/libc/fs/mkstemp_immutable_arg.rs b/src/tools/miri/tests/fail-dep/libc/fs/mkstemp_immutable_arg.rs index 2c676f12b4f0e..abdafe2b0fb38 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/mkstemp_immutable_arg.rs +++ b/src/tools/miri/tests/fail-dep/libc/fs/mkstemp_immutable_arg.rs @@ -6,6 +6,6 @@ fn main() { } fn test_mkstemp_immutable_arg() { - let s: *mut libc::c_char = b"fooXXXXXX\0" as *const _ as *mut _; + let s: *mut libc::c_char = c"fooXXXXXX".as_ptr().cast_mut(); let _fd = unsafe { libc::mkstemp(s) }; //~ ERROR: Undefined Behavior: writing to alloc1 which is read-only } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs index 457f32e55446e..29548c17443a6 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs @@ -6,7 +6,6 @@ fn main() { } fn test_file_open_missing_needed_mode() { - let name = b"missing_arg.txt\0"; - let name_ptr = name.as_ptr().cast::(); - let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: not enough variadic arguments + let name = c"missing_arg.txt".as_ptr(); + let _fd = unsafe { libc::open(name, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: not enough variadic arguments } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr index a85fae9c7dd27..186ca4ccdd406 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: not enough variadic arguments for `open(pathname, O_CREAT, ...)`: got 0, expected at least 1 --> tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs:LL:CC | -LL | let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | let _fd = unsafe { libc::open(name, libc::O_CREAT) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs index 8bf46af71e821..3f9c42a782233 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs @@ -1,5 +1,6 @@ fn main() { - fn f() -> u32 { //~ ERROR: type u32 passing return place of type () + fn f() -> u32 { + //~^ERROR: type u32 passing return place of type () 42 } diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs index 7bc26237576a3..0635fdd149204 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs @@ -5,7 +5,8 @@ use std::intrinsics::mir::*; use std::num::NonZero; use std::ptr; -fn f(c: u32) { //~ERROR: expected something greater or equal to 1 +fn f(c: u32) { + //~^ERROR: expected something greater or equal to 1 println!("{c}"); } diff --git a/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs index 57def78b0ab17..03f14dcc3cc9b 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs @@ -176,7 +176,7 @@ fn test_swap_ptr_triple_dangling() { } extern "C" { - fn swap_ptr_triple_dangling(t_ptr: *const Triple); + fn swap_ptr_triple_dangling(t_ptr: *mut Triple); } let x = 101; @@ -184,9 +184,9 @@ fn test_swap_ptr_triple_dangling() { let ptr = Box::as_ptr(&b); drop(b); let z = 121; - let triple = Triple { ptr0: &raw const x, ptr1: ptr, ptr2: &raw const z }; + let mut triple = Triple { ptr0: &raw const x, ptr1: ptr, ptr2: &raw const z }; - unsafe { swap_ptr_triple_dangling(&triple) } + unsafe { swap_ptr_triple_dangling(&mut triple) } assert_eq!(unsafe { *triple.ptr2 }, x); } diff --git a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs index 231df67bb5b8c..07584ba236b98 100644 --- a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs +++ b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs @@ -1,3 +1,10 @@ +#[allow(unused)] +#[repr(C)] +enum CEnum { + A, + B, +} + extern "C" { fn add_one_int(x: i32) -> i32; fn add_int16(x: i16) -> i16; @@ -19,6 +26,7 @@ extern "C" { fn get_unsigned_int() -> u32; fn add_float(x: f32) -> f32; fn printer(); + fn scalar_enum(e: CEnum) -> u8; } fn main() { @@ -43,5 +51,8 @@ fn main() { // test void function that prints from C printer(); + + // test passing enums with scalar layout + assert_eq!(scalar_enum(CEnum::B), 1); } } diff --git a/src/tools/miri/tests/native-lib/scalar_arguments.c b/src/tools/miri/tests/native-lib/scalar_arguments.c index 720f1982178c8..19ca940204a08 100644 --- a/src/tools/miri/tests/native-lib/scalar_arguments.c +++ b/src/tools/miri/tests/native-lib/scalar_arguments.c @@ -4,6 +4,11 @@ // See comments in build_native_lib() #define EXPORT __attribute__((visibility("default"))) +enum cenum { + cenum_a, + cenum_b, +}; + EXPORT int32_t add_one_int(int32_t x) { return 2 + x; } @@ -38,6 +43,10 @@ EXPORT uint8_t u8_id(uint8_t x) { return x; } +EXPORT uint8_t scalar_enum(enum cenum e) { + return (uint8_t)e; +} + // To test that functions not marked with EXPORT cannot be called by Miri. int32_t not_exported(void) { return 0; diff --git a/src/tools/miri/tests/pass-dep/concurrency/env-cleanup-data-race.rs b/src/tools/miri/tests/pass-dep/concurrency/env-cleanup-data-race.rs index 91cf24a944ad6..44e969578989b 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/env-cleanup-data-race.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/env-cleanup-data-race.rs @@ -8,7 +8,7 @@ fn main() { unsafe { thread::spawn(|| { // Access the environment in another thread without taking the env lock - let s = libc::getenv("MIRI_ENV_VAR_TEST\0".as_ptr().cast()); + let s = libc::getenv(c"MIRI_ENV_VAR_TEST".as_ptr()); if s.is_null() { panic!("null"); } diff --git a/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs b/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs index 9e5627c75a97a..70fa6c183c84a 100644 --- a/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs +++ b/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs @@ -7,8 +7,8 @@ mod utils; type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int; fn main() { - let name = "getentropy\0"; - let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize }; + let name = c"getentropy"; + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize }; // If the GC does not account for the extra_fn_ptr entry that this dlsym just added, this GC // run will delete our entry for the base addr of the function pointer we will transmute to, // and the call through the function pointer will report UB. diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index f5e9a56d7d039..9dc1af1be299f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -54,29 +54,23 @@ fn main() { fn test_file_open_unix_allow_two_args() { let path = utils::prepare_with_content("test_file_open_unix_allow_two_args.txt", &[]); + let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); - let mut name = path.into_os_string(); - name.push("\0"); - let name_ptr = name.as_bytes().as_ptr().cast::(); - let _fd = unsafe { libc::open(name_ptr, libc::O_RDONLY) }; + let _fd = unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }; } fn test_file_open_unix_needs_three_args() { let path = utils::prepare_with_content("test_file_open_unix_needs_three_args.txt", &[]); + let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); - let mut name = path.into_os_string(); - name.push("\0"); - let name_ptr = name.as_bytes().as_ptr().cast::(); - let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT, 0o666) }; + let _fd = unsafe { libc::open(name.as_ptr(), libc::O_CREAT, 0o666) }; } fn test_file_open_unix_extra_third_arg() { let path = utils::prepare_with_content("test_file_open_unix_extra_third_arg.txt", &[]); + let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); - let mut name = path.into_os_string(); - name.push("\0"); - let name_ptr = name.as_bytes().as_ptr().cast::(); - let _fd = unsafe { libc::open(name_ptr, libc::O_RDONLY, 42) }; + let _fd = unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }; } fn test_dup_stdout_stderr() { @@ -92,12 +86,10 @@ fn test_dup_stdout_stderr() { fn test_dup() { let bytes = b"dup and dup2"; let path = utils::prepare_with_content("miri_test_libc_dup.txt", bytes); + let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); - let mut name = path.into_os_string(); - name.push("\0"); - let name_ptr = name.as_bytes().as_ptr().cast::(); unsafe { - let fd = libc::open(name_ptr, libc::O_RDONLY); + let fd = libc::open(name.as_ptr(), libc::O_RDONLY); let new_fd = libc::dup(fd); let new_fd2 = libc::dup2(fd, 8); @@ -519,7 +511,7 @@ fn test_read_and_uninit() { { // We test that libc::read initializes its buffer. let path = utils::prepare_with_content("pass-libc-read-and-uninit.txt", &[1u8, 2, 3]); - let cpath = CString::new(path.clone().into_os_string().into_encoded_bytes()).unwrap(); + let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); assert_ne!(fd, -1); @@ -528,8 +520,8 @@ fn test_read_and_uninit() { let buf = buf.assume_init(); assert_eq!(buf, 1); assert_eq!(libc::close(fd), 0); + assert_eq!(libc::unlink(cpath.as_ptr()), 0); } - remove_file(&path).unwrap(); } { // We test that if we requested to read 4 bytes, but actually read 3 bytes, then @@ -567,17 +559,15 @@ fn test_nofollow_not_symlink() { #[cfg(target_os = "macos")] fn test_ioctl() { let path = utils::prepare_with_content("miri_test_libc_ioctl.txt", &[]); + let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); - let mut name = path.into_os_string(); - name.push("\0"); - let name_ptr = name.as_bytes().as_ptr().cast::(); unsafe { // 100 surely is an invalid FD. assert_eq!(libc::ioctl(100, libc::FIOCLEX), -1); let errno = std::io::Error::last_os_error().raw_os_error().unwrap(); assert_eq!(errno, libc::EBADF); - let fd = libc::open(name_ptr, libc::O_RDONLY); + let fd = libc::open(name.as_ptr(), libc::O_RDONLY); assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0); } } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs index d1c0085b024a5..36ed470b353fe 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs @@ -63,15 +63,22 @@ fn test_sigrt() { } fn test_dlsym() { - let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, b"notasymbol\0".as_ptr().cast()) }; + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"notasymbol".as_ptr()) }; assert!(addr as usize == 0); - let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, b"isatty\0".as_ptr().cast()) }; + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"isatty".as_ptr()) }; assert!(addr as usize != 0); let isatty: extern "C" fn(i32) -> i32 = unsafe { transmute(addr) }; assert_eq!(isatty(999), 0); let errno = std::io::Error::last_os_error().raw_os_error().unwrap(); assert_eq!(errno, libc::EBADF); + + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"environ".as_ptr()) }; + assert!(addr as usize != 0); + extern "C" { + static mut environ: *const *const u8; + } + assert!(addr as usize == &raw const environ as usize); } fn test_getuid() { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket.rs index e3c14e60b25e6..8dd00e60200a5 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket.rs @@ -38,6 +38,9 @@ fn main() { test_getsockname_ipv4_random_port(); test_getsockname_ipv4_unbound(); test_getsockname_ipv6(); + + test_getpeername_ipv4(); + test_getpeername_ipv6(); } fn test_socket_close() { @@ -183,7 +186,6 @@ fn test_listen() { /// - Connecting when the server is already accepting /// - Accepting when there is already an incoming connection fn test_accept_connect() { - // Create a new non-blocking server socket. let server_sockfd = unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; let client_sockfd = @@ -379,6 +381,132 @@ fn test_getsockname_ipv6() { assert_eq!(addr.sin6_addr.s6_addr, sock_addr.sin6_addr.s6_addr); } +/// Test the `getpeername` syscall on an IPv4 socket. +/// For a connected socket, the `getpeername` syscall should +/// return the same address as the socket was connected to. +fn test_getpeername_ipv4() { + let server_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + let addr = net::ipv4_sock_addr(net::IPV4_LOCALHOST, 0); + unsafe { + errno_check(libc::bind( + server_sockfd, + (&addr as *const libc::sockaddr_in).cast::(), + size_of::() as libc::socklen_t, + )); + } + + unsafe { + errno_check(libc::listen(server_sockfd, 16)); + } + + // Retrieve actual listener address because we used a randomized port. + let (_, server_addr) = + sockname(|storage, len| unsafe { libc::getsockname(server_sockfd, storage, len) }).unwrap(); + + let LibcSocketAddr::V4(addr) = server_addr else { + // We bound an IPv4 address so we also expect + // an IPv4 address to be returned. + panic!() + }; + + // Spawn the server thread. + let server_thread = thread::spawn(move || { + let (_peerfd, _peer_addr) = + sockname(|storage, len| unsafe { libc::accept(server_sockfd, storage, len) }).unwrap(); + }); + + // Test connecting to an already accepting server. + unsafe { + errno_check(libc::connect( + client_sockfd, + (&addr as *const libc::sockaddr_in).cast::(), + size_of::() as libc::socklen_t, + )); + } + + let (_, peer_addr) = + sockname(|storage, len| unsafe { libc::getpeername(client_sockfd, storage, len) }).unwrap(); + + let LibcSocketAddr::V4(peer_addr) = peer_addr else { + // We connected to an IPv4 address so we also expect + // an IPv4 address to be returned. + panic!() + }; + + assert_eq!(addr.sin_family, peer_addr.sin_family); + assert_eq!(addr.sin_port, peer_addr.sin_port); + assert_eq!(addr.sin_addr.s_addr, peer_addr.sin_addr.s_addr); + + server_thread.join().unwrap(); +} + +/// Test the `getpeername` syscall on an IPv6 socket. +/// For a connected socket, the `getpeername` syscall should +/// return the same address as the socket was connected to. +fn test_getpeername_ipv6() { + let server_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET6, libc::SOCK_STREAM, 0)).unwrap() }; + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET6, libc::SOCK_STREAM, 0)).unwrap() }; + let addr = net::ipv6_sock_addr(net::IPV6_LOCALHOST, 0); + unsafe { + errno_check(libc::bind( + server_sockfd, + (&addr as *const libc::sockaddr_in6).cast::(), + size_of::() as libc::socklen_t, + )); + } + + unsafe { + errno_check(libc::listen(server_sockfd, 16)); + } + + // Retrieve actual listener address because we used a randomized port. + let (_, server_addr) = + sockname(|storage, len| unsafe { libc::getsockname(server_sockfd, storage, len) }).unwrap(); + + let LibcSocketAddr::V6(addr) = server_addr else { + // We bound an IPv6 address so we also expect + // an IPv6 address to be returned. + panic!() + }; + + // Spawn the server thread. + let server_thread = thread::spawn(move || { + let (_peerfd, _peer_addr) = + sockname(|storage, len| unsafe { libc::accept(server_sockfd, storage, len) }).unwrap(); + }); + + // Test connecting to an already accepting server. + unsafe { + errno_check(libc::connect( + client_sockfd, + (&addr as *const libc::sockaddr_in6).cast::(), + size_of::() as libc::socklen_t, + )); + } + + let (_, peer_addr) = + sockname(|storage, len| unsafe { libc::getpeername(client_sockfd, storage, len) }).unwrap(); + + let LibcSocketAddr::V6(peer_addr) = peer_addr else { + // We connected to an IPv6 address so we also expect + // an IPv6 address to be returned. + panic!() + }; + + assert_eq!(addr.sin6_family, peer_addr.sin6_family); + assert_eq!(addr.sin6_port, peer_addr.sin6_port); + assert_eq!(addr.sin6_flowinfo, peer_addr.sin6_flowinfo); + assert_eq!(addr.sin6_scope_id, peer_addr.sin6_scope_id); + assert_eq!(addr.sin6_addr.s6_addr, peer_addr.sin6_addr.s6_addr); + + server_thread.join().unwrap(); +} + /// Set a socket option. It's the caller's responsibility to ensure that `T` is /// associated with the given socket option. /// diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index 91639c5023252..79cb551386a18 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -22,7 +22,7 @@ use windows_sys::Win32::Storage::FileSystem::{ FILE_ALLOCATION_INFO, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_NORMAL, FILE_BEGIN, FILE_CURRENT, FILE_END_OF_FILE_INFO, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, FileAllocationInfo, FileEndOfFileInfo, - FlushFileBuffers, GetFileInformationByHandle, OPEN_ALWAYS, OPEN_EXISTING, + FlushFileBuffers, GetFileInformationByHandle, MoveFileExW, OPEN_ALWAYS, OPEN_EXISTING, SetFileInformationByHandle, SetFilePointerEx, }; use windows_sys::Win32::System::IO::IO_STATUS_BLOCK; @@ -42,6 +42,7 @@ fn main() { test_set_file_info(); test_dup_handle(); test_flush_buffers(); + test_move_file(); } } @@ -376,6 +377,23 @@ unsafe fn test_flush_buffers() { } } +unsafe fn test_move_file() { + let tmp_dir = utils::tmp(); + + let temp = tmp_dir.join("test_move_file.txt"); + let temp_new = tmp_dir.join("test_move_file_new.txt"); + let mut file = fs::File::options().create(true).write(true).open(&temp).unwrap(); + file.write_all(b"Hello, World!\n").unwrap(); + + let from = to_wide_cstr(&temp); + let to = to_wide_cstr(&temp_new); + if MoveFileExW(from.as_ptr(), to.as_ptr(), 1) == 0 { + panic!("Failed to rename file from {} to {}", temp.display(), temp_new.display()); + } + + assert_eq!(fs::read_to_string(temp_new).unwrap(), "Hello, World!\n"); +} + fn to_wide_cstr(path: &Path) -> Vec { let mut raw_path = path.as_os_str().encode_wide().collect::>(); raw_path.extend([0, 0]); diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index 1e86c458ac21c..f81f62e176021 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -134,13 +134,19 @@ fn simd_ops_f16() { assert_eq!(simd_reduce_min(b), -4.0f16); assert_eq!( - simd_maximum_number_nsz(f16x2::from_array([0.0, f16::NAN]), f16x2::from_array([f16::NAN, 0.0])), + simd_maximum_number_nsz( + f16x2::from_array([0.0, f16::NAN]), + f16x2::from_array([f16::NAN, 0.0]) + ), f16x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_max(f16x2::from_array([0.0, f16::NAN])), 0.0f16); assert_eq!(simd_reduce_max(f16x2::from_array([f16::NAN, 0.0])), 0.0f16); assert_eq!( - simd_minimum_number_nsz(f16x2::from_array([0.0, f16::NAN]), f16x2::from_array([f16::NAN, 0.0])), + simd_minimum_number_nsz( + f16x2::from_array([0.0, f16::NAN]), + f16x2::from_array([f16::NAN, 0.0]) + ), f16x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_min(f16x2::from_array([0.0, f16::NAN])), 0.0f16); @@ -348,13 +354,19 @@ fn simd_ops_f128() { assert_eq!(simd_reduce_min(b), -4.0f128); assert_eq!( - simd_maximum_number_nsz(f128x2::from_array([0.0, f128::NAN]), f128x2::from_array([f128::NAN, 0.0])), + simd_maximum_number_nsz( + f128x2::from_array([0.0, f128::NAN]), + f128x2::from_array([f128::NAN, 0.0]) + ), f128x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_max(f128x2::from_array([0.0, f128::NAN])), 0.0f128); assert_eq!(simd_reduce_max(f128x2::from_array([f128::NAN, 0.0])), 0.0f128); assert_eq!( - simd_minimum_number_nsz(f128x2::from_array([0.0, f128::NAN]), f128x2::from_array([f128::NAN, 0.0])), + simd_minimum_number_nsz( + f128x2::from_array([0.0, f128::NAN]), + f128x2::from_array([f128::NAN, 0.0]) + ), f128x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_min(f128x2::from_array([0.0, f128::NAN])), 0.0f128); diff --git a/src/tools/miri/tests/pass/no_std_miri_start.rs b/src/tools/miri/tests/pass/miri_start_no_std.rs similarity index 100% rename from src/tools/miri/tests/pass/no_std_miri_start.rs rename to src/tools/miri/tests/pass/miri_start_no_std.rs diff --git a/src/tools/miri/tests/pass/no_std_miri_start.stdout b/src/tools/miri/tests/pass/miri_start_no_std.stdout similarity index 100% rename from src/tools/miri/tests/pass/no_std_miri_start.stdout rename to src/tools/miri/tests/pass/miri_start_no_std.stdout diff --git a/src/tools/miri/tests/pass/miri_start_with_std.rs b/src/tools/miri/tests/pass/miri_start_with_std.rs new file mode 100644 index 0000000000000..510b9d4196226 --- /dev/null +++ b/src/tools/miri/tests/pass/miri_start_with_std.rs @@ -0,0 +1,8 @@ +#![no_main] + +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { + let _b = Box::new(0); + println!("hello, world!"); + 0 +} diff --git a/src/tools/miri/tests/pass/miri_start_with_std.stdout b/src/tools/miri/tests/pass/miri_start_with_std.stdout new file mode 100644 index 0000000000000..270c611ee72c5 --- /dev/null +++ b/src/tools/miri/tests/pass/miri_start_with_std.stdout @@ -0,0 +1 @@ +hello, world! diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs new file mode 100644 index 0000000000000..849f99ee36cce --- /dev/null +++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs @@ -0,0 +1,61 @@ +// We're testing aarch64 CRC32 target specific features +//@only-target: aarch64 +//@compile-flags: -C target-feature=+crc + +use std::arch::aarch64::*; +use std::arch::is_aarch64_feature_detected; + +fn main() { + assert!(is_aarch64_feature_detected!("crc")); + + unsafe { + test_crc32_standard(); + test_crc32c_castagnoli(); + } +} + +#[target_feature(enable = "crc")] +unsafe fn test_crc32_standard() { + // __crc32b: 8-bit input + assert_eq!(__crc32b(0x00000000, 0x01), 0x77073096); + assert_eq!(__crc32b(0xffffffff, 0x61), 0x174841bc); + assert_eq!(__crc32b(0x2aa1e72b, 0x2a), 0x772d9171); + + // __crc32h: 16-bit input + assert_eq!(__crc32h(0x00000000, 0x0001), 0x191b3141); + assert_eq!(__crc32h(0xffffffff, 0x1234), 0xf6b56fbf); + assert_eq!(__crc32h(0x8ecec3b5, 0x022b), 0x03a1db7c); + + // __crc32w: 32-bit input + assert_eq!(__crc32w(0x00000000, 0x00000001), 0xb8bc6765); + assert_eq!(__crc32w(0xffffffff, 0x12345678), 0x5092782d); + assert_eq!(__crc32w(0xae2912c8, 0x00845fed), 0xc5690dd4); + + // __crc32d: 64-bit input + assert_eq!(__crc32d(0x00000000, 0x0000000000000001), 0xccaa009e); + assert_eq!(__crc32d(0xffffffff, 0x123456789abcdef0), 0xe6ddf8b5); + assert_eq!(__crc32d(0x0badeafe, 0xc0febeefdadafefe), 0x61a45fba); +} + +#[target_feature(enable = "crc")] +unsafe fn test_crc32c_castagnoli() { + // __crc32cb: 8-bit input + assert_eq!(__crc32cb(0x00000000, 0x01), 0xf26b8303); + assert_eq!(__crc32cb(0xffffffff, 0x61), 0x3e2fbccf); + assert_eq!(__crc32cb(0x2aa1e72b, 0x2a), 0xf24122e4); + + // __crc32ch: 16-bit input + assert_eq!(__crc32ch(0x00000000, 0x0001), 0x13a29877); + assert_eq!(__crc32ch(0xffffffff, 0x1234), 0xf13f4cea); + assert_eq!(__crc32ch(0x8ecec3b5, 0x022b), 0x013bb2fb); + + // __crc32cw: 32-bit input + assert_eq!(__crc32cw(0x00000000, 0x00000001), 0xdd45aab8); + assert_eq!(__crc32cw(0xffffffff, 0x12345678), 0x4dece20c); + assert_eq!(__crc32cw(0xae2912c8, 0x00845fed), 0xffae2ed1); + + // __crc32cd: 64-bit input + assert_eq!(__crc32cd(0x00000000, 0x0000000000000001), 0x493c7d27); + assert_eq!(__crc32cd(0xffffffff, 0x123456789abcdef0), 0xd95b664b); + assert_eq!(__crc32cd(0x0badeafe, 0xc0febeefdadafefe), 0x5b44f54f); +} diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs index 6d3f153e194f3..884f8eff41bdb 100644 --- a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs +++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs @@ -12,6 +12,8 @@ fn main() { unsafe { test_vpmaxq_u8(); test_tbl1_v16i8_basic(); + test_vpadd(); + test_vpaddl(); } } @@ -65,3 +67,93 @@ fn test_tbl1_v16i8_basic() { assert_eq!(&got2_arr[3..16], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12][..]); } } +#[target_feature(enable = "neon")] +unsafe fn test_vpadd() { + let a = vld1_s8([1, 2, 3, 4, 5, 6, 7, 8].as_ptr()); + let b = vld1_s8([9, 10, -1, 2, i8::MIN, i8::MIN, i8::MAX, i8::MAX].as_ptr()); + let e = + [3i8, 7, 11, 15, 19, -1 + 2, i8::MIN.wrapping_add(i8::MIN), i8::MAX.wrapping_add(i8::MAX)]; + let mut r = [0i8; 8]; + vst1_s8(r.as_mut_ptr(), vpadd_s8(a, b)); + assert_eq!(r, e); + + let a = vld1_s16([1, 2, 3, 4].as_ptr()); + let b = vld1_s16([-1, 2, i16::MAX, i16::MAX].as_ptr()); + let e = [3i16, 7, -1 + 2, i16::MAX.wrapping_add(i16::MAX)]; + let mut r = [0i16; 4]; + vst1_s16(r.as_mut_ptr(), vpadd_s16(a, b)); + assert_eq!(r, e); + + let a = vld1_s32([1, 2].as_ptr()); + let b = vld1_s32([i32::MAX, i32::MAX].as_ptr()); + let e = [3i32, i32::MAX.wrapping_add(i32::MAX)]; + let mut r = [0i32; 2]; + vst1_s32(r.as_mut_ptr(), vpadd_s32(a, b)); + assert_eq!(r, e); + + let a = vld1_u8([1, 2, 3, 4, 5, 6, 7, 8].as_ptr()); + let b = vld1_u8([9, 10, 11, 12, 13, 14, u8::MAX, u8::MAX].as_ptr()); + let e = [3u8, 7, 11, 15, 19, 23, 27, 254]; + let mut r = [0u8; 8]; + vst1_u8(r.as_mut_ptr(), vpadd_u8(a, b)); + assert_eq!(r, e); + + let a = vld1_u16([1, 2, 3, 4].as_ptr()); + let b = vld1_u16([5, 6, u16::MAX, u16::MAX].as_ptr()); + let e = [3u16, 7, 11, 65534]; + let mut r = [0u16; 4]; + vst1_u16(r.as_mut_ptr(), vpadd_u16(a, b)); + assert_eq!(r, e); + + let a = vld1_u32([1, 2].as_ptr()); + let b = vld1_u32([u32::MAX, u32::MAX].as_ptr()); + let e = [3u32, u32::MAX.wrapping_add(u32::MAX)]; + let mut r = [0u32; 2]; + vst1_u32(r.as_mut_ptr(), vpadd_u32(a, b)); + assert_eq!(r, e); +} + +#[target_feature(enable = "neon")] +unsafe fn test_vpaddl() { + let a = vld1_u8([1, 2, 3, 4, 5, 6, u8::MAX, u8::MAX].as_ptr()); + let e = [3u16, 7, 11, 510]; + let mut r = [0u16; 4]; + vst1_u16(r.as_mut_ptr(), vpaddl_u8(a)); + assert_eq!(r, e); + + let a = vld1q_u8([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, u8::MAX, u8::MAX].as_ptr()); + let e = [3u16, 7, 11, 15, 19, 23, 27, 510]; + let mut r = [0u16; 8]; + vst1q_u16(r.as_mut_ptr(), vpaddlq_u8(a)); + assert_eq!(r, e); + + let a = vld1_u16([1, 2, u16::MAX, u16::MAX].as_ptr()); + let e = [3u32, 131070]; + let mut r = [0u32; 2]; + vst1_u32(r.as_mut_ptr(), vpaddl_u16(a)); + assert_eq!(r, e); + + let a = vld1q_u16([1, 2, 3, 4, 5, 6, u16::MAX, u16::MAX].as_ptr()); + let e = [3u32, 7, 11, 131070]; + let mut r = [0u32; 4]; + vst1q_u32(r.as_mut_ptr(), vpaddlq_u16(a)); + assert_eq!(r, e); + + let a = vld1_u32([1, 2].as_ptr()); + let e = [3u64]; + let mut r = [0u64; 1]; + vst1_u64(r.as_mut_ptr(), vpaddl_u32(a)); + assert_eq!(r, e); + + let a = vld1_u32([u32::MAX, u32::MAX].as_ptr()); + let e = [8589934590]; + let mut r = [0u64; 1]; + vst1_u64(r.as_mut_ptr(), vpaddl_u32(a)); + assert_eq!(r, e); + + let a = vld1q_u32([1, 2, u32::MAX, u32::MAX].as_ptr()); + let e = [3u64, 8589934590]; + let mut r = [0u64; 2]; + vst1q_u64(r.as_mut_ptr(), vpaddlq_u32(a)); + assert_eq!(r, e); +} diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 50b5dbfba1cdd..e6c15c81d9fd4 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -30,9 +30,9 @@ fn main() { test_file_clone(); test_file_set_len(); test_file_sync(); + test_rename(); // Windows file handling is very incomplete. if cfg!(not(windows)) { - test_rename(); test_directory(); test_canonicalize(); #[cfg(unix)] diff --git a/src/tools/miri/tests/pass/shims/socket.rs b/src/tools/miri/tests/pass/shims/socket.rs index 2e63e00c67d90..852397a356916 100644 --- a/src/tools/miri/tests/pass/shims/socket.rs +++ b/src/tools/miri/tests/pass/shims/socket.rs @@ -8,6 +8,7 @@ fn main() { test_create_ipv4_listener(); test_create_ipv6_listener(); test_accept_and_connect(); + test_peer_addr(); } fn test_create_ipv4_listener() { @@ -34,3 +35,22 @@ fn test_accept_and_connect() { handle.join().unwrap(); } + +/// Test whether the [`TcpStream::peer_addr`] of a connected socket +/// is the same address as the one the stream was connected to. +fn test_peer_addr() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + // Get local address with randomized port to know where + // we need to connect to. + let address = listener.local_addr().unwrap(); + + let handle = thread::spawn(move || { + let (_stream, _addr) = listener.accept().unwrap(); + }); + + let stream = TcpStream::connect(address).unwrap(); + let peer_addr = stream.peer_addr().unwrap(); + assert_eq!(address, peer_addr); + + handle.join().unwrap(); +} diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 88fb27386218e..0219db325c8f6 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -51,7 +51,7 @@ StorageLive(_12); StorageLive(_13); - _13 = boxed::box_new_uninit(const <() as std::mem::SizedTypeProperties>::LAYOUT) -> [return: bb2, unwind unreachable]; -+ _13 = boxed::box_new_uninit(const Layout {{ size: 0_usize, align: std::mem::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> [return: bb2, unwind unreachable]; ++ _13 = boxed::box_new_uninit(const Layout {{ size: 0_usize, align: std::mem::Alignment {{ _inner_repr_trick: mem::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> [return: bb2, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index 139cf2116fc49..11d64d05c7d18 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -63,7 +63,7 @@ bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::mem::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::mem::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): mem::alignment::AlignmentEnum }} }}; StorageDead(_8); StorageDead(_2); StorageLive(_3); @@ -73,8 +73,8 @@ StorageLive(_7); - _7 = copy _1; - _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb4, unwind unreachable]; -+ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::mem::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}; -+ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::mem::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}, const false) -> [return: bb4, unwind unreachable]; ++ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::mem::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): mem::alignment::AlignmentEnum }} }}; ++ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::mem::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): mem::alignment::AlignmentEnum }} }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/ui/consts/const-bound.rs b/tests/ui/consts/const-bound.rs deleted file mode 100644 index 00a833ba3f79e..0000000000000 --- a/tests/ui/consts/const-bound.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -// Make sure const bounds work on things, and test that a few types -// are const. - - -fn foo(x: T) -> T { x } - -struct F { field: isize } - -pub fn main() { - /*foo(1); - foo("hi".to_string()); - foo(vec![1, 2, 3]); - foo(F{field: 42}); - foo((1, 2)); - foo(@1);*/ - foo(Box::new(1)); -} diff --git a/tests/ui/consts/const-enum-tuple.rs b/tests/ui/consts/const-enum-tuple.rs deleted file mode 100644 index fe6b54aa79351..0000000000000 --- a/tests/ui/consts/const-enum-tuple.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -enum E { V16(u16), V32(u32) } -static C: (E, u16, u16) = (E::V16(0xDEAD), 0x600D, 0xBAD); - -pub fn main() { - let (_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/tests/ui/consts/const-enum-tuple2.rs b/tests/ui/consts/const-enum-tuple2.rs deleted file mode 100644 index 713209943d3ed..0000000000000 --- a/tests/ui/consts/const-enum-tuple2.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -enum E { V0, V16(u16) } -static C: (E, u16, u16) = (E::V0, 0x600D, 0xBAD); - -pub fn main() { - let (_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/tests/ui/consts/const-enum-tuplestruct2.rs b/tests/ui/consts/const-enum-tuplestruct2.rs deleted file mode 100644 index dc44532369524..0000000000000 --- a/tests/ui/consts/const-enum-tuplestruct2.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -enum E { V0, V16(u16) } -struct S(E, u16, u16); -static C: S = S(E::V0, 0x600D, 0xBAD); - -pub fn main() { - let S(_, n, _) = C; - assert!(n != 0xBAD); - assert_eq!(n, 0x600D); -} diff --git a/tests/ui/consts/const.rs b/tests/ui/consts/const.rs deleted file mode 100644 index 1f1c6e30b4a08..0000000000000 --- a/tests/ui/consts/const.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass -#![allow(non_upper_case_globals)] - -static i: isize = 10; - -pub fn main() { println!("{}", i); }