From 364475b281519695da69736ac2ee38c254b30c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Jan 2025 20:56:37 +0000 Subject: [PATCH 01/13] Add tests for some cases mentioned in #135589 --- .../missing-lifetime-in-assoc-type-1.rs | 16 +++++++++++++ .../missing-lifetime-in-assoc-type-1.stderr | 15 ++++++++++++ .../missing-lifetime-in-assoc-type-2.rs | 14 +++++++++++ .../missing-lifetime-in-assoc-type-2.stderr | 24 +++++++++++++++++++ .../missing-lifetime-in-assoc-type-3.rs | 14 +++++++++++ .../missing-lifetime-in-assoc-type-3.stderr | 20 ++++++++++++++++ .../missing-lifetime-in-assoc-type-4.rs | 14 +++++++++++ .../missing-lifetime-in-assoc-type-4.stderr | 15 ++++++++++++ 8 files changed, 132 insertions(+) create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.rs create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.rs create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs new file mode 100644 index 0000000000000..28e86635b1b79 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs @@ -0,0 +1,16 @@ +struct S; +struct T; + +impl<'a> IntoIterator for &S { + //~^ ERROR E0207 + //~| NOTE unconstrained lifetime parameter + type Item = &T; + //~^ ERROR in the trait associated type + //~| NOTE this lifetime must come from the implemented type + type IntoIter = std::collections::btree_map::Values<'a, i32, T>; + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} +fn main() {} diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr new file mode 100644 index 0000000000000..0796f65b9b2d1 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr @@ -0,0 +1,15 @@ +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + --> $DIR/missing-lifetime-in-assoc-type-1.rs:7:17 + | +LL | type Item = &T; + | ^ this lifetime must come from the implemented type + +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6 + | +LL | impl<'a> IntoIterator for &S { + | ^^ unconstrained lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.rs new file mode 100644 index 0000000000000..dd720f075ac46 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.rs @@ -0,0 +1,14 @@ +struct S; +struct T; + +impl IntoIterator for &S { + type Item = &T; + //~^ ERROR in the trait associated type + type IntoIter = std::collections::btree_map::Values<'a, i32, T>; + //~^ ERROR use of undeclared lifetime name `'a` + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} +fn main() {} diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr new file mode 100644 index 0000000000000..77916b651b13c --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr @@ -0,0 +1,24 @@ +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + --> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17 + | +LL | type Item = &T; + | ^ this lifetime must come from the implemented type + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetime-in-assoc-type-2.rs:7:57 + | +LL | type IntoIter = std::collections::btree_map::Values<'a, i32, T>; + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; + | ++++ +help: consider introducing lifetime `'a` here + | +LL | impl<'a> IntoIterator for &S { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.rs new file mode 100644 index 0000000000000..60d1f0f8fe571 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.rs @@ -0,0 +1,14 @@ +struct S; +struct T; + +impl IntoIterator for &S { + type Item = &T; + //~^ ERROR in the trait associated type + type IntoIter = std::collections::btree_map::Values; + //~^ ERROR missing lifetime specifier + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} +fn main() {} diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr new file mode 100644 index 0000000000000..50012ac72d22f --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr @@ -0,0 +1,20 @@ +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + --> $DIR/missing-lifetime-in-assoc-type-3.rs:5:17 + | +LL | type Item = &T; + | ^ this lifetime must come from the implemented type + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-type-3.rs:7:56 + | +LL | type IntoIter = std::collections::btree_map::Values; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; + | ++++ +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs new file mode 100644 index 0000000000000..b01c59f3ee6d2 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs @@ -0,0 +1,14 @@ +struct S; +struct T; + +impl IntoIterator for &S { + type Item = &T; + //~^ ERROR in the trait associated type + type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; + //~^ ERROR lifetime parameters or bounds on type `IntoIter` do not match the trait declaration + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} +fn main() {} diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr new file mode 100644 index 0000000000000..f17c098ab6d04 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr @@ -0,0 +1,15 @@ +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + --> $DIR/missing-lifetime-in-assoc-type-4.rs:5:17 + | +LL | type Item = &T; + | ^ this lifetime must come from the implemented type + +error[E0195]: lifetime parameters or bounds on type `IntoIter` do not match the trait declaration + --> $DIR/missing-lifetime-in-assoc-type-4.rs:7:18 + | +LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; + | ^^^^ lifetimes do not match type in trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0195`. From 31556877de42e30a27edabb40014535932137cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Jan 2025 21:02:23 +0000 Subject: [PATCH 02/13] Detect case of missing lifetime in assoc type When an associated type is missing a lifetime, point at its enclosing `impl`, whether it has or doesn't have lifetimes defined. If it does have a lifetime, suggest using it. ``` error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/missing-lifetime-in-assoc-type-1.rs:8:17 | LL | impl<'a> IntoIterator for &S { | ---- there is a named lifetime specified on the impl block you could use ... LL | type Item = &T; | ^ this lifetime must come from the implemented type | help: consider using the lifetime from the impl block | LL | type Item = &'a T; | ++ ``` ``` error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17 | LL | impl IntoIterator for &S { | - you could add a lifetime on the impl block, if the trait or the self type can have one LL | type Item = &T; | ^ this lifetime must come from the implemented type ``` --- compiler/rustc_resolve/src/late.rs | 54 +++++++++++++++++-- .../assoc-type.stderr | 2 + .../missing-lifetime-in-assoc-type-1.rs | 2 + .../missing-lifetime-in-assoc-type-1.stderr | 10 +++- .../missing-lifetime-in-assoc-type-2.stderr | 2 + .../missing-lifetime-in-assoc-type-3.stderr | 2 + .../missing-lifetime-in-assoc-type-4.rs | 2 +- .../missing-lifetime-in-assoc-type-4.stderr | 6 ++- .../ui/lifetimes/no_lending_iterators.stderr | 2 + 9 files changed, 74 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e52cbeb733ac0..cc1eaaa46772e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -20,7 +20,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions, + Applicability, Diag, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions, + pluralize, }; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; @@ -1887,9 +1888,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ty: ty.span, }); } else { - self.r.dcx().emit_err(errors::AnonymousLifetimeNonGatReportError { - lifetime: lifetime.ident.span, - }); + let mut err = self.r.dcx().create_err( + errors::AnonymousLifetimeNonGatReportError { + lifetime: lifetime.ident.span, + }, + ); + self.point_at_impl_lifetimes(&mut err, i, lifetime.ident.span); + err.emit(); } } else { self.r.dcx().emit_err(errors::ElidedAnonymousLifetimeReportError { @@ -1926,6 +1931,47 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); } + fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) { + let Some((rib, span)) = self.lifetime_ribs[..i] + .iter() + .rev() + .skip(1) + .filter_map(|rib| match rib.kind { + LifetimeRibKind::Generics { span, kind: LifetimeBinderKind::ImplBlock, .. } => { + Some((rib, span)) + } + _ => None, + }) + .next() + else { + return; + }; + if !rib.bindings.is_empty() { + err.span_label( + span, + format!( + "there {} named lifetime{} specified on the impl block you could use", + if rib.bindings.len() == 1 { "is a" } else { "are" }, + pluralize!(rib.bindings.len()), + ), + ); + if rib.bindings.len() == 1 { + err.span_suggestion_verbose( + lifetime.shrink_to_hi(), + "consider using the lifetime from the impl block", + format!("{} ", rib.bindings.keys().next().unwrap()), + Applicability::MaybeIncorrect, + ); + } + } else { + err.span_label( + span, + "you could add a lifetime on the impl block, if the trait or the self type can \ + have one", + ); + } + } + #[instrument(level = "debug", skip(self))] fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) { let id = self.r.next_node_id(); diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr index e650eeca48ad9..72c066426bd99 100644 --- a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr +++ b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr @@ -1,6 +1,8 @@ error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/assoc-type.rs:11:19 | +LL | impl MyTrait for &i32 { + | - you could add a lifetime on the impl block, if the trait or the self type can have one LL | type Output = &i32; | ^ this lifetime must come from the implemented type diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs index 28e86635b1b79..5953466375d4e 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs @@ -3,9 +3,11 @@ struct T; impl<'a> IntoIterator for &S { //~^ ERROR E0207 + //~| NOTE there is a named lifetime specified on the impl block you could use //~| NOTE unconstrained lifetime parameter type Item = &T; //~^ ERROR in the trait associated type + //~| HELP consider using the lifetime from the impl block //~| NOTE this lifetime must come from the implemented type type IntoIter = std::collections::btree_map::Values<'a, i32, T>; diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr index 0796f65b9b2d1..1fbde0cfb3988 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr @@ -1,8 +1,16 @@ error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - --> $DIR/missing-lifetime-in-assoc-type-1.rs:7:17 + --> $DIR/missing-lifetime-in-assoc-type-1.rs:8:17 | +LL | impl<'a> IntoIterator for &S { + | ---- there is a named lifetime specified on the impl block you could use +... LL | type Item = &T; | ^ this lifetime must come from the implemented type + | +help: consider using the lifetime from the impl block + | +LL | type Item = &'a T; + | ++ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates --> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6 diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr index 77916b651b13c..8408d37a901fd 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr @@ -1,6 +1,8 @@ error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17 | +LL | impl IntoIterator for &S { + | - you could add a lifetime on the impl block, if the trait or the self type can have one LL | type Item = &T; | ^ this lifetime must come from the implemented type diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr index 50012ac72d22f..d93852aee1bd3 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr @@ -1,6 +1,8 @@ error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/missing-lifetime-in-assoc-type-3.rs:5:17 | +LL | impl IntoIterator for &S { + | - you could add a lifetime on the impl block, if the trait or the self type can have one LL | type Item = &T; | ^ this lifetime must come from the implemented type diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs index b01c59f3ee6d2..0c99e8874c354 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs @@ -5,7 +5,7 @@ impl IntoIterator for &S { type Item = &T; //~^ ERROR in the trait associated type type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; - //~^ ERROR lifetime parameters or bounds on type `IntoIter` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `IntoIter` do not match the trait declaration fn into_iter(self) -> Self::IntoIter { todo!() diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr index f17c098ab6d04..ebe051509aad2 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.stderr @@ -1,14 +1,16 @@ error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/missing-lifetime-in-assoc-type-4.rs:5:17 | +LL | impl IntoIterator for &S { + | - you could add a lifetime on the impl block, if the trait or the self type can have one LL | type Item = &T; | ^ this lifetime must come from the implemented type -error[E0195]: lifetime parameters or bounds on type `IntoIter` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `IntoIter` do not match the trait declaration --> $DIR/missing-lifetime-in-assoc-type-4.rs:7:18 | LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr index 340ef93588515..cadba149c234d 100644 --- a/tests/ui/lifetimes/no_lending_iterators.stderr +++ b/tests/ui/lifetimes/no_lending_iterators.stderr @@ -13,6 +13,8 @@ LL | impl Iterator for Data { error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/no_lending_iterators.rs:18:17 | +LL | impl Bar for usize { + | - you could add a lifetime on the impl block, if the trait or the self type can have one LL | type Item = &usize; | ^ this lifetime must come from the implemented type From 02b8028cb3b677940a5d3620da79206a9d42dd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Jan 2025 21:38:14 +0000 Subject: [PATCH 03/13] On unconstrained lifetime on `impl` block, suggest using it if there's an implicit borrow in the self type ``` error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates --> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6 | LL | impl<'a> IntoIterator for &S { | ^^ unconstrained lifetime parameter | help: consider using the named lifetime here instead of an implict lifetime | LL | impl<'a> IntoIterator for &'a S { | ++ ``` --- .../rustc_hir_analysis/src/impl_wf_check.rs | 24 +++++++++++++++- .../missing-lifetime-in-assoc-type-1.rs | 1 + .../missing-lifetime-in-assoc-type-1.stderr | 7 ++++- .../missing-lifetime-in-assoc-type-5.rs | 19 +++++++++++++ .../missing-lifetime-in-assoc-type-5.stderr | 28 +++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.rs create mode 100644 tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index cbdc501291bc8..5b8eef0965759 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -12,11 +12,12 @@ use std::assert_matches::debug_assert_matches; use min_specialization::check_min_specialization; use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; use rustc_errors::codes::*; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::ErrorGuaranteed; +use rustc_span::{ErrorGuaranteed, kw}; use crate::constrained_generic_params as cgp; use crate::errors::UnconstrainedGenericParameter; @@ -158,6 +159,27 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( const_param_note2: false, }); diag.code(E0207); + for p in &impl_generics.own_params { + if p.name == kw::UnderscoreLifetime { + let span = tcx.def_span(p.def_id); + let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) else { + continue; + }; + + let (span, sugg) = if &snippet == "'_" { + (span, param.name.to_string()) + } else { + (span.shrink_to_hi(), format!("{} ", param.name)) + }; + diag.span_suggestion_verbose( + span, + "consider using the named lifetime here instead of an implict \ + lifetime", + sugg, + Applicability::MaybeIncorrect, + ); + } + } res = Err(diag.emit()); } } diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs index 5953466375d4e..1ae381ef7bc02 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.rs @@ -5,6 +5,7 @@ impl<'a> IntoIterator for &S { //~^ ERROR E0207 //~| NOTE there is a named lifetime specified on the impl block you could use //~| NOTE unconstrained lifetime parameter + //~| HELP consider using the named lifetime here instead of an implict lifetime type Item = &T; //~^ ERROR in the trait associated type //~| HELP consider using the lifetime from the impl block diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr index 1fbde0cfb3988..bf26ce4a63027 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-1.stderr @@ -1,5 +1,5 @@ error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - --> $DIR/missing-lifetime-in-assoc-type-1.rs:8:17 + --> $DIR/missing-lifetime-in-assoc-type-1.rs:9:17 | LL | impl<'a> IntoIterator for &S { | ---- there is a named lifetime specified on the impl block you could use @@ -17,6 +17,11 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, | LL | impl<'a> IntoIterator for &S { | ^^ unconstrained lifetime parameter + | +help: consider using the named lifetime here instead of an implict lifetime + | +LL | impl<'a> IntoIterator for &'a S { + | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.rs b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.rs new file mode 100644 index 0000000000000..ff64d6b900949 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.rs @@ -0,0 +1,19 @@ +struct S; +struct T; + +impl<'a> IntoIterator for &'_ S { + //~^ ERROR E0207 + //~| NOTE there is a named lifetime specified on the impl block you could use + //~| NOTE unconstrained lifetime parameter + //~| HELP consider using the named lifetime here instead of an implict lifetime + type Item = &T; + //~^ ERROR in the trait associated type + //~| HELP consider using the lifetime from the impl block + //~| NOTE this lifetime must come from the implemented type + type IntoIter = std::collections::btree_map::Values<'a, i32, T>; + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} +fn main() {} diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr new file mode 100644 index 0000000000000..7a63bd5b05eff --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr @@ -0,0 +1,28 @@ +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + --> $DIR/missing-lifetime-in-assoc-type-5.rs:9:17 + | +LL | impl<'a> IntoIterator for &'_ S { + | ---- there is a named lifetime specified on the impl block you could use +... +LL | type Item = &T; + | ^ this lifetime must come from the implemented type + | +help: consider using the lifetime from the impl block + | +LL | type Item = &'a T; + | ++ + +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/missing-lifetime-in-assoc-type-5.rs:4:6 + | +LL | impl<'a> IntoIterator for &'_ S { + | ^^ unconstrained lifetime parameter + | +help: consider using the named lifetime here instead of an implict lifetime + | +LL | impl<'a> IntoIterator for &'a S { + | ~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. From 6fcc9f5b16526f9c221eba01bacf5ad84cf859f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Jan 2025 22:12:35 +0000 Subject: [PATCH 04/13] Do not suggest introducing lifetime in impl assoc type ``` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/missing-lifetime-in-assoc-type-2.rs:7:57 | LL | impl IntoIterator for &S { | - help: consider introducing lifetime `'a` here: `<'a>` ... LL | type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | ^^ undeclared lifetime ``` ``` error[E0106]: missing lifetime specifier --> $DIR/issue-74918-missing-lifetime.rs:9:30 | LL | type Item = IteratorChunk; | ^ expected named lifetime parameter | help: consider introducing a named lifetime parameter | LL ~ impl<'a, T, S: Iterator> Iterator for ChunkingIterator { LL ~ type Item = IteratorChunk<'a, T, S>; | ``` --- compiler/rustc_resolve/src/late.rs | 4 +++- compiler/rustc_resolve/src/late/diagnostics.rs | 3 +++ tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr | 4 ---- tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr | 7 +++++-- tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr | 5 +++-- .../mismatched_types/issue-74918-missing-lifetime.stderr | 5 +++-- .../ui/nll/user-annotations/region-error-ice-109072.stderr | 4 ---- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index cc1eaaa46772e..12c5f7fbc1113 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -378,6 +378,7 @@ enum LifetimeBinderKind { Function, Closure, ImplBlock, + ImplAssocType, } impl LifetimeBinderKind { @@ -388,6 +389,7 @@ impl LifetimeBinderKind { PolyTrait => "bound", WhereBound => "bound", Item | ConstItem => "item", + ImplAssocType => "associated type", ImplBlock => "impl block", Function => "function", Closure => "closure", @@ -3406,7 +3408,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &generics.params, RibKind::AssocItem, item.id, - LifetimeBinderKind::Item, + LifetimeBinderKind::ImplAssocType, generics.span, |this| { this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index aca251da71d39..f1fde99f1fc12 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3154,6 +3154,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { continue; } + if let LifetimeBinderKind::ImplAssocType = kind { + continue; + } if !span.can_be_used_for_suggestions() && suggest_note diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr index 8408d37a901fd..7a0246eaac8fd 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-2.stderr @@ -14,10 +14,6 @@ LL | type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | help: consider introducing lifetime `'a` here | -LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; - | ++++ -help: consider introducing lifetime `'a` here - | LL | impl<'a> IntoIterator for &S { | ++++ diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr index d93852aee1bd3..408d5bb40664d 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-3.stderr @@ -14,8 +14,11 @@ LL | type IntoIter = std::collections::btree_map::Values; | help: consider introducing a named lifetime parameter | -LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; - | ++++ +++ +LL ~ impl<'a> IntoIterator for &S { +LL | type Item = &T; +LL | +LL ~ type IntoIter = std::collections::btree_map::Values<'a, i32, T>; + | error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr index 7a63bd5b05eff..9c960c67e2502 100644 --- a/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr +++ b/tests/ui/lifetimes/missing-lifetime-in-assoc-type-5.stderr @@ -20,8 +20,9 @@ LL | impl<'a> IntoIterator for &'_ S { | help: consider using the named lifetime here instead of an implict lifetime | -LL | impl<'a> IntoIterator for &'a S { - | ~~ +LL - impl<'a> IntoIterator for &'_ S { +LL + impl<'a> IntoIterator for &'a S { + | error: aborting due to 2 previous errors diff --git a/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr index 5020395eb6aea..dc21c2e3cf9bf 100644 --- a/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr +++ b/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr @@ -6,8 +6,9 @@ LL | type Item = IteratorChunk; | help: consider introducing a named lifetime parameter | -LL | type Item<'a> = IteratorChunk<'a, T, S>; - | ++++ +++ +LL ~ impl<'a, T, S: Iterator> Iterator for ChunkingIterator { +LL ~ type Item = IteratorChunk<'a, T, S>; + | error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/region-error-ice-109072.stderr b/tests/ui/nll/user-annotations/region-error-ice-109072.stderr index 42551b87f6234..026f5b5f80a9b 100644 --- a/tests/ui/nll/user-annotations/region-error-ice-109072.stderr +++ b/tests/ui/nll/user-annotations/region-error-ice-109072.stderr @@ -17,10 +17,6 @@ LL | type T = &'missing (); | help: consider introducing lifetime `'missing` here | -LL | type T<'missing> = &'missing (); - | ++++++++++ -help: consider introducing lifetime `'missing` here - | LL | impl<'missing> Lt<'missing> for () { | ++++++++++ From 6e225424a66886fa44e671dfa94063fb3a9f4529 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Sun, 28 Sep 2025 16:45:24 -0600 Subject: [PATCH 05/13] test: Add empty line to tests getting new flag in next commit --- .../non-1-width-unicode-multiline-label.ascii.stderr | 8 ++++---- .../non-1-width-unicode-multiline-label.rs | 1 + .../non-1-width-unicode-multiline-label.unicode.stderr | 8 ++++---- .../non-whitespace-trimming-2.ascii.stderr | 2 +- tests/ui/diagnostic-width/non-whitespace-trimming-2.rs | 1 + .../non-whitespace-trimming-2.unicode.stderr | 2 +- .../diagnostic-width/non-whitespace-trimming-unicode.rs | 1 + .../non-whitespace-trimming-unicode.stderr | 2 +- tests/ui/diagnostic-width/non-whitespace-trimming.rs | 1 + tests/ui/diagnostic-width/non-whitespace-trimming.stderr | 2 +- 10 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr index 60ce0d9a14839..fe1ecfbe71d4c 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `&str` to `&str` - --> $DIR/non-1-width-unicode-multiline-label.rs:7:237 + --> $DIR/non-1-width-unicode-multiline-label.rs:8:237 | LL | ...๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ"; let _a = unicode_is_fun + " really fun!"; | -------------- ^ -------------- &str @@ -14,7 +14,7 @@ LL | let _ = "๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง | +++++++++++ error[E0369]: cannot add `&str` to `&str` - --> $DIR/non-1-width-unicode-multiline-label.rs:9:384 + --> $DIR/non-1-width-unicode-multiline-label.rs:10:384 | LL | ...๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ"; let _a = unicode_is_fun + " really fun!"; | -------------- ^ -------------- &str @@ -29,7 +29,7 @@ LL | let _ = "๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง | +++++++++++ error[E0369]: cannot add `&str` to `&str` - --> $DIR/non-1-width-unicode-multiline-label.rs:11:260 + --> $DIR/non-1-width-unicode-multiline-label.rs:12:260 | LL | ...เฟ‡เฟˆเฟ‰เฟŠเฟ‹เฟŒเฟเฟŽเฟเฟเฟ‘เฟ’เฟ“เฟ”เฟ•เฟ–เฟ—เฟ˜เฟ™เฟš"; let _a = unicode_is_fun + " really fun!"; | -------------- ^ -------------- &str @@ -44,7 +44,7 @@ LL | let _ = "เผ€เผเผ‚เผƒเผ„เผ…เผ†เผ‡เผˆเผ‰เผŠเผ‹เผŒเผเผŽเผเผเผ‘เผ’เผ“ | +++++++++++ error[E0369]: cannot add `&str` to `&str` - --> $DIR/non-1-width-unicode-multiline-label.rs:13:219 + --> $DIR/non-1-width-unicode-multiline-label.rs:14:219 | LL | ...xxxxxxxxxxxxxxxxxxxx"; let _a = unicode_is_fun + " really fun!"; | -------------- ^ -------------- &str diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs index 6b9b27f6297fc..0940b987fea11 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs @@ -1,4 +1,5 @@ //@ revisions: ascii unicode + //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr index 15b5dd9d7e2d7..4dff15642aeb4 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `&str` to `&str` - โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:7:237 + โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:8:237 โ”‚ LL โ”‚ โ€ฆ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ"; let _a = unicode_is_fun + " really fun!"; โ”‚ โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”ฏ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ &str @@ -14,7 +14,7 @@ LL โ”‚ let _ = "๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง โ•ฐโ•ด +++++++++++ error[E0369]: cannot add `&str` to `&str` - โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:9:384 + โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:10:384 โ”‚ LL โ”‚ โ€ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ"; let _a = unicode_is_fun + " really fun!"; โ”‚ โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”ฏ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ &str @@ -29,7 +29,7 @@ LL โ”‚ let _ = "๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง โ•ฐโ•ด +++++++++++ error[E0369]: cannot add `&str` to `&str` - โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:11:260 + โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:12:260 โ”‚ LL โ”‚ โ€ฆเฟ…เฟ†เฟ‡เฟˆเฟ‰เฟŠเฟ‹เฟŒเฟเฟŽเฟเฟเฟ‘เฟ’เฟ“เฟ”เฟ•เฟ–เฟ—เฟ˜เฟ™เฟš"; let _a = unicode_is_fun + " really fun!"; โ”‚ โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”ฏ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ &str @@ -44,7 +44,7 @@ LL โ”‚ let _ = "เผ€เผเผ‚เผƒเผ„เผ…เผ†เผ‡เผˆเผ‰เผŠเผ‹เผŒเผเผŽเผเผเผ‘เผ’เผ“ โ•ฐโ•ด +++++++++++ error[E0369]: cannot add `&str` to `&str` - โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:13:219 + โ•ญโ–ธ $DIR/non-1-width-unicode-multiline-label.rs:14:219 โ”‚ LL โ”‚ โ€ฆxxxxxxxxxxxxxxxxxxxxxx"; let _a = unicode_is_fun + " really fun!"; โ”‚ โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”ฏ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ &str diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr index 70bd149545cfe..fe90cfc7b4168 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/non-whitespace-trimming-2.rs:6:311 + --> $DIR/non-whitespace-trimming-2.rs:7:311 | LL | ...13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let ... | -- ^^ expected `()`, found integer diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs index de2f42a4a7292..cdbef418f888b 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs @@ -1,4 +1,5 @@ //@ revisions: ascii unicode + //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr index 600d196de1673..b0151272cd120 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - โ•ญโ–ธ $DIR/non-whitespace-trimming-2.rs:6:311 + โ•ญโ–ธ $DIR/non-whitespace-trimming-2.rs:7:311 โ”‚ LL โ”‚ โ€ฆ= 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _:โ€ฆ โ”‚ โ”ฌโ”€ โ”โ” expected `()`, found integer diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs index 8d4d1b1627940..f5d1926e1eb62 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs @@ -1,3 +1,4 @@ + // ignore-tidy-linelength fn main() { diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr index 18d80810ab0c3..e74afbfeac478 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/non-whitespace-trimming-unicode.rs:4:415 + --> $DIR/non-whitespace-trimming-unicode.rs:5:415 | LL | ...โ™ฃโ™คโ™ฅโ™ฆโ™งโ™จโ™ฉโ™ชโ™ซโ™ฌโ™ญโ™ฎโ™ฏโ™ฐโ™ฑโ™ฒโ™ณโ™ดโ™ตโ™ถโ™ทโ™ธโ™นโ™บโ™ปโ™ผโ™ฝโ™พโ™ฟโš€โšโš‚โšƒโš„โš…โš†โšˆโš‰4"; let _: () = 42; let _: &str = "๐Ÿฆ€โ˜€โ˜โ˜‚โ˜ƒโ˜„โ˜…โ˜†โ˜‡โ˜ˆโ˜‰โ˜Šโ˜‹โ˜Œโ˜โ˜Žโ˜โ˜โ˜‘โ˜’โ˜“ โ˜–โ˜—โ˜˜โ˜™โ˜šโ˜›โ˜œโ˜โ˜žโ˜Ÿโ˜ โ˜กโ˜ขโ˜ฃโ˜คโ˜ฅโ˜ฆโ˜งโ˜จโ˜ฉโ˜ชโ˜ซโ˜ฌโ˜ญโ˜ฎโ˜ฏโ˜ฐโ˜ฑโ˜ฒโ˜ณโ˜ดโ˜ตโ˜ถโ˜ทโ˜ธโ˜นโ˜บโ˜ปโ˜ผโ˜ฝ ... | -- ^^ expected `()`, found integer diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.rs b/tests/ui/diagnostic-width/non-whitespace-trimming.rs index f6c8d345c652e..67066157a60a2 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.rs @@ -1,3 +1,4 @@ + // ignore-tidy-linelength fn main() { diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr index 872c5ae3b7642..3403dc0e6f1fa 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/non-whitespace-trimming.rs:4:241 + --> $DIR/non-whitespace-trimming.rs:5:241 | LL | ... () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ... | -- ^^ expected `()`, found integer From 0a5817aa2eb82f03fb8246eedaec089a81291aba Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 29 Jul 2025 18:56:32 -0600 Subject: [PATCH 06/13] test: Set diagnostic-width flag for long diagnostic width tests --- .../ui/diagnostic-width/non-1-width-unicode-multiline-label.rs | 2 +- tests/ui/diagnostic-width/non-whitespace-trimming-2.rs | 2 +- tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs | 2 +- tests/ui/diagnostic-width/non-whitespace-trimming.rs | 2 +- tests/ui/diagnostic-width/tabs-trimming.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs index 0940b987fea11..7fb95a4ac1e21 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs @@ -1,5 +1,5 @@ //@ revisions: ascii unicode - +//@ compile-flags: --diagnostic-width=145 //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs index cdbef418f888b..6e80649fee86e 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs @@ -1,5 +1,5 @@ //@ revisions: ascii unicode - +//@ compile-flags: --diagnostic-width=145 //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode // ignore-tidy-linelength diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs index f5d1926e1eb62..258eb090aae36 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs @@ -1,4 +1,4 @@ - +//@ compile-flags: --diagnostic-width=145 // ignore-tidy-linelength fn main() { diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.rs b/tests/ui/diagnostic-width/non-whitespace-trimming.rs index 67066157a60a2..cb9450f0de0bd 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.rs @@ -1,4 +1,4 @@ - +//@ compile-flags: --diagnostic-width=145 // ignore-tidy-linelength fn main() { diff --git a/tests/ui/diagnostic-width/tabs-trimming.rs b/tests/ui/diagnostic-width/tabs-trimming.rs index 96babde33e9a4..5cf6bc89a1675 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.rs +++ b/tests/ui/diagnostic-width/tabs-trimming.rs @@ -1,5 +1,5 @@ // Test for #78438: ensure underline alignment with many tabs on the left, long line on the right - +//@ compile-flags: --diagnostic-width=145 // ignore-tidy-linelength // ignore-tidy-tab From 9c6897bd07ddb519d0c2f809bb1f83044a170b92 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Fri, 30 May 2025 16:22:56 -0600 Subject: [PATCH 07/13] test: Subtract code_offset from width for ui_testing --- compiler/rustc_errors/src/emitter.rs | 2 +- .../clippy/tests/ui/option_env_unwrap.stderr | 2 +- .../ui/too_long_first_doc_paragraph.stderr | 2 +- .../libc_pthread_join_joined.stderr | 4 +- .../concurrency/libc_pthread_join_main.stderr | 4 +- .../fail/data_race/dealloc_read_race1.stderr | 14 +++---- .../data_race/dealloc_read_race_stack.stderr | 4 +- .../fail/data_race/dealloc_write_race1.stderr | 14 +++---- .../data_race/dealloc_write_race_stack.stderr | 4 +- .../fail/intrinsics/copy_unaligned.stderr | 4 +- .../fail/intrinsics/simd-float-to-int.stderr | 4 +- .../retag_data_race_read.stderr | 4 +- .../ui/async-await/async-drop/ex-ice1.stderr | 8 ++-- .../ui/cast/func-pointer-issue-140491.stderr | 4 +- tests/ui/consts/offset_ub.stderr | 4 +- tests/ui/deprecation/deprecation-lint.stderr | 24 +++++------ .../ui/lint/lint-stability-deprecated.stderr | 40 +++++++++---------- tests/ui/parser/raw/too-many-hash.stderr | 4 +- .../empty-match.exhaustive_patterns.stderr | 4 +- .../usefulness/empty-match.normal.stderr | 4 +- tests/ui/simd/not-out-of-bounds.stderr | 4 +- .../alignment/align-fail.stderr | 4 +- 22 files changed, 81 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 93b1e6b761520..cc3db167316e0 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2021,7 +2021,7 @@ impl HumanEmitter { if let Some(width) = self.diagnostic_width { width.saturating_sub(code_offset) } else if self.ui_testing || cfg!(miri) { - DEFAULT_COLUMN_WIDTH + DEFAULT_COLUMN_WIDTH.saturating_sub(code_offset) } else { termize::dimensions() .map(|(w, _)| w.saturating_sub(code_offset)) diff --git a/src/tools/clippy/tests/ui/option_env_unwrap.stderr b/src/tools/clippy/tests/ui/option_env_unwrap.stderr index bbcbfedb78822..c14a3ea23ff3e 100644 --- a/src/tools/clippy/tests/ui/option_env_unwrap.stderr +++ b/src/tools/clippy/tests/ui/option_env_unwrap.stderr @@ -19,7 +19,7 @@ LL | let _ = option_env!("PATH").expect("environment variable PATH isn't set error: this will panic at run-time if the environment variable doesn't exist at compile-time --> tests/ui/option_env_unwrap.rs:14:13 | -LL | let _ = option_env!("__Y__do_not_use").unwrap(); // This test only works if you don't have a __Y__do_not_use env variable in your env... +LL | let _ = option_env!("__Y__do_not_use").unwrap(); // This test only works if you don't have a __Y__do_not_use env variable in you... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using the `env!` macro instead diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr index f3f182aa54222..949ada30dc97d 100644 --- a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr @@ -42,7 +42,7 @@ LL | | /// gravida non lacinia at, rhoncus eu lacus. error: first doc comment paragraph is too long --> tests/ui/too_long_first_doc_paragraph.rs:65:1 | -LL | / /// Some function. This doc-string paragraph is too long. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lore... +LL | / /// Some function. This doc-string paragraph is too long. Lorem Ipsum is simply dummy text of the printing and typesetting industr... LL | | LL | | /// LL | | /// Here's a second paragraph. It would be preferable to put the details here. diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr index 354ad5dfc6022..e22f4dadf3f64 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: trying to join an already joined thread --> tests/fail-dep/concurrency/libc_pthread_join_joined.rs:LL:CC | -LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | ... assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr index 41190f3f903eb..978a9bdac94d5 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: trying to join a detached thread --> tests/fail-dep/concurrency/libc_pthread_join_main.rs:LL:CC | -LL | assert_eq!(libc::pthread_join(thread_id, ptr::null_mut()), 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | ... assert_eq!(libc::pthread_join(thread_id, ptr::null_mut()), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr index 55e4c4a0d9e83..006946f3f5080 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr @@ -1,13 +1,13 @@ error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `unnamed-ID` at ALLOC --> tests/fail/data_race/dealloc_read_race1.rs:LL:CC | -LL | / __rust_dealloc( -LL | | -LL | | ptr.0 as *mut _, -LL | | std::mem::size_of::(), -LL | | std::mem::align_of::(), -LL | | ); - | |_____________^ (2) just happened here +LL | / ... __rust_dealloc( +LL | | ... +LL | | ... ptr.0 as *mut _, +LL | | ... std::mem::size_of::(), +LL | | ... std::mem::align_of::(), +LL | | ... ); + | |_______^ (2) just happened here | help: and (1) occurred earlier here --> tests/fail/data_race/dealloc_read_race1.rs:LL:CC diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr index ea8fd73393c4e..f80e36d4b8fbf 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `unnamed-ID` at ALLOC --> tests/fail/data_race/dealloc_read_race_stack.rs:LL:CC | -LL | } - | ^ (2) just happened here +LL | ... } + | ^ (2) just happened here | help: and (1) occurred earlier here --> tests/fail/data_race/dealloc_read_race_stack.rs:LL:CC diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr index b306f18123127..41482e4941c1b 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr @@ -1,13 +1,13 @@ error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) deallocation on thread `unnamed-ID` at ALLOC --> tests/fail/data_race/dealloc_write_race1.rs:LL:CC | -LL | / __rust_dealloc( -LL | | -LL | | ptr.0 as *mut _, -LL | | std::mem::size_of::(), -LL | | std::mem::align_of::(), -LL | | ); - | |_____________^ (2) just happened here +LL | / ... __rust_dealloc( +LL | | ... +LL | | ... ptr.0 as *mut _, +LL | | ... std::mem::size_of::(), +LL | | ... std::mem::align_of::(), +LL | | ... ); + | |_______^ (2) just happened here | help: and (1) occurred earlier here --> tests/fail/data_race/dealloc_write_race1.rs:LL:CC diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr index f3a8707ed14ed..e6ebd5b6278ec 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `unnamed-ID` and (2) deallocation on thread `unnamed-ID` at ALLOC --> tests/fail/data_race/dealloc_write_race_stack.rs:LL:CC | -LL | } - | ^ (2) just happened here +LL | ... } + | ^ (2) just happened here | help: and (1) occurred earlier here --> tests/fail/data_race/dealloc_write_race_stack.rs:LL:CC diff --git a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr index f561e502b5146..d9b41f5b0581c 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr +++ b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required --> tests/fail/intrinsics/copy_unaligned.rs:LL:CC | -LL | std::intrinsics::copy_nonoverlapping(&data[5], ptr, 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | ... std::intrinsics::copy_nonoverlapping(&data[5], ptr, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr index 04e9cb338cdd3..64b8e166c1668 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32` --> tests/fail/intrinsics/simd-float-to-int.rs:LL:CC | -LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | ... let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr index d84fbc76056d6..ee82bbbb1ed14 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: Data race detected between (1) retag read on thread `unnamed-ID` and (2) non-atomic write on thread `unnamed-ID` at ALLOC --> tests/fail/stacked_borrows/retag_data_race_read.rs:LL:CC | -LL | *p = 5; - | ^^^^^^ (2) just happened here +LL | ... *p = 5; + | ^^^^^^ (2) just happened here | help: and (1) occurred earlier here --> tests/fail/stacked_borrows/retag_data_race_read.rs:LL:CC diff --git a/tests/ui/async-await/async-drop/ex-ice1.stderr b/tests/ui/async-await/async-drop/ex-ice1.stderr index 68533edeb086c..a1fa89f2c4001 100644 --- a/tests/ui/async-await/async-drop/ex-ice1.stderr +++ b/tests/ui/async-await/async-drop/ex-ice1.stderr @@ -1,14 +1,14 @@ error[E0423]: expected function, found module `core::future::async_drop` --> $DIR/ex-ice1.rs:9:35 | -LL | let async_drop_fut = pin!(core::future::async_drop(async {})); - | ^^^^^^^^^^^^^^^^^^^^^^^^ not a function +LL | ... let async_drop_fut = pin!(core::future::async_drop(async {})); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not a function error[E0603]: module `async_drop` is private --> $DIR/ex-ice1.rs:9:49 | -LL | let async_drop_fut = pin!(core::future::async_drop(async {})); - | ^^^^^^^^^^ private module +LL | ... let async_drop_fut = pin!(core::future::async_drop(async {})); + | ^^^^^^^^^^ private module | note: the module `async_drop` is defined here --> $SRC_DIR/core/src/future/mod.rs:LL:COL diff --git a/tests/ui/cast/func-pointer-issue-140491.stderr b/tests/ui/cast/func-pointer-issue-140491.stderr index e1c07010e691c..0b777905da1f9 100644 --- a/tests/ui/cast/func-pointer-issue-140491.stderr +++ b/tests/ui/cast/func-pointer-issue-140491.stderr @@ -1,8 +1,8 @@ error[E0605]: non-primitive cast: `&for<'a, 'b> fn(&'a Event<'b>) {my_fn}` as `&for<'a, 'b> fn(&'a Event<'b>)` --> $DIR/func-pointer-issue-140491.rs:6:34 | -LL | ..._>) = &my_fn as _; - | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object +LL | ... = &my_fn as _; + | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object | = note: casting reference expression `&my_fn` because `&` binds tighter than `as` diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index d92ca09223de7..f40d342758360 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -43,8 +43,8 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got ALLOC3-0x2 which points to before the beginning of the allocation --> $DIR/offset_ub.rs:16:49 | -LL | ...*const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `NEGATIVE_OFFSET` failed here +LL | ...nst u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `NEGATIVE_OFFSET` failed here error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by 1 byte, but got ALLOC4 which is at or beyond the end of the allocation of size $BYTES bytes --> $DIR/offset_ub.rs:18:50 diff --git a/tests/ui/deprecation/deprecation-lint.stderr b/tests/ui/deprecation/deprecation-lint.stderr index 95ae1b04d8611..5a39b0cf31516 100644 --- a/tests/ui/deprecation/deprecation-lint.stderr +++ b/tests/ui/deprecation/deprecation-lint.stderr @@ -73,8 +73,8 @@ LL | let _ = nested::DeprecatedStruct { error: use of deprecated unit struct `deprecation_lint::nested::DeprecatedUnitStruct`: text --> $DIR/deprecation-lint.rs:48:25 | -LL | let _ = nested::DeprecatedUnitStruct; - | ^^^^^^^^^^^^^^^^^^^^ +LL | ... let _ = nested::DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text --> $DIR/deprecation-lint.rs:50:31 @@ -97,8 +97,8 @@ LL | macro_test_arg!(deprecated_text()); error: use of deprecated function `deprecation_lint::deprecated_text`: text --> $DIR/deprecation-lint.rs:60:41 | -LL | macro_test_arg!(macro_test_arg!(deprecated_text())); - | ^^^^^^^^^^^^^^^ +LL | ... macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text --> $DIR/deprecation-lint.rs:65:16 @@ -211,8 +211,8 @@ LL | Trait::trait_deprecated_text(&foo); error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text --> $DIR/deprecation-lint.rs:261:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_future`: text --> $DIR/deprecation-lint.rs:264:9 @@ -295,8 +295,8 @@ LL | Trait::trait_deprecated_text(&foo); error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text --> $DIR/deprecation-lint.rs:299:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` --> $DIR/deprecation-lint.rs:317:13 @@ -391,8 +391,8 @@ LL | foo.method_deprecated_text(); error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text --> $DIR/deprecation-lint.rs:27:14 | -LL | Foo::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text --> $DIR/deprecation-lint.rs:28:16 @@ -589,8 +589,8 @@ LL | Foo::method_deprecated_text(&foo); error: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text --> $DIR/deprecation-lint.rs:257:16 | -LL | ::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text --> $DIR/deprecation-lint.rs:258:13 diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index 0399fab746ec4..bda4ee82d1fc6 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -43,8 +43,8 @@ LL | Trait::trait_deprecated_text(&foo); warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:40:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:42:9 @@ -115,8 +115,8 @@ LL | let _ = Enum::DeprecatedVariant; warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text --> $DIR/lint-stability-deprecated.rs:121:23 | -LL | let _ = Enum::DeprecatedUnstableVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... let _ = Enum::DeprecatedUnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:125:17 @@ -127,8 +127,8 @@ LL | let _ = DeprecatedTupleStruct (1); warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:126:17 | -LL | let _ = DeprecatedUnstableTupleStruct (1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... let _ = DeprecatedUnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:135:25 @@ -139,14 +139,14 @@ LL | macro_test_arg!(deprecated_text()); warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text --> $DIR/lint-stability-deprecated.rs:136:25 | -LL | macro_test_arg!(deprecated_unstable_text()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... macro_test_arg!(deprecated_unstable_text()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:137:41 | -LL | macro_test_arg!(macro_test_arg!(deprecated_text())); - | ^^^^^^^^^^^^^^^ +LL | ... macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text --> $DIR/lint-stability-deprecated.rs:142:16 @@ -169,8 +169,8 @@ LL | Trait::trait_deprecated_text(&foo); warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:148:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:150:16 @@ -211,8 +211,8 @@ LL | trait LocalTrait2 : DeprecatedTrait { } warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text --> $DIR/lint-stability-deprecated.rs:205:23 | -LL | unstable_mod::deprecated(); - | ^^^^^^^^^^ +LL | ... unstable_mod::deprecated(); + | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text --> $DIR/lint-stability-deprecated.rs:327:9 @@ -367,14 +367,14 @@ LL | foo.method_deprecated_text(); warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:35:14 | -LL | Foo::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:36:16 | -LL | ::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:37:13 @@ -397,8 +397,8 @@ LL | foo.method_deprecated_unstable(); warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:44:14 | -LL | Foo::method_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:45:16 diff --git a/tests/ui/parser/raw/too-many-hash.stderr b/tests/ui/parser/raw/too-many-hash.stderr index 6b3854eb4a237..499b21d3982c8 100644 --- a/tests/ui/parser/raw/too-many-hash.stderr +++ b/tests/ui/parser/raw/too-many-hash.stderr @@ -1,8 +1,8 @@ error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 256 --> $DIR/too-many-hash.rs:4:19 | -LL | ... = r####################################################...#######################################; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... = r###################################################...######################################; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index f2067f0341fcd..b649aa122b255 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -346,8 +346,8 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:71:24 | -LL | match_guarded_arm!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered +LL | ...ded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:38:10 diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index f2067f0341fcd..b649aa122b255 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -346,8 +346,8 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:71:24 | -LL | match_guarded_arm!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered +LL | ...ded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:38:10 diff --git a/tests/ui/simd/not-out-of-bounds.stderr b/tests/ui/simd/not-out-of-bounds.stderr index 734c21fbf4158..d5bcd15d97d6c 100644 --- a/tests/ui/simd/not-out-of-bounds.stderr +++ b/tests/ui/simd/not-out-of-bounds.stderr @@ -79,8 +79,8 @@ LL | simd_insert(v, 2, 0u8); error[E0511]: invalid monomorphization of `simd_extract` intrinsic: SIMD index #1 is out of bounds (limit 2) --> $DIR/not-out-of-bounds.rs:85:24 | -LL | let _val: u8 = simd_extract(v, 2); - | ^^^^^^^^^^^^^^^^^^ +LL | ... let _val: u8 = simd_extract(v, 2); + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index 7b69820a3c6df..164c57a362442 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -1,8 +1,8 @@ error[E0277]: `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` --> $DIR/align-fail.rs:21:55 | -LL | ...tatic [u8; 0], &'static [u16; 0]>(); - | ^^^^^^^^^^^^^^^^^ the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) +LL | ...ic [u8; 0], &'static [u16; 0]>(); + | ^^^^^^^^^^^^^^^^^ the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) | note: required by a bound in `is_maybe_transmutable` --> $DIR/align-fail.rs:9:14 From d24ee20876dc3438810ddf640f6ceb732bd75ed3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 6 Oct 2025 12:09:57 +0200 Subject: [PATCH 08/13] use `fluent_syntax` to parse fluent files --- src/tools/tidy/src/fluent_alphabetical.rs | 41 ++++++++++++----------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index b1d1c16b4549c..1fadc523591c7 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -5,6 +5,8 @@ use std::fs::OpenOptions; use std::io::Write; use std::path::Path; +use fluent_syntax::ast::Entry; +use fluent_syntax::parser; use regex::Regex; use crate::diagnostics::{CheckId, DiagCtx, RunningCheck}; @@ -24,30 +26,31 @@ fn check_alphabetic( check: &mut RunningCheck, all_defined_msgs: &mut HashMap, ) { - let mut matches = message().captures_iter(fluent).peekable(); - while let Some(m) = matches.next() { - let name = m.get(1).unwrap(); - if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { - check.error(format!( - "{filename}: message `{}` is already defined in {defined_filename}", - name.as_str(), - )); - } + let Ok(resource) = parser::parse(fluent) else { + panic!("Errors encountered while parsing fluent file `{filename}`"); + }; - all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); + let mut prev: Option<&str> = None; - if let Some(next) = matches.peek() { - let next = next.get(1).unwrap(); - if name.as_str() > next.as_str() { + for entry in &resource.body { + if let Entry::Message(msg) = entry { + let name: &str = msg.id.name; + if let Some(defined_filename) = all_defined_msgs.get(name) { check.error(format!( - "{filename}: message `{}` appears before `{}`, but is alphabetically later than it -run `./x.py test tidy --bless` to sort the file correctly", - name.as_str(), - next.as_str() + "{filename}: message `{name}` is already defined in {defined_filename}", + )); + } else { + all_defined_msgs.insert(name.to_string(), filename.to_owned()); + } + if let Some(prev) = prev + && prev > name + { + check.error(format!( + "{filename}: message `{prev}` appears before `{name}`, but is alphabetically \ +later than it. Run `./x.py test tidy --bless` to sort the file correctly", )); } - } else { - break; + prev = Some(name); } } } From 831cdf3144f23871e9923ddeb9a36d0192e7244a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 6 Oct 2025 12:11:56 +0200 Subject: [PATCH 09/13] Fail if no fluent messages were found --- src/tools/tidy/src/fluent_alphabetical.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index 1fadc523591c7..769f92d04f0af 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -118,5 +118,7 @@ pub fn check(path: &Path, bless: bool, diag_ctx: DiagCtx) { }, ); + assert!(!all_defined_msgs.is_empty()); + crate::fluent_used::check(path, all_defined_msgs, diag_ctx); } From 696b6ac14dd9c3aaae12c000cf5fa1bd0fec8c34 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 16 Aug 2025 22:08:41 +0800 Subject: [PATCH 10/13] use declarative macro for `#[derive(TryFromU32)]` --- .../src/coverageinfo/mapgen.rs | 3 +- compiler/rustc_codegen_llvm/src/lib.rs | 4 ++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 +- compiler/rustc_codegen_llvm/src/macros.rs | 22 ++++++++ compiler/rustc_macros/src/lib.rs | 9 --- compiler/rustc_macros/src/try_from.rs | 55 ------------------- tests/ui-fulldeps/try-from-u32/errors.rs | 24 -------- tests/ui-fulldeps/try-from-u32/errors.stderr | 32 ----------- tests/ui-fulldeps/try-from-u32/hygiene.rs | 32 ----------- tests/ui-fulldeps/try-from-u32/values.rs | 36 ------------ 10 files changed, 28 insertions(+), 192 deletions(-) create mode 100644 compiler/rustc_codegen_llvm/src/macros.rs delete mode 100644 compiler/rustc_macros/src/try_from.rs delete mode 100644 tests/ui-fulldeps/try-from-u32/errors.rs delete mode 100644 tests/ui-fulldeps/try-from-u32/errors.stderr delete mode 100644 tests/ui-fulldeps/try-from-u32/hygiene.rs delete mode 100644 tests/ui-fulldeps/try-from-u32/values.rs diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index d1cb95507d91c..7e873347c82b0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -6,7 +6,6 @@ use rustc_abi::Align; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods}; use rustc_data_structures::fx::FxIndexMap; use rustc_index::IndexVec; -use rustc_macros::TryFromU32; use rustc_middle::ty::TyCtxt; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; @@ -16,7 +15,7 @@ use tracing::debug; use crate::common::CodegenCx; use crate::coverageinfo::llvm_cov; use crate::coverageinfo::mapgen::covfun::prepare_covfun_record; -use crate::llvm; +use crate::{TryFromU32, llvm}; mod covfun; mod spans; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 2405a25c7020b..807049f08d367 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -14,6 +14,7 @@ #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] #![feature(iter_intersperse)] +#![feature(macro_derive)] #![feature(rustdoc_internals)] #![feature(slice_as_array)] #![feature(try_blocks)] @@ -65,6 +66,7 @@ mod errors; mod intrinsic; mod llvm; mod llvm_util; +mod macros; mod mono_item; mod type_; mod type_of; @@ -74,6 +76,8 @@ mod value; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } +pub(crate) use macros::TryFromU32; + #[derive(Clone)] pub struct LlvmCodegenBackend(()); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ccbc999dad1f0..c4b5cf413a725 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -19,7 +19,6 @@ use std::ptr; use bitflags::bitflags; use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t}; -use rustc_macros::TryFromU32; use super::RustString; use super::debuginfo::{ @@ -27,8 +26,8 @@ use super::debuginfo::{ DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind, }; -use crate::llvm; use crate::llvm::MetadataKindId; +use crate::{TryFromU32, llvm}; /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, /// which has a different ABI from Rust or C++ `bool`. diff --git a/compiler/rustc_codegen_llvm/src/macros.rs b/compiler/rustc_codegen_llvm/src/macros.rs new file mode 100644 index 0000000000000..fddc428ca273b --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/macros.rs @@ -0,0 +1,22 @@ +macro_rules! TryFromU32 { + derive() ( + $(#[$meta:meta])* + $vis:vis enum $Type:ident { + $( + $(#[$varmeta:meta])* + $Variant:ident $(= $discr:expr)? + ),* $(,)? + } + ) => { + impl ::core::convert::TryFrom for $Type { + type Error = u32; + #[allow(deprecated)] // Don't warn about deprecated variants. + fn try_from(value: u32) -> ::core::result::Result<$Type, Self::Error> { + $( if value == const { $Type::$Variant as u32 } { return Ok($Type::$Variant) } )* + Err(value) + } + } + } +} + +pub(crate) use TryFromU32; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 803b3621c887e..a6f53d92e1006 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -18,7 +18,6 @@ mod print_attribute; mod query; mod serialize; mod symbols; -mod try_from; mod type_foldable; mod type_visitable; mod visitable; @@ -176,14 +175,6 @@ decl_derive!( applicability)] => diagnostics::subdiagnostic_derive ); -decl_derive! { - [TryFromU32] => - /// Derives `TryFrom` for the annotated `enum`, which must have no fields. - /// Each variant maps to the value it would produce under an `as u32` cast. - /// - /// The error type is `u32`. - try_from::try_from_u32 -} decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. diff --git a/compiler/rustc_macros/src/try_from.rs b/compiler/rustc_macros/src/try_from.rs deleted file mode 100644 index 9338c1c2b3361..0000000000000 --- a/compiler/rustc_macros/src/try_from.rs +++ /dev/null @@ -1,55 +0,0 @@ -use proc_macro2::TokenStream; -use quote::{quote, quote_spanned}; -use syn::Data; -use syn::spanned::Spanned; -use synstructure::Structure; - -pub(crate) fn try_from_u32(s: Structure<'_>) -> TokenStream { - let span_error = |span, message: &str| { - quote_spanned! { span => const _: () = ::core::compile_error!(#message); } - }; - - // Must be applied to an enum type. - if let Some(span) = match &s.ast().data { - Data::Enum(_) => None, - Data::Struct(s) => Some(s.struct_token.span()), - Data::Union(u) => Some(u.union_token.span()), - } { - return span_error(span, "type is not an enum (TryFromU32)"); - } - - // The enum's variants must not have fields. - let variant_field_errors = s - .variants() - .iter() - .filter_map(|v| v.ast().fields.iter().map(|f| f.span()).next()) - .map(|span| span_error(span, "enum variant cannot have fields (TryFromU32)")) - .collect::(); - if !variant_field_errors.is_empty() { - return variant_field_errors; - } - - let ctor = s - .variants() - .iter() - .map(|v| v.construct(|_, _| -> TokenStream { unreachable!() })) - .collect::>(); - // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? - #[allow(keyword_idents_2024)] - s.gen_impl(quote! { - // The surrounding code might have shadowed these identifiers. - use ::core::convert::TryFrom; - use ::core::primitive::u32; - use ::core::result::Result::{self, Ok, Err}; - - gen impl TryFrom for @Self { - type Error = u32; - - #[allow(deprecated)] // Don't warn about deprecated variants. - fn try_from(value: u32) -> Result { - #( if value == const { #ctor as u32 } { return Ok(#ctor) } )* - Err(value) - } - } - }) -} diff --git a/tests/ui-fulldeps/try-from-u32/errors.rs b/tests/ui-fulldeps/try-from-u32/errors.rs deleted file mode 100644 index a25069c0a53cb..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/errors.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![feature(rustc_private)] -//@ edition: 2021 - -// Checks the error messages produced by `#[derive(TryFromU32)]`. - -extern crate rustc_macros; - -use rustc_macros::TryFromU32; - -#[derive(TryFromU32)] -struct MyStruct {} //~ ERROR type is not an enum - -#[derive(TryFromU32)] -enum NonTrivial { - A, - B(), - C {}, - D(bool), //~ ERROR enum variant cannot have fields - E(bool, bool), //~ ERROR enum variant cannot have fields - F { x: bool }, //~ ERROR enum variant cannot have fields - G { x: bool, y: bool }, //~ ERROR enum variant cannot have fields -} - -fn main() {} diff --git a/tests/ui-fulldeps/try-from-u32/errors.stderr b/tests/ui-fulldeps/try-from-u32/errors.stderr deleted file mode 100644 index d20567061d7bb..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/errors.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: type is not an enum (TryFromU32) - --> $DIR/errors.rs:11:1 - | -LL | struct MyStruct {} - | ^^^^^^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:18:7 - | -LL | D(bool), - | ^^^^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:19:7 - | -LL | E(bool, bool), - | ^^^^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:20:9 - | -LL | F { x: bool }, - | ^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:21:9 - | -LL | G { x: bool, y: bool }, - | ^ - -error: aborting due to 5 previous errors - diff --git a/tests/ui-fulldeps/try-from-u32/hygiene.rs b/tests/ui-fulldeps/try-from-u32/hygiene.rs deleted file mode 100644 index e0655a64a64db..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/hygiene.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(rustc_private)] -//@ edition: 2021 -//@ check-pass - -// Checks that the derive macro still works even if the surrounding code has -// shadowed the relevant library types. - -extern crate rustc_macros; - -mod submod { - use rustc_macros::TryFromU32; - - struct Result; - trait TryFrom {} - #[allow(non_camel_case_types)] - struct u32; - struct Ok; - struct Err; - mod core {} - mod std {} - - #[derive(TryFromU32)] - pub(crate) enum MyEnum { - Zero, - One, - } -} - -fn main() { - use submod::MyEnum; - let _: Result = MyEnum::try_from(1u32); -} diff --git a/tests/ui-fulldeps/try-from-u32/values.rs b/tests/ui-fulldeps/try-from-u32/values.rs deleted file mode 100644 index 180a8f2beb75b..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/values.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![feature(assert_matches)] -#![feature(rustc_private)] -//@ edition: 2021 -//@ run-pass - -// Checks the values accepted by the `TryFrom` impl produced by `#[derive(TryFromU32)]`. - -extern crate rustc_macros; - -use core::assert_matches::assert_matches; -use rustc_macros::TryFromU32; - -#[derive(TryFromU32, Debug, PartialEq)] -#[repr(u32)] -enum Repr { - Zero, - One(), - Seven = 7, -} - -#[derive(TryFromU32, Debug)] -enum NoRepr { - Zero, - One, -} - -fn main() { - assert_eq!(Repr::try_from(0u32), Ok(Repr::Zero)); - assert_eq!(Repr::try_from(1u32), Ok(Repr::One())); - assert_eq!(Repr::try_from(2u32), Err(2)); - assert_eq!(Repr::try_from(7u32), Ok(Repr::Seven)); - - assert_matches!(NoRepr::try_from(0u32), Ok(NoRepr::Zero)); - assert_matches!(NoRepr::try_from(1u32), Ok(NoRepr::One)); - assert_matches!(NoRepr::try_from(2u32), Err(2)); -} From 490fd3ddd24418188dc6e419ed54ac0fa16f2cf4 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 6 Oct 2025 19:01:25 +0200 Subject: [PATCH 11/13] Update books --- src/doc/reference | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference b/src/doc/reference index e11adf6016a36..8efb980568672 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit e11adf6016a362766eea5a3f9832e193994dd0c8 +Subproject commit 8efb9805686722dba511b7b27281bb6b77d32130 From 02126adc1b8d0b61ddaec2adb9c0d2c9dddcd493 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Mon, 6 Oct 2025 19:03:48 +0900 Subject: [PATCH 12/13] Improve diagnostics: replace 'non-inline module' with 'file module' and update note/help messages --- compiler/rustc_expand/messages.ftl | 5 +++-- compiler/rustc_expand/src/errors.rs | 3 ++- tests/ui/directory_ownership/file-mod-restriction.rs | 5 +++++ .../ui/directory_ownership/file-mod-restriction.stderr | 10 ++++++++++ tests/ui/directory_ownership/macro-expanded-mod.rs | 4 ++-- tests/ui/directory_ownership/macro-expanded-mod.stderr | 3 ++- .../directory_ownership/non-inline-mod-restriction.rs | 5 ----- .../non-inline-mod-restriction.stderr | 8 -------- 8 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 tests/ui/directory_ownership/file-mod-restriction.rs create mode 100644 tests/ui/directory_ownership/file-mod-restriction.stderr delete mode 100644 tests/ui/directory_ownership/non-inline-mod-restriction.rs delete mode 100644 tests/ui/directory_ownership/non-inline-mod-restriction.stderr diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 47c00bff5c950..7c2c9002a32c4 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -118,8 +118,9 @@ expand_module_file_not_found = .note = if there is a `mod {$name}` elsewhere in the crate already, import it with `use crate::...` instead expand_module_in_block = - cannot declare a non-inline module inside a block unless it has a path attribute - .note = maybe `use` the module `{$name}` instead of redeclaring it + cannot declare a file module inside a block unless it has a path attribute + .help = maybe `use` the module `{$name}` instead of redeclaring it + .note = file modules are usually placed outside of blocks, at the top level of the file expand_module_multiple_candidates = file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}" diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index c37c2d88d9cd2..6bae16b3bba15 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -265,6 +265,7 @@ pub(crate) struct ModuleCircular { #[derive(Diagnostic)] #[diag(expand_module_in_block)] +#[note] pub(crate) struct ModuleInBlock { #[primary_span] pub span: Span, @@ -273,7 +274,7 @@ pub(crate) struct ModuleInBlock { } #[derive(Subdiagnostic)] -#[note(expand_note)] +#[help(expand_help)] pub(crate) struct ModuleInBlockName { #[primary_span] pub span: Span, diff --git a/tests/ui/directory_ownership/file-mod-restriction.rs b/tests/ui/directory_ownership/file-mod-restriction.rs new file mode 100644 index 0000000000000..cff876941dbc8 --- /dev/null +++ b/tests/ui/directory_ownership/file-mod-restriction.rs @@ -0,0 +1,5 @@ +// Test that file modules are not allowed inside blocks. + +fn main() { + mod foo; //~ ERROR cannot declare a file module inside a block unless it has a path attribute +} diff --git a/tests/ui/directory_ownership/file-mod-restriction.stderr b/tests/ui/directory_ownership/file-mod-restriction.stderr new file mode 100644 index 0000000000000..4c1ff777f37fd --- /dev/null +++ b/tests/ui/directory_ownership/file-mod-restriction.stderr @@ -0,0 +1,10 @@ +error: cannot declare a file module inside a block unless it has a path attribute + --> $DIR/file-mod-restriction.rs:4:5 + | +LL | mod foo; + | ^^^^^^^^ + | + = note: file modules are usually placed outside of blocks, at the top level of the file + +error: aborting due to 1 previous error + diff --git a/tests/ui/directory_ownership/macro-expanded-mod.rs b/tests/ui/directory_ownership/macro-expanded-mod.rs index fa81769e5a800..1495764a9d8cb 100644 --- a/tests/ui/directory_ownership/macro-expanded-mod.rs +++ b/tests/ui/directory_ownership/macro-expanded-mod.rs @@ -1,8 +1,8 @@ -// Test that macro-expanded non-inline modules behave correctly +// Test that macro-expanded file modules behave correctly macro_rules! mod_decl { ($i:ident) => { - mod $i; //~ ERROR cannot declare a non-inline module inside a block + mod $i; //~ ERROR cannot declare a file module inside a block unless it has a path attribute }; } diff --git a/tests/ui/directory_ownership/macro-expanded-mod.stderr b/tests/ui/directory_ownership/macro-expanded-mod.stderr index 2cacd52b94ef6..cb00a3fe60823 100644 --- a/tests/ui/directory_ownership/macro-expanded-mod.stderr +++ b/tests/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,4 +1,4 @@ -error: cannot declare a non-inline module inside a block unless it has a path attribute +error: cannot declare a file module inside a block unless it has a path attribute --> $DIR/macro-expanded-mod.rs:5:9 | LL | mod $i; @@ -7,6 +7,7 @@ LL | mod $i; LL | mod_decl!(foo); | -------------- in this macro invocation | + = note: file modules are usually placed outside of blocks, at the top level of the file = note: this error originates in the macro `mod_decl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/directory_ownership/non-inline-mod-restriction.rs b/tests/ui/directory_ownership/non-inline-mod-restriction.rs deleted file mode 100644 index de4f816656cc4..0000000000000 --- a/tests/ui/directory_ownership/non-inline-mod-restriction.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Test that non-inline modules are not allowed inside blocks. - -fn main() { - mod foo; //~ ERROR cannot declare a non-inline module inside a block -} diff --git a/tests/ui/directory_ownership/non-inline-mod-restriction.stderr b/tests/ui/directory_ownership/non-inline-mod-restriction.stderr deleted file mode 100644 index 882c8652520b0..0000000000000 --- a/tests/ui/directory_ownership/non-inline-mod-restriction.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/non-inline-mod-restriction.rs:4:5 - | -LL | mod foo; - | ^^^^^^^^ - -error: aborting due to 1 previous error - From cb06d91cd0ec0cd0393cee3a943f312ed849b530 Mon Sep 17 00:00:00 2001 From: Karol Zwolak Date: Mon, 6 Oct 2025 19:51:37 +0200 Subject: [PATCH 13/13] don't panic on extern with just multiple quotes in the name --- compiler/rustc_span/src/symbol.rs | 6 ++-- ....rs => extern-only-quotes-issue-147365.rs} | 6 +++- .../extern-only-quotes-issue-147365.stderr | 32 +++++++++++++++++++ .../extern-single-quote-issue-147365.stderr | 16 ---------- 4 files changed, 41 insertions(+), 19 deletions(-) rename tests/ui/extern/{extern-single-quote-issue-147365.rs => extern-only-quotes-issue-147365.rs} (63%) create mode 100644 tests/ui/extern/extern-only-quotes-issue-147365.stderr delete mode 100644 tests/ui/extern/extern-single-quote-issue-147365.stderr diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 92dd56f3d5894..36214dd1c3ed2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2511,9 +2511,11 @@ impl Ident { } /// Creates a new ident with the same span and name with leading quote removed, if any. - /// If called on an empty ident, or with name just a single quote, returns an empty ident which is invalid. + /// Calling it on a `'` ident will return an empty ident, which triggers debug assertions. pub fn without_first_quote(self) -> Ident { - Ident::new(Symbol::intern(self.as_str().trim_start_matches('\'')), self.span) + self.as_str() + .strip_prefix('\'') + .map_or(self, |name| Ident::new(Symbol::intern(name), self.span)) } /// "Normalize" ident for use in comparisons using "item hygiene". diff --git a/tests/ui/extern/extern-single-quote-issue-147365.rs b/tests/ui/extern/extern-only-quotes-issue-147365.rs similarity index 63% rename from tests/ui/extern/extern-single-quote-issue-147365.rs rename to tests/ui/extern/extern-only-quotes-issue-147365.rs index b50016bd65f31..3a492b4fb4f86 100644 --- a/tests/ui/extern/extern-single-quote-issue-147365.rs +++ b/tests/ui/extern/extern-only-quotes-issue-147365.rs @@ -2,8 +2,12 @@ // https://github.com/rust-lang/rust/issues/147365 // Ensures we don't trigger debug assert by creating an empty Ident when determining whether -// the single quote is a raw lifetime. +// the quotes are a raw lifetime. extern "'" {} //~ ERROR invalid ABI: found `'` +extern "''" {} //~ ERROR invalid ABI: found `''` + +extern "'''" {} //~ ERROR invalid ABI: found `'''` + fn main() {} diff --git a/tests/ui/extern/extern-only-quotes-issue-147365.stderr b/tests/ui/extern/extern-only-quotes-issue-147365.stderr new file mode 100644 index 0000000000000..fabc0fd4916b7 --- /dev/null +++ b/tests/ui/extern/extern-only-quotes-issue-147365.stderr @@ -0,0 +1,32 @@ +error[E0703]: invalid ABI: found `'` + --> $DIR/extern-only-quotes-issue-147365.rs:7:8 + | +LL | extern "'" {} + | ^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions +help: there's a similarly named valid ABI `C` + | +LL - extern "'" {} +LL + extern "C" {} + | + +error[E0703]: invalid ABI: found `''` + --> $DIR/extern-only-quotes-issue-147365.rs:9:8 + | +LL | extern "''" {} + | ^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `'''` + --> $DIR/extern-only-quotes-issue-147365.rs:11:8 + | +LL | extern "'''" {} + | ^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/extern/extern-single-quote-issue-147365.stderr b/tests/ui/extern/extern-single-quote-issue-147365.stderr deleted file mode 100644 index d761bc3ebf323..0000000000000 --- a/tests/ui/extern/extern-single-quote-issue-147365.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0703]: invalid ABI: found `'` - --> $DIR/extern-single-quote-issue-147365.rs:7:8 - | -LL | extern "'" {} - | ^^^ invalid ABI - | - = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions -help: there's a similarly named valid ABI `C` - | -LL - extern "'" {} -LL + extern "C" {} - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0703`.