From 82348ef1e660592d7ca0aea20b7a8e5615a074aa Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 30 Sep 2021 22:47:41 -0700 Subject: [PATCH 01/25] nice_region_error: Include lifetime placeholders in error output As you can see in src/test/ui/traits/self-without-lifetime-constraint.stderr you can get very confusing type names if you don't have this. Fixes #87763 --- .../trait_impl_difference.rs | 59 +++++++++++++++---- .../mismatched_trait_impl-2.stderr | 8 +-- .../mismatched_trait_impl.stderr | 8 +-- ...ime-mismatch-between-trait-and-impl.stderr | 8 +-- .../issue-75361-mismatched-impl.stderr | 8 +-- .../param-without-lifetime-constraint.stderr | 8 +-- .../self-without-lifetime-constraint.stderr | 8 +-- 7 files changed, 72 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 43aa8a6efcec4..a362ef8b7564f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -9,10 +9,13 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_middle::ty::error::ExpectedFound; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::print::RegionHighlightMode; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}; + use rustc_span::{MultiSpan, Span, Symbol}; +use std::ops::ControlFlow; + impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { @@ -67,6 +70,47 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .tcx() .sess .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature"); + + // Mark all unnamed regions in the type with a number. + // This diagnostic is called in response to lifetime errors, so be informative. + struct HighlightBuilder<'tcx> { + highlight: RegionHighlightMode, + tcx: TyCtxt<'tcx>, + counter: usize, + } + + impl HighlightBuilder<'tcx> { + fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode { + let mut builder = + HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx }; + builder.visit_ty(ty); + builder.highlight + } + } + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> { + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + if !r.has_name() && self.counter <= 3 { + self.highlight.highlighting_region(r, self.counter); + self.counter += 1; + } + r.super_visit_with(self) + } + } + + let expected_highlight = HighlightBuilder::build(self.tcx(), expected); + let expected = self + .infcx + .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight)) + .name; + let found_highlight = HighlightBuilder::build(self.tcx(), found); + let found = + self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; + err.span_label(sp, &format!("found `{}`", found)); err.span_label(trait_sp, &format!("expected `{}`", expected)); @@ -94,15 +138,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - if let Some((expected, found)) = - self.infcx.expected_found_str_ty(ExpectedFound { expected, found }) - { - // Highlighted the differences when showing the "expected/found" note. - err.note_expected_found(&"", expected, &"", found); - } else { - // This fallback shouldn't be necessary, but let's keep it in just in case. - err.note(&format!("expected `{}`\n found `{}`", expected, found)); - } + err.note(&format!("expected `{}`\n found `{}`", expected, found)); + err.span_help( type_param_span, "the lifetime requirements from the `impl` do not correspond to the requirements in \ diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index b15efd6c770eb..0546b6b51b273 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -2,15 +2,15 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl-2.rs:8:5 | LL | fn deref(&self) -> &dyn Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Struct) -> &dyn Trait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct) -> &'1 (dyn Trait + '1)` | ::: $SRC_DIR/core/src/ops/deref.rs:LL:COL | LL | fn deref(&self) -> &Self::Target; - | --------------------------------- expected `fn(&Struct) -> &(dyn Trait + 'static)` + | --------------------------------- expected `fn(&'1 Struct) -> &'1 (dyn Trait + 'static)` | - = note: expected `fn(&Struct) -> &(dyn Trait + 'static)` - found `fn(&Struct) -> &dyn Trait` + = note: expected `fn(&'1 Struct) -> &'1 (dyn Trait + 'static)` + found `fn(&'1 Struct) -> &'1 (dyn Trait + '1)` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 9a0bd827850cf..84e5339122ead 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32; - | ---------------------------------------------- expected `fn(&i32, &'a u32, &u32) -> &'a u32` + | ---------------------------------------------- expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32` ... LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &u32, &u32) -> &u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32` | - = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` - found `fn(&i32, &u32, &u32) -> &u32` + = note: expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32` + found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index 060e6954403c0..3040a8512ce1d 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 | LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; - | ------------------------------------------- expected `fn(&i32, &'a i32) -> &'a i32` + | ------------------------------------------- expected `fn(&'1 i32, &'a i32) -> &'a i32` ... LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &i32) -> &i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'1 i32) -> &'1 i32` | - = note: expected `fn(&i32, &'a i32) -> &'a i32` - found `fn(&i32, &i32) -> &i32` + = note: expected `fn(&'1 i32, &'a i32) -> &'a i32` + found `fn(&'1 i32, &'1 i32) -> &'1 i32` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr index 9867addaf38e7..2a2c23c94212f 100644 --- a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr +++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/issue-75361-mismatched-impl.rs:18:3 | LL | fn adjacent_edges(&self) -> Box>; - | --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait + 'static)>` + | --------------------------------------------------------------------- expected `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` ... LL | fn adjacent_edges(&self) -> Box + '_> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` | - = note: expected `fn(&T) -> Box<(dyn MyTrait + 'static)>` - found `fn(&T) -> Box>` + = note: expected `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` + found `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/issue-75361-mismatched-impl.rs:12:55 | diff --git a/src/test/ui/traits/param-without-lifetime-constraint.stderr b/src/test/ui/traits/param-without-lifetime-constraint.stderr index 763fb5186cc9a..118b2cf3ecd85 100644 --- a/src/test/ui/traits/param-without-lifetime-constraint.stderr +++ b/src/test/ui/traits/param-without-lifetime-constraint.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/param-without-lifetime-constraint.rs:14:5 | LL | fn get_relation(&self) -> To; - | ----------------------------- expected `fn(&Article) -> &ProofReader` + | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader` ... LL | fn get_relation(&self) -> &ProofReader { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Article) -> &ProofReader` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader` | - = note: expected `fn(&Article) -> &ProofReader` - found `fn(&Article) -> &ProofReader` + = note: expected `fn(&'1 Article) -> &'2 ProofReader` + found `fn(&'1 Article) -> &'1 ProofReader` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/param-without-lifetime-constraint.rs:10:31 | diff --git a/src/test/ui/traits/self-without-lifetime-constraint.stderr b/src/test/ui/traits/self-without-lifetime-constraint.stderr index 73b5aec022c60..85fada3b87c38 100644 --- a/src/test/ui/traits/self-without-lifetime-constraint.stderr +++ b/src/test/ui/traits/self-without-lifetime-constraint.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/self-without-lifetime-constraint.rs:45:5 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; - | -------------------------------------------------------------------- expected `fn(ValueRef<'_>) -> Result<(&str, &&str), FromSqlError>` + | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` ... LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'_>) -> Result<(&str, &&str), FromSqlError>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` | - = note: expected `fn(ValueRef<'_>) -> Result<(&str, &&str), _>` - found `fn(ValueRef<'_>) -> Result<(&str, &&str), _>` + = note: expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` + found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/self-without-lifetime-constraint.rs:41:60 | From 729ff2d00653feec9810857a7a6b06559d78cfb8 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sat, 25 Sep 2021 20:51:46 +0100 Subject: [PATCH 02/25] Give better error for `macro_rules name` --- compiler/rustc_parse/src/parser/item.rs | 50 +++++++++++++++---- src/test/ui/macros/missing-bang-in-decl.fixed | 16 ++++++ src/test/ui/macros/missing-bang-in-decl.rs | 16 ++++++ .../ui/macros/missing-bang-in-decl.stderr | 20 ++++++++ 4 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/macros/missing-bang-in-decl.fixed create mode 100644 src/test/ui/macros/missing-bang-in-decl.rs create mode 100644 src/test/ui/macros/missing-bang-in-decl.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 624390a406ff2..c436e82d9748b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -279,9 +279,9 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Macro) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? - } else if self.is_macro_rules_item() { + } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() { // MACRO_RULES ITEM - self.parse_item_macro_rules(vis)? + self.parse_item_macro_rules(vis, has_bang)? } else if vis.kind.is_pub() && self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; return Ok(None); @@ -300,7 +300,7 @@ impl<'a> Parser<'a> { || self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` - || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` + || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac` } /// Are we sure this could not possibly be a macro invocation? @@ -1534,18 +1534,43 @@ impl<'a> Parser<'a> { Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) } - /// Is this unambiguously the start of a `macro_rules! foo` item definition? - fn is_macro_rules_item(&mut self) -> bool { - self.check_keyword(kw::MacroRules) - && self.look_ahead(1, |t| *t == token::Not) - && self.look_ahead(2, |t| t.is_ident()) + /// Is this a possibly malformed start of a `macro_rules! foo` item definition? + + fn is_macro_rules_item(&mut self) -> IsMacroRulesItem { + if self.check_keyword(kw::MacroRules) { + let macro_rules_span = self.token.span; + + if self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) { + return IsMacroRulesItem::Yes { has_bang: true }; + } else if self.look_ahead(1, |t| (t.is_ident())) { + // macro_rules foo + self.struct_span_err(macro_rules_span, "expected `!` after `macro_rules`") + .span_suggestion( + macro_rules_span, + "add a `!`", + "macro_rules!".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + + return IsMacroRulesItem::Yes { has_bang: false }; + } + } + + IsMacroRulesItem::No } /// Parses a `macro_rules! foo { ... }` declarative macro. - fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + fn parse_item_macro_rules( + &mut self, + vis: &Visibility, + has_bang: bool, + ) -> PResult<'a, ItemInfo> { self.expect_keyword(kw::MacroRules)?; // `macro_rules` - self.expect(&token::Not)?; // `!` + if has_bang { + self.expect(&token::Not)?; // `!` + } let ident = self.parse_ident()?; if self.eat(&token::Not) { @@ -2121,3 +2146,8 @@ impl<'a> Parser<'a> { } } } + +enum IsMacroRulesItem { + Yes { has_bang: bool }, + No, +} diff --git a/src/test/ui/macros/missing-bang-in-decl.fixed b/src/test/ui/macros/missing-bang-in-decl.fixed new file mode 100644 index 0000000000000..b1aa3298bfa56 --- /dev/null +++ b/src/test/ui/macros/missing-bang-in-decl.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_macros)] + +macro_rules! foo { + //~^ ERROR expected `!` after `macro_rules` + () => {}; +} + +macro_rules! bar { + //~^ ERROR expected `!` after `macro_rules` + //~^^ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/src/test/ui/macros/missing-bang-in-decl.rs b/src/test/ui/macros/missing-bang-in-decl.rs new file mode 100644 index 0000000000000..8393f15fc52f4 --- /dev/null +++ b/src/test/ui/macros/missing-bang-in-decl.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_macros)] + +macro_rules foo { + //~^ ERROR expected `!` after `macro_rules` + () => {}; +} + +macro_rules bar! { + //~^ ERROR expected `!` after `macro_rules` + //~^^ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/src/test/ui/macros/missing-bang-in-decl.stderr b/src/test/ui/macros/missing-bang-in-decl.stderr new file mode 100644 index 0000000000000..dfabafb0a7ab8 --- /dev/null +++ b/src/test/ui/macros/missing-bang-in-decl.stderr @@ -0,0 +1,20 @@ +error: expected `!` after `macro_rules` + --> $DIR/missing-bang-in-decl.rs:5:1 + | +LL | macro_rules foo { + | ^^^^^^^^^^^ help: add a `!`: `macro_rules!` + +error: expected `!` after `macro_rules` + --> $DIR/missing-bang-in-decl.rs:10:1 + | +LL | macro_rules bar! { + | ^^^^^^^^^^^ help: add a `!`: `macro_rules!` + +error: macro names aren't followed by a `!` + --> $DIR/missing-bang-in-decl.rs:10:16 + | +LL | macro_rules bar! { + | ^ help: remove the `!` + +error: aborting due to 3 previous errors + From 1bb399c3420038d54a1eda799a941e77ccd61a05 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 8 Oct 2021 09:59:33 +0100 Subject: [PATCH 03/25] Ensure that pushing empty path works as before Fixes: https://github.com/rust-lang/rust/issues/89658 --- library/std/src/path.rs | 5 ++++- library/std/src/path/tests.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 47156dc33e518..8f00d2260e4c6 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1208,6 +1208,9 @@ impl PathBuf { /// * if `path` has a root but no prefix (e.g., `\windows`), it /// replaces everything except for the prefix (if any) of `self`. /// * if `path` has a prefix but no root, it replaces `self`. + /// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`) + /// and `path` is not empty, the new path is normalized: all references + /// to `.` and `..` are removed. /// /// # Examples /// @@ -1254,7 +1257,7 @@ impl PathBuf { self.as_mut_vec().truncate(0); // verbatim paths need . and .. removed - } else if comps.prefix_verbatim() { + } else if comps.prefix_verbatim() && !path.inner.is_empty() { let mut buf: Vec<_> = comps.collect(); for c in path.components() { match c { diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index 3973a6829d3d3..0a16ff2a721ce 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1271,6 +1271,7 @@ pub fn test_push() { tp!(r"\\?\A:\x\y", "/foo", r"\\?\A:\foo"); tp!(r"\\?\A:", r"..\foo\.", r"\\?\A:\foo"); tp!(r"\\?\A:\x\y", r".\foo\.", r"\\?\A:\x\y\foo"); + tp!(r"\\?\A:\x\y", r"", r"\\?\A:\x\y\"); } } From bd1a1e4f0d2f3fbd0788f30370437ffcbca0c777 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 14 Oct 2021 16:19:39 -0500 Subject: [PATCH 04/25] Don't mark for loop head span with desugaring --- compiler/rustc_ast_lowering/src/expr.rs | 15 ++--- .../src/diagnostics/conflict_errors.rs | 60 +++++++++---------- .../src/diagnostics/move_errors.rs | 21 +++---- compiler/rustc_lint/src/array_into_iter.rs | 3 +- src/test/incremental/hashes/for_loops.rs | 2 +- 5 files changed, 48 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6027027428eee..bc8ea4fb5efa5 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1331,15 +1331,10 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Block, opt_label: Option