From f94fa6bee3bf1c7d313452db0bafbce0960196ff Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 7 May 2024 18:08:36 -0600 Subject: [PATCH 01/18] 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 b2b627fe6a9cc..16c97284104d4 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/18] 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 16c97284104d4..b82351ea1fa3c 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/18] 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 b82351ea1fa3c..6a77f9f63a88d 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/18] 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 877e5b75912ea..e7cc2cb1a0b5a 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 fdeccb9070082..11a8d218ae3db 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 278212342ec2b2659c0e5b6e0038642fb6f37347 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Sat, 25 May 2024 10:38:18 +0800 Subject: [PATCH 05/18] 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 8f18055f83817..8349727ade7fb 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 3901b82eb52ec..5c2b9198a89da 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 06/18] Add "better" edition handling on lint-docs tool --- compiler/rustc_lint_defs/src/builtin.rs | 4 ++-- src/tools/lint-docs/src/lib.rs | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 5369454577249..8727dcfad9ab4 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 22ab576b07762..c79b377727abf 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") { + 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 { - cmd.arg("--edition=2018"); + // 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 07/18] 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 228521747ede7..61655dad63857 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 19119a073c5fa..54c900a36b8fe 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 08/18] 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 2f9eaf51c3414..bfe3622e40d37 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 09/18] 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 6a77f9f63a88d..77c4ef957ac52 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 10/18] 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 1e3ed0f7c49f1..c9b3c62dc4167 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 11/18] 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 77c4ef957ac52..b40a585699b10 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 12/18] 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 b40a585699b10..2954284bda796 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 13/18] 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 c9b3c62dc4167..1fb65c845aff6 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 14/18] 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 1fb65c845aff6..9a527073602e6 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 bbcdb4fd3e4df3554e6d406a2f2e9e47114521f6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 26 May 2024 20:03:47 -0400 Subject: [PATCH 15/18] 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 44bf8fd2d93ee..119f5da725a35 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 b760b86a7bfb4..a3797669af0ec 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 dd1d209389dcf..50c93e9f1d7e2 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 1475e53c47c29..ed942cc50bb42 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 1de7a0f7bc739..bbfadbb5c3087 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 e6c582667ba57..af08f50f65596 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 b3e93748a1665..87ee5f5362803 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 695525e755de9..19bb943e6bccd 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 825034cf96a91..c2cf5b6b7125b 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 b0e72eaf5a4cd..bf6ab80006455 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 34748afa863d0..d39422b2b04d3 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 d025dc360a248..e107c2c12bd65 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 2b2b9392a7093..02e5174a715d1 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 320d49ea64674..1e36f034cc220 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 8ca7a465c2a8b..6ad4b7c40fb2a 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 941911c223090..ccd0c7cb10c49 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 dc46b470b6f48..7fb5e9aadae79 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 48193754077d0..8e946bc8b314d 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 40a0dbeb2c222..3bf0fc4443264 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 d138cd9ceb9d4..40871dd4adafd 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 c7b15c64b0869..6628eb247d655 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 1c4462fc1dcb3..7cb1a6f727371 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 7da7f69a9543b..a887047f62f21 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 79cfeb71d47e4..70cd833aea881 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 e2cfabfdafaa4..fb16cf5bd3632 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 571c6e918dcbe..f394b3c990ce5 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 40f3db89df56e..41b5e6d4dcc41 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 5a3d90221ebd8..cacaa859d526d 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 79f36cfe56957..4ae475d35d14d 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 be20924670c37..572dbe3bb821d 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 77ac4be35ea1f..87c8b1cda5041 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 67ffb8a58b5ad..58447f6d6a31d 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 617e8a5436569..38950c97c9d58 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 16/18] 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 92e6a22b4b916..5e8d179e53653 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 3bf0fc4443264..6416bbbe889cb 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 d432aeada2c88..b5b36cbd1ba13 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 6628eb247d655..7a516b9f2c809 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 70cd833aea881..f24074cb472d9 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 958e7e401684b..dcab202330867 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 41b5e6d4dcc41..5cf96d298375b 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 cef3f4e8ce05f..18a09067a2c9c 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 5336b915a1d38..e50d59ba5f0e6 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 405aba30241b7..501311ff72f71 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 77fe30a466087..e7e893f27daa9 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 c77414afc52c7..d9485e91479f4 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 4a461b5b5f3c8..217c056d0baee 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 17/18] 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 40871dd4adafd..500c298a78e38 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 d9485e91479f4..e49db171a534a 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 4e12c6b3d6713..48a6f79993cc6 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 e4abfaeb620e75a1f84b94dcb89e41eac495f52b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 May 2024 11:37:27 +0200 Subject: [PATCH 18/18] 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 9a6ae18abeade..55d65fe898741 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 b3d7cc777a019..0000000000000 --- 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 0000000000000..f93080dfdc4fe --- /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"); +}