From f94fa6bee3bf1c7d313452db0bafbce0960196ff Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 7 May 2024 18:08:36 -0600 Subject: [PATCH 01/36] Some Result combinations work like an Option. --- library/core/src/result.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b2b627fe6a9c..16c97284104d 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -224,6 +224,21 @@ //! [`Err(E)`]: Err //! [io::Error]: ../../std/io/struct.Error.html "io::Error" //! +//! # Representation +//! +//! In some cases, [`Result`] will gain the same size, alignment, and ABI +//! guarantees as [`Option`] has. One of either the `T` or `E` type must be a +//! type that qualifies for `Option` guarantees, and the *other* type must meet +//! all of the following conditions: +//! * Is a zero-sized type with alignment 1 (a "1-ZST"). +//! * Has no fields. +//! * Does not have the #[non_exhaustive] attribute. +//! +//! For example, `Result` or `Result<(), NonZeroI32>` would both +//! have the same guarantees as `Option`. The only difference is the +//! implied semantics: `Result` is "a non-zero success value" +//! while `Result<(), NonZeroI32>` is "a non-zero error value". +//! //! # Method overview //! //! In addition to working with pattern matching, [`Result`] provides a From 10f8d1ffef464d8c6cc8add49f5850cf8a33cfb3 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 7 May 2024 18:35:00 -0600 Subject: [PATCH 02/36] use teletype on the attribute name --- library/core/src/result.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 16c97284104d..b82351ea1fa3 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -232,7 +232,7 @@ //! all of the following conditions: //! * Is a zero-sized type with alignment 1 (a "1-ZST"). //! * Has no fields. -//! * Does not have the #[non_exhaustive] attribute. +//! * Does not have the `#[non_exhaustive]` attribute. //! //! For example, `Result` or `Result<(), NonZeroI32>` would both //! have the same guarantees as `Option`. The only difference is the From b468f21051d9562175e6eba0da40c9091d1b903e Mon Sep 17 00:00:00 2001 From: Lokathor Date: Mon, 13 May 2024 10:36:42 -0600 Subject: [PATCH 03/36] Don't use `T` with both Result and Option, improve explanation. --- library/core/src/result.rs | 137 +++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b82351ea1fa3..6a77f9f63a88 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1,9 +1,9 @@ //! Error handling with the `Result` type. //! //! [`Result`][`Result`] is the type used for returning and propagating -//! errors. It is an enum with the variants, [`Ok(T)`], representing -//! success and containing a value, and [`Err(E)`], representing error -//! and containing an error value. +//! errors. It is an enum with the variants, [`Ok(T)`], representing success and +//! containing a value, and [`Err(E)`], representing error and containing an +//! error value. //! //! ``` //! # #[allow(dead_code)] @@ -13,12 +13,11 @@ //! } //! ``` //! -//! Functions return [`Result`] whenever errors are expected and -//! recoverable. In the `std` crate, [`Result`] is most prominently used -//! for [I/O](../../std/io/index.html). +//! Functions return [`Result`] whenever errors are expected and recoverable. In +//! the `std` crate, [`Result`] is most prominently used for +//! [I/O](../../std/io/index.html). //! -//! A simple function returning [`Result`] might be -//! defined and used like so: +//! A simple function returning [`Result`] might be defined and used like so: //! //! ``` //! #[derive(Debug)] @@ -40,9 +39,9 @@ //! } //! ``` //! -//! Pattern matching on [`Result`]s is clear and straightforward for -//! simple cases, but [`Result`] comes with some convenience methods -//! that make working with it more succinct. +//! Pattern matching on [`Result`]s is clear and straightforward for simple +//! cases, but [`Result`] comes with some convenience methods that make working +//! with it more succinct. //! //! ``` //! let good_result: Result = Ok(10); @@ -68,16 +67,15 @@ //! //! # Results must be used //! -//! A common problem with using return values to indicate errors is -//! that it is easy to ignore the return value, thus failing to handle -//! the error. [`Result`] is annotated with the `#[must_use]` attribute, -//! which will cause the compiler to issue a warning when a Result -//! value is ignored. This makes [`Result`] especially useful with -//! functions that may encounter errors but don't otherwise return a -//! useful value. +//! A common problem with using return values to indicate errors is that it is +//! easy to ignore the return value, thus failing to handle the error. +//! [`Result`] is annotated with the `#[must_use]` attribute, which will cause +//! the compiler to issue a warning when a Result value is ignored. This makes +//! [`Result`] especially useful with functions that may encounter errors but +//! don't otherwise return a useful value. //! -//! Consider the [`write_all`] method defined for I/O types -//! by the [`Write`] trait: +//! Consider the [`write_all`] method defined for I/O types by the [`Write`] +//! trait: //! //! ``` //! use std::io; @@ -87,12 +85,11 @@ //! } //! ``` //! -//! *Note: The actual definition of [`Write`] uses [`io::Result`], which -//! is just a synonym for [Result].* +//! *Note: The actual definition of [`Write`] uses [`io::Result`], which is just +//! a synonym for [Result].* //! -//! This method doesn't produce a value, but the write may -//! fail. It's crucial to handle the error case, and *not* write -//! something like this: +//! This method doesn't produce a value, but the write may fail. It's crucial to +//! handle the error case, and *not* write something like this: //! //! ```no_run //! # #![allow(unused_must_use)] // \o/ @@ -105,12 +102,12 @@ //! file.write_all(b"important message"); //! ``` //! -//! If you *do* write that in Rust, the compiler will give you a -//! warning (by default, controlled by the `unused_must_use` lint). +//! If you *do* write that in Rust, the compiler will give you a warning (by +//! default, controlled by the `unused_must_use` lint). //! -//! You might instead, if you don't want to handle the error, simply -//! assert success with [`expect`]. This will panic if the -//! write fails, providing a marginally useful message indicating why: +//! You might instead, if you don't want to handle the error, simply assert +//! success with [`expect`]. This will panic if the write fails, providing a +//! marginally useful message indicating why: //! //! ```no_run //! use std::fs::File; @@ -145,10 +142,9 @@ //! //! # The question mark operator, `?` //! -//! When writing code that calls many functions that return the -//! [`Result`] type, the error handling can be tedious. The question mark -//! operator, [`?`], hides some of the boilerplate of propagating errors -//! up the call stack. +//! When writing code that calls many functions that return the [`Result`] type, +//! the error handling can be tedious. The question mark operator, [`?`], hides +//! some of the boilerplate of propagating errors up the call stack. //! //! It replaces this: //! @@ -209,15 +205,17 @@ //! //! *It's much nicer!* //! -//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result -//! is [`Err`], in which case [`Err`] is returned early from the enclosing function. +//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped +//! value, unless the result is [`Err`], in which case [`Err`] is returned early +//! from the enclosing function. //! -//! [`?`] can be used in functions that return [`Result`] because of the -//! early return of [`Err`] that it provides. +//! [`?`] can be used in functions that return [`Result`] because of the early +//! return of [`Err`] that it provides. //! //! [`expect`]: Result::expect //! [`Write`]: ../../std/io/trait.Write.html "io::Write" -//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all "io::Write::write_all" +//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all +//! "io::Write::write_all" //! [`io::Result`]: ../../std/io/type.Result.html "io::Result" //! [`?`]: crate::ops::Try //! [`Ok(T)`]: Ok @@ -227,27 +225,33 @@ //! # Representation //! //! In some cases, [`Result`] will gain the same size, alignment, and ABI -//! guarantees as [`Option`] has. One of either the `T` or `E` type must be a -//! type that qualifies for `Option` guarantees, and the *other* type must meet -//! all of the following conditions: +//! guarantees as [`Option`] has. One of either the `T` or `E` type must be a +//! type that qualifies for the `Option` [representation guarantees][opt-rep], +//! and the *other* type must meet all of the following conditions: //! * Is a zero-sized type with alignment 1 (a "1-ZST"). //! * Has no fields. //! * Does not have the `#[non_exhaustive]` attribute. //! -//! For example, `Result` or `Result<(), NonZeroI32>` would both -//! have the same guarantees as `Option`. The only difference is the -//! implied semantics: `Result` is "a non-zero success value" -//! while `Result<(), NonZeroI32>` is "a non-zero error value". +//! For example, `NonZeroI32` qualifies for the `Option` representation +//! guarantees, and `()` is a zero-sized type with alignment 1, no fields, and +//! it isn't `non_exhaustive`. This means that both `Result` and +//! `Result<(), NonZeroI32>` have the same size, alignment, and ABI guarantees +//! as `Option`. The only difference is the implied semantics: +//! * `Option` is "a non-zero i32 might be present" +//! * `Result` is "a non-zero i32 success result, if any" +//! * `Result<(), NonZeroI32>` is "a non-zero i32 error result, if any" +//! +//! [opt-rep]: ../option/index.html#representation "Option Representation" //! //! # Method overview //! -//! In addition to working with pattern matching, [`Result`] provides a -//! wide variety of different methods. +//! In addition to working with pattern matching, [`Result`] provides a wide +//! variety of different methods. //! //! ## Querying the variant //! -//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] -//! is [`Ok`] or [`Err`], respectively. +//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] is +//! [`Ok`] or [`Err`], respectively. //! //! [`is_err`]: Result::is_err //! [`is_ok`]: Result::is_ok @@ -257,8 +261,8 @@ //! * [`as_ref`] converts from `&Result` to `Result<&T, &E>` //! * [`as_mut`] converts from `&mut Result` to `Result<&mut T, &mut E>` //! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` -//! * [`as_deref_mut`] converts from `&mut Result` to -//! `Result<&mut T::Target, &mut E>` +//! * [`as_deref_mut`] converts from `&mut Result` to `Result<&mut +//! T::Target, &mut E>` //! //! [`as_deref`]: Result::as_deref //! [`as_deref_mut`]: Result::as_deref_mut @@ -267,19 +271,18 @@ //! //! ## Extracting contained values //! -//! These methods extract the contained value in a [`Result`] when it -//! is the [`Ok`] variant. If the [`Result`] is [`Err`]: +//! These methods extract the contained value in a [`Result`] when it is +//! the [`Ok`] variant. If the [`Result`] is [`Err`]: //! //! * [`expect`] panics with a provided custom message //! * [`unwrap`] panics with a generic message //! * [`unwrap_or`] returns the provided default value -//! * [`unwrap_or_default`] returns the default value of the type `T` -//! (which must implement the [`Default`] trait) -//! * [`unwrap_or_else`] returns the result of evaluating the provided -//! function +//! * [`unwrap_or_default`] returns the default value of the type `T` (which +//! must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided function //! -//! The panicking methods [`expect`] and [`unwrap`] require `E` to -//! implement the [`Debug`] trait. +//! The panicking methods [`expect`] and [`unwrap`] require `E` to implement the +//! [`Debug`] trait. //! //! [`Debug`]: crate::fmt::Debug //! [`expect`]: Result::expect @@ -288,9 +291,9 @@ //! [`unwrap_or_default`]: Result::unwrap_or_default //! [`unwrap_or_else`]: Result::unwrap_or_else //! -//! These methods extract the contained value in a [`Result`] when it -//! is the [`Err`] variant. They require `T` to implement the [`Debug`] -//! trait. If the [`Result`] is [`Ok`]: +//! These methods extract the contained value in a [`Result`] when it is +//! the [`Err`] variant. They require `T` to implement the [`Debug`] trait. If +//! the [`Result`] is [`Ok`]: //! //! * [`expect_err`] panics with a provided custom message //! * [`unwrap_err`] panics with a generic message @@ -305,10 +308,10 @@ //! //! * [`err`][Result::err] transforms [`Result`] into [`Option`], //! mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`] -//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], -//! mapping [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] -//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an -//! [`Option`] of a [`Result`] +//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], mapping +//! [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] +//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an [`Option`] +//! of a [`Result`] //! // Do NOT add link reference definitions for `err` or `ok`, because they // will generate numerous incorrect URLs for `Err` and `Ok` elsewhere, due From 17bd43cb250ff3bf0c29d021e232969d9d1765fa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 15 May 2024 17:33:26 +0200 Subject: [PATCH 04/36] codegen: tweak/extend shift comments --- compiler/rustc_codegen_ssa/src/base.rs | 9 +++++---- compiler/rustc_codegen_ssa/src/traits/builder.rs | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 877e5b75912e..e7cc2cb1a0b5 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -293,12 +293,13 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -/// Returns `rhs` sufficiently masked, truncated, and/or extended so that -/// it can be used to shift `lhs`. +/// Returns `rhs` sufficiently masked, truncated, and/or extended so that it can be used to shift +/// `lhs`: it has the same size as `lhs`, and the value, when interpreted unsigned (no matter its +/// type), will not exceed the size of `lhs`. /// -/// Shifts in MIR are all allowed to have mismatched LHS & RHS types. +/// Shifts in MIR are all allowed to have mismatched LHS & RHS types, and signed RHS. /// The shift methods in `BuilderMethods`, however, are fully homogeneous -/// (both parameters and the return type are all the same type). +/// (both parameters and the return type are all the same size) and assume an unsigned RHS. /// /// If `is_unchecked` is false, this masks the RHS to ensure it stays in-bounds, /// as the `BuilderMethods` shifts are UB for out-of-bounds shift amounts. diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index fdeccb907008..11a8d218ae3d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -110,8 +110,16 @@ pub trait BuilderMethods<'a, 'tcx>: fn frem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn frem_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn frem_algebraic(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; + /// Generate a left-shift. Both operands must have the same size. The right operand must be + /// interpreted as unsigned and can be assumed to be less than the size of the left operand. fn shl(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; + /// Generate a logical right-shift. Both operands must have the same size. The right operand + /// must be interpreted as unsigned and can be assumed to be less than the size of the left + /// operand. fn lshr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; + /// Generate an arithmetic right-shift. Both operands must have the same size. The right operand + /// must be interpreted as unsigned and can be assumed to be less than the size of the left + /// operand. fn ashr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; From c8b0e5b1a4698576b3d3637783cc3aeb09c74b1f Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 20 May 2024 20:37:28 +0200 Subject: [PATCH 05/36] The number of tests does not depend on the architecture's pointer width Use `u32` instead of `usize` for counting them. --- src/tools/tidy/src/ui_tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 37324639edfc..055d620361fb 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -12,10 +12,10 @@ use std::path::{Path, PathBuf}; // should all be 1000 or lower. Limits significantly smaller than 1000 are also // desirable, because large numbers of files are unwieldy in general. See issue // #73494. -const ENTRY_LIMIT: usize = 900; +const ENTRY_LIMIT: u32 = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1676; +const ISSUES_ENTRY_LIMIT: u32 = 1676; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files @@ -53,7 +53,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ ]; fn check_entries(tests_path: &Path, bad: &mut bool) { - let mut directories: HashMap = HashMap::new(); + let mut directories: HashMap = HashMap::new(); for dir in Walk::new(&tests_path.join("ui")) { if let Ok(entry) = dir { @@ -62,7 +62,7 @@ fn check_entries(tests_path: &Path, bad: &mut bool) { } } - let (mut max, mut max_issues) = (0usize, 0usize); + let (mut max, mut max_issues) = (0, 0); for (dir_path, count) in directories { let is_issues_dir = tests_path.join("ui/issues") == dir_path; let (limit, maxcnt) = if is_issues_dir { From 24b5466892956b26b5e261ed418aee3c9c6e6d45 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 22 May 2024 16:56:10 +0000 Subject: [PATCH 06/36] drop region constraints for ambiguous goals --- .../src/solve/eval_ctxt/canonical.rs | 62 ++++++++++++------- .../leak-check-in-selection-5-ambig.rs | 28 +++++++++ ...eck-in-selection-6-ambig-unify.next.stderr | 22 +++++++ ...heck-in-selection-6-ambig-unify.old.stderr | 22 +++++++ .../leak-check-in-selection-6-ambig-unify.rs | 32 ++++++++++ .../ambig-goal-infer-in-type-oulives.rs | 29 +++++++++ 6 files changed, 171 insertions(+), 24 deletions(-) create mode 100644 tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs create mode 100644 tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr create mode 100644 tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr create mode 100644 tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs create mode 100644 tests/ui/traits/next-solver/normalize/ambig-goal-infer-in-type-oulives.rs diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 9590a82c0677..f6ec65490845 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -99,6 +99,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { previous call to `try_evaluate_added_goals!`" ); + // We only check for leaks from universes which were entered inside + // of the query. + self.infcx.leak_check(self.max_input_universe, None).map_err(|e| { + trace!(?e, "failed the leak check"); + NoSolution + })?; + // When normalizing, we've replaced the expected term with an unconstrained // inference variable. This means that we dropped information which could // have been important. We handle this by instead returning the nested goals @@ -121,7 +128,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { }; let external_constraints = - self.compute_external_query_constraints(normalization_nested_goals)?; + self.compute_external_query_constraints(certainty, normalization_nested_goals); let (var_values, mut external_constraints) = (self.var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx)); // Remove any trivial region constraints once we've resolved regions @@ -170,30 +177,37 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { #[instrument(level = "trace", skip(self), ret)] fn compute_external_query_constraints( &self, + certainty: Certainty, normalization_nested_goals: NestedNormalizationGoals<'tcx>, - ) -> Result, NoSolution> { - // We only check for leaks from universes which were entered inside - // of the query. - self.infcx.leak_check(self.max_input_universe, None).map_err(|e| { - trace!(?e, "failed the leak check"); - NoSolution - })?; + ) -> ExternalConstraintsData<'tcx> { + // We only return region constraints once the certainty is `Yes`. This + // is necessary as we may drop nested goals on ambiguity, which may result + // in unconstrained inference variables in the region constraints. It also + // prevents us from emitting duplicate region constraints, avoiding some + // unnecessary work. This slightly weakens the leak check in case it uses + // region constraints from an ambiguous nested goal. This is tested in both + // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and + // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`. + let region_constraints = if certainty == Certainty::Yes { + // Cannot use `take_registered_region_obligations` as we may compute the response + // inside of a `probe` whenever we have multiple choices inside of the solver. + let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); + let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| { + make_query_region_constraints( + self.tcx(), + region_obligations.iter().map(|r_o| { + (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()) + }), + region_constraints, + ) + }); - // Cannot use `take_registered_region_obligations` as we may compute the response - // inside of a `probe` whenever we have multiple choices inside of the solver. - let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); - let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| { - make_query_region_constraints( - self.tcx(), - region_obligations - .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), - region_constraints, - ) - }); - - let mut seen = FxHashSet::default(); - region_constraints.outlives.retain(|outlives| seen.insert(*outlives)); + let mut seen = FxHashSet::default(); + region_constraints.outlives.retain(|outlives| seen.insert(*outlives)); + region_constraints + } else { + Default::default() + }; let mut opaque_types = self.infcx.clone_opaque_types_for_query_response(); // Only return opaque type keys for newly-defined opaques @@ -201,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a) }); - Ok(ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }) + ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } } /// After calling a canonical query, we apply the constraints returned diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs new file mode 100644 index 000000000000..beda719ac208 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs @@ -0,0 +1,28 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// The new trait solver does not return region constraints if the goal +// is still ambiguous. This causes the following test to fail with ambiguity, +// even though `(): LeakCheckFailure<'!a, V>` would return `'!a: 'static` +// which would have caused a leak check failure. + +trait Ambig {} +impl Ambig for u32 {} +impl Ambig for u16 {} + +trait Id {} +impl Id for u32 {} +impl Id for u16 {} + + +trait LeakCheckFailure<'a, V: ?Sized> {} +impl LeakCheckFailure<'static, V> for () {} + +trait Trait {} +impl Trait for () where for<'a> (): LeakCheckFailure<'a, V> {} +impl Trait for () {} +fn impls_trait, U: Id, V>() {} +fn main() { + impls_trait::<(), _, _>() +} diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr new file mode 100644 index 000000000000..a12e3312230a --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.next.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:5 + | +LL | impls_trait::<(), _, _>() + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` + | +note: multiple `impl`s satisfying `(): Trait<_, _>` found + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:26:1 + | +LL | impl Trait for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_trait` + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:19 + | +LL | fn impls_trait, U: Id, V>() {} + | ^^^^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr new file mode 100644 index 000000000000..a12e3312230a --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.old.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:30:5 + | +LL | impls_trait::<(), _, _>() + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` + | +note: multiple `impl`s satisfying `(): Trait<_, _>` found + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:26:1 + | +LL | impl Trait for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_trait` + --> $DIR/leak-check-in-selection-6-ambig-unify.rs:28:19 + | +LL | fn impls_trait, U: Id, V>() {} + | ^^^^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs new file mode 100644 index 000000000000..592d581695e5 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs @@ -0,0 +1,32 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +// The new trait solver does not return region constraints if the goal +// is still ambiguous. This should cause the following test to fail with +// ambiguity as even if `(): LeakCheckFailure<'static, '!b, V>` unifies +// `'!b` with `'static`, we erase all region constraints. +// +// However, we do still unify the var_value for `'b` with `'static`, +// causing us to return this requirement via the `var_values` even if +// we don't return any region constraints. This is a bit inconsistent +// but isn't something we should really worry about imo. +trait Ambig {} +impl Ambig for u32 {} +impl Ambig for u16 {} + +trait Id {} +impl Id for u32 {} +impl Id for u16 {} + + +trait LeakCheckFailure<'a, 'b, V: ?Sized> {} +impl<'a, 'b: 'a, V: ?Sized + Ambig> LeakCheckFailure<'a, 'b, V> for () {} + +trait Trait {} +impl Trait for () where for<'b> (): LeakCheckFailure<'static, 'b, V> {} +impl Trait for () {} +fn impls_trait, U: Id, V>() {} +fn main() { + impls_trait::<(), _, _>() + //~^ ERROR type annotations needed +} diff --git a/tests/ui/traits/next-solver/normalize/ambig-goal-infer-in-type-oulives.rs b/tests/ui/traits/next-solver/normalize/ambig-goal-infer-in-type-oulives.rs new file mode 100644 index 000000000000..18dc34f7cc43 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/ambig-goal-infer-in-type-oulives.rs @@ -0,0 +1,29 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicitly enabled) + +// Regression test for an ICE when trying to bootstrap rustc +// with #125343. An ambiguous goal returned a `TypeOutlives` +// constraint referencing an inference variable. This inference +// variable was created inside of the goal, causing it to be +// unconstrained in the caller. This then caused an ICE in MIR +// borrowck. + +struct Foo(T); +trait Extend { + fn extend>(iter: I); +} + +impl Extend for Foo { + fn extend>(_: I) { + todo!() + } +} + +impl<'a, T: 'a + Copy> Extend<&'a T> for Foo { + fn extend>(iter: I) { + >::extend(iter.into_iter().copied()) + } +} + +fn main() {} From 278212342ec2b2659c0e5b6e0038642fb6f37347 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Sat, 25 May 2024 10:38:18 +0800 Subject: [PATCH 07/36] cleanup dependence of `ExtCtxt` in transcribe when macro expansion --- compiler/rustc_expand/src/mbe/macro_rules.rs | 3 +- compiler/rustc_expand/src/mbe/transcribe.rs | 60 ++++++++++---------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8f18055f8381..8349727ade7f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -224,7 +224,8 @@ fn expand_macro<'cx>( let arm_span = rhses[i].span(); // rhs has holes ( `$id` and `$(...)` that need filled) - let tts = match transcribe(cx, &named_matches, rhs, rhs_span, transparency) { + let id = cx.current_expansion.id; + let tts = match transcribe(psess, &named_matches, rhs, rhs_span, transparency, id) { Ok(tts) => tts, Err(err) => { let guar = err.emit(); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 3901b82eb52e..5c2b9198a89d 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,4 +1,3 @@ -use crate::base::ExtCtxt; use crate::errors::{ CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce, NoSyntaxVarsExprRepeat, VarStillRepeating, @@ -9,12 +8,13 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{pluralize, Diag, PResult}; +use rustc_errors::{pluralize, Diag, DiagCtxt, PResult}; use rustc_parse::parser::ParseNtResult; use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent}; use rustc_span::{with_metavar_spans, Span, SyntaxContext}; +use rustc_session::parse::ParseSess; use smallvec::{smallvec, SmallVec}; use std::mem; @@ -99,11 +99,12 @@ impl<'a> Iterator for Frame<'a> { /// /// Along the way, we do some additional error checking. pub(super) fn transcribe<'a>( - cx: &ExtCtxt<'a>, + psess: &'a ParseSess, interp: &FxHashMap, src: &mbe::Delimited, src_span: DelimSpan, transparency: Transparency, + expand_id: LocalExpnId, ) -> PResult<'a, TokenStream> { // Nothing for us to transcribe... if src.tts.is_empty() { @@ -137,8 +138,9 @@ pub(super) fn transcribe<'a>( // again, and we are done transcribing. let mut result: Vec = Vec::new(); let mut result_stack = Vec::new(); - let mut marker = Marker(cx.current_expansion.id, transparency, Default::default()); + let mut marker = Marker(expand_id, transparency, Default::default()); + let dcx = &psess.dcx; loop { // Look at the last frame on the stack. // If it still has a TokenTree we have not looked at yet, use that tree. @@ -201,9 +203,7 @@ pub(super) fn transcribe<'a>( seq @ mbe::TokenTree::Sequence(_, seq_rep) => { match lockstep_iter_size(seq, interp, &repeats) { LockstepIterSize::Unconstrained => { - return Err(cx - .dcx() - .create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); + return Err(dcx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); } LockstepIterSize::Contradiction(msg) => { @@ -211,9 +211,9 @@ pub(super) fn transcribe<'a>( // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - return Err(cx - .dcx() - .create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg })); + return Err( + dcx.create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg }) + ); } LockstepIterSize::Constraint(len, _) => { @@ -227,9 +227,7 @@ pub(super) fn transcribe<'a>( // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. - return Err(cx - .dcx() - .create_err(MustRepeatOnce { span: sp.entire() })); + return Err(dcx.create_err(MustRepeatOnce { span: sp.entire() })); } } else { // 0 is the initial counter (we have done 0 repetitions so far). `len` @@ -259,7 +257,7 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", // without wrapping them into groups. - maybe_use_metavar_location(cx, &stack, sp, tt, &mut marker) + maybe_use_metavar_location(psess, &stack, sp, tt, &mut marker) } MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { marker.visit_span(&mut sp); @@ -280,7 +278,7 @@ pub(super) fn transcribe<'a>( } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. - return Err(cx.dcx().create_err(VarStillRepeating { span: sp, ident })); + return Err(dcx.create_err(VarStillRepeating { span: sp, ident })); } }; result.push(tt) @@ -299,7 +297,7 @@ pub(super) fn transcribe<'a>( // Replace meta-variable expressions with the result of their expansion. mbe::TokenTree::MetaVarExpr(sp, expr) => { - transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, sp)?; + transcribe_metavar_expr(dcx, expr, interp, &mut marker, &repeats, &mut result, sp)?; } // If we are entering a new delimiter, we push its contents to the `stack` to be @@ -359,7 +357,7 @@ pub(super) fn transcribe<'a>( /// combine with each other and not with tokens outside of the sequence. /// - The metavariable span comes from a different crate, then we prefer the more local span. fn maybe_use_metavar_location( - cx: &ExtCtxt<'_>, + psess: &ParseSess, stack: &[Frame<'_>], mut metavar_span: Span, orig_tt: &TokenTree, @@ -397,7 +395,7 @@ fn maybe_use_metavar_location( && insert(mspans, dspan.entire(), metavar_span) }), }; - if no_collision || cx.source_map().is_imported(metavar_span) { + if no_collision || psess.source_map().is_imported(metavar_span) { return orig_tt.clone(); } @@ -558,7 +556,7 @@ fn lockstep_iter_size( /// * `[ $( ${count(foo, 1)} ),* ]` will return an error because `${count(foo, 1)}` is /// declared inside a single repetition and the index `1` implies two nested repetitions. fn count_repetitions<'a>( - cx: &ExtCtxt<'a>, + dcx: &'a DiagCtxt, depth_user: usize, mut matched: &NamedMatch, repeats: &[(usize, usize)], @@ -595,7 +593,7 @@ fn count_repetitions<'a>( .and_then(|el| el.checked_sub(repeats.len())) .unwrap_or_default(); if depth_user > depth_max { - return Err(out_of_bounds_err(cx, depth_max + 1, sp.entire(), "count")); + return Err(out_of_bounds_err(dcx, depth_max + 1, sp.entire(), "count")); } // `repeats` records all of the nested levels at which we are currently @@ -611,7 +609,7 @@ fn count_repetitions<'a>( } if let MatchedSingle(_) = matched { - return Err(cx.dcx().create_err(CountRepetitionMisplaced { span: sp.entire() })); + return Err(dcx.create_err(CountRepetitionMisplaced { span: sp.entire() })); } count(depth_user, depth_max, matched) @@ -619,7 +617,7 @@ fn count_repetitions<'a>( /// Returns a `NamedMatch` item declared on the LHS given an arbitrary [Ident] fn matched_from_ident<'ctx, 'interp, 'rslt>( - cx: &ExtCtxt<'ctx>, + dcx: &'ctx DiagCtxt, ident: Ident, interp: &'interp FxHashMap, ) -> PResult<'ctx, &'rslt NamedMatch> @@ -628,12 +626,12 @@ where { let span = ident.span; let key = MacroRulesNormalizedIdent::new(ident); - interp.get(&key).ok_or_else(|| cx.dcx().create_err(MetaVarExprUnrecognizedVar { span, key })) + interp.get(&key).ok_or_else(|| dcx.create_err(MetaVarExprUnrecognizedVar { span, key })) } /// Used by meta-variable expressions when an user input is out of the actual declared bounds. For /// example, index(999999) in an repetition of only three elements. -fn out_of_bounds_err<'a>(cx: &ExtCtxt<'a>, max: usize, span: Span, ty: &str) -> Diag<'a> { +fn out_of_bounds_err<'a>(dcx: &'a DiagCtxt, max: usize, span: Span, ty: &str) -> Diag<'a> { let msg = if max == 0 { format!( "meta-variable expression `{ty}` with depth parameter \ @@ -645,11 +643,11 @@ fn out_of_bounds_err<'a>(cx: &ExtCtxt<'a>, max: usize, span: Span, ty: &str) -> must be less than {max}" ) }; - cx.dcx().struct_span_err(span, msg) + dcx.struct_span_err(span, msg) } fn transcribe_metavar_expr<'a>( - cx: &ExtCtxt<'a>, + dcx: &'a DiagCtxt, expr: &MetaVarExpr, interp: &FxHashMap, marker: &mut Marker, @@ -664,8 +662,8 @@ fn transcribe_metavar_expr<'a>( }; match *expr { MetaVarExpr::Count(original_ident, depth) => { - let matched = matched_from_ident(cx, original_ident, interp)?; - let count = count_repetitions(cx, depth, matched, repeats, sp)?; + let matched = matched_from_ident(dcx, original_ident, interp)?; + let count = count_repetitions(dcx, depth, matched, repeats, sp)?; let tt = TokenTree::token_alone( TokenKind::lit(token::Integer, sym::integer(count), None), visited_span(), @@ -674,7 +672,7 @@ fn transcribe_metavar_expr<'a>( } MetaVarExpr::Ignore(original_ident) => { // Used to ensure that `original_ident` is present in the LHS - let _ = matched_from_ident(cx, original_ident, interp)?; + let _ = matched_from_ident(dcx, original_ident, interp)?; } MetaVarExpr::Index(depth) => match repeats.iter().nth_back(depth) { Some((index, _)) => { @@ -683,7 +681,7 @@ fn transcribe_metavar_expr<'a>( visited_span(), )); } - None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "index")), + None => return Err(out_of_bounds_err(dcx, repeats.len(), sp.entire(), "index")), }, MetaVarExpr::Len(depth) => match repeats.iter().nth_back(depth) { Some((_, length)) => { @@ -692,7 +690,7 @@ fn transcribe_metavar_expr<'a>( visited_span(), )); } - None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "len")), + None => return Err(out_of_bounds_err(dcx, repeats.len(), sp.entire(), "len")), }, } Ok(()) From 41d4a95fcaa49560a8b6cd2048ed5ef4bfdfa7c1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 24 May 2024 23:58:00 -0300 Subject: [PATCH 08/36] Add "better" edition handling on lint-docs tool --- compiler/rustc_lint_defs/src/builtin.rs | 4 ++-- src/tools/lint-docs/src/lib.rs | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 536945457724..8727dcfad9ab 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3803,7 +3803,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,compile_fail + /// ```rust,edition2018,compile_fail /// #![deny(rust_2021_incompatible_or_patterns)] /// /// macro_rules! match_any { @@ -3843,7 +3843,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,compile_fail + /// ```rust,edition2018,compile_fail /// #![deny(rust_2021_prelude_collisions)] /// /// trait Foo { diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 22ab576b0776..c79b377727ab 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -441,10 +441,19 @@ impl<'a> LintExtractor<'a> { fs::write(&tempfile, source) .map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?; let mut cmd = Command::new(self.rustc_path); - if options.contains(&"edition2015") { - cmd.arg("--edition=2015"); - } else { + if options.contains(&"edition2024") { + cmd.arg("--edition=2024"); + } else if options.contains(&"edition2021") { + cmd.arg("--edition=2021"); + } else if options.contains(&"edition2018") { cmd.arg("--edition=2018"); + } else if options.contains(&"edition2015") { + cmd.arg("--edition=2015"); + } else if options.contains(&"edition") { + panic!("lint-docs: unknown edition"); + } else { + // defaults to latest edition + cmd.arg("--edition=2021"); } cmd.arg("--error-format=json"); cmd.arg("--target").arg(self.rustc_target); From 56dddd4c7e53d6b40293e31426f7925a7663e34e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 25 May 2024 10:34:33 +0300 Subject: [PATCH 09/36] Remove deprecated field `dist.missing-tools` It's been 5 months since this field was deprecated. Signed-off-by: onur-ozkan --- config.example.toml | 3 --- src/bootstrap/src/core/config/config.rs | 4 ---- 2 files changed, 7 deletions(-) diff --git a/config.example.toml b/config.example.toml index 228521747ede..61655dad6385 100644 --- a/config.example.toml +++ b/config.example.toml @@ -904,9 +904,6 @@ # on linux #src-tarball = true -# Whether to allow failures when building tools -#missing-tools = false - # List of compression formats to use when generating dist tarballs. The list of # formats is provided to rust-installer, which must support all of them. # diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 19119a073c5f..54c900a36b8f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -314,7 +314,6 @@ pub struct Config { pub save_toolstates: Option, pub print_step_timings: bool, pub print_step_rusage: bool, - pub missing_tools: bool, // FIXME: Deprecated field. Remove it at 2024. // Fallback musl-root for all targets pub musl_root: Option, @@ -892,7 +891,6 @@ define_config! { sign_folder: Option = "sign-folder", upload_addr: Option = "upload-addr", src_tarball: Option = "src-tarball", - missing_tools: Option = "missing-tools", compression_formats: Option> = "compression-formats", compression_profile: Option = "compression-profile", include_mingw_linker: Option = "include-mingw-linker", @@ -1923,7 +1921,6 @@ impl Config { sign_folder, upload_addr, src_tarball, - missing_tools, compression_formats, compression_profile, include_mingw_linker, @@ -1933,7 +1930,6 @@ impl Config { config.dist_compression_formats = compression_formats; set(&mut config.dist_compression_profile, compression_profile); set(&mut config.rust_dist_src, src_tarball); - set(&mut config.missing_tools, missing_tools); set(&mut config.dist_include_mingw_linker, include_mingw_linker) } From c76477d9095e89fd62f6a880e90bc84399d19bff Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 25 May 2024 10:37:36 +0300 Subject: [PATCH 10/36] add change entry Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 2f9eaf51c341..bfe3622e40d3 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -190,4 +190,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "`rust.lld` has a new default value of `true` on `x86_64-unknown-linux-gnu`. Starting at stage1, `rust-lld` will thus be this target's default linker. No config changes should be necessary.", }, + ChangeInfo { + change_id: 125535, + severity: ChangeSeverity::Warning, + summary: "Removed `dist.missing-tools` configuration as it was deprecated long time ago.", + }, ]; From 939f2671a054315a6235fad8982fd1a443b74caa Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 25 May 2024 15:41:18 -0600 Subject: [PATCH 11/36] revert to the inconsistent paragraph wrapping. --- library/core/src/result.rs | 107 +++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 6a77f9f63a88..77c4ef957ac5 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -2,8 +2,8 @@ //! //! [`Result`][`Result`] is the type used for returning and propagating //! errors. It is an enum with the variants, [`Ok(T)`], representing success and -//! containing a value, and [`Err(E)`], representing error and containing an -//! error value. +//! success and containing a value, and [`Err(E)`], representing error +//! and containing an error value. //! //! ``` //! # #[allow(dead_code)] @@ -14,10 +14,11 @@ //! ``` //! //! Functions return [`Result`] whenever errors are expected and recoverable. In -//! the `std` crate, [`Result`] is most prominently used for -//! [I/O](../../std/io/index.html). +//! recoverable. In the `std` crate, [`Result`] is most prominently used +//! for [I/O](../../std/io/index.html). //! -//! A simple function returning [`Result`] might be defined and used like so: +//! A simple function returning [`Result`] might be +//! defined and used like so: //! //! ``` //! #[derive(Debug)] @@ -40,8 +41,8 @@ //! ``` //! //! Pattern matching on [`Result`]s is clear and straightforward for simple -//! cases, but [`Result`] comes with some convenience methods that make working -//! with it more succinct. +//! simple cases, but [`Result`] comes with some convenience methods +//! that make working with it more succinct. //! //! ``` //! let good_result: Result = Ok(10); @@ -67,15 +68,16 @@ //! //! # Results must be used //! -//! A common problem with using return values to indicate errors is that it is -//! easy to ignore the return value, thus failing to handle the error. -//! [`Result`] is annotated with the `#[must_use]` attribute, which will cause -//! the compiler to issue a warning when a Result value is ignored. This makes -//! [`Result`] especially useful with functions that may encounter errors but -//! don't otherwise return a useful value. +//! A common problem with using return values to indicate errors is +//! that it is easy to ignore the return value, thus failing to handle +//! the error. [`Result`] is annotated with the `#[must_use]` attribute, +//! which will cause the compiler to issue a warning when a Result +//! value is ignored. This makes [`Result`] especially useful with +//! functions that may encounter errors but don't otherwise return a +//! useful value. //! -//! Consider the [`write_all`] method defined for I/O types by the [`Write`] -//! trait: +//! Consider the [`write_all`] method defined for I/O types +//! by the [`Write`] trait: //! //! ``` //! use std::io; @@ -85,11 +87,12 @@ //! } //! ``` //! -//! *Note: The actual definition of [`Write`] uses [`io::Result`], which is just -//! a synonym for [Result].* +//! *Note: The actual definition of [`Write`] uses [`io::Result`], which +//! is just a synonym for [Result].* //! -//! This method doesn't produce a value, but the write may fail. It's crucial to -//! handle the error case, and *not* write something like this: +//! This method doesn't produce a value, but the write may +//! fail. It's crucial to handle the error case, and *not* write +//! something like this: //! //! ```no_run //! # #![allow(unused_must_use)] // \o/ @@ -102,12 +105,12 @@ //! file.write_all(b"important message"); //! ``` //! -//! If you *do* write that in Rust, the compiler will give you a warning (by -//! default, controlled by the `unused_must_use` lint). +//! If you *do* write that in Rust, the compiler will give you a +//! warning (by default, controlled by the `unused_must_use` lint). //! -//! You might instead, if you don't want to handle the error, simply assert -//! success with [`expect`]. This will panic if the write fails, providing a -//! marginally useful message indicating why: +//! You might instead, if you don't want to handle the error, simply +//! assert success with [`expect`]. This will panic if the +//! write fails, providing a marginally useful message indicating why: //! //! ```no_run //! use std::fs::File; @@ -142,9 +145,10 @@ //! //! # The question mark operator, `?` //! -//! When writing code that calls many functions that return the [`Result`] type, -//! the error handling can be tedious. The question mark operator, [`?`], hides -//! some of the boilerplate of propagating errors up the call stack. +//! When writing code that calls many functions that return the +//! [`Result`] type, the error handling can be tedious. The question mark +//! operator, [`?`], hides some of the boilerplate of propagating errors +//! up the call stack. //! //! It replaces this: //! @@ -205,17 +209,15 @@ //! //! *It's much nicer!* //! -//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped -//! value, unless the result is [`Err`], in which case [`Err`] is returned early -//! from the enclosing function. +//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result +//! is [`Err`], in which case [`Err`] is returned early from the enclosing function. //! -//! [`?`] can be used in functions that return [`Result`] because of the early -//! return of [`Err`] that it provides. +//! [`?`] can be used in functions that return [`Result`] because of the +//! early return of [`Err`] that it provides. //! //! [`expect`]: Result::expect //! [`Write`]: ../../std/io/trait.Write.html "io::Write" -//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all -//! "io::Write::write_all" +//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all "io::Write::write_all" //! [`io::Result`]: ../../std/io/type.Result.html "io::Result" //! [`?`]: crate::ops::Try //! [`Ok(T)`]: Ok @@ -250,8 +252,8 @@ //! //! ## Querying the variant //! -//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] is -//! [`Ok`] or [`Err`], respectively. +//! In addition to working with pattern matching, [`Result`] provides a +//! wide variety of different methods. //! //! [`is_err`]: Result::is_err //! [`is_ok`]: Result::is_ok @@ -261,8 +263,8 @@ //! * [`as_ref`] converts from `&Result` to `Result<&T, &E>` //! * [`as_mut`] converts from `&mut Result` to `Result<&mut T, &mut E>` //! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` -//! * [`as_deref_mut`] converts from `&mut Result` to `Result<&mut -//! T::Target, &mut E>` +//! * [`as_deref_mut`] converts from `&mut Result` to +//! `Result<&mut T::Target, &mut E>` //! //! [`as_deref`]: Result::as_deref //! [`as_deref_mut`]: Result::as_deref_mut @@ -271,18 +273,19 @@ //! //! ## Extracting contained values //! -//! These methods extract the contained value in a [`Result`] when it is -//! the [`Ok`] variant. If the [`Result`] is [`Err`]: +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Ok`] variant. If the [`Result`] is [`Err`]: //! //! * [`expect`] panics with a provided custom message //! * [`unwrap`] panics with a generic message //! * [`unwrap_or`] returns the provided default value -//! * [`unwrap_or_default`] returns the default value of the type `T` (which -//! must implement the [`Default`] trait) -//! * [`unwrap_or_else`] returns the result of evaluating the provided function +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function //! -//! The panicking methods [`expect`] and [`unwrap`] require `E` to implement the -//! [`Debug`] trait. +//! The panicking methods [`expect`] and [`unwrap`] require `E` to +//! implement the [`Debug`] trait. //! //! [`Debug`]: crate::fmt::Debug //! [`expect`]: Result::expect @@ -291,9 +294,9 @@ //! [`unwrap_or_default`]: Result::unwrap_or_default //! [`unwrap_or_else`]: Result::unwrap_or_else //! -//! These methods extract the contained value in a [`Result`] when it is -//! the [`Err`] variant. They require `T` to implement the [`Debug`] trait. If -//! the [`Result`] is [`Ok`]: +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Err`] variant. They require `T` to implement the [`Debug`] +//! trait. If the [`Result`] is [`Ok`]: //! //! * [`expect_err`] panics with a provided custom message //! * [`unwrap_err`] panics with a generic message @@ -308,10 +311,10 @@ //! //! * [`err`][Result::err] transforms [`Result`] into [`Option`], //! mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`] -//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], mapping -//! [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] -//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an [`Option`] -//! of a [`Result`] +//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], +//! mapping [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] +//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an +//! [`Option`] of a [`Result`] //! // Do NOT add link reference definitions for `err` or `ok`, because they // will generate numerous incorrect URLs for `Err` and `Ok` elsewhere, due From 22668e83f6b179ba3fd6f985a332e1cd2022af79 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 25 May 2024 15:46:55 -0600 Subject: [PATCH 12/36] Resolve https://github.com/rust-lang/rust/pull/124870#issuecomment-2128824959 --- library/core/src/option.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 1e3ed0f7c49f..c9b3c62dc416 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -137,10 +137,13 @@ //! //! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`) //! +//! Under some conditions the above types `T` are also null pointer optimized when wrapped in a [`Result`][result_repr]. +//! //! [`Box`]: ../../std/boxed/struct.Box.html //! [`num::NonZero*`]: crate::num //! [`ptr::NonNull`]: crate::ptr::NonNull //! [function call ABI]: ../primitive.fn.html#abi-compatibility +//! [result_repr]: crate::result::Result#Representation //! //! This is called the "null pointer optimization" or NPO. //! From 2e8f14fb371c13ee196e48caaefcfd749d04759f Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 25 May 2024 16:04:26 -0600 Subject: [PATCH 13/36] correct for copy paste errors when fixing wrapping. --- library/core/src/result.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 77c4ef957ac5..b40a585699b1 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -13,7 +13,7 @@ //! } //! ``` //! -//! Functions return [`Result`] whenever errors are expected and recoverable. In +//! Functions return [`Result`] whenever errors are expected and //! recoverable. In the `std` crate, [`Result`] is most prominently used //! for [I/O](../../std/io/index.html). //! @@ -40,7 +40,7 @@ //! } //! ``` //! -//! Pattern matching on [`Result`]s is clear and straightforward for simple +//! Pattern matching on [`Result`]s is clear and straightforward for //! simple cases, but [`Result`] comes with some convenience methods //! that make working with it more succinct. //! @@ -247,13 +247,13 @@ //! //! # Method overview //! -//! In addition to working with pattern matching, [`Result`] provides a wide -//! variety of different methods. +//! In addition to working with pattern matching, [`Result`] provides a +//! wide variety of different methods. //! //! ## Querying the variant //! -//! In addition to working with pattern matching, [`Result`] provides a -//! wide variety of different methods. +//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] +//! is [`Ok`] or [`Err`], respectively. //! //! [`is_err`]: Result::is_err //! [`is_ok`]: Result::is_ok From 2b2f83e5ffcc01a1ab77e2384893654191df603d Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 25 May 2024 16:05:22 -0600 Subject: [PATCH 14/36] github showed that weird. --- library/core/src/result.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b40a585699b1..2954284bda79 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1,7 +1,7 @@ //! Error handling with the `Result` type. //! //! [`Result`][`Result`] is the type used for returning and propagating -//! errors. It is an enum with the variants, [`Ok(T)`], representing success and +//! errors. It is an enum with the variants, [`Ok(T)`], representing //! success and containing a value, and [`Err(E)`], representing error //! and containing an error value. //! From f8279b10c3ed4c71b62d519b67aaa985950012ce Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 25 May 2024 16:46:58 -0600 Subject: [PATCH 15/36] Fix URL target, it's in the module not the type. --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c9b3c62dc416..1fb65c845aff 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -143,7 +143,7 @@ //! [`num::NonZero*`]: crate::num //! [`ptr::NonNull`]: crate::ptr::NonNull //! [function call ABI]: ../primitive.fn.html#abi-compatibility -//! [result_repr]: crate::result::Result#Representation +//! [result_repr]: crate::result#Representation //! //! This is called the "null pointer optimization" or NPO. //! From 9b480da36790ea8314b77cf97ecaf7653afb3a1a Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sat, 25 May 2024 17:44:48 -0600 Subject: [PATCH 16/36] It seems that anchor names are implicitly all lowercase --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 1fb65c845aff..9a527073602e 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -143,7 +143,7 @@ //! [`num::NonZero*`]: crate::num //! [`ptr::NonNull`]: crate::ptr::NonNull //! [function call ABI]: ../primitive.fn.html#abi-compatibility -//! [result_repr]: crate::result#Representation +//! [result_repr]: crate::result#representation //! //! This is called the "null pointer optimization" or NPO. //! From fa7a3f9049c6d3f781516ca10c163efcf3e01326 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 25 May 2024 23:05:27 -0700 Subject: [PATCH 17/36] rustdoc: Elide const-unstable if also unstable overall It's confusing because if a function is unstable overall, there's no need to highlight the constness is also unstable. Technically, these attributes (overall stability and const-stability) are separate, but in practice, we don't even show the const-unstable's feature flag (it's normally the same as the overall function). --- src/librustdoc/html/render/mod.rs | 21 +++++++++++++-------- tests/rustdoc/const-display.rs | 6 ++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f3ae4b76883e..1d0bc3286415 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1016,18 +1016,23 @@ fn render_stability_since_raw_with_extra( .map(|since| (format!("const since {since}"), format!("const: {since}"))) } Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => { - let unstable = if let Some(n) = issue { - format!( - "unstable" - ) - } else { - String::from("unstable") - }; + ) + } else { + String::from("unstable") + }; - Some((String::from("const unstable"), format!("const: {unstable}"))) + Some((String::from("const unstable"), format!("const: {unstable}"))) + } } _ => None, }; diff --git a/tests/rustdoc/const-display.rs b/tests/rustdoc/const-display.rs index c8967f426f0a..35665f2aef93 100644 --- a/tests/rustdoc/const-display.rs +++ b/tests/rustdoc/const-display.rs @@ -24,6 +24,12 @@ pub const unsafe fn foo_unsafe() -> u32 { 42 } #[unstable(feature = "humans", issue = "none")] pub const fn foo2() -> u32 { 42 } +// @has 'foo/fn.foo3.html' '//pre' 'pub fn foo3() -> u32' +// @!hasraw - '//span[@class="since"]' +#[unstable(feature = "humans", issue = "none")] +#[rustc_const_unstable(feature = "humans", issue = "none")] +pub const fn foo3() -> u32 { 42 } + // @has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32' // @has - //span '1.0.0 (const: 1.0.0)' #[stable(feature = "rust1", since = "1.0.0")] From bbcdb4fd3e4df3554e6d406a2f2e9e47114521f6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 26 May 2024 20:03:47 -0400 Subject: [PATCH 18/36] Give EarlyBinder a tcx parameter We are gonna need it to uplift EarlyBinder --- .../src/check/compare_impl_item.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/item_bounds.rs | 12 +-- .../rustc_hir_analysis/src/collect/type_of.rs | 4 +- .../src/outlives/explicit.rs | 4 +- .../src/outlives/implicit_infer.rs | 6 +- compiler/rustc_lint/src/non_local_def.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 +- compiler/rustc_metadata/src/rmeta/mod.rs | 10 +-- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_middle/src/mir/consts.rs | 5 +- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/query/erase.rs | 16 ++-- compiler/rustc_middle/src/query/mod.rs | 26 +++--- .../rustc_middle/src/query/on_disk_cache.rs | 2 +- .../rustc_middle/src/ty/abstract_const.rs | 3 +- compiler/rustc_middle/src/ty/adt.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_middle/src/ty/generic_args.rs | 80 +++++++++++-------- compiler/rustc_middle/src/ty/generics.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 6 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../src/ty/normalize_erasing_regions.rs | 4 +- compiler/rustc_middle/src/ty/parameterized.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 4 +- compiler/rustc_middle/src/values.rs | 6 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 2 +- .../src/traits/project.rs | 2 +- compiler/rustc_ty_utils/src/consts.rs | 6 +- compiler/rustc_ty_utils/src/ty.rs | 4 +- 33 files changed, 129 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 44bf8fd2d93e..119f5da725a3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -449,7 +449,7 @@ impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, impl_m_def_id: LocalDefId, -) -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { +) -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap(); let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b760b86a7bfb..a3797669af0e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1278,7 +1278,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { } #[instrument(level = "debug", skip(tcx))] -fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { +fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> { use rustc_hir::Node::*; use rustc_hir::*; diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index dd1d209389dc..50c93e9f1d7e 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -82,14 +82,14 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All) } pub(super) fn explicit_item_super_predicates( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::SelfOnly) } @@ -97,7 +97,7 @@ pub(super) fn explicit_item_bounds_with_filter( tcx: TyCtxt<'_>, def_id: LocalDefId, filter: PredicateFilter, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { match tcx.opt_rpitit_info(def_id.to_def_id()) { // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. @@ -166,7 +166,7 @@ pub(super) fn explicit_item_bounds_with_filter( ty::EarlyBinder::bind(bounds) } -pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> { +pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { tcx.explicit_item_bounds(def_id).map_bound(|bounds| { tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound))) }) @@ -175,7 +175,7 @@ pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder, def_id: DefId, -) -> ty::EarlyBinder> { +) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| { tcx.mk_clauses_from_iter( util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(), @@ -186,7 +186,7 @@ pub(super) fn item_super_predicates( pub(super) fn item_non_self_assumptions( tcx: TyCtxt<'_>, def_id: DefId, -) -> ty::EarlyBinder> { +) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect(); let own_bounds: FxIndexSet<_> = tcx.item_super_predicates(def_id).skip_binder().iter().collect(); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1475e53c47c2..ed942cc50bb4 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -309,7 +309,7 @@ fn get_path_containing_arg_in_pat<'hir>( arg_path } -pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { +pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> { use rustc_hir::*; use rustc_middle::ty::Ty; @@ -512,7 +512,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder, def_id: DefId, -) -> Result>, CyclePlaceholder> { +) -> Result>, CyclePlaceholder> { if let Some(def_id) = def_id.as_local() { use rustc_hir::*; diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 1de7a0f7bc73..bbfadbb5c308 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -6,7 +6,7 @@ use super::utils::*; #[derive(Debug)] pub struct ExplicitPredicatesMap<'tcx> { - map: FxIndexMap>>, + map: FxIndexMap>>, } impl<'tcx> ExplicitPredicatesMap<'tcx> { @@ -18,7 +18,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { &mut self, tcx: TyCtxt<'tcx>, def_id: DefId, - ) -> &ty::EarlyBinder> { + ) -> &ty::EarlyBinder<'tcx, RequiredPredicates<'tcx>> { self.map.entry(def_id).or_insert_with(|| { let predicates = if def_id.is_local() { tcx.explicit_predicates_of(def_id) diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index e6c582667ba5..af08f50f6559 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -15,7 +15,7 @@ use super::utils::*; /// now be filled with inferred predicates. pub(super) fn infer_predicates( tcx: TyCtxt<'_>, -) -> FxIndexMap>> { +) -> FxIndexMap>> { debug!("infer_predicates"); let mut explicit_map = ExplicitPredicatesMap::new(); @@ -101,7 +101,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, - global_inferred_outlives: &FxIndexMap>>, + global_inferred_outlives: &FxIndexMap>>, required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, ) { @@ -322,7 +322,7 @@ fn check_inferred_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>, - global_inferred_outlives: &FxIndexMap>>, + global_inferred_outlives: &FxIndexMap>>, required_predicates: &mut RequiredPredicates<'tcx>, ) { // Load the current set of inferred and explicit predicates from `global_inferred_outlives` diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index b3e93748a166..87ee5f536280 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -270,7 +270,7 @@ fn impl_trait_ref_has_enough_non_local_candidates<'tcx>( tcx: TyCtxt<'tcx>, infer_span: Span, trait_def_id: DefId, - binder: EarlyBinder>, + binder: EarlyBinder<'tcx, TraitRef<'tcx>>, mut did_has_local_parent: impl FnMut(DefId) -> bool, ) -> bool { let infcx = tcx diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 695525e755de..19bb943e6bcc 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1074,7 +1074,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self, index: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let lazy = self.root.tables.explicit_item_bounds.get(self, index); let output = if lazy.is_default() { &mut [] @@ -1088,7 +1088,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self, index: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let lazy = self.root.tables.explicit_item_super_predicates.get(self, index); let output = if lazy.is_default() { &mut [] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 825034cf96a9..c2cf5b6b7125 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -418,19 +418,19 @@ define_tables! { // As an optimization, we only store this for trait aliases, // since it's identical to super_predicates_of for traits. implied_predicates_of: Table>>, - type_of: Table>>>, + type_of: Table>>>, variances_of: Table>, - fn_sig: Table>>>, + fn_sig: Table>>>, codegen_fn_attrs: Table>, impl_trait_header: Table>>, - const_param_default: Table>>>, + const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, closure_saved_names_of_captured_variables: Table>>, mir_coroutine_witnesses: Table>>, promoted_mir: Table>>>, - thir_abstract_const: Table>>>, + thir_abstract_const: Table>>>, impl_parent: Table, constness: Table, defaultness: Table, @@ -459,7 +459,7 @@ define_tables! { macro_definition: Table>, proc_macro: Table, deduced_param_attrs: Table>, - trait_impl_trait_tys: Table>>>>, + trait_impl_trait_tys: Table>>>>, doc_link_resolutions: Table>, doc_link_traits_in_scope: Table>, assumed_wf_types_for_rpitit: Table, Span)>>, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index b0e72eaf5a4c..bf6ab8000645 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -108,7 +108,7 @@ macro_rules! arena_types { [decode] trait_impl_trait_tys: rustc_data_structures::unord::UnordMap< rustc_hir::def_id::DefId, - rustc_middle::ty::EarlyBinder> + rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>> >, [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 34748afa863d..d39422b2b04d 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -121,7 +121,7 @@ impl<'tcx> TyCtxt<'tcx> { LocalModDefId::new_unchecked(id) } - pub fn impl_subject(self, def_id: DefId) -> EarlyBinder> { + pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<'tcx, ImplSubject<'tcx>> { match self.impl_trait_ref(def_id) { Some(t) => t.map_bound(ImplSubject::Trait), None => self.type_of(def_id).map_bound(ImplSubject::Inherent), diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index d025dc360a24..e107c2c12bd6 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -220,7 +220,10 @@ pub enum Const<'tcx> { } impl<'tcx> Const<'tcx> { - pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder> { + pub fn identity_unevaluated( + tcx: TyCtxt<'tcx>, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, Const<'tcx>> { ty::EarlyBinder::bind(Const::Unevaluated( UnevaluatedConst { def: def_id, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 2b2b9392a709..02e5174a715d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -624,7 +624,7 @@ impl<'tcx> Body<'tcx> { /// Returns the return type; it always return first element from `local_decls` array. #[inline] - pub fn bound_return_ty(&self) -> ty::EarlyBinder> { + pub fn bound_return_ty(&self) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty) } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 320d49ea6467..1e36f034cc22 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -114,9 +114,11 @@ impl EraseType for Result { type Result = [u8; size_of::>()]; } -impl EraseType for Result>>, rustc_errors::ErrorGuaranteed> { +impl EraseType + for Result>>, rustc_errors::ErrorGuaranteed> +{ type Result = [u8; size_of::< - Result>>, rustc_errors::ErrorGuaranteed>, + Result>>, rustc_errors::ErrorGuaranteed>, >()]; } @@ -165,8 +167,8 @@ impl EraseType for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { [u8; size_of::>, ty::util::AlwaysRequiresDrop>>()]; } -impl EraseType for Result>, CyclePlaceholder> { - type Result = [u8; size_of::>, CyclePlaceholder>>()]; +impl EraseType for Result>, CyclePlaceholder> { + type Result = [u8; size_of::>, CyclePlaceholder>>()]; } impl EraseType for Option<&'_ T> { @@ -185,15 +187,15 @@ impl EraseType for Option> { type Result = [u8; size_of::>>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl EraseType for Option>> { + type Result = [u8; size_of::>>>()]; } impl EraseType for rustc_hir::MaybeOwner<'_> { type Result = [u8; size_of::>()]; } -impl EraseType for ty::EarlyBinder { +impl EraseType for ty::EarlyBinder<'_, T> { type Result = T::Result; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8ca7a465c2a8..6ad4b7c40fb2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -209,7 +209,7 @@ rustc_queries! { /// Given the def_id of a const-generic parameter, computes the associated default const /// parameter. e.g. `fn example` called on `N` would return `3`. - query const_param_default(param: DefId) -> ty::EarlyBinder> { + query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) } cache_on_disk_if { param.is_local() } separate_provide_extern @@ -219,7 +219,7 @@ rustc_queries! { /// to an alias, it will "skip" this alias to return the aliased type. /// /// [`DefId`]: rustc_hir::def_id::DefId - query type_of(key: DefId) -> ty::EarlyBinder> { + query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { desc { |tcx| "{action} `{path}`", action = { @@ -240,7 +240,7 @@ rustc_queries! { /// Specialized instance of `type_of` that detects cycles that are due to /// revealing opaque because of an auto trait bound. Unless `CyclePlaceholder` needs /// to be handled separately, call `type_of` instead. - query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { + query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { desc { |tcx| "computing type of opaque `{path}`", path = tcx.def_path_str(key), @@ -257,7 +257,7 @@ rustc_queries! { } query collect_return_position_impl_trait_in_trait_tys(key: DefId) - -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> + -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } cache_on_disk_if { key.is_local() } @@ -363,7 +363,7 @@ rustc_queries! { /// `key` is the `DefId` of the associated type or opaque type. /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -373,7 +373,7 @@ rustc_queries! { /// share the `Self` type of the item. These are a subset of the bounds /// that may explicitly be used for things like closure signature /// deduction. - query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -399,15 +399,15 @@ rustc_queries! { /// ``` /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query item_bounds(key: DefId) -> ty::EarlyBinder> { + query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } - query item_super_predicates(key: DefId) -> ty::EarlyBinder> { + query item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } - query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder> { + query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } @@ -504,7 +504,7 @@ rustc_queries! { /// Try to build an abstract representation of the given constant. query thir_abstract_const( key: DefId - ) -> Result>>, ErrorGuaranteed> { + ) -> Result>>, ErrorGuaranteed> { desc { |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), } @@ -704,7 +704,7 @@ rustc_queries! { separate_provide_extern } - query adt_sized_constraint(key: DefId) -> Option>> { + query adt_sized_constraint(key: DefId) -> Option>> { desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) } } @@ -849,7 +849,7 @@ rustc_queries! { query self_ty_of_trait_impl_enabling_order_dep_trait_object_hack( key: DefId - ) -> Option>> { + ) -> Option>> { desc { |tcx| "computing self type wrt issue #33140 `{}`", tcx.def_path_str(key) } } @@ -888,7 +888,7 @@ rustc_queries! { } /// Computes the signature of the function. - query fn_sig(key: DefId) -> ty::EarlyBinder> { + query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 941911c22309..ccd0c7cb10c4 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -752,7 +752,7 @@ impl<'a, 'tcx> Decodable> for &'tcx UnordSet } impl<'a, 'tcx> Decodable> - for &'tcx UnordMap>> + for &'tcx UnordMap>> { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index dc46b470b6f4..7fb5e9aadae7 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -30,7 +30,8 @@ impl From for NotConstEvaluatable { TrivialTypeTraversalImpls! { NotConstEvaluatable } -pub type BoundAbstractConst<'tcx> = Result>>, ErrorGuaranteed>; +pub type BoundAbstractConst<'tcx> = + Result>>, ErrorGuaranteed>; impl<'tcx> TyCtxt<'tcx> { pub fn expand_abstract_consts>>(self, ac: T) -> T { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 48193754077d..8e946bc8b314 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -579,7 +579,7 @@ impl<'tcx> AdtDef<'tcx> { /// Returns a type such that `Self: Sized` if and only if that type is `Sized`, /// or `None` if the type is always sized. - pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option>> { + pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option>> { if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None } } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 40a0dbeb2c22..3bf0fc444326 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -486,7 +486,10 @@ impl<'tcx> Const<'tcx> { } } -pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { +pub fn const_param_default<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> ty::EarlyBinder<'tcx, Const<'tcx>> { let default_def_id = match tcx.hir_node_by_def_id(def_id) { hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { default: Some(ac), .. }, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d138cd9ceb9d..40871dd4adaf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -681,7 +681,7 @@ impl<'tcx> TyCtxt<'tcx> { /// In order to break cycles involving `AnonConst`, we need to set the expected type by side /// effect. However, we do not want this as a general capability, so this interface restricts /// to the only allowed case. - pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder>) { + pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<'tcx, Ty<'tcx>>) { debug_assert_eq!(self.def_kind(key), DefKind::AnonConst); TyCtxtFeed { tcx: self, key }.type_of(value) } @@ -2746,7 +2746,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn impl_trait_ref( self, def_id: impl IntoQueryParam, - ) -> Option>> { + ) -> Option>> { Some(self.impl_trait_header(def_id)?.trait_ref) } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index c7b15c64b086..6628eb247d65 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -584,48 +584,49 @@ impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx /// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] -pub struct EarlyBinder { +pub struct EarlyBinder<'tcx, T> { value: T, + _tcx: PhantomData<&'tcx ()>, } /// For early binders, you should first call `instantiate` before using any visitors. -impl<'tcx, T> !TypeFoldable> for ty::EarlyBinder {} -impl<'tcx, T> !TypeVisitable> for ty::EarlyBinder {} +impl<'tcx, T> !TypeFoldable> for ty::EarlyBinder<'tcx, T> {} +impl<'tcx, T> !TypeVisitable> for ty::EarlyBinder<'tcx, T> {} -impl EarlyBinder { - pub fn bind(value: T) -> EarlyBinder { - EarlyBinder { value } +impl<'tcx, T> EarlyBinder<'tcx, T> { + pub fn bind(value: T) -> EarlyBinder<'tcx, T> { + EarlyBinder { value, _tcx: PhantomData } } - pub fn as_ref(&self) -> EarlyBinder<&T> { - EarlyBinder { value: &self.value } + pub fn as_ref(&self) -> EarlyBinder<'tcx, &T> { + EarlyBinder { value: &self.value, _tcx: PhantomData } } - pub fn map_bound_ref(&self, f: F) -> EarlyBinder + pub fn map_bound_ref(&self, f: F) -> EarlyBinder<'tcx, U> where F: FnOnce(&T) -> U, { self.as_ref().map_bound(f) } - pub fn map_bound(self, f: F) -> EarlyBinder + pub fn map_bound(self, f: F) -> EarlyBinder<'tcx, U> where F: FnOnce(T) -> U, { let value = f(self.value); - EarlyBinder { value } + EarlyBinder { value, _tcx: PhantomData } } - pub fn try_map_bound(self, f: F) -> Result, E> + pub fn try_map_bound(self, f: F) -> Result, E> where F: FnOnce(T) -> Result, { let value = f(self.value)?; - Ok(EarlyBinder { value }) + Ok(EarlyBinder { value, _tcx: PhantomData }) } - pub fn rebind(&self, value: U) -> EarlyBinder { - EarlyBinder { value } + pub fn rebind(&self, value: U) -> EarlyBinder<'tcx, U> { + EarlyBinder { value, _tcx: PhantomData } } /// Skips the binder and returns the "bound" value. @@ -634,7 +635,7 @@ impl EarlyBinder { /// arguments of an `FnSig`). Otherwise, consider using /// [`instantiate_identity`](EarlyBinder::instantiate_identity). /// - /// To skip the binder on `x: &EarlyBinder` to obtain `&T`, leverage + /// To skip the binder on `x: &EarlyBinder<'tcx, T>` to obtain `&T`, leverage /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. /// /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is @@ -644,13 +645,13 @@ impl EarlyBinder { } } -impl EarlyBinder> { - pub fn transpose(self) -> Option> { - self.value.map(|value| EarlyBinder { value }) +impl<'tcx, T> EarlyBinder<'tcx, Option> { + pub fn transpose(self) -> Option> { + self.value.map(|value| EarlyBinder { value, _tcx: PhantomData }) } } -impl<'tcx, 's, I: IntoIterator> EarlyBinder +impl<'tcx, 's, I: IntoIterator> EarlyBinder<'tcx, I> where I::Item: TypeFoldable>, { @@ -682,7 +683,10 @@ where type Item = I::Item; fn next(&mut self) -> Option { - Some(EarlyBinder { value: self.it.next()? }.instantiate(self.tcx, self.args)) + Some( + EarlyBinder { value: self.it.next()?, _tcx: PhantomData } + .instantiate(self.tcx, self.args), + ) } fn size_hint(&self) -> (usize, Option) { @@ -696,7 +700,10 @@ where I::Item: TypeFoldable>, { fn next_back(&mut self) -> Option { - Some(EarlyBinder { value: self.it.next_back()? }.instantiate(self.tcx, self.args)) + Some( + EarlyBinder { value: self.it.next_back()?, _tcx: PhantomData } + .instantiate(self.tcx, self.args), + ) } } @@ -707,7 +714,7 @@ where { } -impl<'tcx, 's, I: IntoIterator> EarlyBinder +impl<'tcx, 's, I: IntoIterator> EarlyBinder<'tcx, I> where I::Item: Deref, ::Target: Copy + TypeFoldable>, @@ -743,7 +750,9 @@ where type Item = ::Target; fn next(&mut self) -> Option { - self.it.next().map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) + self.it.next().map(|value| { + EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) + }) } fn size_hint(&self) -> (usize, Option) { @@ -758,9 +767,9 @@ where ::Target: Copy + TypeFoldable>, { fn next_back(&mut self) -> Option { - self.it - .next_back() - .map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) + self.it.next_back().map(|value| { + EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) + }) } } @@ -772,21 +781,22 @@ where { } -pub struct EarlyBinderIter { +pub struct EarlyBinderIter<'tcx, T> { t: T, + _tcx: PhantomData<&'tcx ()>, } -impl EarlyBinder { - pub fn transpose_iter(self) -> EarlyBinderIter { - EarlyBinderIter { t: self.value.into_iter() } +impl<'tcx, T: IntoIterator> EarlyBinder<'tcx, T> { + pub fn transpose_iter(self) -> EarlyBinderIter<'tcx, T::IntoIter> { + EarlyBinderIter { t: self.value.into_iter(), _tcx: PhantomData } } } -impl Iterator for EarlyBinderIter { - type Item = EarlyBinder; +impl<'tcx, T: Iterator> Iterator for EarlyBinderIter<'tcx, T> { + type Item = EarlyBinder<'tcx, T::Item>; fn next(&mut self) -> Option { - self.t.next().map(|value| EarlyBinder { value }) + self.t.next().map(|value| EarlyBinder { value, _tcx: PhantomData }) } fn size_hint(&self) -> (usize, Option) { @@ -794,7 +804,7 @@ impl Iterator for EarlyBinderIter { } } -impl<'tcx, T: TypeFoldable>> ty::EarlyBinder { +impl<'tcx, T: TypeFoldable>> ty::EarlyBinder<'tcx, T> { pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T { let mut folder = ArgFolder { tcx, args, binders_passed: 0 }; self.value.fold_with(&mut folder) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 1c4462fc1dcb..7cb1a6f72737 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -88,7 +88,7 @@ impl GenericParamDef { pub fn default_value<'tcx>( &self, tcx: TyCtxt<'tcx>, - ) -> Option>> { + ) -> Option>> { match self.kind { GenericParamDefKind::Type { has_default, .. } if has_default => { Some(tcx.type_of(self.def_id).map_bound(|t| t.into())) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 7da7f69a9543..a887047f62f2 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -764,7 +764,7 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T + pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T where T: TypeFoldable> + Copy, { @@ -782,7 +782,7 @@ impl<'tcx> Instance<'tcx> { &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - v: EarlyBinder, + v: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, @@ -800,7 +800,7 @@ impl<'tcx> Instance<'tcx> { &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - v: EarlyBinder, + v: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 79cfeb71d47e..70cd833aea88 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -266,7 +266,7 @@ pub struct ImplHeader<'tcx> { #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct ImplTraitHeader<'tcx> { - pub trait_ref: ty::EarlyBinder>, + pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub safety: hir::Safety, } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index e2cfabfdafaa..fb16cf5bd363 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -125,7 +125,7 @@ impl<'tcx> TyCtxt<'tcx> { self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, - value: EarlyBinder, + value: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, @@ -143,7 +143,7 @@ impl<'tcx> TyCtxt<'tcx> { self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, - value: EarlyBinder, + value: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 571c6e918dcb..f394b3c990ce 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -33,8 +33,8 @@ impl ParameterizedOverTcx for ty::Binder<'static, T> { type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; } -impl ParameterizedOverTcx for ty::EarlyBinder { - type Value<'tcx> = ty::EarlyBinder>; +impl ParameterizedOverTcx for ty::EarlyBinder<'static, T> { + type Value<'tcx> = ty::EarlyBinder<'tcx, T::Value<'tcx>>; } #[macro_export] diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 40f3db89df56..41b5e6d4dcc4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2055,7 +2055,7 @@ impl<'tcx> Ty<'tcx> { fn async_destructor_combinator( tcx: TyCtxt<'tcx>, lang_item: LangItem, - ) -> ty::EarlyBinder> { + ) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { tcx.fn_sig(tcx.require_lang_item(lang_item, None)) .map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap()) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 5a3d90221ebd..cacaa859d526 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -694,7 +694,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn coroutine_hidden_types( self, def_id: DefId, - ) -> impl Iterator>> { + ) -> impl Iterator>> { let coroutine_layout = self.mir_coroutine_witnesses(def_id); coroutine_layout .as_ref() @@ -709,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn bound_coroutine_hidden_types( self, def_id: DefId, - ) -> impl Iterator>>> { + ) -> impl Iterator>>> { let coroutine_layout = self.mir_coroutine_witnesses(def_id); coroutine_layout .as_ref() diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 79f36cfe5695..4ae475d35d14 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -23,7 +23,7 @@ impl<'tcx> Value> for Ty<'_> { } } -impl<'tcx> Value> for Result>, CyclePlaceholder> { +impl<'tcx> Value> for Result>, CyclePlaceholder> { fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { Err(CyclePlaceholder(guar)) } @@ -111,7 +111,7 @@ impl<'tcx> Value> for Representability { } } -impl<'tcx> Value> for ty::EarlyBinder> { +impl<'tcx> Value> for ty::EarlyBinder<'_, Ty<'_>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -121,7 +121,7 @@ impl<'tcx> Value> for ty::EarlyBinder> { } } -impl<'tcx> Value> for ty::EarlyBinder>> { +impl<'tcx> Value> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index be20924670c3..572dbe3bb821 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -194,7 +194,7 @@ where } } -impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder +impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<'tcx, S> where S: Stable<'tcx, T = V>, { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 77ac4be35ea1..87c8b1cda504 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2097,7 +2097,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node); let ty = tcx.type_of(assoc_ty.item.def_id); let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); - let term: ty::EarlyBinder> = if is_const { + let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const { let did = assoc_ty.item.def_id; let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did); let uv = ty::UnevaluatedConst::new(did, identity_args); diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 67ffb8a58b5a..58447f6d6a31 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -398,10 +398,10 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> { } /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead. -fn thir_abstract_const( - tcx: TyCtxt<'_>, +fn thir_abstract_const<'tcx>( + tcx: TyCtxt<'tcx>, def: LocalDefId, -) -> Result>>, ErrorGuaranteed> { +) -> Result>>, ErrorGuaranteed> { if !tcx.features().generic_const_exprs { return Ok(None); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 617e8a543656..38950c97c9d5 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -77,7 +77,7 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { fn adt_sized_constraint<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, -) -> Option>> { +) -> Option>> { if let Some(def_id) = def_id.as_local() { if let ty::Representability::Infinite(_) = tcx.representability(def_id) { return None; @@ -253,7 +253,7 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE fn self_ty_of_trait_impl_enabling_order_dep_trait_object_hack( tcx: TyCtxt<'_>, def_id: DefId, -) -> Option>> { +) -> Option>> { let impl_ = tcx.impl_trait_header(def_id).unwrap_or_else(|| bug!("called on inherent impl {def_id:?}")); From 993553ceb8e11210381e2baffd3fce63244dcf6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 26 May 2024 20:45:37 -0400 Subject: [PATCH 19/36] Uplift EarlyBinder --- Cargo.lock | 1 + compiler/rustc_middle/src/ty/consts.rs | 9 + compiler/rustc_middle/src/ty/fold.rs | 104 +--- compiler/rustc_middle/src/ty/generic_args.rs | 506 +----------------- compiler/rustc_middle/src/ty/mod.rs | 6 +- compiler/rustc_middle/src/ty/region.rs | 14 + compiler/rustc_middle/src/ty/sty.rs | 17 + compiler/rustc_type_ir/Cargo.toml | 1 + compiler/rustc_type_ir/src/binder.rs | 519 ++++++++++++++++++- compiler/rustc_type_ir/src/fold.rs | 96 +++- compiler/rustc_type_ir/src/inherent.rs | 11 + compiler/rustc_type_ir/src/interner.rs | 6 +- compiler/rustc_type_ir/src/lib.rs | 2 +- 13 files changed, 679 insertions(+), 613 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92e6a22b4b91..5e8d179e5365 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4686,6 +4686,7 @@ dependencies = [ "rustc_span", "rustc_type_ir_macros", "smallvec", + "tracing", ] [[package]] diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 3bf0fc444326..6416bbbe889c 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -184,6 +184,15 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { Const::new_var(tcx, vid, ty) } + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ty: Ty<'tcx>, + ) -> Self { + Const::new_bound(interner, debruijn, var, ty) + } + fn new_anon_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index d432aeada2c8..b5b36cbd1ba1 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -3,7 +3,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use tracing::{debug, instrument}; -pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +pub use rustc_type_ir::fold::{ + shift_region, shift_vars, FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, +}; /////////////////////////////////////////////////////////////////////////// // Some sample folders @@ -412,103 +414,3 @@ impl<'tcx> TyCtxt<'tcx> { Binder::bind_with_vars(inner, bound_vars) } } - -/////////////////////////////////////////////////////////////////////////// -// Shifter -// -// Shifts the De Bruijn indices on all escaping bound vars by a -// fixed amount. Useful in instantiation or when otherwise introducing -// a binding level that is not intended to capture the existing bound -// vars. See comment on `shift_vars_through_binders` method in -// `rustc_middle/src/ty/generic_args.rs` for more details. - -struct Shifter<'tcx> { - tcx: TyCtxt<'tcx>, - current_index: ty::DebruijnIndex, - amount: u32, -} - -impl<'tcx> Shifter<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self { - Shifter { tcx, current_index: ty::INNERMOST, amount } - } -} - -impl<'tcx> TypeFolder> for Shifter<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_binder>>( - &mut self, - t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.current_index.shift_in(1); - let t = t.super_fold_with(self); - self.current_index.shift_out(1); - t - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReBound(debruijn, br) if debruijn >= self.current_index => { - let debruijn = debruijn.shifted_in(self.amount); - ty::Region::new_bound(self.tcx, debruijn, br) - } - _ => r, - } - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { - let debruijn = debruijn.shifted_in(self.amount); - Ty::new_bound(self.tcx, debruijn, bound_ty) - } - - _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), - _ => ty, - } - } - - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() - && debruijn >= self.current_index - { - let debruijn = debruijn.shifted_in(self.amount); - ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) - } else { - ct.super_fold_with(self) - } - } - - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { - if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } - } -} - -pub fn shift_region<'tcx>( - tcx: TyCtxt<'tcx>, - region: ty::Region<'tcx>, - amount: u32, -) -> ty::Region<'tcx> { - match *region { - ty::ReBound(debruijn, br) if amount > 0 => { - ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br) - } - _ => region, - } -} - -pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T -where - T: TypeFoldable>, -{ - debug!("shift_vars(value={:?}, amount={})", value, amount); - - if amount == 0 || !value.has_escaping_bound_vars() { - return value; - } - - value.fold_with(&mut Shifter::new(tcx, amount)) -} diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 6628eb247d65..7a516b9f2c80 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -1,10 +1,10 @@ // Generic arguments. use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs}; -use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use crate::ty::visit::{TypeVisitable, TypeVisitor}; +use crate::ty::{self, Lift, List, Ty, TyCtxt}; use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::walk_visitable_list; @@ -12,19 +12,15 @@ use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; use rustc_macros::extension; -use rustc_macros::{ - Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, -}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; -use tracing::debug; use core::intrinsics; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::Deref; use std::ptr::NonNull; pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind>; @@ -576,500 +572,6 @@ impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx } } -/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo(T)` -/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call -/// `instantiate`. -/// -/// If you don't have anything to `instantiate`, you may be looking for -/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable)] -pub struct EarlyBinder<'tcx, T> { - value: T, - _tcx: PhantomData<&'tcx ()>, -} - -/// For early binders, you should first call `instantiate` before using any visitors. -impl<'tcx, T> !TypeFoldable> for ty::EarlyBinder<'tcx, T> {} -impl<'tcx, T> !TypeVisitable> for ty::EarlyBinder<'tcx, T> {} - -impl<'tcx, T> EarlyBinder<'tcx, T> { - pub fn bind(value: T) -> EarlyBinder<'tcx, T> { - EarlyBinder { value, _tcx: PhantomData } - } - - pub fn as_ref(&self) -> EarlyBinder<'tcx, &T> { - EarlyBinder { value: &self.value, _tcx: PhantomData } - } - - pub fn map_bound_ref(&self, f: F) -> EarlyBinder<'tcx, U> - where - F: FnOnce(&T) -> U, - { - self.as_ref().map_bound(f) - } - - pub fn map_bound(self, f: F) -> EarlyBinder<'tcx, U> - where - F: FnOnce(T) -> U, - { - let value = f(self.value); - EarlyBinder { value, _tcx: PhantomData } - } - - pub fn try_map_bound(self, f: F) -> Result, E> - where - F: FnOnce(T) -> Result, - { - let value = f(self.value)?; - Ok(EarlyBinder { value, _tcx: PhantomData }) - } - - pub fn rebind(&self, value: U) -> EarlyBinder<'tcx, U> { - EarlyBinder { value, _tcx: PhantomData } - } - - /// Skips the binder and returns the "bound" value. - /// This can be used to extract data that does not depend on generic parameters - /// (e.g., getting the `DefId` of the inner value or getting the number of - /// arguments of an `FnSig`). Otherwise, consider using - /// [`instantiate_identity`](EarlyBinder::instantiate_identity). - /// - /// To skip the binder on `x: &EarlyBinder<'tcx, T>` to obtain `&T`, leverage - /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. - /// - /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is - /// the analogous operation on [`super::Binder`]. - pub fn skip_binder(self) -> T { - self.value - } -} - -impl<'tcx, T> EarlyBinder<'tcx, Option> { - pub fn transpose(self) -> Option> { - self.value.map(|value| EarlyBinder { value, _tcx: PhantomData }) - } -} - -impl<'tcx, 's, I: IntoIterator> EarlyBinder<'tcx, I> -where - I::Item: TypeFoldable>, -{ - pub fn iter_instantiated( - self, - tcx: TyCtxt<'tcx>, - args: &'s [GenericArg<'tcx>], - ) -> IterInstantiated<'s, 'tcx, I> { - IterInstantiated { it: self.value.into_iter(), tcx, args } - } - - /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), - /// but on an iterator of `TypeFoldable` values. - pub fn instantiate_identity_iter(self) -> I::IntoIter { - self.value.into_iter() - } -} - -pub struct IterInstantiated<'s, 'tcx, I: IntoIterator> { - it: I::IntoIter, - tcx: TyCtxt<'tcx>, - args: &'s [GenericArg<'tcx>], -} - -impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I> -where - I::Item: TypeFoldable>, -{ - type Item = I::Item; - - fn next(&mut self) -> Option { - Some( - EarlyBinder { value: self.it.next()?, _tcx: PhantomData } - .instantiate(self.tcx, self.args), - ) - } - - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } -} - -impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I> -where - I::IntoIter: DoubleEndedIterator, - I::Item: TypeFoldable>, -{ - fn next_back(&mut self) -> Option { - Some( - EarlyBinder { value: self.it.next_back()?, _tcx: PhantomData } - .instantiate(self.tcx, self.args), - ) - } -} - -impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiated<'_, 'tcx, I> -where - I::IntoIter: ExactSizeIterator, - I::Item: TypeFoldable>, -{ -} - -impl<'tcx, 's, I: IntoIterator> EarlyBinder<'tcx, I> -where - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ - pub fn iter_instantiated_copied( - self, - tcx: TyCtxt<'tcx>, - args: &'s [GenericArg<'tcx>], - ) -> IterInstantiatedCopied<'s, 'tcx, I> { - IterInstantiatedCopied { it: self.value.into_iter(), tcx, args } - } - - /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), - /// but on an iterator of values that deref to a `TypeFoldable`. - pub fn instantiate_identity_iter_copied( - self, - ) -> impl Iterator::Target> { - self.value.into_iter().map(|v| *v) - } -} - -pub struct IterInstantiatedCopied<'a, 'tcx, I: IntoIterator> { - it: I::IntoIter, - tcx: TyCtxt<'tcx>, - args: &'a [GenericArg<'tcx>], -} - -impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I> -where - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ - type Item = ::Target; - - fn next(&mut self) -> Option { - self.it.next().map(|value| { - EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) - }) - } - - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } -} - -impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, 'tcx, I> -where - I::IntoIter: DoubleEndedIterator, - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ - fn next_back(&mut self) -> Option { - self.it.next_back().map(|value| { - EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) - }) - } -} - -impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiatedCopied<'_, 'tcx, I> -where - I::IntoIter: ExactSizeIterator, - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ -} - -pub struct EarlyBinderIter<'tcx, T> { - t: T, - _tcx: PhantomData<&'tcx ()>, -} - -impl<'tcx, T: IntoIterator> EarlyBinder<'tcx, T> { - pub fn transpose_iter(self) -> EarlyBinderIter<'tcx, T::IntoIter> { - EarlyBinderIter { t: self.value.into_iter(), _tcx: PhantomData } - } -} - -impl<'tcx, T: Iterator> Iterator for EarlyBinderIter<'tcx, T> { - type Item = EarlyBinder<'tcx, T::Item>; - - fn next(&mut self) -> Option { - self.t.next().map(|value| EarlyBinder { value, _tcx: PhantomData }) - } - - fn size_hint(&self) -> (usize, Option) { - self.t.size_hint() - } -} - -impl<'tcx, T: TypeFoldable>> ty::EarlyBinder<'tcx, T> { - pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T { - let mut folder = ArgFolder { tcx, args, binders_passed: 0 }; - self.value.fold_with(&mut folder) - } - - /// Makes the identity replacement `T0 => T0, ..., TN => TN`. - /// Conceptually, this converts universally bound variables into placeholders - /// when inside of a given item. - /// - /// For example, consider `for fn foo(){ .. }`: - /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). - /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling - /// `instantiate_identity` to discharge the `EarlyBinder`. - pub fn instantiate_identity(self) -> T { - self.value - } - - /// Returns the inner value, but only if it contains no bound vars. - pub fn no_bound_vars(self) -> Option { - if !self.value.has_param() { Some(self.value) } else { None } - } -} - -/////////////////////////////////////////////////////////////////////////// -// The actual instantiation engine itself is a type folder. - -struct ArgFolder<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - args: &'a [GenericArg<'tcx>], - - /// Number of region binders we have passed through while doing the instantiation - binders_passed: u32, -} - -impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { - #[inline] - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_binder>>( - &mut self, - t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.binders_passed += 1; - let t = t.super_fold_with(self); - self.binders_passed -= 1; - t - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - #[cold] - #[inline(never)] - fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! { - bug!( - "Region parameter out of range when instantiating in region {} (index={}, args = {:?})", - data.name, - data.index, - args, - ) - } - - #[cold] - #[inline(never)] - fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! { - bug!( - "Unexpected parameter {:?} when instantiating in region {} (index={})", - other, - data.name, - data.index - ) - } - - // Note: This routine only handles regions that are bound on - // type declarations and other outer declarations, not those - // bound in *fn types*. Region instantiation of the bound - // regions that appear in a function signature is done using - // the specialized routine `ty::replace_late_regions()`. - match *r { - ty::ReEarlyParam(data) => { - let rk = self.args.get(data.index as usize).map(|k| k.unpack()); - match rk { - Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), - Some(other) => region_param_invalid(data, other), - None => region_param_out_of_range(data, self.args), - } - } - ty::ReBound(..) - | ty::ReLateParam(_) - | ty::ReStatic - | ty::RePlaceholder(_) - | ty::ReErased - | ty::ReError(_) => r, - ty::ReVar(_) => bug!("unexpected region: {r:?}"), - } - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_param() { - return t; - } - - match *t.kind() { - ty::Param(p) => self.ty_for_param(p, t), - _ => t.super_fold_with(self), - } - } - - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Param(p) = c.kind() { - self.const_for_param(p, c) - } else { - c.super_fold_with(self) - } - } -} - -impl<'a, 'tcx> ArgFolder<'a, 'tcx> { - fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { - // Look up the type in the args. It really should be in there. - let opt_ty = self.args.get(p.index as usize).map(|k| k.unpack()); - let ty = match opt_ty { - Some(GenericArgKind::Type(ty)) => ty, - Some(kind) => self.type_param_expected(p, source_ty, kind), - None => self.type_param_out_of_range(p, source_ty), - }; - - self.shift_vars_through_binders(ty) - } - - #[cold] - #[inline(never)] - fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! { - bug!( - "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", - p, - ty, - p.index, - kind, - self.args, - ) - } - - #[cold] - #[inline(never)] - fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! { - bug!( - "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", - p, - ty, - p.index, - self.args, - ) - } - - fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - // Look up the const in the args. It really should be in there. - let opt_ct = self.args.get(p.index as usize).map(|k| k.unpack()); - let ct = match opt_ct { - Some(GenericArgKind::Const(ct)) => ct, - Some(kind) => self.const_param_expected(p, source_ct, kind), - None => self.const_param_out_of_range(p, source_ct), - }; - - self.shift_vars_through_binders(ct) - } - - #[cold] - #[inline(never)] - fn const_param_expected( - &self, - p: ty::ParamConst, - ct: ty::Const<'tcx>, - kind: GenericArgKind<'tcx>, - ) -> ! { - bug!( - "expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}", - p, - ct, - p.index, - kind, - self.args, - ) - } - - #[cold] - #[inline(never)] - fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! { - bug!( - "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", - p, - ct, - p.index, - self.args, - ) - } - - /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs - /// when we are instantating a type with escaping bound vars into a context where we have - /// passed through binders. That's quite a mouthful. Let's see an example: - /// - /// ``` - /// type Func = fn(A); - /// type MetaFunc = for<'a> fn(Func<&'a i32>); - /// ``` - /// - /// The type `MetaFunc`, when fully expanded, will be - /// ```ignore (illustrative) - /// for<'a> fn(fn(&'a i32)) - /// // ^~ ^~ ^~~ - /// // | | | - /// // | | DebruijnIndex of 2 - /// // Binders - /// ``` - /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the - /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip - /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the - /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a - /// De Bruijn index of 1. It's only during the instantiation that we can see we must increase the - /// depth by 1 to account for the binder that we passed through. - /// - /// As a second example, consider this twist: - /// - /// ``` - /// type FuncTuple = (A,fn(A)); - /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>); - /// ``` - /// - /// Here the final type will be: - /// ```ignore (illustrative) - /// for<'a> fn((&'a i32, fn(&'a i32))) - /// // ^~~ ^~~ - /// // | | - /// // DebruijnIndex of 1 | - /// // DebruijnIndex of 2 - /// ``` - /// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the - /// first case we do not increase the De Bruijn index and in the second case we do. The reason - /// is that only in the second case have we passed through a fn binder. - fn shift_vars_through_binders>>(&self, val: T) -> T { - debug!( - "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", - val, - self.binders_passed, - val.has_escaping_bound_vars() - ); - - if self.binders_passed == 0 || !val.has_escaping_bound_vars() { - return val; - } - - let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed); - debug!("shift_vars: shifted result = {:?}", result); - - result - } - - fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> { - if self.binders_passed == 0 || !region.has_escaping_bound_vars() { - return region; - } - ty::fold::shift_region(self.tcx, region, self.binders_passed) - } -} - /// Stores the user-given args to reach some fully qualified path /// (e.g., `::Item` or `::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 70cd833aea88..f24074cb472d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -114,9 +114,9 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, - CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, - InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, - VarianceDiagInfo, + CoroutineClosureArgsParts, CoroutineClosureSignature, EarlyBinder, FnSig, GenSig, + InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, + UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 958e7e401684..dcab20233086 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -138,6 +138,14 @@ impl<'tcx> Region<'tcx> { } impl<'tcx> rustc_type_ir::inherent::Region> for Region<'tcx> { + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundRegion, + ) -> Self { + Region::new_bound(interner, debruijn, var) + } + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }) } @@ -340,6 +348,12 @@ pub struct EarlyParamRegion { pub name: Symbol, } +impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion { + fn index(self) -> u32 { + self.index + } +} + impl std::fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // FIXME(BoxyUwU): self.def_id goes first because of `erased-regions-in-hidden-ty.rs` being impossible to write diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 41b5e6d4dcc4..5cf96d298375 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -40,6 +40,7 @@ pub type TypeAndMut<'tcx> = ir::TypeAndMut>; pub type AliasTy<'tcx> = ir::AliasTy>; pub type FnSig<'tcx> = ir::FnSig>; pub type Binder<'tcx, T> = ir::Binder, T>; +pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub trait Article { fn article(&self) -> &'static str; @@ -954,6 +955,12 @@ pub struct ParamTy { pub name: Symbol, } +impl rustc_type_ir::inherent::ParamLike for ParamTy { + fn index(self) -> u32 { + self.index + } +} + impl<'tcx> ParamTy { pub fn new(index: u32, name: Symbol) -> ParamTy { ParamTy { index, name } @@ -982,6 +989,12 @@ pub struct ParamConst { pub name: Symbol, } +impl rustc_type_ir::inherent::ParamLike for ParamConst { + fn index(self) -> u32 { + self.index + } +} + impl ParamConst { pub fn new(index: u32, name: Symbol) -> ParamConst { ParamConst { index, name } @@ -1423,6 +1436,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { Ty::new_var(tcx, vid) } + fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self { + Ty::new_bound(interner, debruijn, var) + } + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) } diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index cef3f4e8ce05..18a09067a2c9 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -15,6 +15,7 @@ rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", default-features = false } +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 5336b915a1d3..e50d59ba5f0e 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,12 +1,14 @@ use std::fmt::Debug; use std::hash::Hash; +use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; #[cfg(feature = "nightly")] -use rustc_macros::HashStable_NoContext; +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_serialize::Decodable; +use tracing::debug; -use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; +use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; use crate::lift::Lift; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; @@ -338,3 +340,516 @@ impl TypeVisitor for ValidateBoundVars { ControlFlow::Continue(()) } } + +/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo(T)` +/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call +/// `instantiate`. +/// +/// If you don't have anything to `instantiate`, you may be looking for +/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = "T: Clone"), + Copy(bound = "T: Copy"), + PartialEq(bound = "T: PartialEq"), + Eq(bound = "T: Eq"), + Ord(bound = "T: Ord"), + PartialOrd(bound = "T: Ord"), + Hash(bound = "T: Hash"), + Debug(bound = "T: Debug") +)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +pub struct EarlyBinder { + value: T, + _tcx: PhantomData, +} + +/// For early binders, you should first call `instantiate` before using any visitors. +#[cfg(feature = "nightly")] +impl !TypeFoldable for ty::EarlyBinder {} + +/// For early binders, you should first call `instantiate` before using any visitors. +#[cfg(feature = "nightly")] +impl !TypeVisitable for ty::EarlyBinder {} + +impl EarlyBinder { + pub fn bind(value: T) -> EarlyBinder { + EarlyBinder { value, _tcx: PhantomData } + } + + pub fn as_ref(&self) -> EarlyBinder { + EarlyBinder { value: &self.value, _tcx: PhantomData } + } + + pub fn map_bound_ref(&self, f: F) -> EarlyBinder + where + F: FnOnce(&T) -> U, + { + self.as_ref().map_bound(f) + } + + pub fn map_bound(self, f: F) -> EarlyBinder + where + F: FnOnce(T) -> U, + { + let value = f(self.value); + EarlyBinder { value, _tcx: PhantomData } + } + + pub fn try_map_bound(self, f: F) -> Result, E> + where + F: FnOnce(T) -> Result, + { + let value = f(self.value)?; + Ok(EarlyBinder { value, _tcx: PhantomData }) + } + + pub fn rebind(&self, value: U) -> EarlyBinder { + EarlyBinder { value, _tcx: PhantomData } + } + + /// Skips the binder and returns the "bound" value. + /// This can be used to extract data that does not depend on generic parameters + /// (e.g., getting the `DefId` of the inner value or getting the number of + /// arguments of an `FnSig`). Otherwise, consider using + /// [`instantiate_identity`](EarlyBinder::instantiate_identity). + /// + /// To skip the binder on `x: &EarlyBinder` to obtain `&T`, leverage + /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. + /// + /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is + /// the analogous operation on [`super::Binder`]. + pub fn skip_binder(self) -> T { + self.value + } +} + +impl EarlyBinder> { + pub fn transpose(self) -> Option> { + self.value.map(|value| EarlyBinder { value, _tcx: PhantomData }) + } +} + +impl<'s, I: Interner, Iter: IntoIterator> EarlyBinder +where + Iter::Item: TypeFoldable, +{ + pub fn iter_instantiated( + self, + tcx: I, + args: &'s [I::GenericArg], + ) -> IterInstantiated<'s, I, Iter> { + IterInstantiated { it: self.value.into_iter(), tcx, args } + } + + /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), + /// but on an iterator of `TypeFoldable` values. + pub fn instantiate_identity_iter(self) -> Iter::IntoIter { + self.value.into_iter() + } +} + +pub struct IterInstantiated<'s, I: Interner, Iter: IntoIterator> { + it: Iter::IntoIter, + tcx: I, + args: &'s [I::GenericArg], +} + +impl Iterator for IterInstantiated<'_, I, Iter> +where + Iter::Item: TypeFoldable, +{ + type Item = Iter::Item; + + fn next(&mut self) -> Option { + Some( + EarlyBinder { value: self.it.next()?, _tcx: PhantomData } + .instantiate(self.tcx, self.args), + ) + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl DoubleEndedIterator for IterInstantiated<'_, I, Iter> +where + Iter::IntoIter: DoubleEndedIterator, + Iter::Item: TypeFoldable, +{ + fn next_back(&mut self) -> Option { + Some( + EarlyBinder { value: self.it.next_back()?, _tcx: PhantomData } + .instantiate(self.tcx, self.args), + ) + } +} + +impl ExactSizeIterator for IterInstantiated<'_, I, Iter> +where + Iter::IntoIter: ExactSizeIterator, + Iter::Item: TypeFoldable, +{ +} + +impl<'s, I: Interner, Iter: IntoIterator> EarlyBinder +where + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ + pub fn iter_instantiated_copied( + self, + tcx: I, + args: &'s [I::GenericArg], + ) -> IterInstantiatedCopied<'s, I, Iter> { + IterInstantiatedCopied { it: self.value.into_iter(), tcx, args } + } + + /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), + /// but on an iterator of values that deref to a `TypeFoldable`. + pub fn instantiate_identity_iter_copied( + self, + ) -> impl Iterator::Target> { + self.value.into_iter().map(|v| *v) + } +} + +pub struct IterInstantiatedCopied<'a, I: Interner, Iter: IntoIterator> { + it: Iter::IntoIter, + tcx: I, + args: &'a [I::GenericArg], +} + +impl Iterator for IterInstantiatedCopied<'_, I, Iter> +where + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ + type Item = ::Target; + + fn next(&mut self) -> Option { + self.it.next().map(|value| { + EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) + }) + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl DoubleEndedIterator for IterInstantiatedCopied<'_, I, Iter> +where + Iter::IntoIter: DoubleEndedIterator, + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ + fn next_back(&mut self) -> Option { + self.it.next_back().map(|value| { + EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) + }) + } +} + +impl ExactSizeIterator for IterInstantiatedCopied<'_, I, Iter> +where + Iter::IntoIter: ExactSizeIterator, + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ +} + +pub struct EarlyBinderIter { + t: T, + _tcx: PhantomData, +} + +impl EarlyBinder { + pub fn transpose_iter(self) -> EarlyBinderIter { + EarlyBinderIter { t: self.value.into_iter(), _tcx: PhantomData } + } +} + +impl Iterator for EarlyBinderIter { + type Item = EarlyBinder; + + fn next(&mut self) -> Option { + self.t.next().map(|value| EarlyBinder { value, _tcx: PhantomData }) + } + + fn size_hint(&self) -> (usize, Option) { + self.t.size_hint() + } +} + +impl> ty::EarlyBinder { + pub fn instantiate(self, tcx: I, args: &[I::GenericArg]) -> T { + let mut folder = ArgFolder { tcx, args, binders_passed: 0 }; + self.value.fold_with(&mut folder) + } + + /// Makes the identity replacement `T0 => T0, ..., TN => TN`. + /// Conceptually, this converts universally bound variables into placeholders + /// when inside of a given item. + /// + /// For example, consider `for fn foo(){ .. }`: + /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). + /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling + /// `instantiate_identity` to discharge the `EarlyBinder`. + pub fn instantiate_identity(self) -> T { + self.value + } + + /// Returns the inner value, but only if it contains no bound vars. + pub fn no_bound_vars(self) -> Option { + if !self.value.has_param() { Some(self.value) } else { None } + } +} + +/////////////////////////////////////////////////////////////////////////// +// The actual instantiation engine itself is a type folder. + +struct ArgFolder<'a, I: Interner> { + tcx: I, + args: &'a [I::GenericArg], + + /// Number of region binders we have passed through while doing the instantiation + binders_passed: u32, +} + +impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { + #[inline] + fn interner(&self) -> I { + self.tcx + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + self.binders_passed += 1; + let t = t.super_fold_with(self); + self.binders_passed -= 1; + t + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + // Note: This routine only handles regions that are bound on + // type declarations and other outer declarations, not those + // bound in *fn types*. Region instantiation of the bound + // regions that appear in a function signature is done using + // the specialized routine `ty::replace_late_regions()`. + match r.kind() { + ty::ReEarlyParam(data) => { + let rk = self.args.get(data.index() as usize).map(|k| k.kind()); + match rk { + Some(ty::GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), + Some(other) => self.region_param_expected(data, r, other), + None => self.region_param_out_of_range(data, r), + } + } + ty::ReBound(..) + | ty::ReLateParam(_) + | ty::ReStatic + | ty::RePlaceholder(_) + | ty::ReErased + | ty::ReError(_) => r, + ty::ReVar(_) => panic!("unexpected region: {r:?}"), + } + } + + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + if !t.has_param() { + return t; + } + + match t.kind() { + ty::Param(p) => self.ty_for_param(p, t), + _ => t.super_fold_with(self), + } + } + + fn fold_const(&mut self, c: I::Const) -> I::Const { + if let ty::ConstKind::Param(p) = c.kind() { + self.const_for_param(p, c) + } else { + c.super_fold_with(self) + } + } +} + +impl<'a, I: Interner> ArgFolder<'a, I> { + fn ty_for_param(&self, p: I::ParamTy, source_ty: I::Ty) -> I::Ty { + // Look up the type in the args. It really should be in there. + let opt_ty = self.args.get(p.index() as usize).map(|k| k.kind()); + let ty = match opt_ty { + Some(ty::GenericArgKind::Type(ty)) => ty, + Some(kind) => self.type_param_expected(p, source_ty, kind), + None => self.type_param_out_of_range(p, source_ty), + }; + + self.shift_vars_through_binders(ty) + } + + #[cold] + #[inline(never)] + fn type_param_expected(&self, p: I::ParamTy, ty: I::Ty, kind: ty::GenericArgKind) -> ! { + panic!( + "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", + p, + ty, + p.index(), + kind, + self.args, + ) + } + + #[cold] + #[inline(never)] + fn type_param_out_of_range(&self, p: I::ParamTy, ty: I::Ty) -> ! { + panic!( + "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", + p, + ty, + p.index(), + self.args, + ) + } + + fn const_for_param(&self, p: I::ParamConst, source_ct: I::Const) -> I::Const { + // Look up the const in the args. It really should be in there. + let opt_ct = self.args.get(p.index() as usize).map(|k| k.kind()); + let ct = match opt_ct { + Some(ty::GenericArgKind::Const(ct)) => ct, + Some(kind) => self.const_param_expected(p, source_ct, kind), + None => self.const_param_out_of_range(p, source_ct), + }; + + self.shift_vars_through_binders(ct) + } + + #[cold] + #[inline(never)] + fn const_param_expected( + &self, + p: I::ParamConst, + ct: I::Const, + kind: ty::GenericArgKind, + ) -> ! { + panic!( + "expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}", + p, + ct, + p.index(), + kind, + self.args, + ) + } + + #[cold] + #[inline(never)] + fn const_param_out_of_range(&self, p: I::ParamConst, ct: I::Const) -> ! { + panic!( + "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", + p, + ct, + p.index(), + self.args, + ) + } + + #[cold] + #[inline(never)] + fn region_param_expected( + &self, + ebr: I::EarlyParamRegion, + r: I::Region, + kind: ty::GenericArgKind, + ) -> ! { + panic!( + "expected region for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}", + ebr, + r, + ebr.index(), + kind, + self.args, + ) + } + + #[cold] + #[inline(never)] + fn region_param_out_of_range(&self, ebr: I::EarlyParamRegion, r: I::Region) -> ! { + panic!( + "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", + ebr, + r, + ebr.index(), + self.args, + ) + } + + /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs + /// when we are instantating a type with escaping bound vars into a context where we have + /// passed through binders. That's quite a mouthful. Let's see an example: + /// + /// ``` + /// type Func = fn(A); + /// type MetaFunc = for<'a> fn(Func<&'a i32>); + /// ``` + /// + /// The type `MetaFunc`, when fully expanded, will be + /// ```ignore (illustrative) + /// for<'a> fn(fn(&'a i32)) + /// // ^~ ^~ ^~~ + /// // | | | + /// // | | DebruijnIndex of 2 + /// // Binders + /// ``` + /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the + /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip + /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the + /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a + /// De Bruijn index of 1. It's only during the instantiation that we can see we must increase the + /// depth by 1 to account for the binder that we passed through. + /// + /// As a second example, consider this twist: + /// + /// ``` + /// type FuncTuple = (A,fn(A)); + /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>); + /// ``` + /// + /// Here the final type will be: + /// ```ignore (illustrative) + /// for<'a> fn((&'a i32, fn(&'a i32))) + /// // ^~~ ^~~ + /// // | | + /// // DebruijnIndex of 1 | + /// // DebruijnIndex of 2 + /// ``` + /// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the + /// first case we do not increase the De Bruijn index and in the second case we do. The reason + /// is that only in the second case have we passed through a fn binder. + fn shift_vars_through_binders>(&self, val: T) -> T { + debug!( + "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", + val, + self.binders_passed, + val.has_escaping_bound_vars() + ); + + if self.binders_passed == 0 || !val.has_escaping_bound_vars() { + return val; + } + + let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed); + debug!("shift_vars: shifted result = {:?}", result); + + result + } + + fn shift_region_through_binders(&self, region: I::Region) -> I::Region { + if self.binders_passed == 0 || !region.has_escaping_bound_vars() { + return region; + } + ty::fold::shift_region(self.tcx, region, self.binders_passed) + } +} diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 405aba30241b..501311ff72f7 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -47,8 +47,10 @@ use rustc_index::{Idx, IndexVec}; use std::mem; +use tracing::debug; -use crate::visit::TypeVisitable; +use crate::inherent::*; +use crate::visit::{TypeVisitable, TypeVisitableExt as _}; use crate::{self as ty, Interner, Lrc}; #[cfg(feature = "nightly")] @@ -325,3 +327,95 @@ impl, Ix: Idx> TypeFoldable for IndexVec { + tcx: I, + current_index: ty::DebruijnIndex, + amount: u32, +} + +impl Shifter { + pub fn new(tcx: I, amount: u32) -> Self { + Shifter { tcx, current_index: ty::INNERMOST, amount } + } +} + +impl TypeFolder for Shifter { + fn interner(&self) -> I { + self.tcx + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + match r.kind() { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + Region::new_bound(self.tcx, debruijn, br) + } + _ => r, + } + } + + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + match ty.kind() { + ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + Ty::new_bound(self.tcx, debruijn, bound_ty) + } + + _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), + _ => ty, + } + } + + fn fold_const(&mut self, ct: I::Const) -> I::Const { + match ct.kind() { + ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) + } + _ => ct.super_fold_with(self), + } + } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } + } +} + +pub fn shift_region(tcx: I, region: I::Region, amount: u32) -> I::Region { + match region.kind() { + ty::ReBound(debruijn, br) if amount > 0 => { + Region::new_bound(tcx, debruijn.shifted_in(amount), br) + } + _ => region, + } +} + +pub fn shift_vars(tcx: I, value: T, amount: u32) -> T +where + T: TypeFoldable, +{ + debug!("shift_vars(value={:?}, amount={})", value, amount); + + if amount == 0 || !value.has_escaping_bound_vars() { + return value; + } + + value.fold_with(&mut Shifter::new(tcx, amount)) +} diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 77fe30a46608..e7e893f27daa 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -29,6 +29,8 @@ pub trait Ty>: fn new_var(interner: I, var: ty::TyVid) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundTy) -> Self; + fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self; @@ -65,7 +67,10 @@ pub trait Region>: + Into + IntoKind> + Flags + + TypeVisitable { + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self; + fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_static(interner: I) -> Self; @@ -87,6 +92,8 @@ pub trait Const>: fn new_var(interner: I, var: ty::ConstVid, ty: I::Ty) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst, ty: I::Ty) -> Self; + fn new_anon_bound( interner: I, debruijn: ty::DebruijnIndex, @@ -162,3 +169,7 @@ pub trait BoundVarLike { fn assert_eq(self, var: I::BoundVarKind); } + +pub trait ParamLike { + fn index(self) -> u32; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c77414afc52c..d9485e91479f 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -65,7 +65,7 @@ pub trait Interner: type Ty: Ty; type Tys: Tys; type FnInputTys: Copy + Debug + Hash + Eq + Deref + TypeVisitable; - type ParamTy: Copy + Debug + Hash + Eq; + type ParamTy: Copy + Debug + Hash + Eq + ParamLike; type BoundTy: Copy + Debug + Hash + Eq + BoundVarLike; type PlaceholderTy: PlaceholderLike; @@ -81,14 +81,14 @@ pub trait Interner: // Kinds of consts type Const: Const; type PlaceholderConst: PlaceholderLike; - type ParamConst: Copy + Debug + Hash + Eq; + type ParamConst: Copy + Debug + Hash + Eq + ParamLike; type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike; type ValueConst: Copy + Debug + Hash + Eq; type ExprConst: Copy + DebugWithInfcx + Hash + Eq; // Kinds of regions type Region: Region; - type EarlyParamRegion: Copy + Debug + Hash + Eq; + type EarlyParamRegion: Copy + Debug + Hash + Eq + ParamLike; type LateParamRegion: Copy + Debug + Hash + Eq; type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike; type PlaceholderRegion: PlaceholderLike; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 4a461b5b5f3c..217c056d0bae 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr( feature = "nightly", - feature(associated_type_defaults, min_specialization, never_type, rustc_attrs) + feature(associated_type_defaults, min_specialization, never_type, rustc_attrs, negative_impls) )] #![allow(rustc::usage_of_ty_tykind)] #![cfg_attr(feature = "nightly", allow(internal_features))] From f92292978f7b8ff985efdf5f4c471e051c3f6a92 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 26 May 2024 20:53:00 -0400 Subject: [PATCH 20/36] Use EarlyBinder in rustc_type_ir, simplify imports --- compiler/rustc_middle/src/ty/context.rs | 4 +-- compiler/rustc_type_ir/src/interner.rs | 44 +++++++++++-------------- compiler/rustc_type_ir/src/predicate.rs | 2 +- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 40871dd4adaf..500c298a78e3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -151,8 +151,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.generics_of(def_id) } - fn type_of_instantiated(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Ty<'tcx> { - self.type_of(def_id).instantiate(self, args) + fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of(def_id) } fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index d9485e91479f..e49db171a534 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -7,26 +7,22 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::solve::inspect::CanonicalGoalEvaluationStep; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{ - AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, - DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, FnSig, GenericArgKind, - NormalizesTo, ProjectionPredicate, SubtypePredicate, TermKind, TraitPredicate, TraitRef, -}; +use crate::{self as ty, DebugWithInfcx}; pub trait Interner: Sized + Copy - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> { type DefId: Copy + Debug + Hash + Eq + TypeVisitable; type AdtDef: Copy + Debug + Hash + Eq; @@ -39,9 +35,9 @@ pub trait Interner: + DebugWithInfcx + Hash + Eq - + IntoKind> + + IntoKind> + TypeVisitable; - type Term: Copy + Debug + Hash + Eq + IntoKind> + TypeVisitable; + type Term: Copy + Debug + Hash + Eq + IntoKind> + TypeVisitable; type BoundVarKinds: Copy + Debug @@ -51,7 +47,7 @@ pub trait Interner: + Default; type BoundVarKind: Copy + Debug + Hash + Eq; - type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; + type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; type PredefinedOpaques: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type ExternalConstraints: Copy + Debug + Hash + Eq; @@ -99,23 +95,23 @@ pub trait Interner: type Clause: Clause; type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; - fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo]) -> Self::CanonicalVars; + fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars; type GenericsOf: GenericsOf; fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf; // FIXME: Remove after uplifting `EarlyBinder` - fn type_of_instantiated(self, def_id: Self::DefId, args: Self::GenericArgs) -> Self::Ty; + fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; - fn alias_ty_kind(self, alias: AliasTy) -> AliasTyKind; + fn alias_ty_kind(self, alias: ty::AliasTy) -> ty::AliasTyKind; - fn alias_term_kind(self, alias: AliasTerm) -> AliasTermKind; + fn alias_term_kind(self, alias: ty::AliasTerm) -> ty::AliasTermKind; fn trait_ref_and_own_args_for_alias( self, def_id: Self::DefId, args: Self::GenericArgs, - ) -> (TraitRef, Self::OwnItemArgs); + ) -> (ty::TraitRef, Self::OwnItemArgs); fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 4e12c6b3d671..48a6f79993cc 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -567,7 +567,7 @@ impl AliasTerm { I::Const::new_unevaluated( interner, ty::UnevaluatedConst::new(self.def_id, self.args), - interner.type_of_instantiated(self.def_id, self.args), + interner.type_of(self.def_id).instantiate(interner, &self.args), ) .into() } From 699d28f968178e6b20084b2a71ba89b4de7562cf Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 26 May 2024 12:28:47 -0700 Subject: [PATCH 21/36] rustdoc: Show "const" for const-unstable if also overall unstable If a const function is unstable overall (and thus, in all circumstances I know of, also const-unstable), we should show the option to use it as const. You need to enable a feature to use the function at all anyway. If the function is stabilized without also being const-stabilized, then we do not show the const keyword and instead show "const: unstable" in the version info. --- src/librustdoc/clean/types.rs | 7 +++--- src/librustdoc/html/format.rs | 29 +++++++++++++++--------- src/librustdoc/html/render/mod.rs | 8 ++++--- src/librustdoc/html/render/print_item.rs | 13 ++++++++++- tests/rustdoc/const-display.rs | 2 +- 5 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b54ec6245247..7425fb627e0d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -627,7 +627,7 @@ impl Item { ) -> hir::FnHeader { let sig = tcx.fn_sig(def_id).skip_binder(); let constness = - if tcx.is_const_fn(def_id) && is_unstable_const_fn(tcx, def_id).is_none() { + if tcx.is_const_fn(def_id) || is_unstable_const_fn(tcx, def_id).is_some() { hir::Constness::Const } else { hir::Constness::NotConst @@ -649,9 +649,8 @@ impl Item { hir::Safety::Unsafe }, abi, - constness: if abi == Abi::RustIntrinsic - && tcx.is_const_fn(def_id) - && is_unstable_const_fn(tcx, def_id).is_none() + constness: if tcx.is_const_fn(def_id) + || is_unstable_const_fn(tcx, def_id).is_some() { hir::Constness::Const } else { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 587c464b0ed1..57949001774f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -13,7 +13,7 @@ use std::fmt::{self, Display, Write}; use std::iter::{self, once}; use rustc_ast as ast; -use rustc_attr::{ConstStability, StabilityLevel}; +use rustc_attr::{ConstStability, StabilityLevel, StableSince}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -1633,17 +1633,24 @@ impl PrintWithSpace for hir::Mutability { pub(crate) fn print_constness_with_space( c: &hir::Constness, - s: Option, + overall_stab: Option, + const_stab: Option, ) -> &'static str { - match (c, s) { - // const stable or when feature(staged_api) is not set - ( - hir::Constness::Const, - Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }), - ) - | (hir::Constness::Const, None) => "const ", - // const unstable or not const - _ => "", + match c { + hir::Constness::Const => match (overall_stab, const_stab) { + // const stable... + (_, Some(ConstStability { level: StabilityLevel::Stable { .. }, .. })) + // ...or when feature(staged_api) is not set... + | (_, None) + // ...or when const unstable, but overall unstable too + | (None, Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => { + "const " + } + // const unstable (and overall stable) + (Some(_), Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => "", + }, + // not const + hir::Constness::NotConst => "", } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1d0bc3286415..8ee4cc5c75e4 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -928,9 +928,11 @@ fn assoc_method( // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove // this condition. let constness = match render_mode { - RenderMode::Normal => { - print_constness_with_space(&header.constness, meth.const_stability(tcx)) - } + RenderMode::Normal => print_constness_with_space( + &header.constness, + meth.stable_since(tcx), + meth.const_stability(tcx), + ), RenderMode::ForDeref { .. } => "", }; let asyncness = header.asyncness.print_with_space(); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c7a23aa8503a..c5b88c7a951f 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -615,7 +615,18 @@ fn extra_info_tags<'a, 'tcx: 'a>( fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) { let tcx = cx.tcx(); let header = it.fn_header(tcx).expect("printing a function which isn't a function"); - let constness = print_constness_with_space(&header.constness, it.const_stability(tcx)); + debug!( + "item_function/const: {:?} {:?} {:?} {:?}", + it.name, + &header.constness, + it.stable_since(tcx), + it.const_stability(tcx), + ); + let constness = print_constness_with_space( + &header.constness, + it.stable_since(tcx), + it.const_stability(tcx), + ); let safety = header.safety.print_with_space(); let abi = print_abi_with_space(header.abi).to_string(); let asyncness = header.asyncness.print_with_space(); diff --git a/tests/rustdoc/const-display.rs b/tests/rustdoc/const-display.rs index 35665f2aef93..959a00102b7e 100644 --- a/tests/rustdoc/const-display.rs +++ b/tests/rustdoc/const-display.rs @@ -24,7 +24,7 @@ pub const unsafe fn foo_unsafe() -> u32 { 42 } #[unstable(feature = "humans", issue = "none")] pub const fn foo2() -> u32 { 42 } -// @has 'foo/fn.foo3.html' '//pre' 'pub fn foo3() -> u32' +// @has 'foo/fn.foo3.html' '//pre' 'pub const fn foo3() -> u32' // @!hasraw - '//span[@class="since"]' #[unstable(feature = "humans", issue = "none")] #[rustc_const_unstable(feature = "humans", issue = "none")] From e4abfaeb620e75a1f84b94dcb89e41eac495f52b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 May 2024 11:37:27 +0200 Subject: [PATCH 22/36] Migrate `run-make/compile-stdin` to `rmake.rs` --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/compile-stdin/Makefile | 9 --------- tests/run-make/compile-stdin/rmake.rs | 13 +++++++++++++ 3 files changed, 13 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/compile-stdin/Makefile create mode 100644 tests/run-make/compile-stdin/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 9a6ae18abead..55d65fe89874 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -18,7 +18,6 @@ run-make/cdylib-fewer-symbols/Makefile run-make/cdylib/Makefile run-make/codegen-options-parsing/Makefile run-make/comment-section/Makefile -run-make/compile-stdin/Makefile run-make/compiler-lookup-paths-2/Makefile run-make/compiler-lookup-paths/Makefile run-make/compiler-rt-works-on-mingw/Makefile diff --git a/tests/run-make/compile-stdin/Makefile b/tests/run-make/compile-stdin/Makefile deleted file mode 100644 index b3d7cc777a01..000000000000 --- a/tests/run-make/compile-stdin/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# When provided standard input piped directly into rustc, this test checks that the compilation completes successfully and that the output can be executed. -# See https://github.com/rust-lang/rust/pull/28805 - -# ignore-cross-compile -include ../tools.mk - -all: - echo 'fn main(){}' | $(RUSTC) - - $(call RUN,rust_out) diff --git a/tests/run-make/compile-stdin/rmake.rs b/tests/run-make/compile-stdin/rmake.rs new file mode 100644 index 000000000000..f93080dfdc4f --- /dev/null +++ b/tests/run-make/compile-stdin/rmake.rs @@ -0,0 +1,13 @@ +// When provided standard input piped directly into rustc, this test checks that the compilation +// completes successfully and that the output can be executed. +// +// See . + +//@ ignore-cross-compile + +use run_make_support::{run, rustc}; + +fn main() { + rustc().arg("-").stdin("fn main() {}").run(); + run("rust_out"); +} From 05fa647dc7810a756a206d2300f12b3dafec779f Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 27 May 2024 12:05:00 +0200 Subject: [PATCH 23/36] Always use the general case char count --- library/core/src/str/count.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/str/count.rs b/library/core/src/str/count.rs index 28567a7e753a..d8667864fe55 100644 --- a/library/core/src/str/count.rs +++ b/library/core/src/str/count.rs @@ -24,7 +24,7 @@ const UNROLL_INNER: usize = 4; #[inline] pub(super) fn count_chars(s: &str) -> usize { - if s.len() < USIZE_SIZE * UNROLL_INNER { + if cfg!(feature = "optimize_for_size") || s.len() < USIZE_SIZE * UNROLL_INNER { // Avoid entering the optimized implementation for strings where the // difference is not likely to matter, or where it might even be slower. // That said, a ton of thought was not spent on the particular threshold From 90fec5a0873c82674890a9f67b73a4f0a35e9d0b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 May 2024 13:03:23 +0200 Subject: [PATCH 24/36] Add `copy_dir_all` and `recursive_diff` functions to `run-make-support` --- src/tools/run-make-support/src/lib.rs | 67 +++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 9854d91e19e3..d96c8b891278 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -12,6 +12,8 @@ pub mod rustc; pub mod rustdoc; use std::env; +use std::fs; +use std::io; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; @@ -201,6 +203,71 @@ pub fn set_host_rpath(cmd: &mut Command) { }); } +/// Copy a directory into another. +pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) { + fn copy_dir_all_inner(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { + let dst = dst.as_ref(); + if !dst.is_dir() { + fs::create_dir_all(&dst)?; + } + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?; + } else { + fs::copy(entry.path(), dst.join(entry.file_name()))?; + } + } + Ok(()) + } + + if let Err(e) = copy_dir_all_inner(&src, &dst) { + // Trying to give more context about what exactly caused the failure + panic!( + "failed to copy `{}` to `{}`: {:?}", + src.as_ref().display(), + dst.as_ref().display(), + e + ); + } +} + +/// Check that all files in `dir1` exist and have the same content in `dir2`. Panic otherwise. +pub fn recursive_diff(dir1: impl AsRef, dir2: impl AsRef) { + fn read_file(path: &Path) -> Vec { + match fs::read(path) { + Ok(c) => c, + Err(e) => panic!("Failed to read `{}`: {:?}", path.display(), e), + } + } + + let dir2 = dir2.as_ref(); + for entry in fs::read_dir(dir1).unwrap() { + let entry = entry.unwrap(); + let entry_name = entry.file_name(); + let path = entry.path(); + + if path.is_dir() { + recursive_diff(&path, &dir2.join(entry_name)); + } else { + let path2 = dir2.join(entry_name); + let file1 = read_file(&path); + let file2 = read_file(&path2); + + // We don't use `assert_eq!` because they are `Vec`, so not great for display. + // Why not using String? Because there might be minified files or even potentially + // binary ones, so that would display useless output. + assert!( + file1 == file2, + "`{}` and `{}` have different content", + path.display(), + path2.display(), + ); + } + } +} + /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct /// containing a `cmd: Command` field and a `output` function. The provided helpers are: /// From 1551fd12023e3b84d844bde2e376c407af1e9a04 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 May 2024 13:03:53 +0200 Subject: [PATCH 25/36] Add file path in case it cannot be read in `Diff::actual_file` --- src/tools/run-make-support/src/diff/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs index 332126939c08..d864ddf4eb17 100644 --- a/src/tools/run-make-support/src/diff/mod.rs +++ b/src/tools/run-make-support/src/diff/mod.rs @@ -51,7 +51,10 @@ impl Diff { /// Specify the actual output for the diff from a file. pub fn actual_file>(&mut self, path: P) -> &mut Self { let path = path.as_ref(); - let content = std::fs::read_to_string(path).expect("failed to read file"); + let content = match std::fs::read_to_string(path) { + Ok(c) => c, + Err(e) => panic!("failed to read `{}`: {:?}", path.display(), e), + }; let name = path.to_string_lossy().to_string(); self.actual = Some(content); From f0ab814aec56418ec0792d41db27e7d94c7d4380 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 May 2024 13:04:08 +0200 Subject: [PATCH 26/36] Add `Rustdoc::output_format` --- src/tools/run-make-support/src/rustdoc.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index c4f4e9f9bd23..9c77f1ca4624 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -151,6 +151,13 @@ impl Rustdoc { self } + /// Specify the output format. + pub fn output_format(&mut self, format: &str) -> &mut Self { + self.cmd.arg("--output-format"); + self.cmd.arg(format); + self + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); From bdf3864d51f7141d9e0fd14c754c7c3b5650af60 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 May 2024 13:04:41 +0200 Subject: [PATCH 27/36] Migrate `run-make/rustdoc-verify-output-files` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../rustdoc-verify-output-files/Makefile | 32 ------------ .../rustdoc-verify-output-files/rmake.rs | 49 +++++++++++++++++++ 3 files changed, 49 insertions(+), 33 deletions(-) delete mode 100644 tests/run-make/rustdoc-verify-output-files/Makefile create mode 100644 tests/run-make/rustdoc-verify-output-files/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 9a6ae18abead..d3f712258c48 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -227,7 +227,6 @@ run-make/rlib-format-packed-bundled-libs/Makefile run-make/rmeta-preferred/Makefile run-make/rustc-macro-dep-files/Makefile run-make/rustdoc-io-error/Makefile -run-make/rustdoc-verify-output-files/Makefile run-make/sanitizer-cdylib-link/Makefile run-make/sanitizer-dylib-link/Makefile run-make/sanitizer-staticlib-link/Makefile diff --git a/tests/run-make/rustdoc-verify-output-files/Makefile b/tests/run-make/rustdoc-verify-output-files/Makefile deleted file mode 100644 index 76f233ab445d..000000000000 --- a/tests/run-make/rustdoc-verify-output-files/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -include ../tools.mk - -OUTPUT_DIR := "$(TMPDIR)/rustdoc" -TMP_OUTPUT_DIR := "$(TMPDIR)/tmp-rustdoc" - -all: - # Generate html docs - $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) - - # Copy first output for to check if it's exactly same after second compilation - cp -R $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) - - # Generate html docs once again on same output - $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) - - # Check if everything exactly same - $(DIFF) -r $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) - - # Generate json doc on the same output - $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json - - # Check if expected json file is generated - [ -e $(OUTPUT_DIR)/foobar.json ] - - # Copy first json output to check if it's exactly same after second compilation - cp -R $(OUTPUT_DIR)/foobar.json $(TMP_OUTPUT_DIR)/foobar.json - - # Generate json doc on the same output - $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json - - # Check if all docs(including both json and html formats) are still the same after multiple compilations - $(DIFF) -r $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) diff --git a/tests/run-make/rustdoc-verify-output-files/rmake.rs b/tests/run-make/rustdoc-verify-output-files/rmake.rs new file mode 100644 index 000000000000..212e7eaba2d6 --- /dev/null +++ b/tests/run-make/rustdoc-verify-output-files/rmake.rs @@ -0,0 +1,49 @@ +use std::fs::copy; +use std::path::{Path, PathBuf}; + +use run_make_support::{copy_dir_all, recursive_diff, rustdoc, tmp_dir}; + +#[derive(PartialEq)] +enum JsonOutput { + Yes, + No, +} + +fn generate_docs(out_dir: &Path, json_output: JsonOutput) { + let mut rustdoc = rustdoc(); + rustdoc.input("src/lib.rs").crate_name("foobar").crate_type("lib").out_dir(&out_dir); + if json_output == JsonOutput::Yes { + rustdoc.arg("-Zunstable-options").output_format("json"); + } + rustdoc.run(); +} + +fn main() { + let out_dir = tmp_dir().join("rustdoc"); + let tmp_out_dir = tmp_dir().join("tmp-rustdoc"); + + // Generate HTML docs. + generate_docs(&out_dir, JsonOutput::No); + + // Copy first output for to check if it's exactly same after second compilation. + copy_dir_all(&out_dir, &tmp_out_dir); + + // Generate html docs once again on same output. + generate_docs(&out_dir, JsonOutput::No); + + // Generate json doc on the same output. + generate_docs(&out_dir, JsonOutput::Yes); + + // Check if expected json file is generated. + assert!(out_dir.join("foobar.json").is_file()); + + // Copy first json output to check if it's exactly same after second compilation. + copy(out_dir.join("foobar.json"), tmp_out_dir.join("foobar.json")).unwrap(); + + // Generate json doc on the same output. + generate_docs(&out_dir, JsonOutput::Yes); + + // Check if all docs(including both json and html formats) are still the same after multiple + // compilations. + recursive_diff(&out_dir, &tmp_out_dir); +} From 7d24f8706823e2f56f42ab7597f50d1b679f0eea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 May 2024 15:28:51 +0200 Subject: [PATCH 28/36] MIR validation: ensure that downcast projection is followed by field projection --- compiler/rustc_middle/src/mir/syntax.rs | 4 +-- compiler/rustc_mir_transform/src/validate.rs | 26 ++++++++++++++++--- .../miri/tests/panic/mir-validation.stderr | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 2b28496faec7..2d4852114332 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1008,8 +1008,8 @@ pub type AssertMessage<'tcx> = AssertKind>; /// element: /// /// - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the -/// given one, and makes no other changes. A `Downcast` projection on a place with its variant -/// index already set is not well-formed. +/// given one, and makes no other changes. A `Downcast` projection must always be followed +/// immediately by a `Field` projection. /// - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a /// place referring to one of the fields of the type. The resulting address is the parent /// address, plus the offset of the field. The type becomes the type of the field. If the parent diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 66cc65de6470..6df32169eecb 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -689,8 +689,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() { self.fail( location, - format!("You can't project to field {f:?} of `DynMetadata` because \ - layout is weird and thinks it doesn't have fields."), + format!( + "You can't project to field {f:?} of `DynMetadata` because \ + layout is weird and thinks it doesn't have fields." + ), ); } @@ -839,7 +841,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { && cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo) && place.projection[1..].contains(&ProjectionElem::Deref) { - self.fail(location, format!("{place:?}, has deref at the wrong place")); + self.fail( + location, + format!("place {place:?} has deref as a later projection (it is only permitted as the first projection)"), + ); + } + + // Ensure all downcast projections are followed by field projections. + let mut projections_iter = place.projection.iter(); + while let Some(proj) = projections_iter.next() { + if matches!(proj, ProjectionElem::Downcast(..)) { + if !matches!(projections_iter.next(), Some(ProjectionElem::Field(..))) { + self.fail( + location, + format!( + "place {place:?} has `Downcast` projection not followed by `Field`" + ), + ); + } + } } self.super_place(place, cntxt, location); diff --git a/src/tools/miri/tests/panic/mir-validation.stderr b/src/tools/miri/tests/panic/mir-validation.stderr index d5dd53d7b4e9..534e2d5881ff 100644 --- a/src/tools/miri/tests/panic/mir-validation.stderr +++ b/src/tools/miri/tests/panic/mir-validation.stderr @@ -1,6 +1,6 @@ thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC: broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]: -(*(_2.0: *mut i32)), has deref at the wrong place +place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection) stack backtrace: error: the compiler unexpectedly panicked. this is a bug. From e5d100363ad5bb72037d56093f794de4e10a99bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 25 May 2024 12:05:49 +0200 Subject: [PATCH 29/36] crashes: increment the number of tracked ones --- tests/crashes/123255.rs | 13 +++++++++++++ tests/crashes/123276.rs | 25 +++++++++++++++++++++++++ tests/crashes/123887.rs | 15 +++++++++++++++ tests/crashes/125013-1.rs | 5 +++++ tests/crashes/125013-2.rs | 16 ++++++++++++++++ tests/crashes/125014.rs | 17 +++++++++++++++++ tests/crashes/125059.rs | 12 ++++++++++++ tests/crashes/125323.rs | 6 ++++++ tests/crashes/125370.rs | 16 ++++++++++++++++ tests/crashes/125432.rs | 17 +++++++++++++++++ tests/crashes/125476.rs | 3 +++ tests/crashes/125512.rs | 10 ++++++++++ tests/crashes/125520.rs | 16 ++++++++++++++++ 13 files changed, 171 insertions(+) create mode 100644 tests/crashes/123255.rs create mode 100644 tests/crashes/123276.rs create mode 100644 tests/crashes/123887.rs create mode 100644 tests/crashes/125013-1.rs create mode 100644 tests/crashes/125013-2.rs create mode 100644 tests/crashes/125014.rs create mode 100644 tests/crashes/125059.rs create mode 100644 tests/crashes/125323.rs create mode 100644 tests/crashes/125370.rs create mode 100644 tests/crashes/125432.rs create mode 100644 tests/crashes/125476.rs create mode 100644 tests/crashes/125512.rs create mode 100644 tests/crashes/125520.rs diff --git a/tests/crashes/123255.rs b/tests/crashes/123255.rs new file mode 100644 index 000000000000..a94a2a0422e7 --- /dev/null +++ b/tests/crashes/123255.rs @@ -0,0 +1,13 @@ +//@ known-bug: rust-lang/rust#123255 +//@ edition:2021 +#![crate_type = "lib"] + +pub fn a() {} + +mod handlers { + pub struct C(&()); + pub fn c() -> impl Fn() -> C { + let a1 = (); + || C((crate::a(), a1).into()) + } +} diff --git a/tests/crashes/123276.rs b/tests/crashes/123276.rs new file mode 100644 index 000000000000..d2246f595838 --- /dev/null +++ b/tests/crashes/123276.rs @@ -0,0 +1,25 @@ +//@ known-bug: rust-lang/rust#123276 +//@ edition:2021 + +async fn create_task() { + _ = Some(async { bind(documentation_filter()) }); +} + +async fn bind>(_: F) {} + +fn documentation_filter() -> impl Filter { + AndThen +} + +trait Filter { + type Future; +} + +struct AndThen; + +impl Filter for AndThen +where + Foo: Filter, +{ + type Future = (); +} diff --git a/tests/crashes/123887.rs b/tests/crashes/123887.rs new file mode 100644 index 000000000000..68e2fb0325c3 --- /dev/null +++ b/tests/crashes/123887.rs @@ -0,0 +1,15 @@ +//@ known-bug: rust-lang/rust#123887 +//@ compile-flags: -Clink-dead-code + +#![feature(extern_types)] +#![feature(unsized_fn_params)] + +extern "C" { + pub type ExternType; +} + +impl ExternType { + pub fn f(self) {} +} + +pub fn main() {} diff --git a/tests/crashes/125013-1.rs b/tests/crashes/125013-1.rs new file mode 100644 index 000000000000..ae66d7a14669 --- /dev/null +++ b/tests/crashes/125013-1.rs @@ -0,0 +1,5 @@ +//@ known-bug: rust-lang/rust#125013 +//@ edition:2021 +use io::{self as std}; +use std::ops::Deref::{self as io}; +pub fn main() {} diff --git a/tests/crashes/125013-2.rs b/tests/crashes/125013-2.rs new file mode 100644 index 000000000000..a14c8a76b63e --- /dev/null +++ b/tests/crashes/125013-2.rs @@ -0,0 +1,16 @@ +//@ known-bug: rust-lang/rust#125013 +//@ edition:2021 +mod a { + pub mod b { + pub mod c { + pub trait D {} + } + } +} + +use a::*; + +use e as b; +use b::c::D as e; + +fn main() { } diff --git a/tests/crashes/125014.rs b/tests/crashes/125014.rs new file mode 100644 index 000000000000..b29042ee5983 --- /dev/null +++ b/tests/crashes/125014.rs @@ -0,0 +1,17 @@ +//@ known-bug: rust-lang/rust#125014 +//@ compile-flags: -Znext-solver=coherence +#![feature(specialization)] + +trait Foo {} + +impl Foo for ::Output {} + +impl Foo for u32 {} + +trait Assoc { + type Output; +} +impl Output for u32 {} +impl Assoc for ::Output { + default type Output = bool; +} diff --git a/tests/crashes/125059.rs b/tests/crashes/125059.rs new file mode 100644 index 000000000000..7e9f7414816e --- /dev/null +++ b/tests/crashes/125059.rs @@ -0,0 +1,12 @@ +//@ known-bug: rust-lang/rust#125059 +#![feature(deref_patterns)] +#![allow(incomplete_features)] + +fn simple_vec(vec: Vec) -> u32 { + (|| match Vec::::new() { + deref!([]) => 100, + _ => 2000, + })() +} + +fn main() {} diff --git a/tests/crashes/125323.rs b/tests/crashes/125323.rs new file mode 100644 index 000000000000..180b7bbad097 --- /dev/null +++ b/tests/crashes/125323.rs @@ -0,0 +1,6 @@ +//@ known-bug: rust-lang/rust#125323 +fn main() { + for _ in 0..0 { + [(); loop {}]; + } +} diff --git a/tests/crashes/125370.rs b/tests/crashes/125370.rs new file mode 100644 index 000000000000..8640d88a5d7f --- /dev/null +++ b/tests/crashes/125370.rs @@ -0,0 +1,16 @@ +//@ known-bug: rust-lang/rust#125370 + +type Field3 = i64; + +#[repr(C)] +union DummyUnion { + field3: Field3, +} + +const UNION: DummyUnion = loop {}; + +const fn read_field2() -> Field2 { + const FIELD2: Field2 = loop { + UNION.field3 + }; +} diff --git a/tests/crashes/125432.rs b/tests/crashes/125432.rs new file mode 100644 index 000000000000..659bb3ce21de --- /dev/null +++ b/tests/crashes/125432.rs @@ -0,0 +1,17 @@ +//@ known-bug: rust-lang/rust#125432 + +fn separate_arms() { + // Here both arms perform assignments, but only one is illegal. + + let mut x = None; + match x { + None => { + // It is ok to reassign x here, because there is in + // fact no outstanding loan of x! + x = Some(0); + } + Some(right) => consume(right), + } +} + +fn main() {} diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs new file mode 100644 index 000000000000..c6cb4db7d231 --- /dev/null +++ b/tests/crashes/125476.rs @@ -0,0 +1,3 @@ +//@ known-bug: rust-lang/rust#125476 +pub struct Data([u8; usize::MAX >> 16]); +const _: &'static [Data] = &[]; diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs new file mode 100644 index 000000000000..1672b24a1143 --- /dev/null +++ b/tests/crashes/125512.rs @@ -0,0 +1,10 @@ +//@ known-bug: rust-lang/rust#125512 +//@ edition:2021 +#![feature(object_safe_for_dispatch)] +trait B { + fn f(a: A) -> A; +} +trait A { + fn concrete(b: B) -> B; +} +fn main() {} diff --git a/tests/crashes/125520.rs b/tests/crashes/125520.rs new file mode 100644 index 000000000000..c6756053c210 --- /dev/null +++ b/tests/crashes/125520.rs @@ -0,0 +1,16 @@ +//@ known-bug: #125520 +#![feature(generic_const_exprs)] + +struct Outer(); +impl Outer +where + [(); A + (B * 2)]:, +{ + fn i() -> Self { + Self + } +} + +fn main() { + Outer::<1, 1>::o(); +} From 7a847fc4fb6266332754af4d07acd037b51dee01 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 27 May 2024 16:35:22 +0000 Subject: [PATCH 30/36] Use grep to implement verify-line-endings --- src/ci/scripts/verify-line-endings.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ci/scripts/verify-line-endings.sh b/src/ci/scripts/verify-line-endings.sh index f3cac13ea480..5f4b4aeb0e4e 100755 --- a/src/ci/scripts/verify-line-endings.sh +++ b/src/ci/scripts/verify-line-endings.sh @@ -4,21 +4,21 @@ # We check both in rust-lang/rust and in a submodule to make sure both are # accurate. Submodules are checked out significantly later than the main # repository in this script, so settings can (and do!) change between then. -# -# Linux (and maybe macOS) builders don't currently have dos2unix so just only -# run this step on Windows. set -euo pipefail IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -if isWindows; then - # print out the git configuration so we can better investigate failures in - # the following - git config --list --show-origin - dos2unix -ih Cargo.lock src/tools/rust-installer/install-template.sh - endings=$(dos2unix -ic Cargo.lock src/tools/rust-installer/install-template.sh) - # if endings has non-zero length, error out - if [ -n "$endings" ]; then exit 1 ; fi +# print out the git configuration so we can better investigate failures in +# the following +git config --list --show-origin +# -U is necessary on Windows to stop grep automatically converting the line ending +endings=$(grep -Ul $(printf '\r$') Cargo.lock src/tools/cargo/Cargo.lock) || true +# if endings has non-zero length, error out +if [[ -n $endings ]]; then + echo "Error: found DOS line endings" + # Print the files with DOS line endings + echo "$endings" + exit 1 fi From bae945201f72cf548b3b2d8cfd545812cccfae4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 27 May 2024 17:58:43 +0200 Subject: [PATCH 31/36] remove fixed crashes, add fixed crashes to tests, add new cashed found in the meantime --- tests/crashes/125370.rs | 16 --- tests/crashes/125432.rs | 17 --- tests/crashes/125476.rs | 1 + tests/crashes/125520.rs | 16 --- tests/crashes/125553.rs | 15 +++ tests/crashes/125556.rs | 14 ++ ...-125520-layout-mismatch-mulwithoverflow.rs | 27 ++++ ...520-layout-mismatch-mulwithoverflow.stderr | 125 ++++++++++++++++++ .../ui/const-generics/issues/issue-105821.rs | 2 +- 9 files changed, 183 insertions(+), 50 deletions(-) delete mode 100644 tests/crashes/125370.rs delete mode 100644 tests/crashes/125432.rs delete mode 100644 tests/crashes/125520.rs create mode 100644 tests/crashes/125553.rs create mode 100644 tests/crashes/125556.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr diff --git a/tests/crashes/125370.rs b/tests/crashes/125370.rs deleted file mode 100644 index 8640d88a5d7f..000000000000 --- a/tests/crashes/125370.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#125370 - -type Field3 = i64; - -#[repr(C)] -union DummyUnion { - field3: Field3, -} - -const UNION: DummyUnion = loop {}; - -const fn read_field2() -> Field2 { - const FIELD2: Field2 = loop { - UNION.field3 - }; -} diff --git a/tests/crashes/125432.rs b/tests/crashes/125432.rs deleted file mode 100644 index 659bb3ce21de..000000000000 --- a/tests/crashes/125432.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: rust-lang/rust#125432 - -fn separate_arms() { - // Here both arms perform assignments, but only one is illegal. - - let mut x = None; - match x { - None => { - // It is ok to reassign x here, because there is in - // fact no outstanding loan of x! - x = Some(0); - } - Some(right) => consume(right), - } -} - -fn main() {} diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs index c6cb4db7d231..aa9a081388d9 100644 --- a/tests/crashes/125476.rs +++ b/tests/crashes/125476.rs @@ -1,3 +1,4 @@ //@ known-bug: rust-lang/rust#125476 +//@ only-x86_64 pub struct Data([u8; usize::MAX >> 16]); const _: &'static [Data] = &[]; diff --git a/tests/crashes/125520.rs b/tests/crashes/125520.rs deleted file mode 100644 index c6756053c210..000000000000 --- a/tests/crashes/125520.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #125520 -#![feature(generic_const_exprs)] - -struct Outer(); -impl Outer -where - [(); A + (B * 2)]:, -{ - fn i() -> Self { - Self - } -} - -fn main() { - Outer::<1, 1>::o(); -} diff --git a/tests/crashes/125553.rs b/tests/crashes/125553.rs new file mode 100644 index 000000000000..142c06775bb8 --- /dev/null +++ b/tests/crashes/125553.rs @@ -0,0 +1,15 @@ +//@ known-bug: rust-lang/rust#125553 +//@ edition:2021 + +#[derive(Copy, Clone)] +struct Foo((u32, u32)); + +fn main() { + type T = impl Copy(Copy, Clone) + let foo: T = Foo((1u32, 1u32)); + let x = move || { + let derive = move || { + let Foo((a, b)) = foo; + }; + }; +} diff --git a/tests/crashes/125556.rs b/tests/crashes/125556.rs new file mode 100644 index 000000000000..f2e2a991b11e --- /dev/null +++ b/tests/crashes/125556.rs @@ -0,0 +1,14 @@ +//@ known-bug: rust-lang/rust#125556 +//@ compile-flags: -Znext-solver=coherence + +#![feature(generic_const_exprs)] + +pub struct A {} + +impl A<2> { + pub const fn B() {} +} + +impl A<2> { + pub const fn B() {} +} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs b/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs new file mode 100644 index 000000000000..cd2dc3f4fe85 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs @@ -0,0 +1,27 @@ +// issue: rust-lang/rust#125520 +#![feature(generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + +struct Outer(); +impl Outer +//~^ ERROR the constant `A` is not of type `i64` +//~| ERROR the constant `B` is not of type `i64` +//~| ERROR mismatched types +//~| ERROR mismatched types +where + [(); A + (B * 2)]:, +{ + fn i() -> Self { + //~^ ERROR the constant `A` is not of type `i64` + //~| ERROR the constant `B` is not of type `i64` + Self + //~^ ERROR mismatched types + //~| ERROR the constant `A` is not of type `i64` + //~| ERROR the constant `B` is not of type `i64` + } +} + +fn main() { + Outer::<1, 1>::o(); + //~^ ERROR no function or associated item named `o` found for struct `Outer` in the current scope +} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr b/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr new file mode 100644 index 000000000000..2dbd69fd3bc1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr @@ -0,0 +1,125 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:2:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: the constant `A` is not of type `i64` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:38 + | +LL | impl Outer + | ^^^^^^^^^^^ expected `i64`, found `usize` + | +note: required by a bound in `Outer` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:14 + | +LL | struct Outer(); + | ^^^^^^^^^^^^ required by this bound in `Outer` + +error: the constant `B` is not of type `i64` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:38 + | +LL | impl Outer + | ^^^^^^^^^^^ expected `i64`, found `usize` + | +note: required by a bound in `Outer` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:28 + | +LL | struct Outer(); + | ^^^^^^^^^^^^ required by this bound in `Outer` + +error: the constant `A` is not of type `i64` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:14:15 + | +LL | fn i() -> Self { + | ^^^^ expected `i64`, found `usize` + | +note: required by a bound in `Outer` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:14 + | +LL | struct Outer(); + | ^^^^^^^^^^^^ required by this bound in `Outer` + +error: the constant `B` is not of type `i64` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:14:15 + | +LL | fn i() -> Self { + | ^^^^ expected `i64`, found `usize` + | +note: required by a bound in `Outer` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:28 + | +LL | struct Outer(); + | ^^^^^^^^^^^^ required by this bound in `Outer` + +error[E0308]: mismatched types + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:17:9 + | +LL | struct Outer(); + | ---------------------------------------- `Outer` defines a struct constructor here, which should be called +... +LL | fn i() -> Self { + | ---- expected `Outer` because of return type +... +LL | Self + | ^^^^ expected `Outer`, found struct constructor + | + = note: expected struct `Outer` + found struct constructor `fn() -> Outer {Outer::}` +help: use parentheses to construct this tuple struct + | +LL | Self() + | ++ + +error: the constant `A` is not of type `i64` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:17:9 + | +LL | Self + | ^^^^ expected `i64`, found `usize` + | +note: required by a bound in `Outer` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:14 + | +LL | struct Outer(); + | ^^^^^^^^^^^^ required by this bound in `Outer` + +error: the constant `B` is not of type `i64` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:17:9 + | +LL | Self + | ^^^^ expected `i64`, found `usize` + | +note: required by a bound in `Outer` + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:28 + | +LL | struct Outer(); + | ^^^^^^^^^^^^ required by this bound in `Outer` + +error[E0599]: no function or associated item named `o` found for struct `Outer` in the current scope + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:25:20 + | +LL | struct Outer(); + | ---------------------------------------- function or associated item `o` not found for this struct +... +LL | Outer::<1, 1>::o(); + | ^ function or associated item not found in `Outer<1, 1>` + +error[E0308]: mismatched types + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:44 + | +LL | impl Outer + | ^ expected `i64`, found `usize` + +error[E0308]: mismatched types + --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:47 + | +LL | impl Outer + | ^ expected `i64`, found `usize` + +error: aborting due to 10 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0308, E0599. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-105821.rs b/tests/ui/const-generics/issues/issue-105821.rs index 282cbe9249d9..e55da461605e 100644 --- a/tests/ui/const-generics/issues/issue-105821.rs +++ b/tests/ui/const-generics/issues/issue-105821.rs @@ -1,5 +1,5 @@ //@ failure-status: 101 -//@ known-bug: unknown +//@ known-bug: rust-lang/rust#125451 //@ normalize-stderr-test "note: .*\n\n" -> "" //@ normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" //@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " From 00b759530e5fc2ffc615e21f3ff14f39cc1c031f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 27 May 2024 16:53:48 -0700 Subject: [PATCH 32/36] Bump backtrace to 0.3.72 --- library/backtrace | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/backtrace b/library/backtrace index e15130618237..5e05efa87905 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit e15130618237eb3e2d4b622549f9647b4c1d9ca3 +Subproject commit 5e05efa87905fb5b351a2bc5644d60c57d6d9327 From 3ec9d8db2769f0743881d209ec789e9df878fa05 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 27 May 2024 17:05:32 -0700 Subject: [PATCH 33/36] Sync libstd deps with backtrace --- Cargo.lock | 32 ++++++++++++++++++++++++++------ library/std/Cargo.toml | 4 ++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e8d179e5365..6e86f6c02f17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,18 @@ name = "addr2line" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli 0.28.1", +] + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "compiler_builtins", - "gimli", + "gimli 0.29.0", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -287,7 +296,7 @@ version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ - "addr2line", + "addr2line 0.21.0", "cc", "cfg-if", "libc", @@ -1575,6 +1584,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + [[package]] name = "glob" version = "0.3.1" @@ -3234,7 +3254,7 @@ dependencies = [ name = "run_make_support" version = "0.0.0" dependencies = [ - "gimli", + "gimli 0.28.1", "object 0.34.0", "regex", "similar", @@ -5130,7 +5150,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "std" version = "0.0.0" dependencies = [ - "addr2line", + "addr2line 0.22.0", "alloc", "cfg-if", "compiler_builtins", @@ -5409,7 +5429,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b" dependencies = [ - "gimli", + "gimli 0.28.1", "hashbrown", "object 0.32.2", "tracing", @@ -5909,7 +5929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b" dependencies = [ "compiler_builtins", - "gimli", + "gimli 0.28.1", "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index bc78c63c577c..79a504c5a5e2 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -24,11 +24,11 @@ hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate -rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } +rustc-demangle = { version = "0.1.24", features = ['rustc-dep-of-std'] } [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] miniz_oxide = { version = "0.7.0", optional = true, default-features = false } -addr2line = { version = "0.21.0", optional = true, default-features = false } +addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true } From 4277ddf54e0a511f196bf3b411d26436f5717479 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 28 May 2024 05:12:58 +0000 Subject: [PATCH 34/36] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 3b24a903d3af..cf698c31801f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -a59072ec4fb6824213df5e9de8cae4812fd4fe97 +d86e1229411c086e1267c80dd9872959ca13b8b9 From 822c3203c65a16bbe14c1b92894ad7fd72ebb432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 28 May 2024 08:36:00 +0000 Subject: [PATCH 35/36] remove legacy rustsrc folder --- src/ci/docker/run.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 22dcb808c743..a4c59b3067ea 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -270,7 +270,6 @@ else args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION" args="$args --volume $objdir:/checkout/obj" args="$args --volume $HOME/.cargo:/cargo" - args="$args --volume $HOME/rustsrc:$HOME/rustsrc" args="$args --volume /tmp/toolstate:/tmp/toolstate" id=$(id -u) From f0273664ce275afe78a25b75f001b77d09186113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 28 May 2024 08:52:33 +0000 Subject: [PATCH 36/36] document DIST_TRY_BUILD --- src/ci/github-actions/jobs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 05470eebf014..174aaeec6b50 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -61,6 +61,12 @@ envs: try: <<: *production + # The following env var activates faster `try` builds in `opt-dist` by, e.g. + # - building only the more commonly useful components (we rarely need e.g. rust-docs in try + # builds) + # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain + # + # If you *want* these to happen however, temporarily uncomment it before triggering a try build. DIST_TRY_BUILD: 1 auto: