diff options
63 files changed, 818 insertions, 607 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3680136d89f..0c20e4dc535 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -393,7 +393,7 @@ jobs: - name: dist-x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths + SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 os: windows-2019-8core-32gb - name: dist-i686-msvc diff --git a/.mailmap b/.mailmap index eb82cf4de8d..7d455ebd45f 100644 --- a/.mailmap +++ b/.mailmap @@ -549,6 +549,8 @@ Timothy Maloney <tmaloney@pdx.edu> Tomas Koutsky <tomas@stepnivlk.net> Torsten Weber <TorstenWeber12@gmail.com> Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com> +Trevor Gross <tmgross@umich.edu> <t.gross35@gmail.com> +Trevor Gross <tmgross@umich.edu> <tgross@intrepidcs.com> Trevor Spiteri <tspiteri@ieee.org> <trevor.spiteri@um.edu.mt> Tshepang Mbambo <tshepang@gmail.com> Ty Overby <ty@pre-alpha.com> diff --git a/Cargo.lock b/Cargo.lock index 386b57e6a44..fe4118db1b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -860,12 +860,36 @@ dependencies = [ [[package]] name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -884,11 +908,22 @@ dependencies = [ [[package]] name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core", + "darling_core 0.20.3", "quote", "syn 2.0.29", ] @@ -920,6 +955,37 @@ dependencies = [ ] [[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + +[[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -938,7 +1004,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", "syn 2.0.29", @@ -2584,6 +2650,8 @@ dependencies = [ "anyhow", "build_helper", "camino", + "clap", + "derive_builder", "env_logger 0.10.0", "fs_extra", "glob", diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 337af89b21f..b40e89e471d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -442,8 +442,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { span: Span, counter: usize, ) -> RegionNameHighlight { - let mut highlight = RegionHighlightMode::new(self.infcx.tcx); - highlight.highlighting_region_vid(needle_fr, counter); + let mut highlight = RegionHighlightMode::default(); + highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter); let type_name = self.infcx.extract_inference_diagnostics_data(ty.into(), Some(highlight)).name; @@ -804,8 +804,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { return None; } - let mut highlight = RegionHighlightMode::new(tcx); - highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); + let mut highlight = RegionHighlightMode::default(); + highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap()); let type_name = self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index f903f7a49ef..4aec28b051f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -385,7 +385,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let highlight_trait_ref = |trait_ref| Highlighted { tcx: self.tcx(), - highlight: RegionHighlightMode::new(self.tcx()), + highlight: RegionHighlightMode::default(), value: trait_ref, }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 12d38ced030..d2ba9966f03 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -67,9 +67,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } impl<'tcx> HighlightBuilder<'tcx> { - fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode<'tcx> { + fn build(ty: Ty<'tcx>) -> RegionHighlightMode<'tcx> { let mut builder = - HighlightBuilder { highlight: RegionHighlightMode::new(tcx), counter: 1 }; + HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1 }; builder.visit_ty(ty); builder.highlight } @@ -85,12 +85,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } - let expected_highlight = HighlightBuilder::build(self.tcx(), expected); + let expected_highlight = HighlightBuilder::build(expected); let expected = self .cx .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight)) .name; - let found_highlight = HighlightBuilder::build(self.tcx(), found); + let found_highlight = HighlightBuilder::build(found); let found = self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 2402a7ea7c7..ed1a2a11719 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -4,7 +4,7 @@ //! and use that to decide when one free region outlives another, and so forth. use rustc_data_structures::transitive_relation::TransitiveRelation; -use rustc_middle::ty::{Lift, Region, TyCtxt}; +use rustc_middle::ty::{Region, TyCtxt}; /// Combines a `FreeRegionMap` and a `TyCtxt`. /// @@ -101,10 +101,3 @@ impl<'tcx> FreeRegionMap<'tcx> { result } } - -impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> { - type Lifted = FreeRegionMap<'tcx>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<FreeRegionMap<'tcx>> { - self.relation.maybe_map(|fr| tcx.lift(fr)).map(|relation| FreeRegionMap { relation }) - } -} diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index b17f1512886..2f2597d6b22 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -34,7 +34,7 @@ use std::ops::Index; /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct Canonical<'tcx, V> { pub value: V, pub max_universe: ty::UniverseIndex, @@ -72,7 +72,7 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> { /// variables. You will need to supply it later to instantiate the /// canonicalized query response. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct CanonicalVarValues<'tcx> { pub var_values: ty::GenericArgsRef<'tcx>, } @@ -311,7 +311,7 @@ pub enum CanonicalTyVarKind { /// After we execute a query with a canonicalized key, we get back a /// `Canonical<QueryResponse<..>>`. You can use /// `instantiate_query_result` to access the data in this result. -#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, @@ -326,7 +326,7 @@ pub struct QueryResponse<'tcx, R> { } #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct QueryRegionConstraints<'tcx> { pub outlives: Vec<QueryOutlivesConstraint<'tcx>>, pub member_constraints: Vec<MemberConstraint<'tcx>>, @@ -432,7 +432,7 @@ impl<'tcx, V> Canonical<'tcx, V> { pub type QueryOutlivesConstraint<'tcx> = (ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>); -TrivialTypeTraversalAndLiftImpls! { +TrivialTypeTraversalImpls! { crate::infer::canonical::Certainty, crate::infer::canonical::CanonicalTyVarKind, } diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs index 493bb8a6823..1384611e146 100644 --- a/compiler/rustc_middle/src/infer/mod.rs +++ b/compiler/rustc_middle/src/infer/mod.rs @@ -13,7 +13,7 @@ use rustc_span::Span; /// R0 member of [O1..On] /// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct MemberConstraint<'tcx> { /// The `DefId` and args of the opaque type causing this constraint. /// Used for error reporting. diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index fca16d8e509..c1884bb8068 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -42,7 +42,7 @@ macro_rules! span_bug { // the impls for you. #[macro_export] -macro_rules! CloneLiftImpls { +macro_rules! TrivialLiftImpls { ($($ty:ty),+ $(,)?) => { $( impl<'tcx> $crate::ty::Lift<'tcx> for $ty { @@ -96,6 +96,6 @@ macro_rules! TrivialTypeTraversalImpls { macro_rules! TrivialTypeTraversalAndLiftImpls { ($($t:tt)*) => { TrivialTypeTraversalImpls! { $($t)* } - CloneLiftImpls! { $($t)* } + TrivialLiftImpls! { $($t)* } } } diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 70d8f3bd54b..cd770c395e4 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -178,7 +178,7 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> { } } -TrivialTypeTraversalAndLiftImpls! { Cache } +TrivialTypeTraversalImpls! { Cache } impl<S: Encoder> Encodable<S> for Cache { #[inline] diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 7e3be0b5d5f..2194ef81cec 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -67,7 +67,7 @@ impl Into<ErrorGuaranteed> for ReportedErrorInfo { } } -TrivialTypeTraversalAndLiftImpls! { ErrorHandled } +TrivialTypeTraversalImpls! { ErrorHandled } pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>; diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 44d1dcbbe17..8c00746a180 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -162,7 +162,7 @@ pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; /// - A constant /// - A static #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, Lift, TypeFoldable, TypeVisitable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct GlobalId<'tcx> { /// For a constant or static, the `Instance` of the item itself. /// For a promoted global, the `Instance` of the function they belong to. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 8df3a79b4d4..5e749776992 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -744,7 +744,7 @@ pub enum BindingForm<'tcx> { RefForGuard, } -TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx> } +TrivialTypeTraversalImpls! { BindingForm<'tcx> } mod binding_form_impl { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -2295,7 +2295,7 @@ pub struct Constant<'tcx> { } #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)] -#[derive(Lift, TypeFoldable, TypeVisitable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum ConstantKind<'tcx> { /// This constant came from the type system. /// @@ -2615,7 +2615,7 @@ impl<'tcx> ConstantKind<'tcx> { } /// An unevaluated (potentially generic) constant used in MIR. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 71bec49af93..0c80610b308 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -334,7 +334,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 06874741bb0..8d427fdb6f5 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -5,7 +5,7 @@ use rustc_ast::InlineAsmTemplatePiece; use super::*; use crate::ty; -TrivialTypeTraversalAndLiftImpls! { +TrivialTypeTraversalImpls! { BlockTailInfo, MirPhase, SourceInfo, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 3465759b913..1340e674568 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -13,7 +13,7 @@ use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::GenericArgsRef; -use crate::ty::{self, AdtKind, Ty, TyCtxt}; +use crate::ty::{self, AdtKind, Ty}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; @@ -86,7 +86,7 @@ pub enum Reveal { /// /// We do not want to intern this as there are a lot of obligation causes which /// only live for a short period of time. -#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub struct ObligationCause<'tcx> { pub span: Span, @@ -194,7 +194,7 @@ impl<'tcx> ObligationCause<'tcx> { } } -#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub struct UnifyReceiverContext<'tcx> { pub assoc_item: ty::AssocItem, @@ -202,7 +202,7 @@ pub struct UnifyReceiverContext<'tcx> { pub args: GenericArgsRef<'tcx>, } -#[derive(Clone, PartialEq, Eq, Lift, Default, HashStable)] +#[derive(Clone, PartialEq, Eq, Default, HashStable)] #[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)] pub struct InternedObligationCauseCode<'tcx> { /// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of @@ -238,7 +238,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> { } } -#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub enum ObligationCauseCode<'tcx> { /// Not well classified or should be obvious from the span. @@ -470,7 +470,7 @@ pub enum WellFormedLoc { }, } -#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub struct ImplDerivedObligationCause<'tcx> { pub derived: DerivedObligationCause<'tcx>, @@ -524,14 +524,7 @@ pub enum StatementAsExpression { NeedsBoxing, } -impl<'tcx> ty::Lift<'tcx> for StatementAsExpression { - type Lifted = StatementAsExpression; - fn lift_to_tcx(self, _tcx: TyCtxt<'tcx>) -> Option<StatementAsExpression> { - Some(self) - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub struct MatchExpressionArmCause<'tcx> { pub arm_block_id: Option<hir::HirId>, @@ -547,7 +540,7 @@ pub struct MatchExpressionArmCause<'tcx> { } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[derive(Lift, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] +#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] pub struct IfExpressionCause<'tcx> { pub then_id: hir::HirId, pub else_id: hir::HirId, @@ -557,7 +550,7 @@ pub struct IfExpressionCause<'tcx> { pub opt_suggest_box_span: Option<Span>, } -#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] pub struct DerivedObligationCause<'tcx> { /// The trait predicate of the parent obligation that led to the @@ -570,7 +563,7 @@ pub struct DerivedObligationCause<'tcx> { pub parent_code: InternedObligationCauseCode<'tcx>, } -#[derive(Clone, Debug, TypeVisitable, Lift)] +#[derive(Clone, Debug, TypeVisitable)] pub enum SelectionError<'tcx> { /// The trait is not implemented. Unimplemented, @@ -593,7 +586,7 @@ pub enum SelectionError<'tcx> { OpaqueTypeAutoTraitLeakageUnknown(DefId), } -#[derive(Clone, Debug, TypeVisitable, Lift)] +#[derive(Clone, Debug, TypeVisitable)] pub struct SelectionOutputTypeParameterMismatch<'tcx> { pub found_trait_ref: ty::PolyTraitRef<'tcx>, pub expected_trait_ref: ty::PolyTraitRef<'tcx>, @@ -638,7 +631,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>; /// ### The type parameter `N` /// /// See explanation on `ImplSourceUserDefinedData`. -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] #[derive(TypeFoldable, TypeVisitable)] pub enum ImplSource<'tcx, N> { /// ImplSource identifying a particular impl. @@ -704,7 +697,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { /// is `Obligation`, as one might expect. During codegen, however, this /// is `()`, because codegen only requires a shallow resolution of an /// impl, and nested obligations are satisfied later. -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceUserDefinedData<'tcx, N> { pub impl_def_id: DefId, @@ -736,7 +729,7 @@ pub enum BuiltinImplSource { TupleUnsizing, } -TrivialTypeTraversalAndLiftImpls! { BuiltinImplSource } +TrivialTypeTraversalImpls! { BuiltinImplSource } #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 950a59e9695..975e3e3ac62 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -17,8 +17,7 @@ pub mod type_op { use crate::ty::{Predicate, Ty, TyCtxt, UserType}; use std::fmt; - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] - #[derive(TypeFoldable, TypeVisitable)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct AscribeUserType<'tcx> { pub mir_ty: Ty<'tcx>, pub user_ty: UserType<'tcx>, @@ -30,22 +29,19 @@ pub mod type_op { } } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] - #[derive(TypeFoldable, TypeVisitable)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct Eq<'tcx> { pub a: Ty<'tcx>, pub b: Ty<'tcx>, } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] - #[derive(TypeFoldable, TypeVisitable)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct Subtype<'tcx> { pub sub: Ty<'tcx>, pub sup: Ty<'tcx>, } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] - #[derive(TypeFoldable, TypeVisitable)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct ProvePredicate<'tcx> { pub predicate: Predicate<'tcx>, } @@ -56,8 +52,7 @@ pub mod type_op { } } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] - #[derive(TypeFoldable, TypeVisitable)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct Normalize<T> { pub value: T, } @@ -101,7 +96,7 @@ impl<'tcx> From<TypeError<'tcx>> for NoSolution { } } -#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)] pub struct DropckOutlivesResult<'tcx> { pub kinds: Vec<GenericArg<'tcx>>, pub overflows: Vec<Ty<'tcx>>, @@ -194,7 +189,7 @@ pub struct MethodAutoderefBadTy<'tcx> { } /// Result from the `normalize_projection_ty` query. -#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct NormalizationResult<'tcx> { /// Result of normalization. pub normalized_ty: Ty<'tcx>, @@ -207,7 +202,7 @@ pub struct NormalizationResult<'tcx> { /// case they are called implied bounds). They are fed to the /// `OutlivesEnv` which in turn is supplied to the region checker and /// other parts of the inference system. -#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift, HashStable)] +#[derive(Clone, Debug, TypeFoldable, TypeVisitable, HashStable)] pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index ffae3579889..90bc5dd8f69 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -305,7 +305,7 @@ impl From<ErrorGuaranteed> for OverflowError { } } -TrivialTypeTraversalAndLiftImpls! { OverflowError } +TrivialTypeTraversalImpls! { OverflowError } impl<'tcx> From<OverflowError> for SelectionError<'tcx> { fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index d8b3a061b77..c3ed40867cf 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -15,9 +15,15 @@ pub enum CacheHit { } #[derive(Eq, PartialEq)] +pub enum GoalEvaluationKind { + Root, + Nested { is_normalizes_to_hack: IsNormalizesToHack }, +} + +#[derive(Eq, PartialEq)] pub struct GoalEvaluation<'tcx> { pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, - pub is_normalizes_to_hack: IsNormalizesToHack, + pub kind: GoalEvaluationKind, pub evaluation: CanonicalGoalEvaluation<'tcx>, pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>, } @@ -25,12 +31,12 @@ pub struct GoalEvaluation<'tcx> { #[derive(Eq, PartialEq)] pub struct CanonicalGoalEvaluation<'tcx> { pub goal: CanonicalInput<'tcx>, - pub kind: GoalEvaluationKind<'tcx>, + pub kind: CanonicalGoalEvaluationKind<'tcx>, pub result: QueryResult<'tcx>, } #[derive(Eq, PartialEq)] -pub enum GoalEvaluationKind<'tcx> { +pub enum CanonicalGoalEvaluationKind<'tcx> { Overflow, CacheHit(CacheHit), Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> }, @@ -52,22 +58,31 @@ pub struct GoalEvaluationStep<'tcx> { pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, /// The actual evaluation of the goal, always `ProbeKind::Root`. - pub evaluation: GoalCandidate<'tcx>, + pub evaluation: Probe<'tcx>, } +/// A self-contained computation during trait solving. This either +/// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation +/// of a goal. #[derive(Eq, PartialEq)] -pub struct GoalCandidate<'tcx> { - pub added_goals_evaluations: Vec<AddedGoalsEvaluation<'tcx>>, - pub candidates: Vec<GoalCandidate<'tcx>>, +pub struct Probe<'tcx> { + pub steps: Vec<ProbeStep<'tcx>>, pub kind: ProbeKind<'tcx>, } -impl Debug for GoalCandidate<'_> { +impl Debug for Probe<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter::new(f).format_candidate(self) + ProofTreeFormatter::new(f).format_probe(self) } } +#[derive(Eq, PartialEq)] +pub enum ProbeStep<'tcx> { + AddGoal(Goal<'tcx, ty::Predicate<'tcx>>), + EvaluateGoals(AddedGoalsEvaluation<'tcx>), + NestedProbe(Probe<'tcx>), +} + #[derive(Debug, PartialEq, Eq)] pub enum ProbeKind<'tcx> { /// The root inference context while proving a goal. diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index d916e80a625..d33e83ae1ed 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -40,9 +40,12 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { } pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result { - let goal_text = match eval.is_normalizes_to_hack { - IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", - IsNormalizesToHack::No => "GOAL", + let goal_text = match eval.kind { + GoalEvaluationKind::Root => "ROOT GOAL", + GoalEvaluationKind::Nested { is_normalizes_to_hack } => match is_normalizes_to_hack { + IsNormalizesToHack::No => "GOAL", + IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", + }, }; writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation))?; @@ -68,16 +71,16 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { writeln!(self.f, "GOAL: {:?}", eval.goal)?; match &eval.kind { - GoalEvaluationKind::Overflow => { + CanonicalGoalEvaluationKind::Overflow => { writeln!(self.f, "OVERFLOW: {:?}", eval.result) } - GoalEvaluationKind::CacheHit(CacheHit::Global) => { + CanonicalGoalEvaluationKind::CacheHit(CacheHit::Global) => { writeln!(self.f, "GLOBAL CACHE HIT: {:?}", eval.result) } - GoalEvaluationKind::CacheHit(CacheHit::Provisional) => { + CanonicalGoalEvaluationKind::CacheHit(CacheHit::Provisional) => { writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result) } - GoalEvaluationKind::Uncached { revisions } => { + CanonicalGoalEvaluationKind::Uncached { revisions } => { for (n, step) in revisions.iter().enumerate() { writeln!(self.f, "REVISION {n}")?; self.nested(|this| this.format_evaluation_step(step))?; @@ -92,11 +95,11 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { evaluation_step: &GoalEvaluationStep<'_>, ) -> std::fmt::Result { writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; - self.format_candidate(&evaluation_step.evaluation) + self.format_probe(&evaluation_step.evaluation) } - pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result { - match &candidate.kind { + pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result { + match &probe.kind { ProbeKind::Root { result } => { writeln!(self.f, "ROOT RESULT: {result:?}") } @@ -118,11 +121,12 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { }?; self.nested(|this| { - for candidate in &candidate.candidates { - this.format_candidate(candidate)?; - } - for nested in &candidate.added_goals_evaluations { - this.format_added_goals_evaluation(nested)?; + for step in &probe.steps { + match step { + ProbeStep::AddGoal(goal) => writeln!(this.f, "ADDED GOAL: {goal:?}")?, + ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?, + ProbeStep::NestedProbe(probe) => this.format_probe(probe)?, + } } Ok(()) }) diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index cdd8351499b..570f896ba29 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -27,7 +27,7 @@ impl From<ErrorGuaranteed> for NotConstEvaluatable { } } -TrivialTypeTraversalAndLiftImpls! { NotConstEvaluatable } +TrivialTypeTraversalImpls! { NotConstEvaluatable } pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>, ErrorGuaranteed>; diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 76931ceaa69..c3e8991c63a 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -76,7 +76,7 @@ pub enum PointerCoercion { /// At some point, of course, `Box` should move out of the compiler, in which /// case this is analogous to transforming a struct. E.g., `Box<[i32; 4]>` -> /// `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`. -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Adjustment<'tcx> { pub kind: Adjust<'tcx>, pub target: Ty<'tcx>, @@ -88,7 +88,7 @@ impl<'tcx> Adjustment<'tcx> { } } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum Adjust<'tcx> { /// Go from ! to any type. NeverToAny, @@ -110,7 +110,7 @@ pub enum Adjust<'tcx> { /// The target type is `U` in both cases, with the region and mutability /// being those shared by both the receiver and the returned reference. #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct OverloadedDeref<'tcx> { pub region: ty::Region<'tcx>, pub mutbl: hir::Mutability, @@ -182,7 +182,7 @@ impl From<AutoBorrowMutability> for hir::Mutability { } #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub enum AutoBorrow<'tcx> { /// Converts from T to &T. Ref(ty::Region<'tcx>, AutoBorrowMutability), diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs index 2fec8ac9095..af594bc5f24 100644 --- a/compiler/rustc_middle/src/ty/binding.rs +++ b/compiler/rustc_middle/src/ty/binding.rs @@ -6,7 +6,7 @@ pub enum BindingMode { BindByValue(Mutability), } -TrivialTypeTraversalAndLiftImpls! { BindingMode } +TrivialTypeTraversalImpls! { BindingMode } impl BindingMode { pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index e25402fe0c2..749b54ca0be 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::HashStable; /// An unevaluated (potentially generic) constant used in the type-system. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f7484048757..e8d50a1c025 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -50,7 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Constness, HirId, Node, TraitCandidate}; +use rustc_hir::{HirId, Node, TraitCandidate}; use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_query_system::dep_graph::DepNodeIndex; @@ -1214,6 +1214,25 @@ macro_rules! nop_lift { impl<'a, 'tcx> Lift<'tcx> for $ty { type Lifted = $lifted; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { + // Assert that the set has the right type. + // Given an argument that has an interned type, the return type has the type of + // the corresponding interner set. This won't actually return anything, we're + // just doing this to compute said type! + fn _intern_set_ty_from_interned_ty<'tcx, Inner>( + _x: Interned<'tcx, Inner>, + ) -> InternedSet<'tcx, Inner> { + unreachable!() + } + fn _type_eq<T>(_x: &T, _y: &T) {} + fn _test<'tcx>(x: $lifted, tcx: TyCtxt<'tcx>) { + // If `x` is a newtype around an `Interned<T>`, then `interner` is an + // interner of appropriate type. (Ideally we'd also check that `x` is a + // newtype with just that one field. Not sure how to do that.) + let interner = _intern_set_ty_from_interned_ty(x.0); + // Now check that this is the same type as `interners.$set`. + _type_eq(&interner, &tcx.interners.$set); + } + tcx.interners .$set .contains_pointer_to(&InternedInSet(&*self.0.0)) @@ -1230,6 +1249,11 @@ macro_rules! nop_list_lift { impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { type Lifted = &'tcx List<$lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { + // Assert that the set has the right type. + if false { + let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set; + } + if self.is_empty() { return Some(List::empty()); } @@ -1251,19 +1275,13 @@ nop_lift! {predicate; Clause<'a> => Clause<'tcx>} nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} -nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>} -nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} -nop_list_lift! {projs; ProjectionKind => ProjectionKind} nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} // This is the impl for `&'a GenericArgs<'a>`. nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>} -CloneLiftImpls! { - Constness, - traits::WellFormedLoc, +TrivialLiftImpls! { ImplPolarity, - crate::mir::ReturnConstraint, } macro_rules! sty_debug_print { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index bf6f082c21c..f939d466078 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -11,7 +11,7 @@ use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::path::PathBuf; -#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub struct ExpectedFound<T> { pub expected: T, pub found: T, @@ -28,7 +28,7 @@ impl<T> ExpectedFound<T> { } // Data structures used in type unification -#[derive(Copy, Clone, Debug, TypeVisitable, Lift, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, TypeVisitable, PartialEq, Eq)] #[rustc_pass_by_value] pub enum TypeError<'tcx> { Mismatch, diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index e598ead791e..72390e4bbb0 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -1029,7 +1029,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> { /// Stores the user-given args to reach some fully qualified path /// (e.g., `<T>::Item` or `<T as Trait>::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct UserArgs<'tcx> { /// The args for the item as given by the user. pub args: GenericArgsRef<'tcx>, @@ -1056,7 +1056,7 @@ pub struct UserArgs<'tcx> { /// the self type, giving `Foo<?A>`. Finally, we unify that with /// the self type here, which contains `?A` to be `&'static u32` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct UserSelfTy<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index e5b9203d12a..2b75f6c4e8f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -18,6 +18,9 @@ use std::fmt; /// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type /// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval /// will do all required substitution as they run. +/// +/// Note: the `Lift` impl is currently not used by rustc, but is used by +/// rustc_codegen_cranelift when the `jit` feature is enabled. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, Lift, TypeFoldable, TypeVisitable)] pub struct Instance<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ff420cf902a..eb8ea0bc114 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1510,7 +1510,7 @@ impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] #[derive(TypeFoldable, TypeVisitable)] pub struct OpaqueTypeKey<'tcx> { pub def_id: LocalDefId, @@ -1793,7 +1793,7 @@ impl<'tcx> ParamEnv<'tcx> { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] -#[derive(HashStable, Lift)] +#[derive(HashStable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, pub value: T, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f24ac79323f..e1d4e43841d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -136,10 +136,8 @@ define_helper!( /// /// Regions not selected by the region highlight mode are presently /// unaffected. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub struct RegionHighlightMode<'tcx> { - tcx: TyCtxt<'tcx>, - /// If enabled, when we see the selected region, use "`'N`" /// instead of the ordinary behavior. highlight_regions: [Option<(ty::Region<'tcx>, usize)>; 3], @@ -155,14 +153,6 @@ pub struct RegionHighlightMode<'tcx> { } impl<'tcx> RegionHighlightMode<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { - Self { - tcx, - highlight_regions: Default::default(), - highlight_bound_region: Default::default(), - } - } - /// If `region` and `number` are both `Some`, invokes /// `highlighting_region`. pub fn maybe_highlighting_region( @@ -188,8 +178,13 @@ impl<'tcx> RegionHighlightMode<'tcx> { } /// Convenience wrapper for `highlighting_region`. - pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) { - self.highlighting_region(ty::Region::new_var(self.tcx, vid), number) + pub fn highlighting_region_vid( + &mut self, + tcx: TyCtxt<'tcx>, + vid: ty::RegionVid, + number: usize, + ) { + self.highlighting_region(ty::Region::new_var(tcx, vid), number) } /// Returns `Some(n)` with the number to use for the given region, if any. @@ -1778,7 +1773,7 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { printed_type_count: 0, type_length_limit, truncated: false, - region_highlight_mode: RegionHighlightMode::new(tcx), + region_highlight_mode: RegionHighlightMode::default(), ty_infer_name_resolver: None, const_infer_name_resolver: None, })) @@ -2746,20 +2741,14 @@ forward_display_to_print! { // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::PolyExistentialPredicate<'tcx>, ty::PolyExistentialProjection<'tcx>, ty::PolyExistentialTraitRef<'tcx>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, - ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>, - ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, - ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>, - ty::Binder<'tcx, ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>, - ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>, ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>> } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7c25d0209c9..f4158597d10 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -9,14 +9,11 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; -use rustc_index::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; use std::fmt::{self, Debug}; use std::ops::ControlFlow; -use std::rc::Rc; -use std::sync::Arc; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Region}; @@ -456,22 +453,16 @@ impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty: // For things for which the type library provides traversal implementations // for all Interners, we only need to provide a Lift implementation: -CloneLiftImpls! { - (), - bool, - usize, - u16, - u32, - u64, - String, - rustc_type_ir::DebruijnIndex, -} - -// For things about which the type library does not know, or does not -// provide any traversal implementations, we need to provide both a Lift -// implementation and traversal implementations (the latter only for -// TyCtxt<'_> interners). -TrivialTypeTraversalAndLiftImpls! { +TrivialLiftImpls! { + (), + bool, + usize, +} + +// For some things about which the type library does not know, or does not +// provide any traversal implementations, we need to provide a traversal +// implementation (only for TyCtxt<'_> interners). +TrivialTypeTraversalImpls! { ::rustc_target::abi::FieldIdx, ::rustc_target::abi::VariantIdx, crate::middle::region::Scope, @@ -481,14 +472,10 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_ast::NodeId, ::rustc_span::symbol::Symbol, ::rustc_hir::def::Res, - ::rustc_hir::def_id::DefId, ::rustc_hir::def_id::LocalDefId, ::rustc_hir::HirId, ::rustc_hir::MatchSource, - ::rustc_hir::Mutability, - ::rustc_hir::Unsafety, ::rustc_target::asm::InlineAsmRegOrRegClass, - ::rustc_target::spec::abi::Abi, crate::mir::coverage::CounterId, crate::mir::coverage::ExpressionId, crate::mir::coverage::MappedExpressionIndex, @@ -506,16 +493,12 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::AssocItem, crate::ty::AssocKind, crate::ty::AliasKind, - crate::ty::AliasRelationDirection, crate::ty::Placeholder<crate::ty::BoundRegion>, crate::ty::Placeholder<crate::ty::BoundTy>, crate::ty::Placeholder<ty::BoundVar>, - crate::ty::ClosureKind, crate::ty::FreeRegion, crate::ty::InferTy, crate::ty::IntVarValue, - crate::ty::ParamConst, - crate::ty::ParamTy, crate::ty::adjustment::PointerCoercion, crate::ty::RegionVid, crate::ty::UniverseIndex, @@ -523,33 +506,30 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_span::Span, ::rustc_span::symbol::Ident, ::rustc_errors::ErrorGuaranteed, - interpret::Scalar, - interpret::AllocId, - rustc_target::abi::Size, ty::BoundVar, + ty::ValTree<'tcx>, } - +// For some things about which the type library does not know, or does not +// provide any traversal implementations, we need to provide a traversal +// implementation and a lift implementation (the former only for TyCtxt<'_> +// interners). TrivialTypeTraversalAndLiftImpls! { - ty::ValTree<'tcx>, + ::rustc_hir::def_id::DefId, + ::rustc_hir::Mutability, + ::rustc_hir::Unsafety, + ::rustc_target::spec::abi::Abi, + crate::ty::AliasRelationDirection, + crate::ty::ClosureKind, + crate::ty::ParamConst, + crate::ty::ParamTy, + interpret::Scalar, + interpret::AllocId, + rustc_target::abi::Size, } /////////////////////////////////////////////////////////////////////////// // Lift implementations -impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) { - type Lifted = (A::Lifted, B::Lifted); - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - Some((tcx.lift(self.0)?, tcx.lift(self.1)?)) - } -} - -impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C) { - type Lifted = (A::Lifted, B::Lifted, C::Lifted); - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - Some((tcx.lift(self.0)?, tcx.lift(self.1)?, tcx.lift(self.2)?)) - } -} - impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> { type Lifted = Option<T::Lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { @@ -560,50 +540,6 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> { } } -impl<'tcx, T: Lift<'tcx>, E: Lift<'tcx>> Lift<'tcx> for Result<T, E> { - type Lifted = Result<T::Lifted, E::Lifted>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - match self { - Ok(x) => tcx.lift(x).map(Ok), - Err(e) => tcx.lift(e).map(Err), - } - } -} - -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Box<T> { - type Lifted = Box<T::Lifted>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - Some(Box::new(tcx.lift(*self)?)) - } -} - -impl<'tcx, T: Lift<'tcx> + Clone> Lift<'tcx> for Rc<T> { - type Lifted = Rc<T::Lifted>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - Some(Rc::new(tcx.lift(self.as_ref().clone())?)) - } -} - -impl<'tcx, T: Lift<'tcx> + Clone> Lift<'tcx> for Arc<T> { - type Lifted = Arc<T::Lifted>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - Some(Arc::new(tcx.lift(self.as_ref().clone())?)) - } -} -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Vec<T> { - type Lifted = Vec<T::Lifted>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - self.into_iter().map(|v| tcx.lift(v)).collect() - } -} - -impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> { - type Lifted = IndexVec<I, T::Lifted>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - self.into_iter().map(|e| tcx.lift(e)).collect() - } -} - impl<'a, 'tcx> Lift<'tcx> for Term<'a> { type Lifted = ty::Term<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { @@ -616,13 +552,6 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { ) } } -impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { - type Lifted = ty::ParamEnv<'tcx>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - tcx.lift(self.caller_bounds()) - .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal())) - } -} /////////////////////////////////////////////////////////////////////////// // Traversal implementations. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2502e303f7a..edab7fe58ba 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -351,7 +351,7 @@ impl<'tcx> ClosureArgs<'tcx> { } /// Similar to `ClosureArgs`; see the above documentation for more. -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] pub struct GeneratorArgs<'tcx> { pub args: GenericArgsRef<'tcx>, } @@ -1305,7 +1305,7 @@ impl<'tcx> AliasTy<'tcx> { } } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct GenSig<'tcx> { pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 159cbb72a3b..69c4c588c44 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -654,7 +654,7 @@ rustc_index::newtype_index! { pub type CanonicalUserTypeAnnotations<'tcx> = IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>; -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct CanonicalUserTypeAnnotation<'tcx> { pub user_ty: Box<CanonicalUserType<'tcx>>, pub span: Span, @@ -714,7 +714,7 @@ impl<'tcx> CanonicalUserType<'tcx> { /// from constants that are named via paths, like `Foo::<A>::new` and /// so forth. #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] -#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum UserType<'tcx> { Ty(Ty<'tcx>), diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index b52827a1e88..fb33b3b49d3 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -105,25 +105,12 @@ impl<'tcx> MirLint<'tcx> for ConstProp { trace!("ConstProp starting for {:?}", def_id); - let dummy_body = &Body::new( - body.source, - (*body.basic_blocks).to_owned(), - body.source_scopes.clone(), - body.local_decls.clone(), - Default::default(), - body.arg_count, - Default::default(), - body.span, - body.generator_kind(), - body.tainted_by_errors, - ); - // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold // constants, instead of just checking for const-folding succeeding. // That would require a uniform one-def no-mutation analysis // and RPO (or recursing when needing the value of a local). - let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx); - optimization_finder.visit_body(body); + let mut linter = ConstPropagator::new(body, tcx); + linter.visit_body(body); trace!("ConstProp done for {:?}", def_id); } @@ -169,11 +156,7 @@ impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> { } impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { - fn new( - body: &Body<'tcx>, - dummy_body: &'mir Body<'tcx>, - tcx: TyCtxt<'tcx>, - ) -> ConstPropagator<'mir, 'tcx> { + fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> { let def_id = body.source.def_id(); let args = &GenericArgs::identity_for_item(tcx, def_id); let param_env = tcx.param_env_reveal_all_normalized(def_id); @@ -204,7 +187,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ecx.push_stack_frame( Instance::new(def_id, args), - dummy_body, + body, &ret, StackPopCleanup::Root { cleanup: false }, ) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 307c0516f70..51cb192a1e8 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -28,8 +28,8 @@ use std::ops::ControlFlow; use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; use super::inspect::ProofTreeBuilder; -use super::search_graph; use super::SolverMode; +use super::{search_graph, GoalEvaluationKind}; use super::{search_graph::SearchGraph, Goal}; pub use select::InferCtxtSelectExt; @@ -85,7 +85,7 @@ pub struct EvalCtxt<'a, 'tcx> { // evaluation code. tainted: Result<(), NoSolution>, - inspect: ProofTreeBuilder<'tcx>, + pub(super) inspect: ProofTreeBuilder<'tcx>, } #[derive(Debug, Clone)] @@ -164,7 +164,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { Option<inspect::GoalEvaluation<'tcx>>, ) { EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { - ecx.evaluate_goal(IsNormalizesToHack::No, goal) + ecx.evaluate_goal(GoalEvaluationKind::Root, goal) }) } } @@ -340,11 +340,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { /// been constrained and the certainty of the result. fn evaluate_goal( &mut self, - is_normalizes_to_hack: IsNormalizesToHack, + goal_evaluation_kind: GoalEvaluationKind, goal: Goal<'tcx, ty::Predicate<'tcx>>, ) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> { let (orig_values, canonical_goal) = self.canonicalize_goal(goal); - let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, is_normalizes_to_hack); + let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, goal_evaluation_kind); let encountered_overflow = self.search_graph.encountered_overflow(); let canonical_response = EvalCtxt::evaluate_canonical_goal( self.tcx(), @@ -389,7 +389,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // solver cycle. if cfg!(debug_assertions) && has_changed - && is_normalizes_to_hack == IsNormalizesToHack::No + && !matches!( + goal_evaluation_kind, + GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::Yes } + ) && !self.search_graph.in_cycle() { // The nested evaluation has to happen with the original state @@ -561,8 +564,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { }, ); - let (_, certainty, instantiate_goals) = - self.evaluate_goal(IsNormalizesToHack::Yes, unconstrained_goal)?; + let (_, certainty, instantiate_goals) = self.evaluate_goal( + GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::Yes }, + unconstrained_goal, + )?; self.add_goals(instantiate_goals); // Finally, equate the goal's RHS with the unconstrained var. @@ -596,8 +601,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } for goal in goals.goals.drain(..) { - let (has_changed, certainty, instantiate_goals) = - self.evaluate_goal(IsNormalizesToHack::No, goal)?; + let (has_changed, certainty, instantiate_goals) = self.evaluate_goal( + GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::No }, + goal, + )?; self.add_goals(instantiate_goals); if has_changed { unchanged_certainty = None; diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs index f88cfbac3f3..6087b916790 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs @@ -24,13 +24,13 @@ where search_graph: outer_ecx.search_graph, nested_goals: outer_ecx.nested_goals.clone(), tainted: outer_ecx.tainted, - inspect: outer_ecx.inspect.new_goal_candidate(), + inspect: outer_ecx.inspect.new_probe(), }; let r = nested_ecx.infcx.probe(|_| f(&mut nested_ecx)); if !outer_ecx.inspect.is_noop() { let probe_kind = probe_kind(&r); nested_ecx.inspect.probe_kind(probe_kind); - outer_ecx.inspect.goal_candidate(nested_ecx.inspect); + outer_ecx.inspect.finish_probe(nested_ecx.inspect); } r } diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect.rs index 46025da7683..749bba33c9b 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect.rs @@ -7,13 +7,13 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::DumpSolverProofTree; use super::eval_ctxt::UseGlobalCache; -use super::GenerateProofTree; +use super::{GenerateProofTree, GoalEvaluationKind}; #[derive(Eq, PartialEq, Debug)] pub struct WipGoalEvaluation<'tcx> { pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, + pub kind: WipGoalEvaluationKind, pub evaluation: Option<WipCanonicalGoalEvaluation<'tcx>>, - pub is_normalizes_to_hack: IsNormalizesToHack, pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>, } @@ -21,8 +21,13 @@ impl<'tcx> WipGoalEvaluation<'tcx> { pub fn finalize(self) -> inspect::GoalEvaluation<'tcx> { inspect::GoalEvaluation { uncanonicalized_goal: self.uncanonicalized_goal, + kind: match self.kind { + WipGoalEvaluationKind::Root => inspect::GoalEvaluationKind::Root, + WipGoalEvaluationKind::Nested { is_normalizes_to_hack } => { + inspect::GoalEvaluationKind::Nested { is_normalizes_to_hack } + } + }, evaluation: self.evaluation.unwrap().finalize(), - is_normalizes_to_hack: self.is_normalizes_to_hack, returned_goals: self.returned_goals, } } @@ -30,6 +35,12 @@ impl<'tcx> WipGoalEvaluation<'tcx> { #[derive(Eq, PartialEq, Debug)] pub enum WipGoalEvaluationKind { + Root, + Nested { is_normalizes_to_hack: IsNormalizesToHack }, +} + +#[derive(Eq, PartialEq, Debug)] +pub enum WipCanonicalGoalEvaluationKind { Overflow, CacheHit(CacheHit), } @@ -37,7 +48,7 @@ pub enum WipGoalEvaluationKind { #[derive(Eq, PartialEq, Debug)] pub struct WipCanonicalGoalEvaluation<'tcx> { pub goal: CanonicalInput<'tcx>, - pub kind: Option<WipGoalEvaluationKind>, + pub kind: Option<WipCanonicalGoalEvaluationKind>, pub revisions: Vec<WipGoalEvaluationStep<'tcx>>, pub result: Option<QueryResult<'tcx>>, } @@ -45,11 +56,13 @@ pub struct WipCanonicalGoalEvaluation<'tcx> { impl<'tcx> WipCanonicalGoalEvaluation<'tcx> { pub fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> { let kind = match self.kind { - Some(WipGoalEvaluationKind::Overflow) => inspect::GoalEvaluationKind::Overflow, - Some(WipGoalEvaluationKind::CacheHit(hit)) => { - inspect::GoalEvaluationKind::CacheHit(hit) + Some(WipCanonicalGoalEvaluationKind::Overflow) => { + inspect::CanonicalGoalEvaluationKind::Overflow } - None => inspect::GoalEvaluationKind::Uncached { + Some(WipCanonicalGoalEvaluationKind::CacheHit(hit)) => { + inspect::CanonicalGoalEvaluationKind::CacheHit(hit) + } + None => inspect::CanonicalGoalEvaluationKind::Uncached { revisions: self .revisions .into_iter() @@ -87,7 +100,7 @@ impl<'tcx> WipAddedGoalsEvaluation<'tcx> { pub struct WipGoalEvaluationStep<'tcx> { pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, - pub evaluation: WipGoalCandidate<'tcx>, + pub evaluation: WipProbe<'tcx>, } impl<'tcx> WipGoalEvaluationStep<'tcx> { @@ -102,26 +115,37 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> { } #[derive(Eq, PartialEq, Debug)] -pub struct WipGoalCandidate<'tcx> { - pub added_goals_evaluations: Vec<WipAddedGoalsEvaluation<'tcx>>, - pub candidates: Vec<WipGoalCandidate<'tcx>>, +pub struct WipProbe<'tcx> { + pub steps: Vec<WipProbeStep<'tcx>>, pub kind: Option<ProbeKind<'tcx>>, } -impl<'tcx> WipGoalCandidate<'tcx> { - pub fn finalize(self) -> inspect::GoalCandidate<'tcx> { - inspect::GoalCandidate { - added_goals_evaluations: self - .added_goals_evaluations - .into_iter() - .map(WipAddedGoalsEvaluation::finalize) - .collect(), - candidates: self.candidates.into_iter().map(WipGoalCandidate::finalize).collect(), +impl<'tcx> WipProbe<'tcx> { + pub fn finalize(self) -> inspect::Probe<'tcx> { + inspect::Probe { + steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(), kind: self.kind.unwrap(), } } } +#[derive(Eq, PartialEq, Debug)] +pub enum WipProbeStep<'tcx> { + AddGoal(Goal<'tcx, ty::Predicate<'tcx>>), + EvaluateGoals(WipAddedGoalsEvaluation<'tcx>), + NestedProbe(WipProbe<'tcx>), +} + +impl<'tcx> WipProbeStep<'tcx> { + pub fn finalize(self) -> inspect::ProbeStep<'tcx> { + match self { + WipProbeStep::AddGoal(goal) => inspect::ProbeStep::AddGoal(goal), + WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()), + WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()), + } + } +} + #[derive(Debug)] pub enum DebugSolver<'tcx> { Root, @@ -129,7 +153,7 @@ pub enum DebugSolver<'tcx> { CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<'tcx>), AddedGoalsEvaluation(WipAddedGoalsEvaluation<'tcx>), GoalEvaluationStep(WipGoalEvaluationStep<'tcx>), - GoalCandidate(WipGoalCandidate<'tcx>), + Probe(WipProbe<'tcx>), } impl<'tcx> From<WipGoalEvaluation<'tcx>> for DebugSolver<'tcx> { @@ -156,9 +180,9 @@ impl<'tcx> From<WipGoalEvaluationStep<'tcx>> for DebugSolver<'tcx> { } } -impl<'tcx> From<WipGoalCandidate<'tcx>> for DebugSolver<'tcx> { - fn from(g: WipGoalCandidate<'tcx>) -> DebugSolver<'tcx> { - DebugSolver::GoalCandidate(g) +impl<'tcx> From<WipProbe<'tcx>> for DebugSolver<'tcx> { + fn from(p: WipProbe<'tcx>) -> DebugSolver<'tcx> { + DebugSolver::Probe(p) } } @@ -249,15 +273,20 @@ impl<'tcx> ProofTreeBuilder<'tcx> { self.state.is_none() } - pub fn new_goal_evaluation( + pub(super) fn new_goal_evaluation( &mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>, - is_normalizes_to_hack: IsNormalizesToHack, + kind: GoalEvaluationKind, ) -> ProofTreeBuilder<'tcx> { self.nested(|| WipGoalEvaluation { uncanonicalized_goal: goal, + kind: match kind { + GoalEvaluationKind::Root => WipGoalEvaluationKind::Root, + GoalEvaluationKind::Nested { is_normalizes_to_hack } => { + WipGoalEvaluationKind::Nested { is_normalizes_to_hack } + } + }, evaluation: None, - is_normalizes_to_hack, returned_goals: vec![], }) } @@ -286,7 +315,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn goal_evaluation_kind(&mut self, kind: WipGoalEvaluationKind) { + pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -329,11 +358,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> { ) -> ProofTreeBuilder<'tcx> { self.nested(|| WipGoalEvaluationStep { instantiated_goal, - evaluation: WipGoalCandidate { - added_goals_evaluations: vec![], - candidates: vec![], - kind: None, - }, + evaluation: WipProbe { steps: vec![], kind: None }, }) } pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) { @@ -350,18 +375,14 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn new_goal_candidate(&mut self) -> ProofTreeBuilder<'tcx> { - self.nested(|| WipGoalCandidate { - added_goals_evaluations: vec![], - candidates: vec![], - kind: None, - }) + pub fn new_probe(&mut self) -> ProofTreeBuilder<'tcx> { + self.nested(|| WipProbe { steps: vec![], kind: None }) } pub fn probe_kind(&mut self, probe_kind: ProbeKind<'tcx>) { if let Some(this) = self.as_mut() { match this { - DebugSolver::GoalCandidate(this) => { + DebugSolver::Probe(this) => { assert_eq!(this.kind.replace(probe_kind), None) } _ => unreachable!(), @@ -369,17 +390,32 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } - pub fn goal_candidate(&mut self, candidate: ProofTreeBuilder<'tcx>) { + pub fn add_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) { if let Some(this) = self.as_mut() { - match (this, candidate.state.unwrap().tree) { + match this { + DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { + evaluation: WipProbe { steps, .. }, + .. + }) + | DebugSolver::Probe(WipProbe { steps, .. }) => { + steps.push(WipProbeStep::AddGoal(goal)) + } + _ => unreachable!(), + } + } + } + + pub fn finish_probe(&mut self, probe: ProofTreeBuilder<'tcx>) { + if let Some(this) = self.as_mut() { + match (this, probe.state.unwrap().tree) { ( - DebugSolver::GoalCandidate(WipGoalCandidate { candidates, .. }) + DebugSolver::Probe(WipProbe { steps, .. }) | DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { - evaluation: WipGoalCandidate { candidates, .. }, + evaluation: WipProbe { steps, .. }, .. }), - DebugSolver::GoalCandidate(candidate), - ) => candidates.push(candidate), + DebugSolver::Probe(probe), + ) => steps.push(WipProbeStep::NestedProbe(probe)), _ => unreachable!(), } } @@ -416,14 +452,12 @@ impl<'tcx> ProofTreeBuilder<'tcx> { match (this, added_goals_evaluation.state.unwrap().tree) { ( DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { - evaluation: WipGoalCandidate { added_goals_evaluations, .. }, + evaluation: WipProbe { steps, .. }, .. }) - | DebugSolver::GoalCandidate(WipGoalCandidate { - added_goals_evaluations, .. - }), + | DebugSolver::Probe(WipProbe { steps, .. }), DebugSolver::AddedGoalsEvaluation(added_goals_evaluation), - ) => added_goals_evaluations.push(added_goals_evaluation), + ) => steps.push(WipProbeStep::EvaluateGoals(added_goals_evaluation)), _ => unreachable!(), } } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index c492408bc76..bd612ce4778 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,7 +19,8 @@ use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::traits::query::NoSolution; use rustc_middle::infer::canonical::CanonicalVarInfos; use rustc_middle::traits::solve::{ - CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, Response, + CanonicalResponse, Certainty, ExternalConstraintsData, Goal, IsNormalizesToHack, QueryResult, + Response, }; use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{ @@ -59,6 +60,12 @@ enum SolverMode { Coherence, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum GoalEvaluationKind { + Root, + Nested { is_normalizes_to_hack: IsNormalizesToHack }, +} + trait CanonicalResponseExt { fn has_no_inference_or_external_constraints(&self) -> bool; @@ -228,6 +235,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { #[instrument(level = "debug", skip(self))] fn add_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) { + self.inspect.add_goal(goal); self.nested_goals.goals.push(goal); } diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index c816b51f67a..16de518e8e0 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -187,7 +187,7 @@ impl<'tcx> SearchGraph<'tcx> { last.encountered_overflow = true; } - inspect.goal_evaluation_kind(inspect::WipGoalEvaluationKind::Overflow); + inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); return Self::response_no_constraints(tcx, input, Certainty::OVERFLOW); }; @@ -203,7 +203,7 @@ impl<'tcx> SearchGraph<'tcx> { available_depth, ) { - inspect.goal_evaluation_kind(inspect::WipGoalEvaluationKind::CacheHit( + inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CacheHit( CacheHit::Global, )); self.on_cache_hit(reached_depth, encountered_overflow); @@ -240,7 +240,7 @@ impl<'tcx> SearchGraph<'tcx> { // Finally we can return either the provisional response for that goal if we have a // coinductive cycle or an ambiguous result if the cycle is inductive. Entry::Occupied(entry_index) => { - inspect.goal_evaluation_kind(inspect::WipGoalEvaluationKind::CacheHit( + inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CacheHit( CacheHit::Provisional, )); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 979498fb6e6..e415d70479e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -13,7 +13,7 @@ use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::DUMMY_SP; use smallvec::{smallvec, SmallVec}; -#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs index 59f4a22ac75..f2c1243f931 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs @@ -6,7 +6,7 @@ use crate::traits::ObligationCtxt; use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution}; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; -#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct DropckOutlives<'tcx> { dropped_ty: Ty<'tcx>, } diff --git a/config.example.toml b/config.example.toml index 2e0558c3f1b..f3c2366d674 100644 --- a/config.example.toml +++ b/config.example.toml @@ -458,7 +458,6 @@ changelog-seen = 2 # Sets the number of codegen units to build the standard library with, # regardless of what the codegen-unit setting for the rest of the compiler is. # NOTE: building with anything other than 1 is known to occasionally have bugs. -# See https://github.com/rust-lang/rust/issues/83600. #codegen-units-std = codegen-units # Whether or not debug assertions are enabled for the compiler and standard library. diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 739f0c360fd..33226b07e04 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1289,6 +1289,91 @@ pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) } +/// Compares and sorts two values, returning minimum and maximum. +/// +/// Returns `[v1, v2]` if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_minmax)] +/// use std::cmp; +/// +/// assert_eq!(cmp::minmax(1, 2), [1, 2]); +/// assert_eq!(cmp::minmax(2, 2), [2, 2]); +/// +/// // You can destructure the result using array patterns +/// let [min, max] = cmp::minmax(42, 17); +/// assert_eq!(min, 17); +/// assert_eq!(max, 42); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_minmax", issue = "115939")] +pub fn minmax<T>(v1: T, v2: T) -> [T; 2] +where + T: Ord, +{ + if v1 <= v2 { [v1, v2] } else { [v2, v1] } +} + +/// Returns minimum and maximum values with respect to the specified comparison function. +/// +/// Returns `[v1, v2]` if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_minmax)] +/// use std::cmp; +/// +/// assert_eq!(cmp::minmax_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [1, -2]); +/// assert_eq!(cmp::minmax_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [-2, 2]); +/// +/// // You can destructure the result using array patterns +/// let [min, max] = cmp::minmax_by(-42, 17, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(min, 17); +/// assert_eq!(max, -42); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_minmax", issue = "115939")] +pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2] +where + F: FnOnce(&T, &T) -> Ordering, +{ + if compare(&v1, &v2).is_le() { [v1, v2] } else { [v2, v1] } +} + +/// Returns minimum and maximum values with respect to the specified key function. +/// +/// Returns `[v1, v2]` if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_minmax)] +/// use std::cmp; +/// +/// assert_eq!(cmp::minmax_by_key(-2, 1, |x: &i32| x.abs()), [1, -2]); +/// assert_eq!(cmp::minmax_by_key(-2, 2, |x: &i32| x.abs()), [-2, 2]); +/// +/// // You can destructure the result using array patterns +/// let [min, max] = cmp::minmax_by_key(-42, 17, |x: &i32| x.abs()); +/// assert_eq!(min, 17); +/// assert_eq!(max, -42); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_minmax", issue = "115939")] +pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2] +where + F: FnMut(&T) -> K, + K: Ord, +{ + minmax_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types mod impls { use crate::cmp::Ordering::{self, Equal, Greater, Less}; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index e4c76226454..a9aa7524e8b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -312,6 +312,14 @@ def default_build_triple(verbose): # non-standard string (e.g. gnuwin32 tools returns `windows32`). In # these cases, fall back to using sys.platform. return 'x86_64-pc-windows-msvc' + elif kernel == 'AIX': + # `uname -m` returns the machine ID rather than machine hardware on AIX, + # so we are unable to use cputype to form triple. AIX 7.2 and + # above supports 32-bit and 64-bit mode simultaneously and `uname -p` + # returns `powerpc`, however we only supports `powerpc64-ibm-aix` in + # rust on AIX. For above reasons, kerneltype_mapper and cputype_mapper + # are not used to infer AIX's triple. + return 'powerpc64-ibm-aix' else: err = "unknown OS type: {}".format(kernel) sys.exit(err) diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile index b6b4fdc67a9..db11700af28 100644 --- a/src/ci/docker/host-x86_64/arm-android/Dockerfile +++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.10 +FROM ubuntu:23.04 ARG DEBIAN_FRONTEND=noninteractive COPY scripts/android-base-apt-get.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile index 9c6f648896b..b09b6edb01a 100644 --- a/src/ci/docker/host-x86_64/dist-android/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.10 +FROM ubuntu:23.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh diff --git a/src/ci/docker/host-x86_64/dist-various-1/install-x86_64-redox.sh b/src/ci/docker/host-x86_64/dist-various-1/install-x86_64-redox.sh index dad97922338..f86402b0180 100755 --- a/src/ci/docker/host-x86_64/dist-various-1/install-x86_64-redox.sh +++ b/src/ci/docker/host-x86_64/dist-various-1/install-x86_64-redox.sh @@ -2,5 +2,5 @@ set -ex -curl https://static.redox-os.org/toolchain/x86_64-unknown-redox/relibc-install.tar.gz | \ +curl https://ci-mirrors.rust-lang.org/rustc/2022-11-27-relibc-install.tar.gz | \ tar --extract --gzip --directory /usr/local diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index f6954275ad4..6f1b2a6a638 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -87,7 +87,7 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.lto=thin ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ - ./build/$HOSTS/stage0-tools-bin/opt-dist python3 ../x.py dist \ + ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ build-manifest bootstrap diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 89b82d59d31..1712d65ece9 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -624,7 +624,7 @@ jobs: --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths + SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c diff --git a/src/tools/cargo b/src/tools/cargo -Subproject d5336f813df39d476e61fc46daabb1446350660 +Subproject b4ddf95ad9954118ac0dae835f2966394ad04c0 diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index 3f7dba81c3a..f1c3dd6aa9b 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -21,3 +21,5 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" glob = "0.3" tempfile = "3.5" +derive_builder = "0.12" +clap = { version = "4", features = ["derive"] } diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs new file mode 100644 index 00000000000..ff782a1687e --- /dev/null +++ b/src/tools/opt-dist/src/environment.rs @@ -0,0 +1,108 @@ +use camino::Utf8PathBuf; +use derive_builder::Builder; + +#[derive(Builder)] +pub struct Environment { + host_triple: String, + python_binary: String, + /// The rustc checkout, where the compiler source is located. + checkout_dir: Utf8PathBuf, + /// The main directory where the build occurs. Stage0 rustc and cargo have to be available in + /// this directory before `opt-dist` is started. + build_dir: Utf8PathBuf, + /// Directory where the optimization artifacts (PGO/BOLT profiles, etc.) + /// will be stored. + artifact_dir: Utf8PathBuf, + /// Path to the host LLVM used to compile LLVM in `src/llvm-project`. + host_llvm_dir: Utf8PathBuf, + /// List of test paths that should be skipped when testing the optimized artifacts. + skipped_tests: Vec<String>, + /// Directory containing a pre-built rustc-perf checkout. + #[builder(default)] + prebuilt_rustc_perf: Option<Utf8PathBuf>, + use_bolt: bool, + shared_llvm: bool, +} + +impl Environment { + pub fn host_triple(&self) -> &str { + &self.host_triple + } + + pub fn python_binary(&self) -> &str { + &self.python_binary + } + + pub fn checkout_path(&self) -> Utf8PathBuf { + self.checkout_dir.clone() + } + + pub fn build_root(&self) -> Utf8PathBuf { + self.build_dir.clone() + } + + pub fn build_artifacts(&self) -> Utf8PathBuf { + self.build_root().join("build").join(&self.host_triple) + } + + pub fn artifact_dir(&self) -> Utf8PathBuf { + self.artifact_dir.clone() + } + + pub fn cargo_stage_0(&self) -> Utf8PathBuf { + self.build_artifacts() + .join("stage0") + .join("bin") + .join(format!("cargo{}", executable_extension())) + } + + pub fn rustc_stage_0(&self) -> Utf8PathBuf { + self.build_artifacts() + .join("stage0") + .join("bin") + .join(format!("rustc{}", executable_extension())) + } + + pub fn rustc_stage_2(&self) -> Utf8PathBuf { + self.build_artifacts() + .join("stage2") + .join("bin") + .join(format!("rustc{}", executable_extension())) + } + + pub fn prebuilt_rustc_perf(&self) -> Option<Utf8PathBuf> { + self.prebuilt_rustc_perf.clone() + } + + /// Path to the built rustc-perf benchmark suite. + pub fn rustc_perf_dir(&self) -> Utf8PathBuf { + self.artifact_dir.join("rustc-perf") + } + + pub fn host_llvm_dir(&self) -> Utf8PathBuf { + self.host_llvm_dir.clone() + } + + pub fn use_bolt(&self) -> bool { + self.use_bolt + } + + pub fn supports_shared_llvm(&self) -> bool { + self.shared_llvm + } + + pub fn skipped_tests(&self) -> &[String] { + &self.skipped_tests + } +} + +/// What is the extension of binary executables on this platform? +#[cfg(target_family = "unix")] +pub fn executable_extension() -> &'static str { + "" +} + +#[cfg(target_family = "windows")] +pub fn executable_extension() -> &'static str { + ".exe" +} diff --git a/src/tools/opt-dist/src/environment/linux.rs b/src/tools/opt-dist/src/environment/linux.rs deleted file mode 100644 index 58b7e6d2306..00000000000 --- a/src/tools/opt-dist/src/environment/linux.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::environment::Environment; -use crate::exec::cmd; -use crate::utils::io::copy_directory; -use camino::{Utf8Path, Utf8PathBuf}; - -pub(super) struct LinuxEnvironment; - -impl Environment for LinuxEnvironment { - fn python_binary(&self) -> &'static str { - "python3" - } - - fn checkout_path(&self) -> Utf8PathBuf { - Utf8PathBuf::from("/checkout") - } - - fn host_llvm_dir(&self) -> Utf8PathBuf { - Utf8PathBuf::from("/rustroot") - } - - fn opt_artifacts(&self) -> Utf8PathBuf { - Utf8PathBuf::from("/tmp/tmp-multistage/opt-artifacts") - } - - fn build_root(&self) -> Utf8PathBuf { - self.checkout_path().join("obj") - } - - fn prepare_rustc_perf(&self) -> anyhow::Result<()> { - // /tmp/rustc-perf comes from the x64 dist Dockerfile - copy_directory(Utf8Path::new("/tmp/rustc-perf"), &self.rustc_perf_dir())?; - cmd(&[self.cargo_stage_0().as_str(), "build", "-p", "collector"]) - .workdir(&self.rustc_perf_dir()) - .env("RUSTC", &self.rustc_stage_0().into_string()) - .env("RUSTC_BOOTSTRAP", "1") - .run()?; - Ok(()) - } - - fn supports_bolt(&self) -> bool { - true - } - - fn supports_shared_llvm(&self) -> bool { - true - } - - fn executable_extension(&self) -> &'static str { - "" - } - - fn skipped_tests(&self) -> &'static [&'static str] { - &[ - // Fails because of linker errors, as of June 2023. - "tests/ui/process/nofile-limit.rs", - ] - } -} diff --git a/src/tools/opt-dist/src/environment/mod.rs b/src/tools/opt-dist/src/environment/mod.rs deleted file mode 100644 index a8650fad011..00000000000 --- a/src/tools/opt-dist/src/environment/mod.rs +++ /dev/null @@ -1,77 +0,0 @@ -use camino::Utf8PathBuf; - -#[cfg(target_family = "unix")] -mod linux; -#[cfg(target_family = "windows")] -mod windows; - -pub trait Environment { - fn host_triple(&self) -> String { - std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing") - } - - fn python_binary(&self) -> &'static str; - - /// The rustc checkout, where the compiler source is located. - fn checkout_path(&self) -> Utf8PathBuf; - - /// Path to the host LLVM used to compile LLVM in `src/llvm-project`. - fn host_llvm_dir(&self) -> Utf8PathBuf; - - /// Directory where the optimization artifacts (PGO/BOLT profiles, etc.) - /// will be stored. - fn opt_artifacts(&self) -> Utf8PathBuf; - - /// The main directory where the build occurs. - fn build_root(&self) -> Utf8PathBuf; - - fn build_artifacts(&self) -> Utf8PathBuf { - self.build_root().join("build").join(self.host_triple()) - } - - fn cargo_stage_0(&self) -> Utf8PathBuf { - self.build_artifacts() - .join("stage0") - .join("bin") - .join(format!("cargo{}", self.executable_extension())) - } - - fn rustc_stage_0(&self) -> Utf8PathBuf { - self.build_artifacts() - .join("stage0") - .join("bin") - .join(format!("rustc{}", self.executable_extension())) - } - - fn rustc_stage_2(&self) -> Utf8PathBuf { - self.build_artifacts() - .join("stage2") - .join("bin") - .join(format!("rustc{}", self.executable_extension())) - } - - /// Path to the built rustc-perf benchmark suite. - fn rustc_perf_dir(&self) -> Utf8PathBuf { - self.opt_artifacts().join("rustc-perf") - } - - /// Download and/or compile rustc-perf. - fn prepare_rustc_perf(&self) -> anyhow::Result<()>; - - fn supports_bolt(&self) -> bool; - - fn supports_shared_llvm(&self) -> bool; - - /// What is the extension of binary executables in this environment? - fn executable_extension(&self) -> &'static str; - - /// List of test paths that should be skipped when testing the optimized artifacts. - fn skipped_tests(&self) -> &'static [&'static str]; -} - -pub fn create_environment() -> Box<dyn Environment> { - #[cfg(target_family = "unix")] - return Box::new(linux::LinuxEnvironment); - #[cfg(target_family = "windows")] - return Box::new(windows::WindowsEnvironment::new()); -} diff --git a/src/tools/opt-dist/src/environment/windows.rs b/src/tools/opt-dist/src/environment/windows.rs deleted file mode 100644 index 79399391798..00000000000 --- a/src/tools/opt-dist/src/environment/windows.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::environment::Environment; -use crate::exec::cmd; -use crate::utils::io::move_directory; -use crate::utils::retry_action; -use camino::Utf8PathBuf; -use std::io::Cursor; -use std::time::Duration; -use zip::ZipArchive; - -pub(super) struct WindowsEnvironment { - checkout_dir: Utf8PathBuf, -} - -impl WindowsEnvironment { - pub fn new() -> Self { - Self { checkout_dir: std::env::current_dir().unwrap().try_into().unwrap() } - } -} - -impl Environment for WindowsEnvironment { - fn python_binary(&self) -> &'static str { - "python" - } - - fn checkout_path(&self) -> Utf8PathBuf { - self.checkout_dir.clone() - } - - fn host_llvm_dir(&self) -> Utf8PathBuf { - self.checkout_path().join("citools").join("clang-rust") - } - - fn opt_artifacts(&self) -> Utf8PathBuf { - self.checkout_path().join("opt-artifacts") - } - - fn build_root(&self) -> Utf8PathBuf { - self.checkout_path() - } - - fn prepare_rustc_perf(&self) -> anyhow::Result<()> { - // FIXME: add some mechanism for synchronization of this commit SHA with - // Linux (which builds rustc-perf in a Dockerfile) - // rustc-perf version from 2023-05-30 - const PERF_COMMIT: &str = "8b2ac3042e1ff2c0074455a0a3618adef97156b1"; - - let url = format!("https://ci-mirrors.rust-lang.org/rustc/rustc-perf-{PERF_COMMIT}.zip"); - let client = reqwest::blocking::Client::builder() - .timeout(Duration::from_secs(60 * 2)) - .connect_timeout(Duration::from_secs(60 * 2)) - .build()?; - let response = retry_action( - || Ok(client.get(&url).send()?.error_for_status()?.bytes()?.to_vec()), - "Download rustc-perf archive", - 5, - )?; - - let mut archive = ZipArchive::new(Cursor::new(response))?; - archive.extract(self.rustc_perf_dir())?; - move_directory( - &self.rustc_perf_dir().join(format!("rustc-perf-{PERF_COMMIT}")), - &self.rustc_perf_dir(), - )?; - - cmd(&[self.cargo_stage_0().as_str(), "build", "-p", "collector"]) - .workdir(&self.rustc_perf_dir()) - .env("RUSTC", &self.rustc_stage_0().into_string()) - .env("RUSTC_BOOTSTRAP", "1") - .run()?; - - Ok(()) - } - - fn supports_bolt(&self) -> bool { - false - } - - fn supports_shared_llvm(&self) -> bool { - false - } - - fn executable_extension(&self) -> &'static str { - ".exe" - } - - fn skipped_tests(&self) -> &'static [&'static str] { - &[ - // Fails as of June 2023. - "tests\\codegen\\vec-shrink-panik.rs", - ] - } -} diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs index 4765dceb5dd..04e0184528a 100644 --- a/src/tools/opt-dist/src/exec.rs +++ b/src/tools/opt-dist/src/exec.rs @@ -96,7 +96,7 @@ pub struct Bootstrap { } impl Bootstrap { - pub fn build(env: &dyn Environment) -> Self { + pub fn build(env: &Environment) -> Self { let metrics_path = env.build_root().join("build").join("metrics.json"); let cmd = cmd(&[ env.python_binary(), @@ -114,7 +114,7 @@ impl Bootstrap { Self { cmd, metrics_path } } - pub fn dist(env: &dyn Environment, dist_args: &[String]) -> Self { + pub fn dist(env: &Environment, dist_args: &[String]) -> Self { let metrics_path = env.build_root().join("build").join("metrics.json"); let cmd = cmd(&dist_args.iter().map(|arg| arg.as_str()).collect::<Vec<_>>()) .env("RUST_BACKTRACE", "full"); diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 8ab19674d05..978e2dfa4e8 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -1,17 +1,22 @@ use crate::bolt::{bolt_optimize, with_bolt_instrumented}; use anyhow::Context; +use camino::{Utf8Path, Utf8PathBuf}; +use clap::Parser; use log::LevelFilter; +use std::io::Cursor; +use std::time::Duration; use utils::io; +use zip::ZipArchive; -use crate::environment::{create_environment, Environment}; -use crate::exec::Bootstrap; +use crate::environment::{Environment, EnvironmentBuilder}; +use crate::exec::{cmd, Bootstrap}; use crate::tests::run_tests; use crate::timer::Timer; use crate::training::{gather_llvm_bolt_profiles, gather_llvm_profiles, gather_rustc_profiles}; -use crate::utils::io::reset_directory; +use crate::utils::io::{copy_directory, move_directory, reset_directory}; use crate::utils::{ clear_llvm_files, format_env_variables, print_binary_sizes, print_free_disk_space, - with_log_group, + retry_action, with_log_group, }; mod bolt; @@ -23,24 +28,169 @@ mod timer; mod training; mod utils; +#[derive(clap::Parser, Debug)] +struct Args { + #[clap(subcommand)] + env: EnvironmentCmd, +} + +#[derive(clap::Parser, Clone, Debug)] +struct SharedArgs { + // Arguments passed to `x` to perform the final (dist) build. + build_args: Vec<String>, +} + +#[derive(clap::Parser, Clone, Debug)] +enum EnvironmentCmd { + /// Perform a custom local PGO/BOLT optimized build. + Local { + /// Target triple of the host. + #[arg(long)] + target_triple: String, + + /// Checkout directory of `rustc`. + #[arg(long)] + checkout_dir: Utf8PathBuf, + + /// Host LLVM installation directory. + #[arg(long)] + llvm_dir: Utf8PathBuf, + + /// Python binary to use in bootstrap invocations. + #[arg(long, default_value = "python3")] + python: String, + + /// Directory where artifacts (like PGO profiles or rustc-perf) of this workflow + /// will be stored. + #[arg(long, default_value = "opt-artifacts")] + artifact_dir: Utf8PathBuf, + + /// Is LLVM for `rustc` built in shared library mode? + #[arg(long, default_value_t = true)] + llvm_shared: bool, + + /// Should BOLT optimization be used? If yes, host LLVM must have BOLT binaries + /// (`llvm-bolt` and `merge-fdata`) available. + #[arg(long, default_value_t = false)] + use_bolt: bool, + + /// Tests that should be skipped when testing the optimized compiler. + #[arg(long)] + skipped_tests: Vec<String>, + + #[clap(flatten)] + shared: SharedArgs, + }, + /// Perform an optimized build on Linux CI, from inside Docker. + LinuxCi { + #[clap(flatten)] + shared: SharedArgs, + }, + /// Perform an optimized build on Windows CI, directly inside Github Actions. + WindowsCi { + #[clap(flatten)] + shared: SharedArgs, + }, +} + fn is_try_build() -> bool { std::env::var("DIST_TRY_BUILD").unwrap_or_else(|_| "0".to_string()) != "0" } +fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)> { + let (env, args) = match args.env { + EnvironmentCmd::Local { + target_triple, + checkout_dir, + llvm_dir, + python, + artifact_dir, + llvm_shared, + use_bolt, + skipped_tests, + shared, + } => { + let env = EnvironmentBuilder::default() + .host_triple(target_triple) + .python_binary(python) + .checkout_dir(checkout_dir.clone()) + .host_llvm_dir(llvm_dir) + .artifact_dir(artifact_dir) + .build_dir(checkout_dir) + .shared_llvm(llvm_shared) + .use_bolt(use_bolt) + .skipped_tests(skipped_tests) + .build()?; + + (env, shared.build_args) + } + EnvironmentCmd::LinuxCi { shared } => { + let target_triple = + std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing"); + + let checkout_dir = Utf8PathBuf::from("/checkout"); + let env = EnvironmentBuilder::default() + .host_triple(target_triple) + .python_binary("python3".to_string()) + .checkout_dir(checkout_dir.clone()) + .host_llvm_dir(Utf8PathBuf::from("/rustroot")) + .artifact_dir(Utf8PathBuf::from("/tmp/tmp-multistage/opt-artifacts")) + .build_dir(checkout_dir.join("obj")) + // /tmp/rustc-perf comes from the x64 dist Dockerfile + .prebuilt_rustc_perf(Some(Utf8PathBuf::from("/tmp/rustc-perf"))) + .shared_llvm(true) + .use_bolt(true) + .skipped_tests(vec![ + // Fails because of linker errors, as of June 2023. + "tests/ui/process/nofile-limit.rs".to_string(), + ]) + .build()?; + + (env, shared.build_args) + } + EnvironmentCmd::WindowsCi { shared } => { + let target_triple = + std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing"); + + let checkout_dir: Utf8PathBuf = std::env::current_dir()?.try_into()?; + let env = EnvironmentBuilder::default() + .host_triple(target_triple) + .python_binary("python".to_string()) + .checkout_dir(checkout_dir.clone()) + .host_llvm_dir(checkout_dir.join("citools").join("clang-rust")) + .artifact_dir(checkout_dir.join("opt-artifacts")) + .build_dir(checkout_dir) + .shared_llvm(false) + .use_bolt(false) + .skipped_tests(vec![ + // Fails as of June 2023. + "tests\\codegen\\vec-shrink-panik.rs".to_string(), + ]) + .build()?; + + (env, shared.build_args) + } + }; + Ok((env, args)) +} + fn execute_pipeline( - env: &dyn Environment, + env: &Environment, timer: &mut Timer, dist_args: Vec<String>, ) -> anyhow::Result<()> { - reset_directory(&env.opt_artifacts())?; + reset_directory(&env.artifact_dir())?; - with_log_group("Building rustc-perf", || env.prepare_rustc_perf())?; + with_log_group("Building rustc-perf", || match env.prebuilt_rustc_perf() { + Some(dir) => copy_rustc_perf(env, &dir), + None => download_rustc_perf(env), + })?; // Stage 1: Build PGO instrumented rustc // We use a normal build of LLVM, because gathering PGO profiles for LLVM and `rustc` at the // same time can cause issues, because the host and in-tree LLVM versions can diverge. let rustc_pgo_profile = timer.section("Stage 1 (Rustc PGO)", |stage| { - let rustc_profile_dir_root = env.opt_artifacts().join("rustc-pgo"); + let rustc_profile_dir_root = env.artifact_dir().join("rustc-pgo"); stage.section("Build PGO instrumented rustc and LLVM", |section| { let mut builder = Bootstrap::build(env).rustc_pgo_instrument(&rustc_profile_dir_root); @@ -74,7 +224,7 @@ fn execute_pipeline( // Remove the previous, uninstrumented build of LLVM. clear_llvm_files(env)?; - let llvm_profile_dir_root = env.opt_artifacts().join("llvm-pgo"); + let llvm_profile_dir_root = env.artifact_dir().join("llvm-pgo"); stage.section("Build PGO instrumented LLVM", |section| { Bootstrap::build(env) @@ -95,7 +245,7 @@ fn execute_pipeline( Ok(profile) })?; - let llvm_bolt_profile = if env.supports_bolt() { + let llvm_bolt_profile = if env.use_bolt() { // Stage 3: Build BOLT instrumented LLVM // We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles. // Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build. @@ -171,8 +321,9 @@ fn main() -> anyhow::Result<()> { .parse_default_env() .init(); - let mut build_args: Vec<String> = std::env::args().skip(1).collect(); - println!("Running optimized build pipeline with args `{}`", build_args.join(" ")); + let args = Args::parse(); + + println!("Running optimized build pipeline with args `{:?}`", args); with_log_group("Environment values", || { println!("Environment values\n{}", format_env_variables()); @@ -184,6 +335,8 @@ fn main() -> anyhow::Result<()> { } }); + let (env, mut build_args) = create_environment(args).context("Cannot create environment")?; + // Skip components that are not needed for try builds to speed them up if is_try_build() { log::info!("Skipping building of unimportant components for a try build"); @@ -202,14 +355,58 @@ fn main() -> anyhow::Result<()> { } let mut timer = Timer::new(); - let env = create_environment(); - let result = execute_pipeline(env.as_ref(), &mut timer, build_args); + let result = execute_pipeline(&env, &mut timer, build_args); log::info!("Timer results\n{}", timer.format_stats()); print_free_disk_space()?; result.context("Optimized build pipeline has failed")?; - print_binary_sizes(env.as_ref())?; + print_binary_sizes(&env)?; + + Ok(()) +} + +// Copy rustc-perf from the given path into the environment and build it. +fn copy_rustc_perf(env: &Environment, dir: &Utf8Path) -> anyhow::Result<()> { + copy_directory(dir, &env.rustc_perf_dir())?; + build_rustc_perf(env) +} + +// Download and build rustc-perf into the given environment. +fn download_rustc_perf(env: &Environment) -> anyhow::Result<()> { + reset_directory(&env.rustc_perf_dir())?; + + // FIXME: add some mechanism for synchronization of this commit SHA with + // Linux (which builds rustc-perf in a Dockerfile) + // rustc-perf version from 2023-05-30 + const PERF_COMMIT: &str = "8b2ac3042e1ff2c0074455a0a3618adef97156b1"; + + let url = format!("https://ci-mirrors.rust-lang.org/rustc/rustc-perf-{PERF_COMMIT}.zip"); + let client = reqwest::blocking::Client::builder() + .timeout(Duration::from_secs(60 * 2)) + .connect_timeout(Duration::from_secs(60 * 2)) + .build()?; + let response = retry_action( + || Ok(client.get(&url).send()?.error_for_status()?.bytes()?.to_vec()), + "Download rustc-perf archive", + 5, + )?; + + let mut archive = ZipArchive::new(Cursor::new(response))?; + archive.extract(env.rustc_perf_dir())?; + move_directory( + &env.rustc_perf_dir().join(format!("rustc-perf-{PERF_COMMIT}")), + &env.rustc_perf_dir(), + )?; + + build_rustc_perf(env) +} +fn build_rustc_perf(env: &Environment) -> anyhow::Result<()> { + cmd(&[env.cargo_stage_0().as_str(), "build", "-p", "collector"]) + .workdir(&env.rustc_perf_dir()) + .env("RUSTC", &env.rustc_stage_0().into_string()) + .env("RUSTC_BOOTSTRAP", "1") + .run()?; Ok(()) } diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 3dd1a3223f5..31aabca09f3 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -1,11 +1,11 @@ -use crate::environment::Environment; +use crate::environment::{executable_extension, Environment}; use crate::exec::cmd; use crate::utils::io::{copy_directory, find_file_in_dir, unpack_archive}; use anyhow::Context; use camino::{Utf8Path, Utf8PathBuf}; /// Run tests on optimized dist artifacts. -pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { +pub fn run_tests(env: &Environment) -> anyhow::Result<()> { // After `dist` is executed, we extract its archived components into a sysroot directory, // and then use that extracted rustc as a stage0 compiler. // Then we run a subset of tests using that compiler, to have a basic smoke test which checks @@ -33,8 +33,8 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { // We need to manually copy libstd to the extracted rustc sysroot copy_directory( - &libstd_dir.join("lib").join("rustlib").join(&host_triple).join("lib"), - &rustc_dir.join("lib").join("rustlib").join(&host_triple).join("lib"), + &libstd_dir.join("lib").join("rustlib").join(host_triple).join("lib"), + &rustc_dir.join("lib").join("rustlib").join(host_triple).join("lib"), )?; // Extract sources - they aren't in the `rustc-nightly-{host}` tarball, so we need to manually copy libstd @@ -45,9 +45,9 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { &rustc_dir.join("lib").join("rustlib").join("src"), )?; - let rustc_path = rustc_dir.join("bin").join(format!("rustc{}", env.executable_extension())); + let rustc_path = rustc_dir.join("bin").join(format!("rustc{}", executable_extension())); assert!(rustc_path.is_file()); - let cargo_path = cargo_dir.join("bin").join(format!("cargo{}", env.executable_extension())); + let cargo_path = cargo_dir.join("bin").join(format!("cargo{}", executable_extension())); assert!(cargo_path.is_file()); // Specify path to a LLVM config so that LLVM is not rebuilt. @@ -56,7 +56,7 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { .build_artifacts() .join("llvm") .join("bin") - .join(format!("llvm-config{}", env.executable_extension())); + .join(format!("llvm-config{}", executable_extension())); assert!(llvm_config.is_file()); let config_content = format!( @@ -109,6 +109,6 @@ fn find_dist_version(directory: &Utf8Path) -> anyhow::Result<String> { .unwrap() .to_string(); let (version, _) = - archive.strip_prefix("reproducible-artifacts-").unwrap().split_once("-").unwrap(); + archive.strip_prefix("reproducible-artifacts-").unwrap().split_once('-').unwrap(); Ok(version.to_string()) } diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index 59c73fbd695..274f4cea0ab 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -1,4 +1,4 @@ -use crate::environment::Environment; +use crate::environment::{executable_extension, Environment}; use crate::exec::{cmd, CmdBuilder}; use crate::utils::io::{count_files, delete_directory}; use crate::utils::with_log_group; @@ -30,7 +30,7 @@ const RUSTC_PGO_CRATES: &[&str] = &[ const LLVM_BOLT_CRATES: &[&str] = LLVM_PGO_CRATES; fn init_compiler_benchmarks( - env: &dyn Environment, + env: &Environment, profiles: &[&str], scenarios: &[&str], crates: &[&str], @@ -75,7 +75,7 @@ enum LlvmProfdata { } fn merge_llvm_profiles( - env: &dyn Environment, + env: &Environment, merged_path: &Utf8Path, profile_dir: &Utf8Path, profdata: LlvmProfdata, @@ -86,7 +86,7 @@ fn merge_llvm_profiles( .build_artifacts() .join("llvm") .join("build") - .join(format!("bin/llvm-profdata{}", env.executable_extension())), + .join(format!("bin/llvm-profdata{}", executable_extension())), }; cmd(&[llvm_profdata.as_str(), "merge", "-o", merged_path.as_str(), profile_dir.as_str()]) @@ -116,7 +116,7 @@ fn log_profile_stats( pub struct LlvmPGOProfile(pub Utf8PathBuf); pub fn gather_llvm_profiles( - env: &dyn Environment, + env: &Environment, profile_root: &Utf8Path, ) -> anyhow::Result<LlvmPGOProfile> { log::info!("Running benchmarks with PGO instrumented LLVM"); @@ -127,7 +127,7 @@ pub fn gather_llvm_profiles( .context("Cannot gather LLVM PGO profiles") })?; - let merged_profile = env.opt_artifacts().join("llvm-pgo.profdata"); + let merged_profile = env.artifact_dir().join("llvm-pgo.profdata"); log::info!("Merging LLVM PGO profiles to {merged_profile}"); merge_llvm_profiles(env, &merged_profile, profile_root, LlvmProfdata::Host)?; @@ -143,7 +143,7 @@ pub fn gather_llvm_profiles( pub struct RustcPGOProfile(pub Utf8PathBuf); pub fn gather_rustc_profiles( - env: &dyn Environment, + env: &Environment, profile_root: &Utf8Path, ) -> anyhow::Result<RustcPGOProfile> { log::info!("Running benchmarks with PGO instrumented rustc"); @@ -163,7 +163,7 @@ pub fn gather_rustc_profiles( .context("Cannot gather rustc PGO profiles") })?; - let merged_profile = env.opt_artifacts().join("rustc-pgo.profdata"); + let merged_profile = env.artifact_dir().join("rustc-pgo.profdata"); log::info!("Merging Rustc PGO profiles to {merged_profile}"); merge_llvm_profiles(env, &merged_profile, profile_root, LlvmProfdata::Target)?; @@ -178,7 +178,7 @@ pub fn gather_rustc_profiles( pub struct LlvmBoltProfile(pub Utf8PathBuf); -pub fn gather_llvm_bolt_profiles(env: &dyn Environment) -> anyhow::Result<LlvmBoltProfile> { +pub fn gather_llvm_bolt_profiles(env: &Environment) -> anyhow::Result<LlvmBoltProfile> { log::info!("Running benchmarks with BOLT instrumented LLVM"); with_log_group("Running benchmarks", || { @@ -187,12 +187,12 @@ pub fn gather_llvm_bolt_profiles(env: &dyn Environment) -> anyhow::Result<LlvmBo .context("Cannot gather LLVM BOLT profiles") })?; - let merged_profile = env.opt_artifacts().join("llvm-bolt.profdata"); + let merged_profile = env.artifact_dir().join("llvm-bolt.profdata"); let profile_root = Utf8PathBuf::from("/tmp/prof.fdata"); log::info!("Merging LLVM BOLT profiles to {merged_profile}"); let profiles: Vec<_> = - glob::glob(&format!("{profile_root}*"))?.into_iter().collect::<Result<Vec<_>, _>>()?; + glob::glob(&format!("{profile_root}*"))?.collect::<Result<Vec<_>, _>>()?; let mut merge_args = vec!["merge-fdata"]; merge_args.extend(profiles.iter().map(|p| p.to_str().unwrap())); diff --git a/src/tools/opt-dist/src/utils/io.rs b/src/tools/opt-dist/src/utils/io.rs index 8bd516fa349..d6bd5cb85e4 100644 --- a/src/tools/opt-dist/src/utils/io.rs +++ b/src/tools/opt-dist/src/utils/io.rs @@ -7,7 +7,7 @@ use std::path::Path; /// Delete and re-create the directory. pub fn reset_directory(path: &Utf8Path) -> anyhow::Result<()> { log::info!("Resetting directory {path}"); - let _ = std::fs::remove_dir(path); + let _ = std::fs::remove_dir_all(path); std::fs::create_dir_all(path)?; Ok(()) } @@ -63,7 +63,6 @@ pub fn get_files_from_dir( let path = format!("{dir}/*{}", suffix.unwrap_or("")); Ok(glob::glob(&path)? - .into_iter() .map(|p| p.map(|p| Utf8PathBuf::from_path_buf(p).unwrap())) .collect::<Result<Vec<_>, _>>()?) } @@ -74,9 +73,8 @@ pub fn find_file_in_dir( prefix: &str, suffix: &str, ) -> anyhow::Result<Utf8PathBuf> { - let files = glob::glob(&format!("{directory}/{prefix}*{suffix}"))? - .into_iter() - .collect::<Result<Vec<_>, _>>()?; + let files = + glob::glob(&format!("{directory}/{prefix}*{suffix}"))?.collect::<Result<Vec<_>, _>>()?; match files.len() { 0 => Err(anyhow::anyhow!("No file with prefix {prefix} found in {directory}")), 1 => Ok(Utf8PathBuf::from_path_buf(files[0].clone()).unwrap()), diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs index 2af28077ed1..6fc96592a88 100644 --- a/src/tools/opt-dist/src/utils/mod.rs +++ b/src/tools/opt-dist/src/utils/mod.rs @@ -26,7 +26,7 @@ pub fn print_free_disk_space() -> anyhow::Result<()> { Ok(()) } -pub fn print_binary_sizes(env: &dyn Environment) -> anyhow::Result<()> { +pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> { use std::fmt::Write; let root = env.build_artifacts().join("stage2"); @@ -48,7 +48,7 @@ pub fn print_binary_sizes(env: &dyn Environment) -> anyhow::Result<()> { Ok(()) } -pub fn clear_llvm_files(env: &dyn Environment) -> anyhow::Result<()> { +pub fn clear_llvm_files(env: &Environment) -> anyhow::Result<()> { // Bootstrap currently doesn't support rebuilding LLVM when PGO options // change (or any other llvm-related options); so just clear out the relevant // directories ourselves. diff --git a/triagebot.toml b/triagebot.toml index d9d523bef39..d35e81c277e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -585,7 +585,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514"] +users_on_vacation = ["jyn514", "jackh726"] [assign.adhoc_groups] compiler-team = [ |
