about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-27 17:49:56 +0000
committerbors <bors@rust-lang.org>2023-01-27 17:49:56 +0000
commitef982929c0b653436a6ea6892a2a839fba7c8b57 (patch)
tree6902983da8c04d8a2ffd9779c84a1ea89f78366f
parent7919ef0ec5776c72dace7fec1c68551a617505ad (diff)
parentc64f4c41f76581807bf7e063ded17f7da51b4478 (diff)
downloadrust-ef982929c0b653436a6ea6892a2a839fba7c8b57.tar.gz
rust-ef982929c0b653436a6ea6892a2a839fba7c8b57.zip
Auto merge of #107372 - JohnTitor:rollup-zkl2ges, r=JohnTitor
Rollup of 9 pull requests

Successful merges:

 - #106806 (Replace format flags u32 by enums and bools.)
 - #107194 (Remove dependency on slice_internals feature in rustc_ast)
 - #107234 (Revisit fix_is_ci_llvm_available logic)
 - #107316 (Update snap from `1.0.1` to `1.1.0`)
 - #107321 (solver comments + remove `TyCtxt::evaluate_goal`)
 - #107332 (Fix wording from `rustbuild` to `bootstrap`)
 - #107347 (reduce rightward-drift)
 - #107352 (compiler: Fix E0587 explanation)
 - #107357 (Fix infinite loop in rustdoc get_all_import_attributes function)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock5
-rw-r--r--compiler/rustc_ast/Cargo.toml1
-rw-r--r--compiler/rustc_ast/src/format.rs26
-rw-r--r--compiler/rustc_ast/src/lib.rs1
-rw-r--r--compiler/rustc_ast/src/util/unicode.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs29
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs28
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs5
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0587.md2
-rw-r--r--compiler/rustc_parse_format/src/lib.rs65
-rw-r--r--compiler/rustc_parse_format/src/tests.rs75
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs20
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs4
-rw-r--r--src/bootstrap/bootstrap.py2
-rw-r--r--src/bootstrap/config.rs3
-rw-r--r--src/bootstrap/config/tests.rs7
-rw-r--r--src/bootstrap/native.rs65
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs8
-rw-r--r--tests/rustdoc/issue-107350.rs18
21 files changed, 255 insertions, 128 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 23b01f23c50..46dd0397280 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3672,6 +3672,7 @@ name = "rustc_ast"
 version = "0.0.0"
 dependencies = [
  "bitflags",
+ "memchr",
  "rustc_data_structures",
  "rustc_index",
  "rustc_lexer",
@@ -5215,9 +5216,9 @@ checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
 
 [[package]]
 name = "snap"
-version = "1.0.1"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
+checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
 
 [[package]]
 name = "snapbox"
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index 9253b7e6891..10d7fa1db60 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 
 [dependencies]
 bitflags = "1.2.1"
+memchr = "2.5.0"
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs
index da05b09b37d..d021bea5eca 100644
--- a/compiler/rustc_ast/src/format.rs
+++ b/compiler/rustc_ast/src/format.rs
@@ -227,8 +227,30 @@ pub struct FormatOptions {
     pub alignment: Option<FormatAlignment>,
     /// The fill character. E.g. the `.` in `{:.>10}`.
     pub fill: Option<char>,
-    /// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
-    pub flags: u32,
+    /// The `+` or `-` flag.
+    pub sign: Option<FormatSign>,
+    /// The `#` flag.
+    pub alternate: bool,
+    /// The `0` flag. E.g. the `0` in `{:02x}`.
+    pub zero_pad: bool,
+    /// The `x` or `X` flag (for `Debug` only). E.g. the `x` in `{:x?}`.
+    pub debug_hex: Option<FormatDebugHex>,
+}
+
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
+pub enum FormatSign {
+    /// The `+` flag.
+    Plus,
+    /// The `-` flag.
+    Minus,
+}
+
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
+pub enum FormatDebugHex {
+    /// The `x` flag in `{:x?}`.
+    Lower,
+    /// The `X` flag in `{:X?}`.
+    Upper,
 }
 
 #[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 0f8ebcfdc15..23c32fa96ca 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -16,7 +16,6 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(negative_impls)]
-#![feature(slice_internals)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs
index 0eae791b25e..6f57d66b227 100644
--- a/compiler/rustc_ast/src/util/unicode.rs
+++ b/compiler/rustc_ast/src/util/unicode.rs
@@ -17,7 +17,7 @@ pub fn contains_text_flow_control_chars(s: &str) -> bool {
     // U+2069 - E2 81 A9
     let mut bytes = s.as_bytes();
     loop {
-        match core::slice::memchr::memchr(0xE2, bytes) {
+        match memchr::memchr(0xE2, bytes) {
             Some(idx) => {
                 // bytes are valid UTF-8 -> E2 must be followed by two bytes
                 let ch = &bytes[idx..idx + 3];
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index 776b532b0de..e7dd0b18a03 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -137,26 +137,43 @@ fn make_format_spec<'hir>(
         }
         Err(_) => ctx.expr(sp, hir::ExprKind::Err),
     };
-    let fill = ctx.expr_char(sp, placeholder.format_options.fill.unwrap_or(' '));
+    let &FormatOptions {
+        ref width,
+        ref precision,
+        alignment,
+        fill,
+        sign,
+        alternate,
+        zero_pad,
+        debug_hex,
+    } = &placeholder.format_options;
+    let fill = ctx.expr_char(sp, fill.unwrap_or(' '));
     let align = ctx.expr_lang_item_type_relative(
         sp,
         hir::LangItem::FormatAlignment,
-        match placeholder.format_options.alignment {
+        match alignment {
             Some(FormatAlignment::Left) => sym::Left,
             Some(FormatAlignment::Right) => sym::Right,
             Some(FormatAlignment::Center) => sym::Center,
             None => sym::Unknown,
         },
     );
-    let flags = ctx.expr_u32(sp, placeholder.format_options.flags);
-    let prec = make_count(ctx, sp, &placeholder.format_options.precision, argmap);
-    let width = make_count(ctx, sp, &placeholder.format_options.width, argmap);
+    // This needs to match `FlagV1` in library/core/src/fmt/mod.rs.
+    let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
+        | ((sign == Some(FormatSign::Minus)) as u32) << 1
+        | (alternate as u32) << 2
+        | (zero_pad as u32) << 3
+        | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4
+        | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5;
+    let flags = ctx.expr_u32(sp, flags);
+    let precision = make_count(ctx, sp, &precision, argmap);
+    let width = make_count(ctx, sp, &width, argmap);
     let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
         sp,
         hir::LangItem::FormatPlaceholder,
         sym::new,
     ));
-    let args = ctx.arena.alloc_from_iter([position, fill, align, flags, prec, width]);
+    let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]);
     ctx.expr_call_mut(sp, format_placeholder_new, args)
 }
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 99ffa19016f..cacfe9eb2f1 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -6,7 +6,10 @@ use rustc_ast::token;
 use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
 use rustc_ast::{self as ast, BlockCheckMode};
-use rustc_ast::{FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatTrait};
+use rustc_ast::{
+    FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign,
+    FormatTrait,
+};
 use std::fmt::Write;
 
 impl<'a> State<'a> {
@@ -675,17 +678,15 @@ pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> St
                     Some(FormatAlignment::Center) => template.push_str("^"),
                     None => {}
                 }
-                let flags = p.format_options.flags;
-                if flags >> (rustc_parse_format::FlagSignPlus as usize) & 1 != 0 {
-                    template.push('+');
-                }
-                if flags >> (rustc_parse_format::FlagSignMinus as usize) & 1 != 0 {
-                    template.push('-');
+                match p.format_options.sign {
+                    Some(FormatSign::Plus) => template.push('+'),
+                    Some(FormatSign::Minus) => template.push('-'),
+                    None => {}
                 }
-                if flags >> (rustc_parse_format::FlagAlternate as usize) & 1 != 0 {
+                if p.format_options.alternate {
                     template.push('#');
                 }
-                if flags >> (rustc_parse_format::FlagSignAwareZeroPad as usize) & 1 != 0 {
+                if p.format_options.zero_pad {
                     template.push('0');
                 }
                 if let Some(width) = &p.format_options.width {
@@ -709,11 +710,10 @@ pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> St
                         }
                     }
                 }
-                if flags >> (rustc_parse_format::FlagDebugLowerHex as usize) & 1 != 0 {
-                    template.push('x');
-                }
-                if flags >> (rustc_parse_format::FlagDebugUpperHex as usize) & 1 != 0 {
-                    template.push('X');
+                match p.format_options.debug_hex {
+                    Some(FormatDebugHex::Lower) => template.push('x'),
+                    Some(FormatDebugHex::Upper) => template.push('X'),
+                    None => {}
                 }
                 template.push_str(match p.format_trait {
                     FormatTrait::Display => "",
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 469f0dc1303..e93a23394c0 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -4,7 +4,7 @@ use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{
     Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
     FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
-    FormatOptions, FormatPlaceholder, FormatTrait,
+    FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, Applicability, MultiSpan, PResult};
@@ -435,7 +435,16 @@ pub fn make_format_args(
                     format_options: FormatOptions {
                         fill: format.fill,
                         alignment,
-                        flags: format.flags,
+                        sign: format.sign.map(|s| match s {
+                            parse::Sign::Plus => FormatSign::Plus,
+                            parse::Sign::Minus => FormatSign::Minus,
+                        }),
+                        alternate: format.alternate,
+                        zero_pad: format.zero_pad,
+                        debug_hex: format.debug_hex.map(|s| match s {
+                            parse::DebugHex::Lower => FormatDebugHex::Lower,
+                            parse::DebugHex::Upper => FormatDebugHex::Upper,
+                        }),
                         precision,
                         width,
                     },
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index d9a73c7a5c9..240a9d2f371 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -295,9 +295,8 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
                 DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator
             ) {
                 return None;
-            } else if ignore_unused_generics
-                && tcx.generics_of(def_id).requires_monomorphization(tcx)
-            {
+            }
+            if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) {
                 return None;
             }
             Some(local_def_id.to_def_id())
diff --git a/compiler/rustc_error_codes/src/error_codes/E0587.md b/compiler/rustc_error_codes/src/error_codes/E0587.md
index ee9031dc379..d7998af85b9 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0587.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0587.md
@@ -11,6 +11,6 @@ You cannot use `packed` and `align` hints on a same type. If you want to pack a
 type to a given size, you should provide a size to packed:
 
 ```
-#[repr(packed)] // ok!
+#[repr(packed(8))] // ok!
 struct Umbrella(i32);
 ```
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 7b016cadac3..a6dfcd29762 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -16,7 +16,6 @@
 
 pub use Alignment::*;
 pub use Count::*;
-pub use Flag::*;
 pub use Piece::*;
 pub use Position::*;
 
@@ -111,8 +110,14 @@ pub struct FormatSpec<'a> {
     pub fill: Option<char>,
     /// Optionally specified alignment.
     pub align: Alignment,
-    /// Packed version of various flags provided.
-    pub flags: u32,
+    /// The `+` or `-` flag.
+    pub sign: Option<Sign>,
+    /// The `#` flag.
+    pub alternate: bool,
+    /// The `0` flag.
+    pub zero_pad: bool,
+    /// The `x` or `X` flag. (Only for `Debug`.)
+    pub debug_hex: Option<DebugHex>,
     /// The integer precision to use.
     pub precision: Count<'a>,
     /// The span of the precision formatting flag (for diagnostics).
@@ -162,24 +167,22 @@ pub enum Alignment {
     AlignUnknown,
 }
 
-/// Various flags which can be applied to format strings. The meaning of these
-/// flags is defined by the formatters themselves.
+/// Enum for the sign flags.
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub enum Flag {
-    /// A `+` will be used to denote positive numbers.
-    FlagSignPlus,
-    /// A `-` will be used to denote negative numbers. This is the default.
-    FlagSignMinus,
-    /// An alternate form will be used for the value. In the case of numbers,
-    /// this means that the number will be prefixed with the supplied string.
-    FlagAlternate,
-    /// For numbers, this means that the number will be padded with zeroes,
-    /// and the sign (`+` or `-`) will precede them.
-    FlagSignAwareZeroPad,
-    /// For Debug / `?`, format integers in lower-case hexadecimal.
-    FlagDebugLowerHex,
-    /// For Debug / `?`, format integers in upper-case hexadecimal.
-    FlagDebugUpperHex,
+pub enum Sign {
+    /// The `+` flag.
+    Plus,
+    /// The `-` flag.
+    Minus,
+}
+
+/// Enum for the debug hex flags.
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum DebugHex {
+    /// The `x` flag in `{:x?}`.
+    Lower,
+    /// The `X` flag in `{:X?}`.
+    Upper,
 }
 
 /// A count is used for the precision and width parameters of an integer, and
@@ -597,7 +600,10 @@ impl<'a> Parser<'a> {
         let mut spec = FormatSpec {
             fill: None,
             align: AlignUnknown,
-            flags: 0,
+            sign: None,
+            alternate: false,
+            zero_pad: false,
+            debug_hex: None,
             precision: CountImplied,
             precision_span: None,
             width: CountImplied,
@@ -626,13 +632,13 @@ impl<'a> Parser<'a> {
         }
         // Sign flags
         if self.consume('+') {
-            spec.flags |= 1 << (FlagSignPlus as u32);
+            spec.sign = Some(Sign::Plus);
         } else if self.consume('-') {
-            spec.flags |= 1 << (FlagSignMinus as u32);
+            spec.sign = Some(Sign::Minus);
         }
         // Alternate marker
         if self.consume('#') {
-            spec.flags |= 1 << (FlagAlternate as u32);
+            spec.alternate = true;
         }
         // Width and precision
         let mut havewidth = false;
@@ -647,7 +653,7 @@ impl<'a> Parser<'a> {
                 spec.width_span = Some(self.span(end - 1, end + 1));
                 havewidth = true;
             } else {
-                spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
+                spec.zero_pad = true;
             }
         }
 
@@ -678,14 +684,14 @@ impl<'a> Parser<'a> {
         // Optional radix followed by the actual format specifier
         if self.consume('x') {
             if self.consume('?') {
-                spec.flags |= 1 << (FlagDebugLowerHex as u32);
+                spec.debug_hex = Some(DebugHex::Lower);
                 spec.ty = "?";
             } else {
                 spec.ty = "x";
             }
         } else if self.consume('X') {
             if self.consume('?') {
-                spec.flags |= 1 << (FlagDebugUpperHex as u32);
+                spec.debug_hex = Some(DebugHex::Upper);
                 spec.ty = "?";
             } else {
                 spec.ty = "X";
@@ -708,7 +714,10 @@ impl<'a> Parser<'a> {
         let mut spec = FormatSpec {
             fill: None,
             align: AlignUnknown,
-            flags: 0,
+            sign: None,
+            alternate: false,
+            zero_pad: false,
+            debug_hex: None,
             precision: CountImplied,
             precision_span: None,
             width: CountImplied,
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 2992ba845ab..45314e2fb55 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -10,7 +10,10 @@ fn fmtdflt() -> FormatSpec<'static> {
     return FormatSpec {
         fill: None,
         align: AlignUnknown,
-        flags: 0,
+        sign: None,
+        alternate: false,
+        zero_pad: false,
+        debug_hex: None,
         precision: CountImplied,
         width: CountImplied,
         precision_span: None,
@@ -126,7 +129,10 @@ fn format_type() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 width: CountImplied,
                 precision_span: None,
@@ -147,7 +153,10 @@ fn format_align_fill() {
             format: FormatSpec {
                 fill: None,
                 align: AlignRight,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 width: CountImplied,
                 precision_span: None,
@@ -165,7 +174,10 @@ fn format_align_fill() {
             format: FormatSpec {
                 fill: Some('0'),
                 align: AlignLeft,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 width: CountImplied,
                 precision_span: None,
@@ -183,7 +195,10 @@ fn format_align_fill() {
             format: FormatSpec {
                 fill: Some('*'),
                 align: AlignLeft,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 width: CountImplied,
                 precision_span: None,
@@ -204,7 +219,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 precision_span: None,
                 width: CountIs(10),
@@ -222,7 +240,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountIs(10),
                 precision_span: Some(InnerSpan { start: 6, end: 9 }),
                 width: CountIsParam(10),
@@ -240,7 +261,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountIs(10),
                 precision_span: Some(InnerSpan { start: 6, end: 9 }),
                 width: CountIsParam(0),
@@ -258,7 +282,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountIsStar(0),
                 precision_span: Some(InnerSpan { start: 3, end: 5 }),
                 width: CountImplied,
@@ -276,7 +303,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountIsParam(10),
                 width: CountImplied,
                 precision_span: Some(InnerSpan::new(3, 7)),
@@ -294,7 +324,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountIsName("b", InnerSpan { start: 6, end: 7 }),
                 precision_span: Some(InnerSpan { start: 5, end: 8 }),
                 width: CountIsName("a", InnerSpan { start: 3, end: 4 }),
@@ -312,7 +345,10 @@ fn format_counts() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: 0,
+                sign: None,
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountIs(4),
                 precision_span: Some(InnerSpan { start: 3, end: 5 }),
                 width: CountImplied,
@@ -333,7 +369,10 @@ fn format_flags() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: (1 << FlagSignMinus as u32),
+                sign: Some(Sign::Minus),
+                alternate: false,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 width: CountImplied,
                 precision_span: None,
@@ -351,7 +390,10 @@ fn format_flags() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
+                sign: Some(Sign::Plus),
+                alternate: true,
+                zero_pad: false,
+                debug_hex: None,
                 precision: CountImplied,
                 width: CountImplied,
                 precision_span: None,
@@ -374,7 +416,10 @@ fn format_mixture() {
                 format: FormatSpec {
                     fill: None,
                     align: AlignUnknown,
-                    flags: 0,
+                    sign: None,
+                    alternate: false,
+                    zero_pad: false,
+                    debug_hex: None,
                     precision: CountImplied,
                     width: CountImplied,
                     precision_span: None,
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index f44648c95d7..7880cbad5fe 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -141,17 +141,6 @@ type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
 /// solver, merge the two responses again.
 pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
 
-pub trait TyCtxtExt<'tcx> {
-    fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx>;
-}
-
-impl<'tcx> TyCtxtExt<'tcx> for TyCtxt<'tcx> {
-    fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx> {
-        let mut search_graph = search_graph::SearchGraph::new(self);
-        EvalCtxt::evaluate_canonical_goal(self, &mut search_graph, goal)
-    }
-}
-
 pub trait InferCtxtEvalExt<'tcx> {
     /// Evaluates a goal from **outside** of the trait solver.
     ///
@@ -194,6 +183,15 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         self.infcx.tcx
     }
 
+    /// The entry point of the solver.
+    ///
+    /// This function deals with (coinductive) cycles, overflow, and caching
+    /// and then calls [`EvalCtxt::compute_goal`] which contains the actual
+    /// logic of the solver.
+    ///
+    /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal]
+    /// if you're inside of the solver or [InferCtxtEvalExt::evaluate_root_goal] if you're
+    /// outside of it.
     #[instrument(level = "debug", skip(tcx, search_graph), ret)]
     fn evaluate_canonical_goal(
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index b583705ac43..30902c2bc45 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -28,8 +28,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // To only compute normalization once for each projection we only
         // normalize if the expected term is an unconstrained inference variable.
         //
-        // E.g. for `<T as Trait>::Assoc = u32` we recursively compute the goal
-        // `exists<U> <T as Trait>::Assoc = U` and then take the resulting type for
+        // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
+        // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
         // `U` and equate it with `u32`. This means that we don't need a separate
         // projection cache in the solver.
         if self.term_is_fully_unconstrained(goal) {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 9cf43fc7a21..abdd12127d3 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -712,7 +712,7 @@ class RustBuild(object):
 
     def build_bootstrap(self, color):
         """Build bootstrap"""
-        print("Building rustbuild")
+        print("Building bootstrap")
         build_dir = os.path.join(self.build_dir, "bootstrap")
         if self.clean and os.path.exists(build_dir):
             shutil.rmtree(build_dir)
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index b41d60d51a8..fdd659c60ca 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -965,6 +965,9 @@ impl Config {
         config.changelog_seen = toml.changelog_seen;
 
         let build = toml.build.unwrap_or_default();
+        if let Some(file_build) = build.build {
+            config.build = TargetSelection::from_user(&file_build);
+        };
 
         set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from)));
         // NOTE: Bootstrap spawns various commands with different working directories.
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index c30c9131745..681ecbfeb5b 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -19,6 +19,13 @@ fn download_ci_llvm() {
     assert_eq!(parse_llvm(""), if_available);
     assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available);
     assert!(!parse_llvm("rust.channel = \"stable\""));
+    assert!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""));
+    assert!(parse_llvm(
+        "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-available\""
+    ));
+    assert!(!parse_llvm(
+        "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-available\""
+    ));
 }
 
 // FIXME: add test for detecting `src` and `out`
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index cb5706ca0a6..3acc2d4b5c4 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -180,43 +180,40 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
     // https://doc.rust-lang.org/rustc/platform-support.html#tier-1
     let supported_platforms = [
         // tier 1
-        "aarch64-unknown-linux-gnu",
-        "i686-pc-windows-gnu",
-        "i686-pc-windows-msvc",
-        "i686-unknown-linux-gnu",
-        "x86_64-unknown-linux-gnu",
-        "x86_64-apple-darwin",
-        "x86_64-pc-windows-gnu",
-        "x86_64-pc-windows-msvc",
+        ("aarch64-unknown-linux-gnu", false),
+        ("i686-pc-windows-gnu", false),
+        ("i686-pc-windows-msvc", false),
+        ("i686-unknown-linux-gnu", false),
+        ("x86_64-unknown-linux-gnu", true),
+        ("x86_64-apple-darwin", true),
+        ("x86_64-pc-windows-gnu", true),
+        ("x86_64-pc-windows-msvc", true),
         // tier 2 with host tools
-        "aarch64-apple-darwin",
-        "aarch64-pc-windows-msvc",
-        "aarch64-unknown-linux-musl",
-        "arm-unknown-linux-gnueabi",
-        "arm-unknown-linux-gnueabihf",
-        "armv7-unknown-linux-gnueabihf",
-        "mips-unknown-linux-gnu",
-        "mips64-unknown-linux-gnuabi64",
-        "mips64el-unknown-linux-gnuabi64",
-        "mipsel-unknown-linux-gnu",
-        "powerpc-unknown-linux-gnu",
-        "powerpc64-unknown-linux-gnu",
-        "powerpc64le-unknown-linux-gnu",
-        "riscv64gc-unknown-linux-gnu",
-        "s390x-unknown-linux-gnu",
-        "x86_64-unknown-freebsd",
-        "x86_64-unknown-illumos",
-        "x86_64-unknown-linux-musl",
-        "x86_64-unknown-netbsd",
+        ("aarch64-apple-darwin", false),
+        ("aarch64-pc-windows-msvc", false),
+        ("aarch64-unknown-linux-musl", false),
+        ("arm-unknown-linux-gnueabi", false),
+        ("arm-unknown-linux-gnueabihf", false),
+        ("armv7-unknown-linux-gnueabihf", false),
+        ("mips-unknown-linux-gnu", false),
+        ("mips64-unknown-linux-gnuabi64", false),
+        ("mips64el-unknown-linux-gnuabi64", false),
+        ("mipsel-unknown-linux-gnu", false),
+        ("powerpc-unknown-linux-gnu", false),
+        ("powerpc64-unknown-linux-gnu", false),
+        ("powerpc64le-unknown-linux-gnu", false),
+        ("riscv64gc-unknown-linux-gnu", false),
+        ("s390x-unknown-linux-gnu", false),
+        ("x86_64-unknown-freebsd", false),
+        ("x86_64-unknown-illumos", false),
+        ("x86_64-unknown-linux-musl", false),
+        ("x86_64-unknown-netbsd", false),
     ];
-    if !supported_platforms.contains(&&*config.build.triple) {
-        return false;
-    }
 
-    let triple = &*config.build.triple;
-    if (triple == "aarch64-unknown-linux-gnu" || triple.contains("i686")) && asserts {
-        // No alt builder for aarch64-unknown-linux-gnu today.
-        return false;
+    if !supported_platforms.contains(&(&*config.build.triple, asserts)) {
+        if asserts == true || !supported_platforms.contains(&(&*config.build.triple, true)) {
+            return false;
+        }
     }
 
     if CiEnv::is_ci() {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a4d86981c26..d6a264f797a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2112,10 +2112,12 @@ fn get_all_import_attributes<'hir>(
 ) {
     let hir_map = tcx.hir();
     let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
+    let mut visited = FxHashSet::default();
     // If the item is an import and has at least a path with two parts, we go into it.
     while let hir::ItemKind::Use(path, _) = item.kind &&
         path.segments.len() > 1 &&
-        let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res
+        let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res &&
+        visited.insert(def_id)
     {
         if let Some(hir::Node::Item(parent_item)) = hir_map.get_if_local(def_id) {
             // We add the attributes from this import into the list.
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index a8f8da67b51..659063b97e7 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -711,8 +711,8 @@ pub struct FormatSpec<'tcx> {
     pub fill: Option<char>,
     /// Optionally specified alignment.
     pub align: Alignment,
-    /// Packed version of various flags provided, see [`rustc_parse_format::Flag`].
-    pub flags: u32,
+    /// Whether all flag options are set to default (no flags specified).
+    pub no_flags: bool,
     /// Represents either the maximum width or the integer precision.
     pub precision: Count<'tcx>,
     /// The minimum width, will be padded according to `width`/`align`
@@ -728,7 +728,7 @@ impl<'tcx> FormatSpec<'tcx> {
         Some(Self {
             fill: spec.fill,
             align: spec.align,
-            flags: spec.flags,
+            no_flags: spec.sign.is_none() && !spec.alternate && !spec.zero_pad && spec.debug_hex.is_none(),
             precision: Count::new(
                 FormatParamUsage::Precision,
                 spec.precision,
@@ -773,7 +773,7 @@ impl<'tcx> FormatSpec<'tcx> {
         self.width.is_implied()
             && self.precision.is_implied()
             && self.align == Alignment::AlignUnknown
-            && self.flags == 0
+            && self.no_flags
     }
 }
 
diff --git a/tests/rustdoc/issue-107350.rs b/tests/rustdoc/issue-107350.rs
new file mode 100644
index 00000000000..75f378ed249
--- /dev/null
+++ b/tests/rustdoc/issue-107350.rs
@@ -0,0 +1,18 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/107350>.
+// It shouldn't loop indefinitely.
+
+#![crate_name = "foo"]
+
+// @has 'foo/oops/enum.OhNo.html'
+
+pub mod oops {
+    pub use crate::oops::OhNo;
+
+    mod inner {
+        pub enum OhNo {
+            Item = 1,
+        }
+    }
+
+    pub use self::inner::*;
+}