about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-04-28 17:22:11 +0000
committerbors <bors@rust-lang.org>2025-04-28 17:22:11 +0000
commit25cdf1f67463c9365d8d83778c933ec7480e940b (patch)
tree3692f9b718b4427606d5f966f253b81328268486 /compiler
parent7d65abfe80f9eee93296d1ce08f845c9bf7039f8 (diff)
parentdd3ca71b4e63a2eb167b37879abb2830af45a0b3 (diff)
downloadrust-25cdf1f67463c9365d8d83778c933ec7480e940b.tar.gz
rust-25cdf1f67463c9365d8d83778c933ec7480e940b.zip
Auto merge of #140388 - GuillaumeGomez:rollup-aj9o3ch, r=GuillaumeGomez
Rollup of 7 pull requests

Successful merges:

 - #140056 (Fix a wrong error message in 2024 edition)
 - #140220 (Fix detection of main function if there are expressions around it)
 - #140249 (Remove `weak` alias terminology)
 - #140316 (Introduce `BoxMarker` to improve pretty-printing correctness)
 - #140347 (ci: clean more disk space in codebuild)
 - #140349 (ci: use aws codebuild for the `dist-x86_64-linux` job)
 - #140379 (rustc-dev-guide subtree update)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_pretty/src/lib.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pp.rs40
-rw-r--r--compiler/rustc_ast_pretty/src/pp/convenience.rs18
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs137
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs128
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs168
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/tests.rs6
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs4
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs383
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/static_mut_refs.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/error.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs42
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs (renamed from compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs)12
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs2
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs6
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs2
-rw-r--r--compiler/rustc_type_ir/src/flags.rs8
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs14
-rw-r--r--compiler/rustc_type_ir/src/relate.rs2
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs6
53 files changed, 566 insertions, 519 deletions
diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs
index 84d9ce278a2..1079ccccb03 100644
--- a/compiler/rustc_ast_pretty/src/lib.rs
+++ b/compiler/rustc_ast_pretty/src/lib.rs
@@ -2,6 +2,7 @@
 #![allow(internal_features)]
 #![doc(rust_logo)]
 #![feature(box_patterns)]
+#![feature(negative_impls)]
 #![feature(rustdoc_internals)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs
index e4fd7e94fde..142c80b8e39 100644
--- a/compiler/rustc_ast_pretty/src/pp.rs
+++ b/compiler/rustc_ast_pretty/src/pp.rs
@@ -234,6 +234,38 @@ struct BufEntry {
     size: isize,
 }
 
+// Boxes opened with methods like `Printer::{cbox,ibox}` must be closed with
+// `Printer::end`. Failure to do so can result in bad indenting, or in extreme
+// cases, cause no output to be produced at all.
+//
+// Box opening and closing used to be entirely implicit, which was hard to
+// understand and easy to get wrong. This marker type is now returned from the
+// box opening methods and forgotten by `Printer::end`. Any marker that isn't
+// forgotten will trigger a panic in `drop`. (Closing a box more than once
+// isn't possible because `BoxMarker` doesn't implement `Copy` or `Clone`.)
+//
+// FIXME(nnethercote): the panic in `drop` is currently disabled because a few
+// places fail to close their boxes. It can be enabled once they are fixed.
+//
+// Note: it would be better to make open/close mismatching impossible and avoid
+// the need for this marker type altogether by having functions like
+// `with_ibox` that open a box, call a closure, and then close the box. That
+// would work for simple cases, but box lifetimes sometimes interact with
+// complex control flow and across function boundaries in ways that are
+// difficult to handle with such a technique.
+#[must_use]
+pub struct BoxMarker;
+
+impl !Clone for BoxMarker {}
+impl !Copy for BoxMarker {}
+
+impl Drop for BoxMarker {
+    fn drop(&mut self) {
+        // FIXME(nnethercote): enable once the bad cases are fixed
+        //panic!("BoxMarker not ended with `Printer::end()`");
+    }
+}
+
 impl Printer {
     pub fn new() -> Self {
         Printer {
@@ -270,7 +302,8 @@ impl Printer {
         }
     }
 
-    fn scan_begin(&mut self, token: BeginToken) {
+    // This is is where `BoxMarker`s are produced.
+    fn scan_begin(&mut self, token: BeginToken) -> BoxMarker {
         if self.scan_stack.is_empty() {
             self.left_total = 1;
             self.right_total = 1;
@@ -278,15 +311,18 @@ impl Printer {
         }
         let right = self.buf.push(BufEntry { token: Token::Begin(token), size: -self.right_total });
         self.scan_stack.push_back(right);
+        BoxMarker
     }
 
-    fn scan_end(&mut self) {
+    // This is is where `BoxMarker`s are consumed.
+    fn scan_end(&mut self, b: BoxMarker) {
         if self.scan_stack.is_empty() {
             self.print_end();
         } else {
             let right = self.buf.push(BufEntry { token: Token::End, size: -1 });
             self.scan_stack.push_back(right);
         }
+        std::mem::forget(b)
     }
 
     fn scan_break(&mut self, token: BreakToken) {
diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs
index a1c07bb07e4..9b902b38122 100644
--- a/compiler/rustc_ast_pretty/src/pp/convenience.rs
+++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs
@@ -1,25 +1,27 @@
 use std::borrow::Cow;
 
-use crate::pp::{BeginToken, BreakToken, Breaks, IndentStyle, Printer, SIZE_INFINITY, Token};
+use crate::pp::{
+    BeginToken, BoxMarker, BreakToken, Breaks, IndentStyle, Printer, SIZE_INFINITY, Token,
+};
 
 impl Printer {
     /// "raw box"
-    pub fn rbox(&mut self, indent: isize, breaks: Breaks) {
+    pub fn rbox(&mut self, indent: isize, breaks: Breaks) -> BoxMarker {
         self.scan_begin(BeginToken { indent: IndentStyle::Block { offset: indent }, breaks })
     }
 
     /// Inconsistent breaking box
-    pub fn ibox(&mut self, indent: isize) {
+    pub fn ibox(&mut self, indent: isize) -> BoxMarker {
         self.rbox(indent, Breaks::Inconsistent)
     }
 
     /// Consistent breaking box
-    pub fn cbox(&mut self, indent: isize) {
+    pub fn cbox(&mut self, indent: isize) -> BoxMarker {
         self.rbox(indent, Breaks::Consistent)
     }
 
-    pub fn visual_align(&mut self) {
-        self.scan_begin(BeginToken { indent: IndentStyle::Visual, breaks: Breaks::Consistent });
+    pub fn visual_align(&mut self) -> BoxMarker {
+        self.scan_begin(BeginToken { indent: IndentStyle::Visual, breaks: Breaks::Consistent })
     }
 
     pub fn break_offset(&mut self, n: usize, off: isize) {
@@ -30,8 +32,8 @@ impl Printer {
         });
     }
 
-    pub fn end(&mut self) {
-        self.scan_end()
+    pub fn end(&mut self, b: BoxMarker) {
+        self.scan_end(b)
     }
 
     pub fn eof(mut self) -> String {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 62a50c73855..985359e1234 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -26,7 +26,7 @@ use rustc_span::symbol::IdentPrinter;
 use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym};
 
 use crate::pp::Breaks::{Consistent, Inconsistent};
-use crate::pp::{self, Breaks};
+use crate::pp::{self, BoxMarker, Breaks};
 use crate::pprust::state::fixup::FixupContext;
 
 pub enum MacHeader<'a> {
@@ -419,7 +419,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     {
         let mut it = elts.into_iter();
 
-        self.rbox(0, b);
+        let rb = self.rbox(0, b);
         if let Some(first) = it.next() {
             op(self, first);
             for elt in it {
@@ -430,7 +430,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                 op(self, elt);
             }
         }
-        self.end();
+        self.end(rb);
     }
 
     fn commasep<'x, T: 'x, F, I>(&mut self, b: Breaks, elts: I, op: F)
@@ -461,7 +461,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                     self.zerobreak();
                 }
                 if let Some((last, lines)) = cmnt.lines.split_last() {
-                    self.ibox(0);
+                    let ib = self.ibox(0);
 
                     for line in lines {
                         self.word(line.clone());
@@ -471,7 +471,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                     self.word(last.clone());
                     self.space();
 
-                    self.end();
+                    self.end(ib);
                 }
                 self.zerobreak()
             }
@@ -494,14 +494,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                     self.word(line.clone());
                     self.hardbreak()
                 } else {
-                    self.visual_align();
+                    let vb = self.visual_align();
                     for line in &cmnt.lines {
                         if !line.is_empty() {
                             self.word(line.clone());
                         }
                         self.hardbreak();
                     }
-                    self.end();
+                    self.end(vb);
                 }
             }
             CommentStyle::BlankLine => {
@@ -620,7 +620,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) {
-        self.ibox(0);
+        let ib = self.ibox(0);
         match item.unsafety {
             ast::Safety::Unsafe(_) => {
                 self.word("unsafe");
@@ -653,7 +653,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             ast::Safety::Unsafe(_) => self.pclose(),
             ast::Safety::Default | ast::Safety::Safe(_) => {}
         }
-        self.end();
+        self.end(ib);
     }
 
     /// This doesn't deserve to be called "pretty" printing, but it should be
@@ -739,9 +739,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         convert_dollar_crate: bool,
         span: Span,
     ) {
-        if delim == Delimiter::Brace {
-            self.cbox(INDENT_UNIT);
-        }
+        let cb = (delim == Delimiter::Brace).then(|| self.cbox(INDENT_UNIT));
         match header {
             Some(MacHeader::Path(path)) => self.print_path(path, false, 0),
             Some(MacHeader::Keyword(kw)) => self.word(kw),
@@ -763,18 +761,18 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                 if !tts.is_empty() {
                     self.space();
                 }
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.print_tts(tts, convert_dollar_crate);
-                self.end();
+                self.end(ib);
                 let empty = tts.is_empty();
-                self.bclose(span, empty);
+                self.bclose(span, empty, cb.unwrap());
             }
             delim => {
                 let token_str = self.token_kind_to_string(&delim.as_open_token_kind());
                 self.word(token_str);
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.print_tts(tts, convert_dollar_crate);
-                self.end();
+                self.end(ib);
                 let token_str = self.token_kind_to_string(&delim.as_close_token_kind());
                 self.word(token_str);
             }
@@ -828,37 +826,38 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         }
     }
 
-    fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
+    fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) -> (BoxMarker, BoxMarker) {
         let w = w.into();
         // Outer-box is consistent.
-        self.cbox(INDENT_UNIT);
+        let cb = self.cbox(INDENT_UNIT);
         // Head-box is inconsistent.
-        self.ibox(0);
+        let ib = self.ibox(0);
         // Keyword that starts the head.
         if !w.is_empty() {
             self.word_nbsp(w);
         }
+        (cb, ib)
     }
 
-    fn bopen(&mut self) {
+    fn bopen(&mut self, ib: BoxMarker) {
         self.word("{");
-        self.end(); // Close the head-box.
+        self.end(ib);
     }
 
-    fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) {
+    fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, cb: Option<BoxMarker>) {
         let has_comment = self.maybe_print_comment(span.hi());
         if !empty || has_comment {
             self.break_offset_if_not_bol(1, -INDENT_UNIT);
         }
         self.word("}");
-        if close_box {
-            self.end(); // Close the outer-box.
+        if let Some(cb) = cb {
+            self.end(cb);
         }
     }
 
-    fn bclose(&mut self, span: rustc_span::Span, empty: bool) {
-        let close_box = true;
-        self.bclose_maybe_open(span, empty, close_box)
+    fn bclose(&mut self, span: rustc_span::Span, empty: bool, cb: BoxMarker) {
+        let cb = Some(cb);
+        self.bclose_maybe_open(span, empty, cb)
     }
 
     fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
@@ -1014,11 +1013,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
 
     fn block_to_string(&self, blk: &ast::Block) -> String {
         Self::to_string(|s| {
-            // Containing cbox, will be closed by `print_block` at `}`.
-            s.cbox(INDENT_UNIT);
-            // Head-ibox, will be closed by `print_block` after `{`.
-            s.ibox(0);
-            s.print_block(blk)
+            let (cb, ib) = s.head("");
+            s.print_block(blk, cb, ib)
         })
     }
 
@@ -1090,7 +1086,7 @@ impl<'a> State<'a> {
         F: FnMut(&mut State<'_>, &T),
         G: FnMut(&T) -> rustc_span::Span,
     {
-        self.rbox(0, b);
+        let rb = self.rbox(0, b);
         let len = elts.len();
         let mut i = 0;
         for elt in elts {
@@ -1103,7 +1099,7 @@ impl<'a> State<'a> {
                 self.space_if_not_bol();
             }
         }
-        self.end();
+        self.end(rb);
     }
 
     fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
@@ -1172,7 +1168,7 @@ impl<'a> State<'a> {
 
     pub fn print_type(&mut self, ty: &ast::Ty) {
         self.maybe_print_comment(ty.span.lo());
-        self.ibox(0);
+        let ib = self.ibox(0);
         match &ty.kind {
             ast::TyKind::Slice(ty) => {
                 self.word("[");
@@ -1214,12 +1210,12 @@ impl<'a> State<'a> {
                 self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params);
             }
             ast::TyKind::UnsafeBinder(f) => {
-                self.ibox(INDENT_UNIT);
+                let ib = self.ibox(INDENT_UNIT);
                 self.word("unsafe");
                 self.print_generic_params(&f.generic_params);
                 self.nbsp();
                 self.print_type(&f.inner_ty);
-                self.end();
+                self.end(ib);
             }
             ast::TyKind::Path(None, path) => {
                 self.print_path(path, false, 0);
@@ -1277,7 +1273,7 @@ impl<'a> State<'a> {
                 self.print_ty_pat(pat);
             }
         }
-        self.end();
+        self.end(ib);
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) {
@@ -1324,15 +1320,15 @@ impl<'a> State<'a> {
             ast::StmtKind::Let(loc) => {
                 self.print_outer_attributes(&loc.attrs);
                 self.space_if_not_bol();
-                self.ibox(INDENT_UNIT);
+                let ib1 = self.ibox(INDENT_UNIT);
                 if loc.super_.is_some() {
                     self.word_nbsp("super");
                 }
                 self.word_nbsp("let");
 
-                self.ibox(INDENT_UNIT);
+                let ib2 = self.ibox(INDENT_UNIT);
                 self.print_local_decl(loc);
-                self.end();
+                self.end(ib2);
                 if let Some((init, els)) = loc.kind.init_else_opt() {
                     self.nbsp();
                     self.word_space("=");
@@ -1342,14 +1338,14 @@ impl<'a> State<'a> {
                         FixupContext::default(),
                     );
                     if let Some(els) = els {
-                        self.cbox(INDENT_UNIT);
-                        self.ibox(INDENT_UNIT);
+                        let cb = self.cbox(INDENT_UNIT);
+                        let ib = self.ibox(INDENT_UNIT);
                         self.word(" else ");
-                        self.print_block(els);
+                        self.print_block(els, cb, ib);
                     }
                 }
                 self.word(";");
-                self.end(); // `let` ibox
+                self.end(ib1);
             }
             ast::StmtKind::Item(item) => self.print_item(item),
             ast::StmtKind::Expr(expr) => {
@@ -1380,23 +1376,30 @@ impl<'a> State<'a> {
         self.maybe_print_trailing_comment(st.span, None)
     }
 
-    fn print_block(&mut self, blk: &ast::Block) {
-        self.print_block_with_attrs(blk, &[])
+    fn print_block(&mut self, blk: &ast::Block, cb: BoxMarker, ib: BoxMarker) {
+        self.print_block_with_attrs(blk, &[], cb, ib)
     }
 
-    fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
-        self.print_block_maybe_unclosed(blk, &[], false)
+    fn print_block_unclosed_indent(&mut self, blk: &ast::Block, ib: BoxMarker) {
+        self.print_block_maybe_unclosed(blk, &[], None, ib)
     }
 
-    fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
-        self.print_block_maybe_unclosed(blk, attrs, true)
+    fn print_block_with_attrs(
+        &mut self,
+        blk: &ast::Block,
+        attrs: &[ast::Attribute],
+        cb: BoxMarker,
+        ib: BoxMarker,
+    ) {
+        self.print_block_maybe_unclosed(blk, attrs, Some(cb), ib)
     }
 
     fn print_block_maybe_unclosed(
         &mut self,
         blk: &ast::Block,
         attrs: &[ast::Attribute],
-        close_box: bool,
+        cb: Option<BoxMarker>,
+        ib: BoxMarker,
     ) {
         match blk.rules {
             BlockCheckMode::Unsafe(..) => self.word_space("unsafe"),
@@ -1404,7 +1407,7 @@ impl<'a> State<'a> {
         }
         self.maybe_print_comment(blk.span.lo());
         self.ann.pre(self, AnnNode::Block(blk));
-        self.bopen();
+        self.bopen(ib);
 
         let has_attrs = self.print_inner_attributes(attrs);
 
@@ -1421,7 +1424,7 @@ impl<'a> State<'a> {
         }
 
         let empty = !has_attrs && blk.stmts.is_empty();
-        self.bclose_maybe_open(blk.span, empty, close_box);
+        self.bclose_maybe_open(blk.span, empty, cb);
         self.ann.post(self, AnnNode::Block(blk))
     }
 
@@ -1556,8 +1559,8 @@ impl<'a> State<'a> {
                         }
                     }
                     InlineAsmOperand::Label { block } => {
-                        s.head("label");
-                        s.print_block(block);
+                        let (cb, ib) = s.head("label");
+                        s.print_block(block, cb, ib);
                     }
                 }
             }
@@ -1671,13 +1674,13 @@ impl<'a> State<'a> {
                     Consistent,
                     fields,
                     |s, f| {
-                        s.cbox(INDENT_UNIT);
+                        let cb = s.cbox(INDENT_UNIT);
                         if !f.is_shorthand {
                             s.print_ident(f.ident);
                             s.word_nbsp(":");
                         }
                         s.print_pat(&f.pat);
-                        s.end();
+                        s.end(cb);
                     },
                     |f| f.pat.span,
                 );
@@ -1928,7 +1931,7 @@ impl<'a> State<'a> {
     }
 
     fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
 
         self.print_outer_attributes_inline(&input.attrs);
 
@@ -1947,16 +1950,16 @@ impl<'a> State<'a> {
                 }
             }
         }
-        self.end();
+        self.end(ib);
     }
 
     fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
         if let ast::FnRetTy::Ty(ty) = fn_ret_ty {
             self.space_if_not_bol();
-            self.ibox(INDENT_UNIT);
+            let ib = self.ibox(INDENT_UNIT);
             self.word_space("->");
             self.print_type(ty);
-            self.end();
+            self.end(ib);
             self.maybe_print_comment(ty.span.lo());
         }
     }
@@ -1969,12 +1972,12 @@ impl<'a> State<'a> {
         name: Option<Ident>,
         generic_params: &[ast::GenericParam],
     ) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.print_formal_generic_params(generic_params);
         let generics = ast::Generics::default();
         let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
         self.print_fn(decl, header, name, &generics);
-        self.end();
+        self.end(ib);
     }
 
     fn print_fn_header_info(&mut self, header: ast::FnHeader) {
@@ -2052,7 +2055,7 @@ impl<'a> State<'a> {
     }
 
     fn print_meta_item(&mut self, item: &ast::MetaItem) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         match &item.kind {
             ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
             ast::MetaItemKind::NameValue(value) => {
@@ -2068,7 +2071,7 @@ impl<'a> State<'a> {
                 self.pclose();
             }
         }
-        self.end();
+        self.end(ib);
     }
 
     pub(crate) fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 48da9fc63b8..38cadc77b77 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -13,7 +13,7 @@ use rustc_ast::{
 
 use crate::pp::Breaks::Inconsistent;
 use crate::pprust::state::fixup::FixupContext;
-use crate::pprust::state::{AnnNode, INDENT_UNIT, PrintState, State};
+use crate::pprust::state::{AnnNode, BoxMarker, INDENT_UNIT, PrintState, State};
 
 impl<'a> State<'a> {
     fn print_else(&mut self, els: Option<&ast::Expr>) {
@@ -21,20 +21,20 @@ impl<'a> State<'a> {
             match &_else.kind {
                 // Another `else if` block.
                 ast::ExprKind::If(i, then, e) => {
-                    self.cbox(0);
-                    self.ibox(0);
+                    let cb = self.cbox(0);
+                    let ib = self.ibox(0);
                     self.word(" else if ");
                     self.print_expr_as_cond(i);
                     self.space();
-                    self.print_block(then);
+                    self.print_block(then, cb, ib);
                     self.print_else(e.as_deref())
                 }
                 // Final `else` block.
                 ast::ExprKind::Block(b, None) => {
-                    self.cbox(0);
-                    self.ibox(0);
+                    let cb = self.cbox(0);
+                    let ib = self.ibox(0);
                     self.word(" else ");
-                    self.print_block(b)
+                    self.print_block(b, cb, ib)
                 }
                 // Constraints would be great here!
                 _ => {
@@ -45,12 +45,12 @@ impl<'a> State<'a> {
     }
 
     fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) {
-        self.cbox(0);
-        self.ibox(0);
+        let cb = self.cbox(0);
+        let ib = self.ibox(0);
         self.word_nbsp("if");
         self.print_expr_as_cond(test);
         self.space();
-        self.print_block(blk);
+        self.print_block(blk, cb, ib);
         self.print_else(elseopt)
     }
 
@@ -112,11 +112,11 @@ impl<'a> State<'a> {
     }
 
     fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word("[");
         self.commasep_exprs(Inconsistent, exprs);
         self.word("]");
-        self.end();
+        self.end(ib);
     }
 
     pub(super) fn print_expr_anon_const(
@@ -124,27 +124,27 @@ impl<'a> State<'a> {
         expr: &ast::AnonConst,
         attrs: &[ast::Attribute],
     ) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word("const");
         self.nbsp();
         if let ast::ExprKind::Block(block, None) = &expr.value.kind {
-            self.cbox(0);
-            self.ibox(0);
-            self.print_block_with_attrs(block, attrs);
+            let cb = self.cbox(0);
+            let ib = self.ibox(0);
+            self.print_block_with_attrs(block, attrs, cb, ib);
         } else {
             self.print_expr(&expr.value, FixupContext::default());
         }
-        self.end();
+        self.end(ib);
     }
 
     fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word("[");
         self.print_expr(element, FixupContext::default());
         self.word_space(";");
         self.print_expr(&count.value, FixupContext::default());
         self.word("]");
-        self.end();
+        self.end(ib);
     }
 
     fn print_expr_struct(
@@ -169,7 +169,7 @@ impl<'a> State<'a> {
             self.word("}");
             return;
         }
-        self.cbox(0);
+        let cb = self.cbox(0);
         for (pos, field) in fields.iter().with_position() {
             let is_first = matches!(pos, Position::First | Position::Only);
             let is_last = matches!(pos, Position::Last | Position::Only);
@@ -200,7 +200,7 @@ impl<'a> State<'a> {
             self.space();
         }
         self.offset(-INDENT_UNIT);
-        self.end();
+        self.end(cb);
         self.word("}");
     }
 
@@ -368,7 +368,7 @@ impl<'a> State<'a> {
             self.print_outer_attributes(attrs);
         }
 
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
 
         // The Match subexpression in `match x {} - 1` must be parenthesized if
         // it is the leftmost subexpression in a statement:
@@ -440,14 +440,14 @@ impl<'a> State<'a> {
             ast::ExprKind::Type(expr, ty) => {
                 self.word("builtin # type_ascribe");
                 self.popen();
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.print_expr(expr, FixupContext::default());
 
                 self.word(",");
                 self.space_if_not_bol();
                 self.print_type(ty);
 
-                self.end();
+                self.end(ib);
                 self.pclose();
             }
             ast::ExprKind::Let(pat, scrutinee, _, _) => {
@@ -459,20 +459,20 @@ impl<'a> State<'a> {
                     self.print_ident(label.ident);
                     self.word_space(":");
                 }
-                self.cbox(0);
-                self.ibox(0);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
                 self.word_nbsp("while");
                 self.print_expr_as_cond(test);
                 self.space();
-                self.print_block_with_attrs(blk, attrs);
+                self.print_block_with_attrs(blk, attrs, cb, ib);
             }
             ast::ExprKind::ForLoop { pat, iter, body, label, kind } => {
                 if let Some(label) = label {
                     self.print_ident(label.ident);
                     self.word_space(":");
                 }
-                self.cbox(0);
-                self.ibox(0);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
                 self.word_nbsp("for");
                 if kind == &ForLoopKind::ForAwait {
                     self.word_nbsp("await");
@@ -482,21 +482,21 @@ impl<'a> State<'a> {
                 self.word_space("in");
                 self.print_expr_as_cond(iter);
                 self.space();
-                self.print_block_with_attrs(body, attrs);
+                self.print_block_with_attrs(body, attrs, cb, ib);
             }
             ast::ExprKind::Loop(blk, opt_label, _) => {
                 if let Some(label) = opt_label {
                     self.print_ident(label.ident);
                     self.word_space(":");
                 }
-                self.cbox(0);
-                self.ibox(0);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
                 self.word_nbsp("loop");
-                self.print_block_with_attrs(blk, attrs);
+                self.print_block_with_attrs(blk, attrs, cb, ib);
             }
             ast::ExprKind::Match(expr, arms, match_kind) => {
-                self.cbox(0);
-                self.ibox(0);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
 
                 match match_kind {
                     MatchKind::Prefix => {
@@ -514,13 +514,13 @@ impl<'a> State<'a> {
                     }
                 }
 
-                self.bopen();
+                self.bopen(ib);
                 self.print_inner_attributes_no_trailing_hardbreak(attrs);
                 for arm in arms {
                     self.print_arm(arm);
                 }
                 let empty = attrs.is_empty() && arms.is_empty();
-                self.bclose(expr.span, empty);
+                self.bclose(expr.span, empty, cb);
             }
             ast::ExprKind::Closure(box ast::Closure {
                 binder,
@@ -542,12 +542,15 @@ impl<'a> State<'a> {
                 self.print_fn_params_and_ret(fn_decl, true);
                 self.space();
                 self.print_expr(body, FixupContext::default());
-                self.end(); // need to close a box
+                // FIXME(nnethercote): Bogus. Reduce visibility of `ended` once it's fixed.
+                let fake_ib = BoxMarker;
+                self.end(fake_ib);
 
-                // a box will be closed by print_expr, but we didn't want an overall
+                // A box will be closed by print_expr, but we didn't want an overall
                 // wrapper so we closed the corresponding opening. so create an
                 // empty box to satisfy the close.
-                self.ibox(0);
+                // FIXME(nnethercote): Bogus.
+                let _ib = self.ibox(0);
             }
             ast::ExprKind::Block(blk, opt_label) => {
                 if let Some(label) = opt_label {
@@ -555,18 +558,18 @@ impl<'a> State<'a> {
                     self.word_space(":");
                 }
                 // containing cbox, will be closed by print-block at }
-                self.cbox(0);
+                let cb = self.cbox(0);
                 // head-box, will be closed by print-block after {
-                self.ibox(0);
-                self.print_block_with_attrs(blk, attrs);
+                let ib = self.ibox(0);
+                self.print_block_with_attrs(blk, attrs, cb, ib);
             }
             ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
                 self.word_nbsp(kind.modifier());
                 self.print_capture_clause(*capture_clause);
                 // cbox/ibox in analogy to the `ExprKind::Block` arm above
-                self.cbox(0);
-                self.ibox(0);
-                self.print_block_with_attrs(blk, attrs);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
+                self.print_block_with_attrs(blk, attrs, cb, ib);
             }
             ast::ExprKind::Await(expr, _) => {
                 self.print_expr_cond_paren(
@@ -728,19 +731,19 @@ impl<'a> State<'a> {
                 // FIXME: Print `builtin # format_args` once macro `format_args` uses `builtin_syntax`.
                 self.word("format_args!");
                 self.popen();
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.word(reconstruct_format_args_template_string(&fmt.template));
                 for arg in fmt.arguments.all_args() {
                     self.word_space(",");
                     self.print_expr(&arg.expr, FixupContext::default());
                 }
-                self.end();
+                self.end(ib);
                 self.pclose();
             }
             ast::ExprKind::OffsetOf(container, fields) => {
                 self.word("builtin # offset_of");
                 self.popen();
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.print_type(container);
                 self.word(",");
                 self.space();
@@ -753,7 +756,7 @@ impl<'a> State<'a> {
                         self.print_ident(field);
                     }
                 }
-                self.end();
+                self.end(ib);
                 self.pclose();
             }
             ast::ExprKind::MacCall(m) => self.print_mac(m),
@@ -791,10 +794,10 @@ impl<'a> State<'a> {
                 self.word("?")
             }
             ast::ExprKind::TryBlock(blk) => {
-                self.cbox(0);
-                self.ibox(0);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
                 self.word_nbsp("try");
-                self.print_block_with_attrs(blk, attrs)
+                self.print_block_with_attrs(blk, attrs, cb, ib)
             }
             ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
                 self.word("builtin # ");
@@ -803,7 +806,7 @@ impl<'a> State<'a> {
                     ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"),
                 }
                 self.popen();
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.print_expr(expr, FixupContext::default());
 
                 if let Some(ty) = ty {
@@ -812,7 +815,7 @@ impl<'a> State<'a> {
                     self.print_type(ty);
                 }
 
-                self.end();
+                self.end(ib);
                 self.pclose();
             }
             ast::ExprKind::Err(_) => {
@@ -833,7 +836,7 @@ impl<'a> State<'a> {
             self.pclose();
         }
 
-        self.end();
+        self.end(ib);
     }
 
     fn print_arm(&mut self, arm: &ast::Arm) {
@@ -841,8 +844,8 @@ impl<'a> State<'a> {
         if arm.attrs.is_empty() {
             self.space();
         }
-        self.cbox(INDENT_UNIT);
-        self.ibox(0);
+        let cb = self.cbox(INDENT_UNIT);
+        let ib = self.ibox(0);
         self.maybe_print_comment(arm.pat.span.lo());
         self.print_outer_attributes(&arm.attrs);
         self.print_pat(&arm.pat);
@@ -863,8 +866,7 @@ impl<'a> State<'a> {
                         self.word_space(":");
                     }
 
-                    // The block will close the pattern's ibox.
-                    self.print_block_unclosed_indent(blk);
+                    self.print_block_unclosed_indent(blk, ib);
 
                     // If it is a user-provided unsafe block, print a comma after it.
                     if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
@@ -872,16 +874,16 @@ impl<'a> State<'a> {
                     }
                 }
                 _ => {
-                    self.end(); // Close the ibox for the pattern.
+                    self.end(ib);
                     self.print_expr(body, FixupContext::new_match_arm());
                     self.word(",");
                 }
             }
         } else {
-            self.end(); // Close the ibox for the pattern.
+            self.end(ib);
             self.word(",");
         }
-        self.end(); // Close enclosing cbox.
+        self.end(cb);
     }
 
     fn print_closure_binder(&mut self, binder: &ast::ClosureBinder) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 653bd77cc4d..1e02ac8fd5d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -5,6 +5,7 @@ use rustc_ast::ModKind;
 use rustc_ast::ptr::P;
 use rustc_span::Ident;
 
+use crate::pp::BoxMarker;
 use crate::pp::Breaks::Inconsistent;
 use crate::pprust::state::fixup::FixupContext;
 use crate::pprust::state::{AnnNode, INDENT_UNIT, PrintState, State};
@@ -96,7 +97,7 @@ impl<'a> State<'a> {
         define_opaque: Option<&[(ast::NodeId, ast::Path)]>,
     ) {
         self.print_define_opaques(define_opaque);
-        self.head("");
+        let (cb, ib) = self.head("");
         self.print_visibility(vis);
         self.print_safety(safety);
         self.print_defaultness(defaultness);
@@ -113,14 +114,14 @@ impl<'a> State<'a> {
         if body.is_some() {
             self.space();
         }
-        self.end(); // end the head-ibox
+        self.end(ib);
         if let Some(body) = body {
             self.word_space("=");
             self.print_expr(body, FixupContext::default());
         }
         self.print_where_clause(&generics.where_clause);
         self.word(";");
-        self.end(); // end the outer cbox
+        self.end(cb);
     }
 
     fn print_associated_type(
@@ -135,7 +136,7 @@ impl<'a> State<'a> {
     ) {
         let (before_predicates, after_predicates) =
             generics.where_clause.predicates.split_at(where_clauses.split);
-        self.head("");
+        let (cb, ib) = self.head("");
         self.print_visibility(vis);
         self.print_defaultness(defaultness);
         self.word_space("type");
@@ -153,8 +154,8 @@ impl<'a> State<'a> {
         }
         self.print_where_clause_parts(where_clauses.after.has_where_token, after_predicates);
         self.word(";");
-        self.end(); // end inner head-block
-        self.end(); // end outer head-block
+        self.end(ib);
+        self.end(cb);
     }
 
     /// Pretty-prints an item.
@@ -165,7 +166,7 @@ impl<'a> State<'a> {
         self.ann.pre(self, AnnNode::Item(item));
         match &item.kind {
             ast::ItemKind::ExternCrate(orig_name, ident) => {
-                self.head(visibility_qualified(&item.vis, "extern crate"));
+                let (cb, ib) = self.head(visibility_qualified(&item.vis, "extern crate"));
                 if let &Some(orig_name) = orig_name {
                     self.print_name(orig_name);
                     self.space();
@@ -174,8 +175,8 @@ impl<'a> State<'a> {
                 }
                 self.print_ident(*ident);
                 self.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
+                self.end(ib);
+                self.end(cb);
             }
             ast::ItemKind::Use(tree) => {
                 self.print_visibility(&item.vis);
@@ -228,7 +229,7 @@ impl<'a> State<'a> {
                 self.print_fn_full(&item.vis, &item.attrs, &*func);
             }
             ast::ItemKind::Mod(safety, ident, mod_kind) => {
-                self.head(Self::to_string(|s| {
+                let (cb, ib) = self.head(Self::to_string(|s| {
                     s.print_visibility(&item.vis);
                     s.print_safety(*safety);
                     s.word("mod");
@@ -238,23 +239,23 @@ impl<'a> State<'a> {
                 match mod_kind {
                     ModKind::Loaded(items, ..) => {
                         self.nbsp();
-                        self.bopen();
+                        self.bopen(ib);
                         self.print_inner_attributes(&item.attrs);
                         for item in items {
                             self.print_item(item);
                         }
                         let empty = item.attrs.is_empty() && items.is_empty();
-                        self.bclose(item.span, empty);
+                        self.bclose(item.span, empty, cb);
                     }
                     ModKind::Unloaded => {
                         self.word(";");
-                        self.end(); // end inner head-block
-                        self.end(); // end outer head-block
+                        self.end(ib);
+                        self.end(cb);
                     }
                 }
             }
             ast::ItemKind::ForeignMod(nmod) => {
-                self.head(Self::to_string(|s| {
+                let (cb, ib) = self.head(Self::to_string(|s| {
                     s.print_safety(nmod.safety);
                     s.word("extern");
                 }));
@@ -262,18 +263,18 @@ impl<'a> State<'a> {
                     self.print_token_literal(abi.as_token_lit(), abi.span);
                     self.nbsp();
                 }
-                self.bopen();
+                self.bopen(ib);
                 self.print_foreign_mod(nmod, &item.attrs);
                 let empty = item.attrs.is_empty() && nmod.items.is_empty();
-                self.bclose(item.span, empty);
+                self.bclose(item.span, empty, cb);
             }
             ast::ItemKind::GlobalAsm(asm) => {
                 // FIXME: Print `builtin # global_asm` once macro `global_asm` uses `builtin_syntax`.
-                self.head(visibility_qualified(&item.vis, "global_asm!"));
+                let (cb, ib) = self.head(visibility_qualified(&item.vis, "global_asm!"));
                 self.print_inline_asm(asm);
                 self.word(";");
-                self.end();
-                self.end();
+                self.end(ib);
+                self.end(cb);
             }
             ast::ItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
@@ -297,12 +298,12 @@ impl<'a> State<'a> {
                 self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis);
             }
             ast::ItemKind::Struct(ident, struct_def, generics) => {
-                self.head(visibility_qualified(&item.vis, "struct"));
-                self.print_struct(struct_def, generics, *ident, item.span, true);
+                let (cb, ib) = self.head(visibility_qualified(&item.vis, "struct"));
+                self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
             }
             ast::ItemKind::Union(ident, struct_def, generics) => {
-                self.head(visibility_qualified(&item.vis, "union"));
-                self.print_struct(struct_def, generics, *ident, item.span, true);
+                let (cb, ib) = self.head(visibility_qualified(&item.vis, "union"));
+                self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
             }
             ast::ItemKind::Impl(box ast::Impl {
                 safety,
@@ -314,7 +315,7 @@ impl<'a> State<'a> {
                 self_ty,
                 items,
             }) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(*defaultness);
                 self.print_safety(*safety);
@@ -343,13 +344,13 @@ impl<'a> State<'a> {
                 self.print_where_clause(&generics.where_clause);
 
                 self.space();
-                self.bopen();
+                self.bopen(ib);
                 self.print_inner_attributes(&item.attrs);
                 for impl_item in items {
                     self.print_assoc_item(impl_item);
                 }
                 let empty = item.attrs.is_empty() && items.is_empty();
-                self.bclose(item.span, empty);
+                self.bclose(item.span, empty, cb);
             }
             ast::ItemKind::Trait(box ast::Trait {
                 safety,
@@ -359,7 +360,7 @@ impl<'a> State<'a> {
                 bounds,
                 items,
             }) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_visibility(&item.vis);
                 self.print_safety(*safety);
                 self.print_is_auto(*is_auto);
@@ -372,16 +373,16 @@ impl<'a> State<'a> {
                 }
                 self.print_where_clause(&generics.where_clause);
                 self.word(" ");
-                self.bopen();
+                self.bopen(ib);
                 self.print_inner_attributes(&item.attrs);
                 for trait_item in items {
                     self.print_assoc_item(trait_item);
                 }
                 let empty = item.attrs.is_empty() && items.is_empty();
-                self.bclose(item.span, empty);
+                self.bclose(item.span, empty, cb);
             }
             ast::ItemKind::TraitAlias(ident, generics, bounds) => {
-                self.head(visibility_qualified(&item.vis, "trait"));
+                let (cb, ib) = self.head(visibility_qualified(&item.vis, "trait"));
                 self.print_ident(*ident);
                 self.print_generic_params(&generics.params);
                 self.nbsp();
@@ -391,8 +392,8 @@ impl<'a> State<'a> {
                 }
                 self.print_where_clause(&generics.where_clause);
                 self.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
+                self.end(ib);
+                self.end(cb);
             }
             ast::ItemKind::MacCall(mac) => {
                 self.print_mac(mac);
@@ -433,28 +434,24 @@ impl<'a> State<'a> {
         span: rustc_span::Span,
         visibility: &ast::Visibility,
     ) {
-        self.head(visibility_qualified(visibility, "enum"));
+        let (cb, ib) = self.head(visibility_qualified(visibility, "enum"));
         self.print_ident(ident);
         self.print_generic_params(&generics.params);
         self.print_where_clause(&generics.where_clause);
         self.space();
-        self.print_variants(&enum_definition.variants, span)
-    }
-
-    fn print_variants(&mut self, variants: &[ast::Variant], span: rustc_span::Span) {
-        self.bopen();
-        for v in variants {
+        self.bopen(ib);
+        for v in enum_definition.variants.iter() {
             self.space_if_not_bol();
             self.maybe_print_comment(v.span.lo());
             self.print_outer_attributes(&v.attrs);
-            self.ibox(0);
+            let ib = self.ibox(0);
             self.print_variant(v);
             self.word(",");
-            self.end();
+            self.end(ib);
             self.maybe_print_trailing_comment(v.span, None);
         }
-        let empty = variants.is_empty();
-        self.bclose(span, empty)
+        let empty = enum_definition.variants.is_empty();
+        self.bclose(span, empty, cb)
     }
 
     pub(crate) fn print_visibility(&mut self, vis: &ast::Visibility) {
@@ -478,33 +475,6 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_record_struct_body(
-        &mut self,
-        fields: &[ast::FieldDef],
-        span: rustc_span::Span,
-    ) {
-        self.nbsp();
-        self.bopen();
-
-        let empty = fields.is_empty();
-        if !empty {
-            self.hardbreak_if_not_bol();
-
-            for field in fields {
-                self.hardbreak_if_not_bol();
-                self.maybe_print_comment(field.span.lo());
-                self.print_outer_attributes(&field.attrs);
-                self.print_visibility(&field.vis);
-                self.print_ident(field.ident.unwrap());
-                self.word_nbsp(":");
-                self.print_type(&field.ty);
-                self.word(",");
-            }
-        }
-
-        self.bclose(span, empty);
-    }
-
     fn print_struct(
         &mut self,
         struct_def: &ast::VariantData,
@@ -512,6 +482,8 @@ impl<'a> State<'a> {
         ident: Ident,
         span: rustc_span::Span,
         print_finalizer: bool,
+        cb: BoxMarker,
+        ib: BoxMarker,
     ) {
         self.print_ident(ident);
         self.print_generic_params(&generics.params);
@@ -531,21 +503,40 @@ impl<'a> State<'a> {
                 if print_finalizer {
                     self.word(";");
                 }
-                self.end();
-                self.end(); // Close the outer-box.
+                self.end(ib);
+                self.end(cb);
             }
             ast::VariantData::Struct { fields, .. } => {
                 self.print_where_clause(&generics.where_clause);
-                self.print_record_struct_body(fields, span);
+                self.nbsp();
+                self.bopen(ib);
+
+                let empty = fields.is_empty();
+                if !empty {
+                    self.hardbreak_if_not_bol();
+
+                    for field in fields {
+                        self.hardbreak_if_not_bol();
+                        self.maybe_print_comment(field.span.lo());
+                        self.print_outer_attributes(&field.attrs);
+                        self.print_visibility(&field.vis);
+                        self.print_ident(field.ident.unwrap());
+                        self.word_nbsp(":");
+                        self.print_type(&field.ty);
+                        self.word(",");
+                    }
+                }
+
+                self.bclose(span, empty, cb);
             }
         }
     }
 
     pub(crate) fn print_variant(&mut self, v: &ast::Variant) {
-        self.head("");
+        let (cb, ib) = self.head("");
         self.print_visibility(&v.vis);
         let generics = ast::Generics::default();
-        self.print_struct(&v.data, &generics, v.ident, v.span, false);
+        self.print_struct(&v.data, &generics, v.ident, v.span, false, cb, ib);
         if let Some(d) = &v.disr_expr {
             self.space();
             self.word_space("=");
@@ -636,9 +627,7 @@ impl<'a> State<'a> {
         kind: DelegationKind<'_>,
         body: &Option<P<ast::Block>>,
     ) {
-        if body.is_some() {
-            self.head("");
-        }
+        let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
         self.print_visibility(vis);
         self.word_nbsp("reuse");
 
@@ -670,9 +659,9 @@ impl<'a> State<'a> {
                 self.word("*");
             }
         }
-        if let Some(body) = body {
+        if let Some((body, (cb, ib))) = body_cb_ib {
             self.nbsp();
-            self.print_block_with_attrs(body, attrs);
+            self.print_block_with_attrs(body, attrs, cb, ib);
         } else {
             self.word(";");
         }
@@ -683,9 +672,8 @@ impl<'a> State<'a> {
 
         self.print_define_opaques(define_opaque.as_deref());
 
-        if body.is_some() {
-            self.head("");
-        }
+        let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
+
         self.print_visibility(vis);
         self.print_defaultness(*defaultness);
         self.print_fn(&sig.decl, sig.header, Some(*ident), generics);
@@ -693,9 +681,9 @@ impl<'a> State<'a> {
             self.nbsp();
             self.print_contract(contract);
         }
-        if let Some(body) = body {
+        if let Some((body, (cb, ib))) = body_cb_ib {
             self.nbsp();
-            self.print_block_with_attrs(body, attrs);
+            self.print_block_with_attrs(body, attrs, cb, ib);
         } else {
             self.word(";");
         }
@@ -851,10 +839,10 @@ impl<'a> State<'a> {
                 } else if let [(item, _)] = items.as_slice() {
                     self.print_use_tree(item);
                 } else {
-                    self.cbox(INDENT_UNIT);
+                    let cb = self.cbox(INDENT_UNIT);
                     self.word("{");
                     self.zerobreak();
-                    self.ibox(0);
+                    let ib = self.ibox(0);
                     for (pos, use_tree) in items.iter().with_position() {
                         let is_last = matches!(pos, Position::Last | Position::Only);
                         self.print_use_tree(&use_tree.0);
@@ -867,11 +855,11 @@ impl<'a> State<'a> {
                             }
                         }
                     }
-                    self.end();
+                    self.end(ib);
                     self.trailing_comma();
                     self.offset(-INDENT_UNIT);
                     self.word("}");
-                    self.end();
+                    self.end(cb);
                 }
             }
         }
diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs
index bc7f22766a5..786de529c5b 100644
--- a/compiler/rustc_ast_pretty/src/pprust/tests.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs
@@ -11,10 +11,10 @@ fn fun_to_string(
     generics: &ast::Generics,
 ) -> String {
     to_string(|s| {
-        s.head("");
+        let (cb, ib) = s.head("");
         s.print_fn(decl, header, Some(ident), generics);
-        s.end(); // Close the head box.
-        s.end(); // Close the outer box.
+        s.end(ib);
+        s.end(cb);
     })
 }
 
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index e14cd603c58..30e96ae4143 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -56,7 +56,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
 
-            ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"),
+            ty::Alias(ty::Free, _) => bug!("type_name: unexpected free alias"),
             ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
             ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"),
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d13fafae4e8..fa36fe79716 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -2019,7 +2019,7 @@ fn check_variances_for_type_defn<'tcx>(
         ItemKind::TyAlias(..) => {
             assert!(
                 tcx.type_alias_is_lazy(item.owner_id),
-                "should not be computing variance of non-weak type alias"
+                "should not be computing variance of non-free type alias"
             );
         }
         kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
@@ -2251,7 +2251,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
         let def_id = match ty.kind() {
             ty::Adt(adt_def, _) => Some(adt_def.did()),
-            ty::Alias(ty::Weak, alias_ty) => Some(alias_ty.def_id),
+            ty::Alias(ty::Free, alias_ty) => Some(alias_ty.def_id),
             _ => None,
         };
         if let Some(def_id) = def_id {
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index c9a9180c5c9..bd25b4a3260 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -150,7 +150,7 @@ impl<'tcx> InherentCollect<'tcx> {
         let id = id.owner_id.def_id;
         let item_span = self.tcx.def_span(id);
         let self_ty = self.tcx.type_of(id).instantiate_identity();
-        let mut self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
+        let mut self_ty = self.tcx.peel_off_free_alias_tys(self_ty);
         // We allow impls on pattern types exactly when we allow impls on the base type.
         // FIXME(pattern_types): Figure out the exact coherence rules we want here.
         while let ty::Pat(base, _) = *self_ty.kind() {
@@ -188,7 +188,7 @@ impl<'tcx> InherentCollect<'tcx> {
             | ty::CoroutineClosure(..)
             | ty::Coroutine(..)
             | ty::CoroutineWitness(..)
-            | ty::Alias(ty::Weak, _)
+            | ty::Alias(ty::Free, _)
             | ty::Bound(..)
             | ty::Placeholder(_)
             | ty::Infer(_) => {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 74ba4ffe25e..c75fef9f716 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -189,7 +189,7 @@ pub(crate) fn orphan_check_impl(
                     ty::Projection => "associated type",
                     // type Foo = (impl Sized, bool)
                     // impl AutoTrait for Foo {}
-                    ty::Weak => "type alias",
+                    ty::Free => "type alias",
                     // type Opaque = impl Trait;
                     // impl AutoTrait for Opaque {}
                     ty::Opaque => "opaque type",
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 951eda72ffe..366b3943a05 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -49,7 +49,7 @@ pub(crate) fn parameters_for<'tcx>(
     include_nonconstraining: bool,
 ) -> Vec<Parameter> {
     let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
-    let value = if !include_nonconstraining { tcx.expand_weak_alias_tys(value) } else { value };
+    let value = if !include_nonconstraining { tcx.expand_free_alias_tys(value) } else { value };
     value.visit_with(&mut collector);
     collector.parameters
 }
@@ -68,9 +68,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
             {
                 return;
             }
-            // All weak alias types should've been expanded beforehand.
-            ty::Alias(ty::Weak, _) if !self.include_nonconstraining => {
-                bug!("unexpected weak alias type")
+            // All free alias types should've been expanded beforehand.
+            ty::Alias(ty::Free, _) if !self.include_nonconstraining => {
+                bug!("unexpected free alias type")
             }
             ty::Param(param) => self.parameters.push(Parameter::from(param)),
             _ => {}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 22162b8b364..8153e6f87f8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -958,7 +958,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
             // then actually instantiate the where bounds of.
             let alias_ty = ty::AliasTy::new_from_args(tcx, did, args);
-            Ty::new_alias(tcx, ty::Weak, alias_ty)
+            Ty::new_alias(tcx, ty::Free, alias_ty)
         } else {
             tcx.at(span).type_of(did).instantiate(tcx, args)
         }
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 780c27d4595..c99eb12efcc 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -157,10 +157,10 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 );
             }
 
-            ty::Alias(ty::Weak, alias) => {
+            ty::Alias(ty::Free, alias) => {
                 // This corresponds to a type like `Type<'a, T>`.
                 // We check inferred and explicit predicates.
-                debug!("Weak");
+                debug!("Free");
                 check_inferred_predicates(
                     tcx,
                     alias.def_id,
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 23223de918c..dc3ce1dd76c 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -107,7 +107,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         let current_item = &CurrentItem { inferred_start };
         let ty = tcx.type_of(def_id).instantiate_identity();
 
-        // The type as returned by `type_of` is the underlying type and generally not a weak projection.
+        // The type as returned by `type_of` is the underlying type and generally not a free alias.
         // Therefore we need to check the `DefKind` first.
         if let DefKind::TyAlias = tcx.def_kind(def_id)
             && tcx.type_alias_is_lazy(def_id)
@@ -282,7 +282,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_invariant_args(current, data.args, variance);
             }
 
-            ty::Alias(ty::Weak, ref data) => {
+            ty::Alias(ty::Free, ref data) => {
                 self.add_constraints_from_args(current, data.def_id, data.args, variance);
             }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index c95d6a277c7..b878147522d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -13,7 +13,7 @@ use rustc_abi::ExternAbi;
 use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
 use rustc_ast::{AttrStyle, DUMMY_NODE_ID, DelimArgs};
 use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
-use rustc_ast_pretty::pp::{self, Breaks};
+use rustc_ast_pretty::pp::{self, BoxMarker, Breaks};
 use rustc_ast_pretty::pprust::state::MacHeader;
 use rustc_ast_pretty::pprust::{Comments, PrintState};
 use rustc_attr_data_structures::{AttributeKind, PrintAttribute};
@@ -127,7 +127,7 @@ impl<'a> State<'a> {
     }
 
     fn print_attr_item(&mut self, item: &hir::AttrItem, span: Span) {
-        self.ibox(0);
+        let ib = self.ibox(0);
         let path = ast::Path {
             span,
             segments: item
@@ -161,7 +161,7 @@ impl<'a> State<'a> {
                 self.word(token_str);
             }
         }
-        self.end();
+        self.end(ib);
     }
 
     fn print_node(&mut self, node: Node<'_>) {
@@ -192,10 +192,10 @@ impl<'a> State<'a> {
             Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
             Node::Block(a) => {
                 // Containing cbox, will be closed by print-block at `}`.
-                self.cbox(INDENT_UNIT);
+                let cb = self.cbox(INDENT_UNIT);
                 // Head-ibox, will be closed by print-block after `{`.
-                self.ibox(0);
-                self.print_block(a);
+                let ib = self.ibox(0);
+                self.print_block(a, cb, ib);
             }
             Node::Lifetime(a) => self.print_lifetime(a),
             Node::GenericParam(_) => panic!("cannot print Node::GenericParam"),
@@ -315,17 +315,17 @@ pub fn item_to_string(ann: &dyn PpAnn, pat: &hir::Item<'_>) -> String {
 }
 
 impl<'a> State<'a> {
-    fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
+    fn bclose_maybe_open(&mut self, span: rustc_span::Span, cb: Option<BoxMarker>) {
         self.maybe_print_comment(span.hi());
         self.break_offset_if_not_bol(1, -INDENT_UNIT);
         self.word("}");
-        if close_box {
-            self.end(); // close the outer-box
+        if let Some(cb) = cb {
+            self.end(cb);
         }
     }
 
-    fn bclose(&mut self, span: rustc_span::Span) {
-        self.bclose_maybe_open(span, true)
+    fn bclose(&mut self, span: rustc_span::Span, cb: BoxMarker) {
+        self.bclose_maybe_open(span, Some(cb))
     }
 
     fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
@@ -333,7 +333,7 @@ impl<'a> State<'a> {
         F: FnMut(&mut State<'_>, &T),
         G: FnMut(&T) -> rustc_span::Span,
     {
-        self.rbox(0, b);
+        let rb = self.rbox(0, b);
         let len = elts.len();
         let mut i = 0;
         for elt in elts {
@@ -346,7 +346,7 @@ impl<'a> State<'a> {
                 self.space_if_not_bol();
             }
         }
-        self.end();
+        self.end(rb);
     }
 
     fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr<'_>]) {
@@ -369,7 +369,7 @@ impl<'a> State<'a> {
 
     fn print_type(&mut self, ty: &hir::Ty<'_>) {
         self.maybe_print_comment(ty.span.lo());
-        self.ibox(0);
+        let ib = self.ibox(0);
         match ty.kind {
             hir::TyKind::Slice(ty) => {
                 self.word("[");
@@ -456,16 +456,16 @@ impl<'a> State<'a> {
                 self.print_ty_pat(pat);
             }
         }
-        self.end()
+        self.end(ib)
     }
 
     fn print_unsafe_binder(&mut self, unsafe_binder: &hir::UnsafeBinderTy<'_>) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word("unsafe");
         self.print_generic_params(unsafe_binder.generic_params);
         self.nbsp();
         self.print_type(unsafe_binder.inner_ty);
-        self.end();
+        self.end(ib);
     }
 
     fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
@@ -474,7 +474,7 @@ impl<'a> State<'a> {
         self.print_attrs_as_outer(self.attrs(item.hir_id()));
         match item.kind {
             hir::ForeignItemKind::Fn(sig, arg_idents, generics) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_fn(
                     sig.decl,
                     sig.header,
@@ -483,13 +483,13 @@ impl<'a> State<'a> {
                     arg_idents,
                     None,
                 );
-                self.end(); // end head-ibox
+                self.end(ib);
                 self.word(";");
-                self.end() // end the outer fn box
+                self.end(cb)
             }
             hir::ForeignItemKind::Static(t, m, safety) => {
                 self.print_safety(safety);
-                self.head("static");
+                let (cb, ib) = self.head("static");
                 if m.is_mut() {
                     self.word_space("mut");
                 }
@@ -497,15 +497,15 @@ impl<'a> State<'a> {
                 self.word_space(":");
                 self.print_type(t);
                 self.word(";");
-                self.end(); // end the head-ibox
-                self.end() // end the outer cbox
+                self.end(ib);
+                self.end(cb)
             }
             hir::ForeignItemKind::Type => {
-                self.head("type");
+                let (cb, ib) = self.head("type");
                 self.print_ident(item.ident);
                 self.word(";");
-                self.end(); // end the head-ibox
-                self.end() // end the outer cbox
+                self.end(ib);
+                self.end(cb)
             }
         }
     }
@@ -561,7 +561,7 @@ impl<'a> State<'a> {
         self.ann.pre(self, AnnNode::Item(item));
         match item.kind {
             hir::ItemKind::ExternCrate(orig_name, ident) => {
-                self.head("extern crate");
+                let (cb, ib) = self.head("extern crate");
                 if let Some(orig_name) = orig_name {
                     self.print_name(orig_name);
                     self.space();
@@ -570,11 +570,11 @@ impl<'a> State<'a> {
                 }
                 self.print_ident(ident);
                 self.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
+                self.end(ib);
+                self.end(cb);
             }
             hir::ItemKind::Use(path, kind) => {
-                self.head("use");
+                let (cb, ib) = self.head("use");
                 self.print_path(path, false);
 
                 match kind {
@@ -589,11 +589,11 @@ impl<'a> State<'a> {
                     hir::UseKind::Glob => self.word("::*;"),
                     hir::UseKind::ListStem => self.word("::{};"),
                 }
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
+                self.end(ib);
+                self.end(cb);
             }
             hir::ItemKind::Static(ident, ty, m, expr) => {
-                self.head("static");
+                let (cb, ib) = self.head("static");
                 if m.is_mut() {
                     self.word_space("mut");
                 }
@@ -601,85 +601,86 @@ impl<'a> State<'a> {
                 self.word_space(":");
                 self.print_type(ty);
                 self.space();
-                self.end(); // end the head-ibox
+                self.end(ib);
 
                 self.word_space("=");
                 self.ann.nested(self, Nested::Body(expr));
                 self.word(";");
-                self.end(); // end the outer cbox
+                self.end(cb);
             }
             hir::ItemKind::Const(ident, ty, generics, expr) => {
-                self.head("const");
+                let (cb, ib) = self.head("const");
                 self.print_ident(ident);
                 self.print_generic_params(generics.params);
                 self.word_space(":");
                 self.print_type(ty);
                 self.space();
-                self.end(); // end the head-ibox
+                self.end(ib);
 
                 self.word_space("=");
                 self.ann.nested(self, Nested::Body(expr));
                 self.print_where_clause(generics);
                 self.word(";");
-                self.end(); // end the outer cbox
+                self.end(cb);
             }
             hir::ItemKind::Fn { ident, sig, generics, body, .. } => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_fn(sig.decl, sig.header, Some(ident.name), generics, &[], Some(body));
                 self.word(" ");
-                self.end(); // need to close a box
-                self.end(); // need to close a box
+                self.end(ib);
+                self.end(cb);
                 self.ann.nested(self, Nested::Body(body));
             }
             hir::ItemKind::Macro(ident, macro_def, _) => {
                 self.print_mac_def(macro_def, &ident, item.span, |_| {});
             }
             hir::ItemKind::Mod(ident, mod_) => {
-                self.head("mod");
+                let (cb, ib) = self.head("mod");
                 self.print_ident(ident);
                 self.nbsp();
-                self.bopen();
+                self.bopen(ib);
                 self.print_mod(mod_, attrs);
-                self.bclose(item.span);
+                self.bclose(item.span, cb);
             }
             hir::ItemKind::ForeignMod { abi, items } => {
-                self.head("extern");
+                let (cb, ib) = self.head("extern");
                 self.word_nbsp(abi.to_string());
-                self.bopen();
+                self.bopen(ib);
                 self.print_attrs_as_inner(self.attrs(item.hir_id()));
                 for item in items {
                     self.ann.nested(self, Nested::ForeignItem(item.id));
                 }
-                self.bclose(item.span);
+                self.bclose(item.span, cb);
             }
             hir::ItemKind::GlobalAsm { asm, .. } => {
-                self.head("global_asm!");
+                // FIXME(nnethercote): `ib` is unclosed
+                let (cb, _ib) = self.head("global_asm!");
                 self.print_inline_asm(asm);
-                self.end()
+                self.end(cb)
             }
             hir::ItemKind::TyAlias(ident, ty, generics) => {
-                self.head("type");
+                let (cb, ib) = self.head("type");
                 self.print_ident(ident);
                 self.print_generic_params(generics.params);
-                self.end(); // end the inner ibox
+                self.end(ib);
 
                 self.print_where_clause(generics);
                 self.space();
                 self.word_space("=");
                 self.print_type(ty);
                 self.word(";");
-                self.end(); // end the outer ibox
+                self.end(cb);
             }
             hir::ItemKind::Enum(ident, ref enum_definition, params) => {
                 self.print_enum_def(enum_definition, params, ident.name, item.span);
             }
             hir::ItemKind::Struct(ident, ref struct_def, generics) => {
-                self.head("struct");
-                self.print_struct(struct_def, generics, ident.name, item.span, true);
+                let (cb, ib) = self.head("struct");
+                self.print_struct(struct_def, generics, ident.name, item.span, true, cb, ib);
             }
             hir::ItemKind::Union(ident, ref struct_def, generics) => {
-                self.head("union");
-                self.print_struct(struct_def, generics, ident.name, item.span, true);
+                let (cb, ib) = self.head("union");
+                self.print_struct(struct_def, generics, ident.name, item.span, true, cb, ib);
             }
             hir::ItemKind::Impl(&hir::Impl {
                 constness,
@@ -692,7 +693,7 @@ impl<'a> State<'a> {
                 self_ty,
                 items,
             }) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_defaultness(defaultness);
                 self.print_safety(safety);
                 self.word_nbsp("impl");
@@ -720,15 +721,15 @@ impl<'a> State<'a> {
                 self.print_where_clause(generics);
 
                 self.space();
-                self.bopen();
+                self.bopen(ib);
                 self.print_attrs_as_inner(attrs);
                 for impl_item in items {
                     self.ann.nested(self, Nested::ImplItem(impl_item.id));
                 }
-                self.bclose(item.span);
+                self.bclose(item.span, cb);
             }
             hir::ItemKind::Trait(is_auto, safety, ident, generics, bounds, trait_items) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_is_auto(is_auto);
                 self.print_safety(safety);
                 self.word_nbsp("trait");
@@ -737,22 +738,22 @@ impl<'a> State<'a> {
                 self.print_bounds(":", bounds);
                 self.print_where_clause(generics);
                 self.word(" ");
-                self.bopen();
+                self.bopen(ib);
                 for trait_item in trait_items {
                     self.ann.nested(self, Nested::TraitItem(trait_item.id));
                 }
-                self.bclose(item.span);
+                self.bclose(item.span, cb);
             }
             hir::ItemKind::TraitAlias(ident, generics, bounds) => {
-                self.head("trait");
+                let (cb, ib) = self.head("trait");
                 self.print_ident(ident);
                 self.print_generic_params(generics.params);
                 self.nbsp();
                 self.print_bounds("=", bounds);
                 self.print_where_clause(generics);
                 self.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
+                self.end(ib);
+                self.end(cb);
             }
         }
         self.ann.post(self, AnnNode::Item(item))
@@ -763,7 +764,8 @@ impl<'a> State<'a> {
     }
 
     fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) {
-        self.head("opaque");
+        // FIXME(nnethercote): `cb` and `ib` are unclosed
+        let (_cb, _ib) = self.head("opaque");
         self.word("{");
         self.print_bounds("impl", o.bounds);
         self.word("}");
@@ -800,27 +802,33 @@ impl<'a> State<'a> {
         name: Symbol,
         span: rustc_span::Span,
     ) {
-        self.head("enum");
+        let (cb, ib) = self.head("enum");
         self.print_name(name);
         self.print_generic_params(generics.params);
         self.print_where_clause(generics);
         self.space();
-        self.print_variants(enum_definition.variants, span);
+        self.print_variants(enum_definition.variants, span, cb, ib);
     }
 
-    fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span::Span) {
-        self.bopen();
+    fn print_variants(
+        &mut self,
+        variants: &[hir::Variant<'_>],
+        span: rustc_span::Span,
+        cb: BoxMarker,
+        ib: BoxMarker,
+    ) {
+        self.bopen(ib);
         for v in variants {
             self.space_if_not_bol();
             self.maybe_print_comment(v.span.lo());
             self.print_attrs_as_outer(self.attrs(v.hir_id));
-            self.ibox(INDENT_UNIT);
+            let ib = self.ibox(INDENT_UNIT);
             self.print_variant(v);
             self.word(",");
-            self.end();
+            self.end(ib);
             self.maybe_print_trailing_comment(v.span, None);
         }
-        self.bclose(span)
+        self.bclose(span, cb)
     }
 
     fn print_defaultness(&mut self, defaultness: hir::Defaultness) {
@@ -837,6 +845,8 @@ impl<'a> State<'a> {
         name: Symbol,
         span: rustc_span::Span,
         print_finalizer: bool,
+        cb: BoxMarker,
+        ib: BoxMarker,
     ) {
         self.print_name(name);
         self.print_generic_params(generics.params);
@@ -855,38 +865,34 @@ impl<'a> State<'a> {
                 if print_finalizer {
                     self.word(";");
                 }
-                self.end();
-                self.end() // close the outer-box
+                self.end(ib);
+                self.end(cb);
             }
             hir::VariantData::Struct { .. } => {
                 self.print_where_clause(generics);
-                self.print_variant_struct(span, struct_def.fields())
-            }
-        }
-    }
-
-    fn print_variant_struct(&mut self, span: rustc_span::Span, fields: &[hir::FieldDef<'_>]) {
-        self.nbsp();
-        self.bopen();
-        self.hardbreak_if_not_bol();
+                self.nbsp();
+                self.bopen(ib);
+                self.hardbreak_if_not_bol();
+
+                for field in struct_def.fields() {
+                    self.hardbreak_if_not_bol();
+                    self.maybe_print_comment(field.span.lo());
+                    self.print_attrs_as_outer(self.attrs(field.hir_id));
+                    self.print_ident(field.ident);
+                    self.word_nbsp(":");
+                    self.print_type(field.ty);
+                    self.word(",");
+                }
 
-        for field in fields {
-            self.hardbreak_if_not_bol();
-            self.maybe_print_comment(field.span.lo());
-            self.print_attrs_as_outer(self.attrs(field.hir_id));
-            self.print_ident(field.ident);
-            self.word_nbsp(":");
-            self.print_type(field.ty);
-            self.word(",");
+                self.bclose(span, cb)
+            }
         }
-
-        self.bclose(span)
     }
 
     pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
-        self.head("");
+        let (cb, ib) = self.head("");
         let generics = hir::Generics::empty();
-        self.print_struct(&v.data, generics, v.ident.name, v.span, false);
+        self.print_struct(&v.data, generics, v.ident.name, v.span, false, cb, ib);
         if let Some(ref d) = v.disr_expr {
             self.space();
             self.word_space("=");
@@ -919,11 +925,11 @@ impl<'a> State<'a> {
                 self.word(";");
             }
             hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(body));
                 self.nbsp();
-                self.end(); // need to close a box
-                self.end(); // need to close a box
+                self.end(ib);
+                self.end(cb);
                 self.ann.nested(self, Nested::Body(body));
             }
             hir::TraitItemKind::Type(bounds, default) => {
@@ -944,11 +950,11 @@ impl<'a> State<'a> {
                 self.print_associated_const(ii.ident, ii.generics, ty, Some(expr));
             }
             hir::ImplItemKind::Fn(ref sig, body) => {
-                self.head("");
+                let (cb, ib) = self.head("");
                 self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(body));
                 self.nbsp();
-                self.end(); // need to close a box
-                self.end(); // need to close a box
+                self.end(ib);
+                self.end(cb);
                 self.ann.nested(self, Nested::Body(body));
             }
             hir::ImplItemKind::Type(ty) => {
@@ -966,15 +972,15 @@ impl<'a> State<'a> {
         decl: impl Fn(&mut Self),
     ) {
         self.space_if_not_bol();
-        self.ibox(INDENT_UNIT);
+        let ibm1 = self.ibox(INDENT_UNIT);
         if super_ {
             self.word_nbsp("super");
         }
         self.word_nbsp("let");
 
-        self.ibox(INDENT_UNIT);
+        let ibm2 = self.ibox(INDENT_UNIT);
         decl(self);
-        self.end();
+        self.end(ibm2);
 
         if let Some(init) = init {
             self.nbsp();
@@ -986,13 +992,13 @@ impl<'a> State<'a> {
             self.nbsp();
             self.word_space("else");
             // containing cbox, will be closed by print-block at `}`
-            self.cbox(0);
+            let cb = self.cbox(0);
             // head-box, will be closed by print-block after `{`
-            self.ibox(0);
-            self.print_block(els);
+            let ib = self.ibox(0);
+            self.print_block(els, cb, ib);
         }
 
-        self.end()
+        self.end(ibm1)
     }
 
     fn print_stmt(&mut self, st: &hir::Stmt<'_>) {
@@ -1020,23 +1026,30 @@ impl<'a> State<'a> {
         self.maybe_print_trailing_comment(st.span, None)
     }
 
-    fn print_block(&mut self, blk: &hir::Block<'_>) {
-        self.print_block_with_attrs(blk, &[])
+    fn print_block(&mut self, blk: &hir::Block<'_>, cb: BoxMarker, ib: BoxMarker) {
+        self.print_block_with_attrs(blk, &[], cb, ib)
     }
 
-    fn print_block_unclosed(&mut self, blk: &hir::Block<'_>) {
-        self.print_block_maybe_unclosed(blk, &[], false)
+    fn print_block_unclosed(&mut self, blk: &hir::Block<'_>, ib: BoxMarker) {
+        self.print_block_maybe_unclosed(blk, &[], None, ib)
     }
 
-    fn print_block_with_attrs(&mut self, blk: &hir::Block<'_>, attrs: &[hir::Attribute]) {
-        self.print_block_maybe_unclosed(blk, attrs, true)
+    fn print_block_with_attrs(
+        &mut self,
+        blk: &hir::Block<'_>,
+        attrs: &[hir::Attribute],
+        cb: BoxMarker,
+        ib: BoxMarker,
+    ) {
+        self.print_block_maybe_unclosed(blk, attrs, Some(cb), ib)
     }
 
     fn print_block_maybe_unclosed(
         &mut self,
         blk: &hir::Block<'_>,
         attrs: &[hir::Attribute],
-        close_box: bool,
+        cb: Option<BoxMarker>,
+        ib: BoxMarker,
     ) {
         match blk.rules {
             hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
@@ -1044,7 +1057,7 @@ impl<'a> State<'a> {
         }
         self.maybe_print_comment(blk.span.lo());
         self.ann.pre(self, AnnNode::Block(blk));
-        self.bopen();
+        self.bopen(ib);
 
         self.print_attrs_as_inner(attrs);
 
@@ -1056,7 +1069,7 @@ impl<'a> State<'a> {
             self.print_expr(expr);
             self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
         }
-        self.bclose_maybe_open(blk.span, close_box);
+        self.bclose_maybe_open(blk.span, cb);
         self.ann.post(self, AnnNode::Block(blk))
     }
 
@@ -1065,20 +1078,20 @@ impl<'a> State<'a> {
             match els_inner.kind {
                 // Another `else if` block.
                 hir::ExprKind::If(i, hir::Expr { kind: hir::ExprKind::Block(t, None), .. }, e) => {
-                    self.cbox(0);
-                    self.ibox(0);
+                    let cb = self.cbox(0);
+                    let ib = self.ibox(0);
                     self.word(" else if ");
                     self.print_expr_as_cond(i);
                     self.space();
-                    self.print_block(t);
+                    self.print_block(t, cb, ib);
                     self.print_else(e);
                 }
                 // Final `else` block.
                 hir::ExprKind::Block(b, None) => {
-                    self.cbox(0);
-                    self.ibox(0);
+                    let cb = self.cbox(0);
+                    let ib = self.ibox(0);
                     self.word(" else ");
-                    self.print_block(b);
+                    self.print_block(b, cb, ib);
                 }
                 // Constraints would be great here!
                 _ => {
@@ -1094,14 +1107,14 @@ impl<'a> State<'a> {
         blk: &hir::Expr<'_>,
         elseopt: Option<&hir::Expr<'_>>,
     ) {
-        self.cbox(0);
-        self.ibox(0);
-        self.word_nbsp("if");
-        self.print_expr_as_cond(test);
-        self.space();
         match blk.kind {
             hir::ExprKind::Block(blk, None) => {
-                self.print_block(blk);
+                let cb = self.cbox(0);
+                let ib = self.ibox(0);
+                self.word_nbsp("if");
+                self.print_expr_as_cond(test);
+                self.space();
+                self.print_block(blk, cb, ib);
                 self.print_else(elseopt)
             }
             _ => panic!("non-block then expr"),
@@ -1175,28 +1188,28 @@ impl<'a> State<'a> {
     }
 
     fn print_expr_vec(&mut self, exprs: &[hir::Expr<'_>]) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word("[");
         self.commasep_exprs(Inconsistent, exprs);
         self.word("]");
-        self.end()
+        self.end(ib)
     }
 
     fn print_inline_const(&mut self, constant: &hir::ConstBlock) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word_space("const");
         self.ann.nested(self, Nested::Body(constant.body));
-        self.end()
+        self.end(ib)
     }
 
     fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ConstArg<'_>) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.word("[");
         self.print_expr(element);
         self.word_space(";");
         self.print_const_arg(count);
         self.word("]");
-        self.end()
+        self.end(ib)
     }
 
     fn print_expr_struct(
@@ -1211,23 +1224,23 @@ impl<'a> State<'a> {
         self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span);
         match wth {
             hir::StructTailExpr::Base(expr) => {
-                self.ibox(INDENT_UNIT);
+                let ib = self.ibox(INDENT_UNIT);
                 if !fields.is_empty() {
                     self.word(",");
                     self.space();
                 }
                 self.word("..");
                 self.print_expr(expr);
-                self.end();
+                self.end(ib);
             }
             hir::StructTailExpr::DefaultFields(_) => {
-                self.ibox(INDENT_UNIT);
+                let ib = self.ibox(INDENT_UNIT);
                 if !fields.is_empty() {
                     self.word(",");
                     self.space();
                 }
                 self.word("..");
-                self.end();
+                self.end(ib);
             }
             hir::StructTailExpr::None => {}
         }
@@ -1236,14 +1249,14 @@ impl<'a> State<'a> {
     }
 
     fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
-        self.cbox(INDENT_UNIT);
+        let cb = self.cbox(INDENT_UNIT);
         self.print_attrs_as_outer(self.attrs(field.hir_id));
         if !field.is_shorthand {
             self.print_ident(field.ident);
             self.word_space(":");
         }
         self.print_expr(field.expr);
-        self.end()
+        self.end(cb)
     }
 
     fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) {
@@ -1416,8 +1429,8 @@ impl<'a> State<'a> {
                     s.print_qpath(path, true);
                 }
                 hir::InlineAsmOperand::Label { block } => {
-                    s.head("label");
-                    s.print_block(block);
+                    let (cb, ib) = s.head("label");
+                    s.print_block(block, cb, ib);
                 }
             },
             AsmArg::Options(opts) => {
@@ -1435,7 +1448,7 @@ impl<'a> State<'a> {
     fn print_expr(&mut self, expr: &hir::Expr<'_>) {
         self.maybe_print_comment(expr.span.lo());
         self.print_attrs_as_outer(self.attrs(expr.hir_id));
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.ann.pre(self, AnnNode::Expr(expr));
         match expr.kind {
             hir::ExprKind::Array(exprs) => {
@@ -1483,21 +1496,21 @@ impl<'a> State<'a> {
             }
             hir::ExprKind::Type(expr, ty) => {
                 self.word("type_ascribe!(");
-                self.ibox(0);
+                let ib = self.ibox(0);
                 self.print_expr(expr);
 
                 self.word(",");
                 self.space_if_not_bol();
                 self.print_type(ty);
 
-                self.end();
+                self.end(ib);
                 self.word(")");
             }
             hir::ExprKind::DropTemps(init) => {
                 // Print `{`:
-                self.cbox(INDENT_UNIT);
-                self.ibox(0);
-                self.bopen();
+                let cb = self.cbox(INDENT_UNIT);
+                let ib = self.ibox(0);
+                self.bopen(ib);
 
                 // Print `let _t = $init;`:
                 let temp = Ident::from_str("_t");
@@ -1509,7 +1522,7 @@ impl<'a> State<'a> {
                 self.print_ident(temp);
 
                 // Print `}`:
-                self.bclose_maybe_open(expr.span, true);
+                self.bclose_maybe_open(expr.span, Some(cb));
             }
             hir::ExprKind::Let(&hir::LetExpr { pat, ty, init, .. }) => {
                 self.print_let(pat, ty, init);
@@ -1522,20 +1535,20 @@ impl<'a> State<'a> {
                     self.print_ident(label.ident);
                     self.word_space(":");
                 }
-                self.head("loop");
-                self.print_block(blk);
+                let (cb, ib) = self.head("loop");
+                self.print_block(blk, cb, ib);
             }
             hir::ExprKind::Match(expr, arms, _) => {
-                self.cbox(INDENT_UNIT);
-                self.ibox(INDENT_UNIT);
+                let cb = self.cbox(INDENT_UNIT);
+                let ib = self.ibox(INDENT_UNIT);
                 self.word_nbsp("match");
                 self.print_expr_as_cond(expr);
                 self.space();
-                self.bopen();
+                self.bopen(ib);
                 for arm in arms {
                     self.print_arm(arm);
                 }
-                self.bclose(expr.span);
+                self.bclose(expr.span, cb);
             }
             hir::ExprKind::Closure(&hir::Closure {
                 binder,
@@ -1558,12 +1571,15 @@ impl<'a> State<'a> {
 
                 // This is a bare expression.
                 self.ann.nested(self, Nested::Body(body));
-                self.end(); // need to close a box
+                // FIXME(nnethercote): this is bogus
+                let fake_ib = BoxMarker;
+                self.end(fake_ib);
 
                 // A box will be closed by `print_expr`, but we didn't want an overall
                 // wrapper so we closed the corresponding opening. so create an
                 // empty box to satisfy the close.
-                self.ibox(0);
+                // FIXME(nnethercote): this is bogus, and `print_expr` is missing
+                let _ib = self.ibox(0);
             }
             hir::ExprKind::Block(blk, opt_label) => {
                 if let Some(label) = opt_label {
@@ -1571,10 +1587,10 @@ impl<'a> State<'a> {
                     self.word_space(":");
                 }
                 // containing cbox, will be closed by print-block at `}`
-                self.cbox(0);
+                let cb = self.cbox(0);
                 // head-box, will be closed by print-block after `{`
-                self.ibox(0);
-                self.print_block(blk);
+                let ib = self.ibox(0);
+                self.print_block(blk, cb, ib);
             }
             hir::ExprKind::Assign(lhs, rhs, _) => {
                 self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
@@ -1675,7 +1691,7 @@ impl<'a> State<'a> {
             }
         }
         self.ann.post(self, AnnNode::Expr(expr));
-        self.end()
+        self.end(ib)
     }
 
     fn print_local_decl(&mut self, loc: &hir::LetStmt<'_>) {
@@ -2043,14 +2059,14 @@ impl<'a> State<'a> {
         if self.attrs(field.hir_id).is_empty() {
             self.space();
         }
-        self.cbox(INDENT_UNIT);
+        let cb = self.cbox(INDENT_UNIT);
         self.print_attrs_as_outer(self.attrs(field.hir_id));
         if !field.is_shorthand {
             self.print_ident(field.ident);
             self.word_nbsp(":");
         }
         self.print_pat(field.pat);
-        self.end();
+        self.end(cb);
     }
 
     fn print_param(&mut self, arg: &hir::Param<'_>) {
@@ -2086,9 +2102,9 @@ impl<'a> State<'a> {
         if self.attrs(arm.hir_id).is_empty() {
             self.space();
         }
-        self.cbox(INDENT_UNIT);
+        let cb = self.cbox(INDENT_UNIT);
         self.ann.pre(self, AnnNode::Arm(arm));
-        self.ibox(0);
+        let ib = self.ibox(0);
         self.print_attrs_as_outer(self.attrs(arm.hir_id));
         self.print_pat(arm.pat);
         self.space();
@@ -2105,8 +2121,7 @@ impl<'a> State<'a> {
                     self.print_ident(label.ident);
                     self.word_space(":");
                 }
-                // the block will close the pattern's ibox
-                self.print_block_unclosed(blk);
+                self.print_block_unclosed(blk, ib);
 
                 // If it is a user-provided unsafe block, print a comma after it
                 if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules
@@ -2115,13 +2130,13 @@ impl<'a> State<'a> {
                 }
             }
             _ => {
-                self.end(); // close the ibox for the pattern
+                self.end(ib);
                 self.print_expr(arm.body);
                 self.word(",");
             }
         }
         self.ann.post(self, AnnNode::Arm(arm));
-        self.end() // close enclosing cbox
+        self.end(cb)
     }
 
     fn print_fn(
@@ -2167,9 +2182,9 @@ impl<'a> State<'a> {
             i += 1;
         };
         self.commasep(Inconsistent, decl.inputs, |s, ty| {
-            s.ibox(INDENT_UNIT);
+            let ib = s.ibox(INDENT_UNIT);
             print_arg(s, Some(ty));
-            s.end();
+            s.end(ib);
         });
         if decl.c_variadic {
             if !decl.inputs.is_empty() {
@@ -2188,7 +2203,7 @@ impl<'a> State<'a> {
         self.word("|");
         let mut i = 0;
         self.commasep(Inconsistent, decl.inputs, |s, ty| {
-            s.ibox(INDENT_UNIT);
+            let ib = s.ibox(INDENT_UNIT);
 
             s.ann.nested(s, Nested::BodyParamPat(body_id, i));
             i += 1;
@@ -2200,7 +2215,7 @@ impl<'a> State<'a> {
                 s.space();
                 s.print_type(ty);
             }
-            s.end();
+            s.end(ib);
         });
         self.word("|");
 
@@ -2442,16 +2457,16 @@ impl<'a> State<'a> {
         match decl.output {
             hir::FnRetTy::Return(ty) => {
                 self.space_if_not_bol();
-                self.ibox(INDENT_UNIT);
+                let ib = self.ibox(INDENT_UNIT);
                 self.word_space("->");
                 self.print_type(ty);
-            }
-            hir::FnRetTy::DefaultReturn(..) => return,
-        }
-        self.end();
+                self.end(ib);
 
-        if let hir::FnRetTy::Return(output) = decl.output {
-            self.maybe_print_comment(output.span.lo());
+                if let hir::FnRetTy::Return(output) = decl.output {
+                    self.maybe_print_comment(output.span.lo());
+                }
+            }
+            hir::FnRetTy::DefaultReturn(..) => {}
         }
     }
 
@@ -2464,7 +2479,7 @@ impl<'a> State<'a> {
         generic_params: &[hir::GenericParam<'_>],
         arg_idents: &[Option<Ident>],
     ) {
-        self.ibox(INDENT_UNIT);
+        let ib = self.ibox(INDENT_UNIT);
         self.print_formal_generic_params(generic_params);
         let generics = hir::Generics::empty();
         self.print_fn(
@@ -2480,7 +2495,7 @@ impl<'a> State<'a> {
             arg_idents,
             None,
         );
-        self.end();
+        self.end(ib);
     }
 
     fn print_fn_header_info(&mut self, header: hir::FnHeader) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 934820eb4da..de189b30109 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -337,7 +337,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
         match ty.kind() {
             ty::Adt(adt_def, _) => Some(*adt_def),
             // FIXME(#104767): Should we handle bound regions here?
-            ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _)
+            ty::Alias(ty::Projection | ty::Inherent | ty::Free, _)
                 if !ty.has_escaping_bound_vars() =>
             {
                 if self.next_trait_solver() {
@@ -357,7 +357,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
             // WF obligations that are registered elsewhere, but they have a
             // better cause code assigned to them in `add_required_obligations_for_hir`.
             // This means that they should shadow obligations with worse spans.
-            if let ty::Alias(ty::Projection | ty::Weak, ty::AliasTy { args, def_id, .. }) =
+            if let ty::Alias(ty::Projection | ty::Free, ty::AliasTy { args, def_id, .. }) =
                 ty.kind()
             {
                 self.add_required_obligations_for_hir(span, *def_id, args, hir_id);
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index b0ccd35e8f0..210b8f37d88 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -113,7 +113,7 @@ impl<'tcx> InferCtxt<'tcx> {
                         }]);
                     }
                     // The old solver only accepts projection predicates for associated types.
-                    ty::Alias(ty::Inherent | ty::Weak | ty::Opaque, _) => {
+                    ty::Alias(ty::Inherent | ty::Free | ty::Opaque, _) => {
                         return Err(TypeError::CyclicTy(source_ty));
                     }
                     _ => bug!("generalized `{source_ty:?} to infer, not an alias"),
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index a6499b07fe2..99b42ee5480 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -761,7 +761,7 @@ lint_single_use_lifetime = lifetime parameter `{$ident}` only used once
 
 lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
 
-lint_static_mut_refs_lint = creating a {$shared_label}reference to mutable static is discouraged
+lint_static_mut_refs_lint = creating a {$shared_label}reference to mutable static
     .label = {$shared_label}reference to mutable static
     .suggestion = use `&raw const` instead to create a raw pointer
     .suggestion_mut = use `&raw mut` instead to create a raw pointer
diff --git a/compiler/rustc_lint/src/static_mut_refs.rs b/compiler/rustc_lint/src/static_mut_refs.rs
index 50021157dda..4dda3c7951b 100644
--- a/compiler/rustc_lint/src/static_mut_refs.rs
+++ b/compiler/rustc_lint/src/static_mut_refs.rs
@@ -51,7 +51,7 @@ declare_lint! {
     /// This lint is "warn" by default on editions up to 2021, in 2024 is "deny".
     pub STATIC_MUT_REFS,
     Warn,
-    "shared references or mutable references of mutable static is discouraged",
+    "creating a shared reference to mutable static",
     @future_incompatible = FutureIncompatibleInfo {
         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
         reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>",
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f9dce5a5198..7b6a723b0b4 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1381,7 +1381,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
 
             ty::Param(..)
-            | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
+            | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
             | ty::Infer(..)
             | ty::Bound(..)
             | ty::Error(_)
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 293b1552beb..b55e4d7d831 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -289,7 +289,7 @@ rustc_queries! {
 
     /// Returns whether the type alias given by `DefId` is lazy.
     ///
-    /// I.e., if the type alias expands / ought to expand to a [weak] [alias type]
+    /// I.e., if the type alias expands / ought to expand to a [free] [alias type]
     /// instead of the underyling aliased type.
     ///
     /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`.
@@ -298,7 +298,7 @@ rustc_queries! {
     ///
     /// This query *may* panic if the given definition is not a type alias.
     ///
-    /// [weak]: rustc_middle::ty::Weak
+    /// [free]: rustc_middle::ty::Free
     /// [alias type]: rustc_middle::ty::AliasTy
     query type_alias_is_lazy(key: DefId) -> bool {
         desc { |tcx|
@@ -2296,7 +2296,7 @@ rustc_queries! {
     /// Do not call this query directly: Invoke `normalize` instead.
     ///
     /// </div>
-    query normalize_canonicalized_weak_ty(
+    query normalize_canonicalized_free_alias(
         goal: CanonicalAliasGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 7e6151745e2..27079af06fc 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -404,7 +404,7 @@ pub enum ObligationCauseCode<'tcx> {
     /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
     ConstParam(Ty<'tcx>),
 
-    /// Obligations emitted during the normalization of a weak type alias.
+    /// Obligations emitted during the normalization of a free type alias.
     TypeAlias(ObligationCauseCodeHandle<'tcx>, Span, DefId),
 }
 
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 76f3d2bab9c..3f6faa1a572 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -181,7 +181,7 @@ pub struct MethodAutoderefBadTy<'tcx> {
     pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
 }
 
-/// Result of the `normalize_canonicalized_{{,inherent_}projection,weak}_ty` queries.
+/// Result of the `normalize_canonicalized_{{,inherent_}projection,free}_ty` queries.
 #[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
 pub struct NormalizationResult<'tcx> {
     /// Result of the normalization.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 23ee6514622..1efd0d1d14b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -226,7 +226,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
                 }
             }
             DefKind::OpaqueTy => ty::Opaque,
-            DefKind::TyAlias => ty::Weak,
+            DefKind::TyAlias => ty::Free,
             kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
         }
     }
@@ -242,7 +242,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
                 }
             }
             DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
-            DefKind::TyAlias => ty::AliasTermKind::WeakTy,
+            DefKind::TyAlias => ty::AliasTermKind::FreeTy,
             DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
             DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => {
                 ty::AliasTermKind::UnevaluatedConst
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 5ecf1174def..13723874ad3 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -205,7 +205,7 @@ impl<'tcx> Ty<'tcx> {
             ty::Placeholder(..) => "higher-ranked type".into(),
             ty::Bound(..) => "bound type variable".into(),
             ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(),
-            ty::Alias(ty::Weak, _) => "type alias".into(),
+            ty::Alias(ty::Free, _) => "type alias".into(),
             ty::Param(_) => "type parameter".into(),
             ty::Alias(ty::Opaque, ..) => "opaque type".into(),
         }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 32988965a35..d8bab58545f 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -127,7 +127,7 @@ impl<'tcx> Ty<'tcx> {
                 InhabitedPredicate::True
             }
             Never => InhabitedPredicate::False,
-            Param(_) | Alias(ty::Projection | ty::Weak, _) => InhabitedPredicate::GenericType(self),
+            Param(_) | Alias(ty::Projection | ty::Free, _) => InhabitedPredicate::GenericType(self),
             Alias(ty::Opaque, alias_ty) => {
                 match alias_ty.def_id.as_local() {
                     // Foreign opaque is considered inhabited.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 1df3bff5244..ad8677f7c7d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -820,7 +820,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::Foreign(def_id) => {
                 p!(print_def_path(def_id, &[]));
             }
-            ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => {
+            ty::Alias(ty::Projection | ty::Inherent | ty::Free, ref data) => {
                 p!(print(data))
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
@@ -3205,7 +3205,7 @@ define_print! {
                     p!(print_def_path(self.def_id, self.args));
                 }
             }
-            | ty::AliasTermKind::WeakTy
+            | ty::AliasTermKind::FreeTy
             | ty::AliasTermKind::OpaqueTy
             | ty::AliasTermKind::UnevaluatedConst
             | ty::AliasTermKind::ProjectionConst => {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index b6043bc740f..2165cf186bd 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -491,7 +491,7 @@ impl<'tcx> Ty<'tcx> {
             (kind, tcx.def_kind(alias_ty.def_id)),
             (ty::Opaque, DefKind::OpaqueTy)
                 | (ty::Projection | ty::Inherent, DefKind::AssocTy)
-                | (ty::Weak, DefKind::TyAlias)
+                | (ty::Free, DefKind::TyAlias)
         );
         Ty::new(tcx, Alias(kind, alias_ty))
     }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index f46a1d4b22e..f5158edffcf 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -892,7 +892,7 @@ impl<'tcx> TyCtxt<'tcx> {
             || self.extern_crate(key).is_some_and(|e| e.is_direct())
     }
 
-    /// Expand any [weak alias types][weak] contained within the given `value`.
+    /// Expand any [free alias types][free] contained within the given `value`.
     ///
     /// This should be used over other normalization routines in situations where
     /// it's important not to normalize other alias types and where the predicates
@@ -907,19 +907,19 @@ impl<'tcx> TyCtxt<'tcx> {
     /// <div class="warning">
     /// This delays a bug on overflow! Therefore you need to be certain that the
     /// contained types get fully normalized at a later stage. Note that even on
-    /// overflow all well-behaved weak alias types get expanded correctly, so the
+    /// overflow all well-behaved free alias types get expanded correctly, so the
     /// result is still useful.
     /// </div>
     ///
-    /// [weak]: ty::Weak
-    pub fn expand_weak_alias_tys<T: TypeFoldable<TyCtxt<'tcx>>>(self, value: T) -> T {
-        value.fold_with(&mut WeakAliasTypeExpander { tcx: self, depth: 0 })
+    /// [free]: ty::Free
+    pub fn expand_free_alias_tys<T: TypeFoldable<TyCtxt<'tcx>>>(self, value: T) -> T {
+        value.fold_with(&mut FreeAliasTypeExpander { tcx: self, depth: 0 })
     }
 
-    /// Peel off all [weak alias types] in this type until there are none left.
+    /// Peel off all [free alias types] in this type until there are none left.
     ///
-    /// This only expands weak alias types in “head” / outermost positions. It can
-    /// be used over [expand_weak_alias_tys] as an optimization in situations where
+    /// This only expands free alias types in “head” / outermost positions. It can
+    /// be used over [expand_free_alias_tys] as an optimization in situations where
     /// one only really cares about the *kind* of the final aliased type but not
     /// the types the other constituent types alias.
     ///
@@ -928,17 +928,17 @@ impl<'tcx> TyCtxt<'tcx> {
     /// type gets fully normalized at a later stage.
     /// </div>
     ///
-    /// [weak]: ty::Weak
-    /// [expand_weak_alias_tys]: Self::expand_weak_alias_tys
-    pub fn peel_off_weak_alias_tys(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
-        let ty::Alias(ty::Weak, _) = ty.kind() else { return ty };
+    /// [free]: ty::Free
+    /// [expand_free_alias_tys]: Self::expand_free_alias_tys
+    pub fn peel_off_free_alias_tys(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+        let ty::Alias(ty::Free, _) = ty.kind() else { return ty };
 
         let limit = self.recursion_limit();
         let mut depth = 0;
 
-        while let ty::Alias(ty::Weak, alias) = ty.kind() {
+        while let ty::Alias(ty::Free, alias) = ty.kind() {
             if !limit.value_within_limit(depth) {
-                let guar = self.dcx().delayed_bug("overflow expanding weak alias type");
+                let guar = self.dcx().delayed_bug("overflow expanding free alias type");
                 return Ty::new_error(self, guar);
             }
 
@@ -966,7 +966,7 @@ impl<'tcx> TyCtxt<'tcx> {
             }
             ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)),
             ty::AliasTermKind::InherentTy
-            | ty::AliasTermKind::WeakTy
+            | ty::AliasTermKind::FreeTy
             | ty::AliasTermKind::UnevaluatedConst
             | ty::AliasTermKind::ProjectionConst => None,
         }
@@ -1059,25 +1059,25 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
     }
 }
 
-struct WeakAliasTypeExpander<'tcx> {
+struct FreeAliasTypeExpander<'tcx> {
     tcx: TyCtxt<'tcx>,
     depth: usize,
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for FreeAliasTypeExpander<'tcx> {
     fn cx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
+        if !ty.has_type_flags(ty::TypeFlags::HAS_TY_FREE_ALIAS) {
             return ty;
         }
-        let ty::Alias(ty::Weak, alias) = ty.kind() else {
+        let ty::Alias(ty::Free, alias) = ty.kind() else {
             return ty.super_fold_with(self);
         };
         if !self.tcx.recursion_limit().value_within_limit(self.depth) {
-            let guar = self.tcx.dcx().delayed_bug("overflow expanding weak alias type");
+            let guar = self.tcx.dcx().delayed_bug("overflow expanding free alias type");
             return Ty::new_error(self.tcx, guar);
         }
 
@@ -1088,7 +1088,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if !ct.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
+        if !ct.has_type_flags(ty::TypeFlags::HAS_TY_FREE_ALIAS) {
             return ct;
         }
         ct.super_fold_with(self)
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 44c7b6a7c9e..3853a804a92 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -139,7 +139,7 @@ impl<'tcx> TyCtxt<'tcx> {
     {
         let mut collector = LateBoundRegionsCollector::new(just_constrained);
         let value = value.skip_binder();
-        let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value };
+        let value = if just_constrained { self.expand_free_alias_tys(value) } else { value };
         value.visit_with(&mut collector);
         collector.regions
     }
@@ -182,8 +182,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
                 ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => {
                     return;
                 }
-                // All weak alias types should've been expanded beforehand.
-                ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"),
+                // All free alias types should've been expanded beforehand.
+                ty::Alias(ty::Free, _) => bug!("unexpected free alias type"),
                 _ => {}
             }
         }
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index 224c44e60fd..101129a231e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -588,7 +588,7 @@ where
             }
 
             ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty),
-            ty::Alias(ty::Inherent | ty::Weak, _) => {
+            ty::Alias(ty::Inherent | ty::Free, _) => {
                 self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF"));
                 return;
             }
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 1526049719e..035bfff89b5 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -48,7 +48,7 @@ where
 
         ty::Dynamic(..)
         | ty::Param(..)
-        | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
+        | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
         | ty::Placeholder(..)
         | ty::Bound(..)
         | ty::Infer(_) => {
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs
index 14e68dd52b6..d077f8a9be8 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs
@@ -1,7 +1,7 @@
 //! Computes a normalizes-to (projection) goal for inherent associated types,
 //! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`.
 //!
-//! Since a weak alias is never ambiguous, this just computes the `type_of` of
+//! Since a free alias is never ambiguous, this just computes the `type_of` of
 //! the alias and registers the where-clauses of the type alias.
 
 use rustc_type_ir::{self as ty, Interner};
@@ -14,22 +14,22 @@ where
     D: SolverDelegate<Interner = I>,
     I: Interner,
 {
-    pub(super) fn normalize_weak_type(
+    pub(super) fn normalize_free_alias(
         &mut self,
         goal: Goal<I, ty::NormalizesTo<I>>,
     ) -> QueryResult<I> {
         let cx = self.cx();
-        let weak_ty = goal.predicate.alias;
+        let free_ty = goal.predicate.alias;
 
         // Check where clauses
         self.add_goals(
             GoalSource::Misc,
-            cx.predicates_of(weak_ty.def_id)
-                .iter_instantiated(cx, weak_ty.args)
+            cx.predicates_of(free_ty.def_id)
+                .iter_instantiated(cx, free_ty.args)
                 .map(|pred| goal.with(cx, pred)),
         );
 
-        let actual = cx.type_of(weak_ty.def_id).instantiate(cx, weak_ty.args);
+        let actual = cx.type_of(free_ty.def_id).instantiate(cx, free_ty.args);
         self.instantiate_normalizes_to_term(goal, actual.into());
 
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 1625da81b85..f5cad623903 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -1,7 +1,7 @@
 mod anon_const;
+mod free_alias;
 mod inherent;
 mod opaque_types;
-mod weak_types;
 
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
@@ -50,7 +50,7 @@ where
             }
             ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal),
             ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal),
-            ty::AliasTermKind::WeakTy => self.normalize_weak_type(goal),
+            ty::AliasTermKind::FreeTy => self.normalize_free_alias(goal),
             ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal),
         }
     }
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 94e181ae8d8..d19249df387 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -1140,7 +1140,7 @@ where
             ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
-            | ty::Alias(ty::Projection | ty::Weak | ty::Inherent, ..)
+            | ty::Alias(ty::Projection | ty::Free | ty::Inherent, ..)
             | ty::Placeholder(..) => Some(Err(NoSolution)),
 
             ty::Infer(_) | ty::Bound(_, _) => panic!("unexpected type `{self_ty:?}`"),
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b56f3e1971c..a3b479fdb7a 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -213,7 +213,7 @@ where
                     }
                 }
             }
-            ty::Alias(kind @ (ty::Inherent | ty::Weak | ty::Projection), data) => {
+            ty::Alias(kind @ (ty::Inherent | ty::Free | ty::Projection), data) => {
                 if self.def_id_visitor.skip_assoc_tys() {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `Type::Alias`
@@ -227,7 +227,7 @@ where
                     data.def_id,
                     match kind {
                         ty::Inherent | ty::Projection => "associated type",
-                        ty::Weak => "type alias",
+                        ty::Free => "type alias",
                         ty::Opaque => unreachable!(),
                     },
                     &LazyDefPathStr { def_id: data.def_id, tcx },
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 5a4aa7fe278..76489dd0913 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -16,7 +16,7 @@ impl<'tcx> Stable<'tcx> for ty::AliasTyKind {
             ty::Projection => stable_mir::ty::AliasKind::Projection,
             ty::Inherent => stable_mir::ty::AliasKind::Inherent,
             ty::Opaque => stable_mir::ty::AliasKind::Opaque,
-            ty::Weak => stable_mir::ty::AliasKind::Weak,
+            ty::Free => stable_mir::ty::AliasKind::Free,
         }
     }
 }
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 0ac9a0fb647..e331e593471 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1026,7 +1026,7 @@ pub enum AliasKind {
     Projection,
     Inherent,
     Opaque,
-    Weak,
+    Free,
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, Serialize)]
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 1cf1ac5403f..242469a225a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -707,7 +707,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 ty::Projection | ty::Inherent => {
                     format!("the associated type `{p}`")
                 }
-                ty::Weak => format!("the type alias `{p}`"),
+                ty::Free => format!("the type alias `{p}`"),
                 ty::Opaque => format!("the opaque type `{p}`"),
             },
         };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index d8e05d9ad97..ab2aa0ae469 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1659,7 +1659,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 ty::Alias(ty::Projection, ..) => Some(12),
                 ty::Alias(ty::Inherent, ..) => Some(13),
                 ty::Alias(ty::Opaque, ..) => Some(14),
-                ty::Alias(ty::Weak, ..) => Some(15),
+                ty::Alias(ty::Free, ..) => Some(15),
                 ty::Never => Some(16),
                 ty::Adt(..) => Some(17),
                 ty::Coroutine(..) => Some(18),
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 7551ac5aa97..d38ddbc825c 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -333,7 +333,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 );
                 normalized_ty
             }
-            ty::Weak => {
+            ty::Free => {
                 let recursion_limit = self.cx().recursion_limit();
                 if !recursion_limit.value_within_limit(self.depth) {
                     self.selcx.infcx.err_ctxt().report_overflow_error(
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 6087d793721..dd868c9d40e 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -468,7 +468,7 @@ fn normalize_to_error<'a, 'tcx>(
         ty::AliasTermKind::ProjectionTy
         | ty::AliasTermKind::InherentTy
         | ty::AliasTermKind::OpaqueTy
-        | ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
+        | ty::AliasTermKind::FreeTy => selcx.infcx.next_ty_var(cause.span).into(),
         ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
             selcx.infcx.next_const_var(cause.span).into()
         }
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 507932699c7..a54eb80fedc 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -253,7 +253,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
                 }
             }
 
-            ty::Projection | ty::Inherent | ty::Weak => {
+            ty::Projection | ty::Inherent | ty::Free => {
                 // See note in `rustc_trait_selection::traits::project`
 
                 let infcx = self.infcx;
@@ -275,7 +275,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                 let result = match kind {
                     ty::Projection => tcx.normalize_canonicalized_projection_ty(c_data),
-                    ty::Weak => tcx.normalize_canonicalized_weak_ty(c_data),
+                    ty::Free => tcx.normalize_canonicalized_free_alias(c_data),
                     ty::Inherent => tcx.normalize_canonicalized_inherent_projection_ty(c_data),
                     kind => unreachable!("did not expect {kind:?} due to match arm above"),
                 }?;
@@ -313,10 +313,10 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
                 };
                 // `tcx.normalize_canonicalized_projection_ty` may normalize to a type that
                 // still has unevaluated consts, so keep normalizing here if that's the case.
-                // Similarly, `tcx.normalize_canonicalized_weak_ty` will only unwrap one layer
+                // Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer
                 // of type and we need to continue folding it to reveal the TAIT behind it.
                 if res != ty
-                    && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Weak)
+                    && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Free)
                 {
                     res.try_fold_with(self)?
                 } else {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 95778242c72..5d0b9dd41b2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -725,7 +725,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                 }
                 ty::Param(..)
-                | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
+                | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
                 | ty::Placeholder(..)
                 | ty::Bound(..) => {
                     // In these cases, we don't know what the actual
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 89febd6ce3d..df02a67c2c9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2323,7 +2323,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             ty::Placeholder(..)
             | ty::Dynamic(..)
             | ty::Param(..)
-            | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
+            | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
             | ty::Bound(..)
             | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble constituent types of unexpected type: {:?}", t);
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 62bd8e1af05..00a4a58a6d8 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -761,7 +761,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 // Simple cases that are WF if their type args are WF.
             }
 
-            ty::Alias(ty::Projection | ty::Opaque | ty::Weak, data) => {
+            ty::Alias(ty::Projection | ty::Opaque | ty::Free, data) => {
                 let obligations = self.nominal_obligations(data.def_id, data.args);
                 self.out.extend(obligations);
             }
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 4c2b7e4769a..14a92ebb9f9 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -13,7 +13,7 @@ use tracing::debug;
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers {
         normalize_canonicalized_projection_ty,
-        normalize_canonicalized_weak_ty,
+        normalize_canonicalized_free_alias,
         normalize_canonicalized_inherent_projection_ty,
         ..*p
     };
@@ -63,11 +63,11 @@ fn normalize_canonicalized_projection_ty<'tcx>(
     )
 }
 
-fn normalize_canonicalized_weak_ty<'tcx>(
+fn normalize_canonicalized_free_alias<'tcx>(
     tcx: TyCtxt<'tcx>,
     goal: CanonicalAliasGoal<'tcx>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
-    debug!("normalize_canonicalized_weak_ty(goal={:#?})", goal);
+    debug!("normalize_canonicalized_free_alias(goal={:#?})", goal);
 
     tcx.infer_ctxt().enter_canonical_trait_query(
         &goal,
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index cd730aeeea9..841f602d985 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -223,7 +223,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
             }
             // Skips type aliases, as they are meant to be transparent.
             // FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly?
-            ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
+            ty::Alias(ty::Free, alias_ty) if alias_ty.def_id.is_local() => {
                 self.tcx
                     .type_of(alias_ty.def_id)
                     .instantiate(self.tcx, alias_ty.args)
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 74fb148a7cc..b37347354fa 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -73,8 +73,8 @@ bitflags::bitflags! {
 
         /// Does this have `Projection`?
         const HAS_TY_PROJECTION           = 1 << 10;
-        /// Does this have `Weak`?
-        const HAS_TY_WEAK                 = 1 << 11;
+        /// Does this have `Free` aliases?
+        const HAS_TY_FREE_ALIAS                 = 1 << 11;
         /// Does this have `Opaque`?
         const HAS_TY_OPAQUE               = 1 << 12;
         /// Does this have `Inherent`?
@@ -86,7 +86,7 @@ bitflags::bitflags! {
         ///
         /// Rephrased, could this term be normalized further?
         const HAS_ALIAS                   = TypeFlags::HAS_TY_PROJECTION.bits()
-                                          | TypeFlags::HAS_TY_WEAK.bits()
+                                          | TypeFlags::HAS_TY_FREE_ALIAS.bits()
                                           | TypeFlags::HAS_TY_OPAQUE.bits()
                                           | TypeFlags::HAS_TY_INHERENT.bits()
                                           | TypeFlags::HAS_CT_PROJECTION.bits();
@@ -273,7 +273,7 @@ impl<I: Interner> FlagComputation<I> {
             ty::Alias(kind, data) => {
                 self.add_flags(match kind {
                     ty::Projection => TypeFlags::HAS_TY_PROJECTION,
-                    ty::Weak => TypeFlags::HAS_TY_WEAK,
+                    ty::Free => TypeFlags::HAS_TY_FREE_ALIAS,
                     ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
                     ty::Inherent => TypeFlags::HAS_TY_INHERENT,
                 });
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 8e10636ff65..0411c5c2325 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -470,10 +470,10 @@ pub enum AliasTermKind {
     /// An opaque type (usually from `impl Trait` in type aliases or function return types)
     /// Can only be normalized away in PostAnalysis mode or its defining scope.
     OpaqueTy,
-    /// A type alias that actually checks its trait bounds.
+    /// A free type alias that actually checks its trait bounds.
     /// Currently only used if the type alias references opaque types.
     /// Can always be normalized away.
-    WeakTy,
+    FreeTy,
     /// An unevaluated const coming from a generic const expression.
     UnevaluatedConst,
     /// An unevaluated const coming from an associated const.
@@ -487,7 +487,7 @@ impl AliasTermKind {
             AliasTermKind::ProjectionConst => "associated const",
             AliasTermKind::InherentTy => "inherent associated type",
             AliasTermKind::OpaqueTy => "opaque type",
-            AliasTermKind::WeakTy => "type alias",
+            AliasTermKind::FreeTy => "type alias",
             AliasTermKind::UnevaluatedConst => "unevaluated constant",
         }
     }
@@ -498,7 +498,7 @@ impl From<ty::AliasTyKind> for AliasTermKind {
         match value {
             ty::Projection => AliasTermKind::ProjectionTy,
             ty::Opaque => AliasTermKind::OpaqueTy,
-            ty::Weak => AliasTermKind::WeakTy,
+            ty::Free => AliasTermKind::FreeTy,
             ty::Inherent => AliasTermKind::InherentTy,
         }
     }
@@ -565,7 +565,7 @@ impl<I: Interner> AliasTerm<I> {
             AliasTermKind::ProjectionTy
             | AliasTermKind::InherentTy
             | AliasTermKind::OpaqueTy
-            | AliasTermKind::WeakTy => {}
+            | AliasTermKind::FreeTy => {}
             AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
                 panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
             }
@@ -597,9 +597,9 @@ impl<I: Interner> AliasTerm<I> {
                 ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
             )
             .into(),
-            AliasTermKind::WeakTy => Ty::new_alias(
+            AliasTermKind::FreeTy => Ty::new_alias(
                 interner,
-                ty::AliasTyKind::Weak,
+                ty::AliasTyKind::Free,
                 ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
             )
             .into(),
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index d065384b58e..c80a567117c 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -273,7 +273,7 @@ impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
                     false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
                 )?,
                 ty::AliasTermKind::ProjectionTy
-                | ty::AliasTermKind::WeakTy
+                | ty::AliasTermKind::FreeTy
                 | ty::AliasTermKind::InherentTy
                 | ty::AliasTermKind::UnevaluatedConst
                 | ty::AliasTermKind::ProjectionConst => {
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 753a72a051a..21adbffc027 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -54,7 +54,7 @@ pub enum AliasTyKind {
     /// A type alias that actually checks its trait bounds.
     /// Currently only used if the type alias references opaque types.
     /// Can always be normalized away.
-    Weak,
+    Free,
 }
 
 impl AliasTyKind {
@@ -63,7 +63,7 @@ impl AliasTyKind {
             AliasTyKind::Projection => "associated type",
             AliasTyKind::Inherent => "inherent associated type",
             AliasTyKind::Opaque => "opaque type",
-            AliasTyKind::Weak => "type alias",
+            AliasTyKind::Free => "type alias",
         }
     }
 }
@@ -223,7 +223,7 @@ pub enum TyKind<I: Interner> {
     /// A tuple type. For example, `(i32, bool)`.
     Tuple(I::Tys),
 
-    /// A projection, opaque type, weak type alias, or inherent associated type.
+    /// A projection, opaque type, free type alias, or inherent associated type.
     /// All of these types are represented as pairs of def-id and args, and can
     /// be normalized, so they are grouped conceptually.
     Alias(AliasTyKind, AliasTy<I>),