From a97b41f1880f3aef9f4669ba56cf2e4d830825bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Aug 2024 21:26:10 -0400 Subject: [PATCH 01/26] Use subtyping for UnsafeFnPointer coercion, too --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 ++-- .../coercion/cast-higher-ranked-unsafe-fn-ptr.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6983cda6ddf3b..3b3898ccd4da1 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2043,9 +2043,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); - if let Err(terr) = self.eq_types( - *ty, + if let Err(terr) = self.sub_types( ty_fn_ptr_from, + *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, ) { diff --git a/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs b/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs new file mode 100644 index 0000000000000..19723bee4d46e --- /dev/null +++ b/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs @@ -0,0 +1,14 @@ +//@ check-pass + +fn higher_ranked_fndef(ctx: &mut ()) {} + +fn test(higher_ranked_fnptr: fn(&mut ())) { + fn as_unsafe(_: unsafe fn(T)) {} + + // Make sure that we can cast higher-ranked fn items and pointers to + // a non-higher-ranked target. + as_unsafe(higher_ranked_fndef); + as_unsafe(higher_ranked_fnptr); +} + +fn main() {} From 147bb17f51b521269929f348b4b2a27afad8a273 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 Aug 2024 14:55:31 -0400 Subject: [PATCH 02/26] Rework how we emit errors for unresolved object lifetimes --- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 7 ++-- .../src/hir_ty_lowering/object_safety.rs | 32 ++++++++++++------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f75954c9edfb7..9e6c431a6e6a3 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -392,7 +392,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { - if let RegionInferReason::BorrowedObjectLifetimeDefault = reason { + if let RegionInferReason::ObjectLifetimeDefault = reason { let e = struct_span_code_err!( self.dcx(), span, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5c8ecf254a54e..73baa05bce660 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -85,10 +85,9 @@ pub enum PredicateFilter { #[derive(Debug)] pub enum RegionInferReason<'a> { - /// Lifetime on a trait object behind a reference. - /// This allows inferring information from the reference. - BorrowedObjectLifetimeDefault, - /// A trait object's lifetime. + /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`. + ExplicitObjectLifetime, + /// A trait object's lifetime when it is elided, e.g. `dyn Any`. ObjectLifetimeDefault, /// Generic lifetime parameter Param(&'a ty::GenericParamDef), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 31d1750f33dfd..082fbb2c41835 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -30,7 +30,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_id: hir::HirId, hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], lifetime: &hir::Lifetime, - borrowed: bool, + _borrowed: bool, representation: DynKind, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -325,22 +325,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { v.dedup(); let existential_predicates = tcx.mk_poly_existential_predicates(&v); - // Use explicitly-specified region bound. + // Use explicitly-specified region bound, unless the bound is missing. let region_bound = if !lifetime.is_elided() { - self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) + self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { + // Curiously, we prefer object lifetime default for `+ '_`... if tcx.named_bound_var(lifetime.hir_id).is_some() { - self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) + self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { - self.re_infer( - span, - if borrowed { - RegionInferReason::ObjectLifetimeDefault + let reason = + if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res { + if let hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Ref(parent_lifetime, _), + .. + }) = tcx.parent_hir_node(hir_id) + && tcx.named_bound_var(parent_lifetime.hir_id).is_none() + { + // Parent lifetime must have failed to resolve. Don't emit a redundant error. + RegionInferReason::ExplicitObjectLifetime + } else { + RegionInferReason::ObjectLifetimeDefault + } } else { - RegionInferReason::BorrowedObjectLifetimeDefault - }, - ) + RegionInferReason::ExplicitObjectLifetime + }; + self.re_infer(span, reason) } }) }; From e7f11b6913eb1549847be2173a20d08f3cbf46ff Mon Sep 17 00:00:00 2001 From: mu001999 Date: Thu, 8 Aug 2024 08:17:55 +0800 Subject: [PATCH 03/26] Removes dead code from the compiler --- compiler/rustc_incremental/messages.ftl | 2 -- compiler/rustc_incremental/src/errors.rs | 7 ------- compiler/rustc_passes/messages.ftl | 4 ---- compiler/rustc_passes/src/errors.rs | 7 ------- .../src/maybe_transmutable/query_context.rs | 6 +----- library/alloc/tests/boxed.rs | 1 + 6 files changed, 2 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index de2177ebb6e0f..2a65101d360d3 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -99,6 +99,4 @@ incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized -incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err} - incremental_write_new = failed to write {$name} to `{$path}`: {$err} diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index b68c149d39823..c6f8b99bcd67b 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -272,13 +272,6 @@ pub struct LoadDepGraph { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag(incremental_write_dep_graph)] -pub struct WriteDepGraph<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - #[derive(Diagnostic)] #[diag(incremental_move_dep_graph)] pub struct MoveDepGraph<'a> { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index dfc726efeb998..bdc229a6c09e4 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -481,10 +481,6 @@ passes_must_not_suspend = `must_not_suspend` attribute should be applied to a struct, enum, union, or trait .label = is not a struct, enum, union, or trait -passes_must_use_async = - `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within - .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use` - passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target} diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1190e60f41f18..644ae23a761c3 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -371,13 +371,6 @@ pub struct FfiConstInvalidTarget { pub attr_span: Span, } -#[derive(LintDiagnostic)] -#[diag(passes_must_use_async)] -pub struct MustUseAsync { - #[label] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_must_use_no_effect)] pub struct MustUseNoEffect { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs index 95373916a71ae..f8b59bdf32684 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs @@ -4,7 +4,6 @@ use crate::layout; pub(crate) trait QueryContext { type Def: layout::Def; type Ref: layout::Ref; - type Scope: Copy; } #[cfg(test)] @@ -28,20 +27,17 @@ pub(crate) mod test { impl QueryContext for UltraMinimal { type Def = Def; type Ref = !; - type Scope = (); } } #[cfg(feature = "rustc")] mod rustc { - use rustc_middle::ty::{Ty, TyCtxt}; + use rustc_middle::ty::TyCtxt; use super::*; impl<'tcx> super::QueryContext for TyCtxt<'tcx> { type Def = layout::rustc::Def<'tcx>; type Ref = layout::rustc::Ref<'tcx>; - - type Scope = Ty<'tcx>; } } diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index faee64b2f6738..bfc31a626fadd 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -59,6 +59,7 @@ fn box_deref_lval() { assert_eq!(x.get(), 1000); } +#[allow(unused)] pub struct ConstAllocator; unsafe impl Allocator for ConstAllocator { From c29e328f6a2a3667034dc668c810373db7a68857 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 24 Aug 2024 21:55:16 +0300 Subject: [PATCH 04/26] gitignore: ignore ICE reports regardless of directory --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a36cb51de33ff..2e6499081a634 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,9 @@ build/ /src/tools/x/target # Created by default with `src/ci/docker/run.sh` /obj/ -/rustc-ice* + +## ICE reports +rustc-ice-*.txt ## Temporary files *~ From 51cd76bf6a19fb4fdc7900077627684710a6682e Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 15 Aug 2024 18:05:59 +0300 Subject: [PATCH 05/26] warn on suspicious elision resolutions --- compiler/rustc_resolve/src/late.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 40fdb01a72c0e..f86fc4975a5e4 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2039,6 +2039,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)") } + match candidate { + LifetimeElisionCandidate::Missing(missing) => match res { + LifetimeRes::Static => tracing::warn!(?missing, "static"), + LifetimeRes::Param { param, binder } => { + tracing::warn!(?missing, ?param, ?binder, "named") + } + LifetimeRes::Fresh { .. } + | LifetimeRes::Infer + | LifetimeRes::Error + | LifetimeRes::ElidedAnchor { .. } => {} + }, + LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {} + } + match res { LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { From 40d837978c057cda4d3365f95a646a43ede8616f Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 16 Aug 2024 00:13:19 +0300 Subject: [PATCH 06/26] elided_named_lifetimes: Lint stub Currently ICEs because we buffer it with NodeId of the missing lifetime, so it ends up not getting emitted --- compiler/rustc_lint/messages.ftl | 3 +++ compiler/rustc_lint/src/context/diagnostics.rs | 1 + compiler/rustc_lint/src/lints.rs | 4 ++++ compiler/rustc_lint_defs/src/builtin.rs | 8 ++++++++ compiler/rustc_lint_defs/src/lib.rs | 1 + compiler/rustc_resolve/src/late.rs | 10 +++++++++- 6 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 08a50050a36d5..aa6c8dae95096 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -252,6 +252,9 @@ lint_duplicate_macro_attribute = lint_duplicate_matcher_binding = duplicate matcher binding +lint_elided_lifetime_static = + this lifetime is static, lol + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index f289d4c81b3c1..886dd981cac8e 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -441,5 +441,6 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } + BuiltinLintDiag::ElidedIsStatic => lints::ElidedIsStatic {}.decorate_lint(diag), } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c12c5427997f9..760b734666851 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2611,6 +2611,10 @@ pub struct ElidedLifetimesInPaths { pub subdiag: ElidedLifetimeInPathSubdiag, } +#[derive(LintDiagnostic)] +#[diag(lint_elided_lifetime_static)] +pub struct ElidedIsStatic {} + #[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] pub struct UnknownCrateTypes { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 44c72e0c4fe33..140f383fb5aef 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -42,6 +42,7 @@ declare_lint_pass! { DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, + ELIDED_NAMED_LIFETIMES, EXPLICIT_BUILTIN_CFGS_IN_FLAGS, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, @@ -1862,6 +1863,13 @@ declare_lint! { "hidden lifetime parameters in types are deprecated" } +declare_lint! { + /// TODO + pub ELIDED_NAMED_LIFETIMES, + Allow, + "TODO" +} + declare_lint! { /// The `bare_trait_objects` lint suggests using `dyn Trait` for trait /// objects. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 0f07de43e80ed..fd708bcf99987 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -585,6 +585,7 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), + ElidedIsStatic, UnknownCrateTypes { span: Span, candidate: Option, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f86fc4975a5e4..baf79e0972d3b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2041,7 +2041,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } match candidate { LifetimeElisionCandidate::Missing(missing) => match res { - LifetimeRes::Static => tracing::warn!(?missing, "static"), + LifetimeRes::Static => { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id, + missing.span, + BuiltinLintDiag::ElidedIsStatic {}, + ); + tracing::warn!(?missing, "static") + } LifetimeRes::Param { param, binder } => { tracing::warn!(?missing, ?param, ?binder, "named") } From 19d11db945bbd4fe0f013e3f2ec3a00a2457faa5 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 16 Aug 2024 13:10:53 +0300 Subject: [PATCH 07/26] elided_named_lifetimes: LintDiagnostic --- compiler/rustc_lint/messages.ftl | 6 ++- .../rustc_lint/src/context/diagnostics.rs | 7 ++- compiler/rustc_lint/src/lints.rs | 16 ++++++- compiler/rustc_lint_defs/src/lib.rs | 8 +++- compiler/rustc_resolve/src/late.rs | 47 ++++++++++++------- 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index aa6c8dae95096..0404446b0e440 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -252,8 +252,10 @@ lint_duplicate_macro_attribute = lint_duplicate_matcher_binding = duplicate matcher binding -lint_elided_lifetime_static = - this lifetime is static, lol +lint_elided_named_lifetime = elided lifetime has a name + .label_static = this elided lifetime gets resolved as `'static` + .label_this = this elided lifetime + .label_that = gets resolved as this named lifetime lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 886dd981cac8e..b52a73f5eda7a 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -441,6 +441,11 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } - BuiltinLintDiag::ElidedIsStatic => lints::ElidedIsStatic {}.decorate_lint(diag), + BuiltinLintDiag::ElidedIsStatic { elided } => { + lints::ElidedNamedLifetime::Static { elided }.decorate_lint(diag) + } + BuiltinLintDiag::ElidedIsParam { elided, param } => { + lints::ElidedNamedLifetime::Param { elided, param }.decorate_lint(diag) + } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 760b734666851..d1d10f319272b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2612,8 +2612,20 @@ pub struct ElidedLifetimesInPaths { } #[derive(LintDiagnostic)] -#[diag(lint_elided_lifetime_static)] -pub struct ElidedIsStatic {} +pub enum ElidedNamedLifetime { + #[diag(lint_elided_named_lifetime)] + Static { + #[label(lint_label_static)] + elided: Span, + }, + #[diag(lint_elided_named_lifetime)] + Param { + #[label(lint_label_this)] + elided: Span, + #[label(lint_label_that)] + param: Span, + }, +} #[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index fd708bcf99987..5ec70290285c6 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -585,7 +585,13 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), - ElidedIsStatic, + ElidedIsStatic { + elided: Span, + }, + ElidedIsParam { + elided: Span, + param: Span, + }, UnknownCrateTypes { span: Span, candidate: Option, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index baf79e0972d3b..94b9dd28dc93f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2039,25 +2039,38 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)") } + match candidate { - LifetimeElisionCandidate::Missing(missing) => match res { - LifetimeRes::Static => { - self.r.lint_buffer.buffer_lint( - lint::builtin::ELIDED_NAMED_LIFETIMES, - missing.id, - missing.span, - BuiltinLintDiag::ElidedIsStatic {}, - ); - tracing::warn!(?missing, "static") - } - LifetimeRes::Param { param, binder } => { - tracing::warn!(?missing, ?param, ?binder, "named") + LifetimeElisionCandidate::Missing(missing) => { + // FIXME: ICEs otherwise + if missing.kind != MissingLifetimeKind::Ampersand { + match res { + LifetimeRes::Static => { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id, + missing.span, + BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + ); + } + LifetimeRes::Param { param, binder: _ } => { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id, + missing.span, + BuiltinLintDiag::ElidedIsParam { + elided: missing.span, + param: self.r.tcx().source_span(param), + }, + ); + } + LifetimeRes::Fresh { .. } + | LifetimeRes::Infer + | LifetimeRes::Error + | LifetimeRes::ElidedAnchor { .. } => {} + } } - LifetimeRes::Fresh { .. } - | LifetimeRes::Infer - | LifetimeRes::Error - | LifetimeRes::ElidedAnchor { .. } => {} - }, + } LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {} } From f735c7a916620a1c173d884bc60476d51d26065a Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 16 Aug 2024 14:54:00 +0300 Subject: [PATCH 08/26] elided_named_lifetimes: fix (hack) the ICE for non-static case --- compiler/rustc_resolve/src/late.rs | 42 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 94b9dd28dc93f..08d4612ccbde3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2042,10 +2042,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { match candidate { LifetimeElisionCandidate::Missing(missing) => { - // FIXME: ICEs otherwise - if missing.kind != MissingLifetimeKind::Ampersand { - match res { - LifetimeRes::Static => { + debug_assert_eq!(id, missing.id); + match res { + LifetimeRes::Static => { + // FIXME: ICEs otherwise + if missing.kind != MissingLifetimeKind::Ampersand { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id, @@ -2053,22 +2054,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, ); } - LifetimeRes::Param { param, binder: _ } => { - self.r.lint_buffer.buffer_lint( - lint::builtin::ELIDED_NAMED_LIFETIMES, - missing.id, - missing.span, - BuiltinLintDiag::ElidedIsParam { - elided: missing.span, - param: self.r.tcx().source_span(param), - }, - ); - } - LifetimeRes::Fresh { .. } - | LifetimeRes::Infer - | LifetimeRes::Error - | LifetimeRes::ElidedAnchor { .. } => {} } + LifetimeRes::Param { param, binder } => { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + // HACK: we can't use `missing.id` instead of `binder` here, + // because for `missing.kind == Ampersand` it is a "fake" node that gets overlooked and its lints do not end up emitted. + // Alternatively, it might be possible to convert `param` to `NodeId` and use that instead. + binder, + missing.span, + BuiltinLintDiag::ElidedIsParam { + elided: missing.span, + param: self.r.tcx().source_span(param), + }, + ); + } + LifetimeRes::Fresh { .. } + | LifetimeRes::Infer + | LifetimeRes::Error + | LifetimeRes::ElidedAnchor { .. } => {} } } LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {} From 4328e8bf2cba2d74fba77faa16f083fc2a8868a3 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 17 Aug 2024 20:28:24 +0300 Subject: [PATCH 09/26] elided_named_lifetimes: try to work around the issues with `NodeId`s for lint buffering --- compiler/rustc_resolve/src/late.rs | 38 +++++++++++-------- .../rustc_resolve/src/late/diagnostics.rs | 17 +++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 08d4612ccbde3..52fd682debdc8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -699,6 +699,11 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Count the number of places a lifetime is used. lifetime_uses: FxHashMap, + + /// We need some "real" `NodeId` to emit + /// [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES). + /// See comments in [`MissingLifetime::id_if_not_fake_or`]. + crate_node_id: NodeId, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -1317,7 +1322,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { - fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { + fn new( + resolver: &'b mut Resolver<'a, 'tcx>, + krate: &Crate, + ) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; @@ -1340,6 +1348,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // errors at module scope should always be reported in_func_body: false, lifetime_uses: Default::default(), + crate_node_id: krate.id, } } @@ -2045,23 +2054,22 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { debug_assert_eq!(id, missing.id); match res { LifetimeRes::Static => { - // FIXME: ICEs otherwise - if missing.kind != MissingLifetimeKind::Ampersand { - self.r.lint_buffer.buffer_lint( - lint::builtin::ELIDED_NAMED_LIFETIMES, - missing.id, - missing.span, - BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, - ); - } + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id_if_not_fake_or(self.crate_node_id), + missing.span, + BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + ); } LifetimeRes::Param { param, binder } => { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, - // HACK: we can't use `missing.id` instead of `binder` here, - // because for `missing.kind == Ampersand` it is a "fake" node that gets overlooked and its lints do not end up emitted. - // Alternatively, it might be possible to convert `param` to `NodeId` and use that instead. - binder, + // It should be possible to use `self.crate_node_id` + // or `param`'s `NodeId` here as a fallback instead of the `binder`, + // but `binder` sounds like a more appropriate place than the crate, + // and to convert `param` from `LocalDefId` to `NodeId`, + // we would have to do some additional work. + missing.id_if_not_fake_or(binder), missing.span, BuiltinLintDiag::ElidedIsParam { elided: missing.span, @@ -4971,7 +4979,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); - let mut late_resolution_visitor = LateResolutionVisitor::new(self); + let mut late_resolution_visitor = LateResolutionVisitor::new(self, krate); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f778b0ee3acc0..ec6d66026a49e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -110,6 +110,23 @@ pub(super) struct MissingLifetime { pub count: usize, } +impl MissingLifetime { + /// As we cannot yet emit lints in this crate and have to buffer them instead, + /// we need to associate each lint with some `NodeId`, + /// however for some `MissingLifetime`s their `NodeId`s are "fake", + /// in a sense that they are temporary and not get preserved down the line, + /// which means that the lints for those nodes will not get emitted. + /// To combat this, we can try to use some other `NodeId`s as a fallback option. + pub(super) fn id_if_not_fake_or(self, fallback: NodeId) -> NodeId { + match self.kind { + MissingLifetimeKind::Underscore + | MissingLifetimeKind::Comma + | MissingLifetimeKind::Brackets => self.id, + MissingLifetimeKind::Ampersand => fallback, + } + } +} + /// Description of the lifetimes appearing in a function parameter. /// This is used to provide a literal explanation to the elision failure. #[derive(Clone, Debug)] From 7a73ed4396af8f1b1de40cd631cdc724c3084e8e Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 17 Aug 2024 23:45:12 +0300 Subject: [PATCH 10/26] elided_named_lifetimes: allow elided `'static` in const/static type annotations --- compiler/rustc_resolve/src/late.rs | 33 ++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 52fd682debdc8..0b18f6fe3c3a3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -704,6 +704,13 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES). /// See comments in [`MissingLifetime::id_if_not_fake_or`]. crate_node_id: NodeId, + /// Don't emit [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES) + /// when we are in a type annotation for a `const` or `static`. + /// ```rust + /// const HELLO_WORLD: &str = "Hello, world!"; + /// static ZEROES: &[u8] = &[0, 0, 0]; + /// ``` + allow_elided_static: bool, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -1349,6 +1356,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { in_func_body: false, lifetime_uses: Default::default(), crate_node_id: krate.id, + allow_elided_static: false, } } @@ -1559,6 +1567,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ret } + #[instrument(level = "debug", skip(self))] + fn visit_ty_allow_elided_static(&mut self, ty: &'ast Ty) { + self.allow_elided_static = true; + self.visit_ty(ty); + self.allow_elided_static = false; + } + #[instrument(level = "debug", skip(self))] fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) { let ident = lifetime.ident; @@ -2054,12 +2069,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { debug_assert_eq!(id, missing.id); match res { LifetimeRes::Static => { - self.r.lint_buffer.buffer_lint( - lint::builtin::ELIDED_NAMED_LIFETIMES, - missing.id_if_not_fake_or(self.crate_node_id), - missing.span, - BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, - ); + if !self.allow_elided_static { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id_if_not_fake_or(self.crate_node_id), + missing.span, + BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + ); + } } LifetimeRes::Param { param, binder } => { self.r.lint_buffer.buffer_lint( @@ -2606,7 +2623,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - this.visit_ty(ty); + this.visit_ty_allow_elided_static(ty); }); if let Some(expr) = expr { // We already forbid generic params because of the above item rib, @@ -2637,7 +2654,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Static), - |this| this.visit_ty(ty), + |this| this.visit_ty_allow_elided_static(ty), ); if let Some(expr) = expr { From 3dac6f946e2b39324dfcebe812cb659645854c5b Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 17 Aug 2024 23:47:37 +0300 Subject: [PATCH 11/26] elided_named_lifetimes: bump to `Warn` & fix libs --- compiler/rustc_lint_defs/src/builtin.rs | 2 +- library/alloc/src/string.rs | 2 +- library/core/src/fmt/rt.rs | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 140f383fb5aef..42b6d8c1da8a9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1866,7 +1866,7 @@ declare_lint! { declare_lint! { /// TODO pub ELIDED_NAMED_LIFETIMES, - Allow, + Warn, "TODO" } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e628be1546f76..bc8b7e24bf12b 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2313,7 +2313,7 @@ impl<'b> Pattern for &'b String { } #[inline] - fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&str> + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> where Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, { diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 65a4d537cc74d..36f5f5d534056 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -110,39 +110,39 @@ impl<'a> Argument<'a> { } #[inline(always)] - pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> { + pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'b> { Self::new(x, Display::fmt) } #[inline(always)] - pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> { + pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'b> { Self::new(x, Debug::fmt) } #[inline(always)] - pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> { + pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'b> { Self::new(x, Octal::fmt) } #[inline(always)] - pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> { + pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'b> { Self::new(x, LowerHex::fmt) } #[inline(always)] - pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> { + pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'b> { Self::new(x, UpperHex::fmt) } #[inline(always)] - pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> { + pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'b> { Self::new(x, Pointer::fmt) } #[inline(always)] - pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> { + pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'b> { Self::new(x, Binary::fmt) } #[inline(always)] - pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> { + pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'b> { Self::new(x, LowerExp::fmt) } #[inline(always)] - pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> { + pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'b> { Self::new(x, UpperExp::fmt) } #[inline(always)] From b9776333075080783aba3492d604f101178294b1 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Mon, 19 Aug 2024 00:49:34 +0300 Subject: [PATCH 12/26] elided_named_lifetimes: improve the message a bit --- compiler/rustc_ast_lowering/src/lib.rs | 4 ++-- compiler/rustc_hir/src/def.rs | 6 +++--- compiler/rustc_lint/messages.ftl | 5 ++--- .../rustc_lint/src/context/diagnostics.rs | 11 +++++++--- compiler/rustc_lint/src/lints.rs | 20 +++++++------------ compiler/rustc_lint_defs/src/lib.rs | 2 +- compiler/rustc_resolve/src/late.rs | 15 ++++++-------- 7 files changed, 29 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4b8c47ac4b411..f379e41d24f8a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1643,7 +1643,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { for lifetime in captured_lifetimes_to_duplicate { let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); let (old_def_id, missing_kind) = match res { - LifetimeRes::Param { param: old_def_id, binder: _ } => (old_def_id, None), + LifetimeRes::Param { param: (old_def_id, _), binder: _ } => (old_def_id, None), LifetimeRes::Fresh { param, kind, .. } => { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); @@ -2061,7 +2061,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { res: LifetimeRes, ) -> &'hir hir::Lifetime { let res = match res { - LifetimeRes::Param { param, .. } => { + LifetimeRes::Param { param: (param, _), .. } => { let param = self.get_remapped_def_id(param); hir::LifetimeName::Param(param) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 59204d799281f..44e2c163dcf54 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -8,7 +8,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, Ident}; use rustc_span::Symbol; use crate::definitions::DefPathData; @@ -796,8 +796,8 @@ impl Res { pub enum LifetimeRes { /// Successfully linked the lifetime to a generic parameter. Param { - /// Id of the generic parameter that introduced it. - param: LocalDefId, + /// `LocalDefId` & `Ident` of the generic parameter that introduced it. + param: (LocalDefId, Ident), /// Id of the introducing place. That can be: /// - an item's id, for the item's generic parameters; /// - a TraitRef's ref_id, identifying the `for<...>` binder; diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 0404446b0e440..31b7eb5ee7df3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -253,9 +253,8 @@ lint_duplicate_macro_attribute = lint_duplicate_matcher_binding = duplicate matcher binding lint_elided_named_lifetime = elided lifetime has a name - .label_static = this elided lifetime gets resolved as `'static` - .label_this = this elided lifetime - .label_that = gets resolved as this named lifetime + .label_elided = this elided lifetime gets resolved as `{$name}` + .label_named = lifetime `{$name}` declared here lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b52a73f5eda7a..05f0a90d3c15e 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -10,6 +10,7 @@ use rustc_errors::{ use rustc_middle::middle::stability; use rustc_session::lint::BuiltinLintDiag; use rustc_session::Session; +use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; @@ -442,10 +443,14 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } BuiltinLintDiag::ElidedIsStatic { elided } => { - lints::ElidedNamedLifetime::Static { elided }.decorate_lint(diag) + lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None } + .decorate_lint(diag) } - BuiltinLintDiag::ElidedIsParam { elided, param } => { - lints::ElidedNamedLifetime::Param { elided, param }.decorate_lint(diag) + BuiltinLintDiag::ElidedIsParam { elided, param } => lints::ElidedNamedLifetime { + elided, + name: param.name, + named_declaration: Some(param.span), } + .decorate_lint(diag), } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index d1d10f319272b..fd7c336daa552 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2612,19 +2612,13 @@ pub struct ElidedLifetimesInPaths { } #[derive(LintDiagnostic)] -pub enum ElidedNamedLifetime { - #[diag(lint_elided_named_lifetime)] - Static { - #[label(lint_label_static)] - elided: Span, - }, - #[diag(lint_elided_named_lifetime)] - Param { - #[label(lint_label_this)] - elided: Span, - #[label(lint_label_that)] - param: Span, - }, +#[diag(lint_elided_named_lifetime)] +pub struct ElidedNamedLifetime { + #[label(lint_label_elided)] + pub elided: Span, + pub name: Symbol, + #[label(lint_label_named)] + pub named_declaration: Option, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 5ec70290285c6..1863769d86ca0 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -590,7 +590,7 @@ pub enum BuiltinLintDiag { }, ElidedIsParam { elided: Span, - param: Span, + param: Ident, }, UnknownCrateTypes { span: Span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0b18f6fe3c3a3..bdc86490c2200 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1597,7 +1597,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) { self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named); - if let LifetimeRes::Param { param, binder } = res { + if let LifetimeRes::Param { param: (param, _), binder } = res { match self.lifetime_uses.entry(param) { Entry::Vacant(v) => { debug!("First use of {:?} at {:?}", res, ident.span); @@ -2065,7 +2065,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } match candidate { - LifetimeElisionCandidate::Missing(missing) => { + LifetimeElisionCandidate::Missing(missing @ MissingLifetime { span: elided, .. }) => { debug_assert_eq!(id, missing.id); match res { LifetimeRes::Static => { @@ -2074,11 +2074,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_if_not_fake_or(self.crate_node_id), missing.span, - BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + BuiltinLintDiag::ElidedIsStatic { elided }, ); } } - LifetimeRes::Param { param, binder } => { + LifetimeRes::Param { param: (_, param), binder } => { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, // It should be possible to use `self.crate_node_id` @@ -2088,10 +2088,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // we would have to do some additional work. missing.id_if_not_fake_or(binder), missing.span, - BuiltinLintDiag::ElidedIsParam { - elided: missing.span, - param: self.r.tcx().source_span(param), - }, + BuiltinLintDiag::ElidedIsParam { elided, param }, ); } LifetimeRes::Fresh { .. } @@ -2826,7 +2823,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { (&mut function_value_rib, DefKind::ConstParam) } GenericParamKind::Lifetime => { - let res = LifetimeRes::Param { param: def_id, binder }; + let res = LifetimeRes::Param { param: (def_id, param.ident), binder }; self.record_lifetime_param(param.id, res); function_lifetime_rib.bindings.insert(ident, (param.id, res)); continue; From a57ebc36efdb1e7d1198256a054182634bed53cb Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Mon, 19 Aug 2024 02:28:09 +0300 Subject: [PATCH 13/26] Rename `allow_elided_static` to `warn_elided_static` for clarity So that you know it's about linting and not about correctness. Yes, it is also inverted now. --- compiler/rustc_resolve/src/late.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index bdc86490c2200..be6f14d112574 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -710,7 +710,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// const HELLO_WORLD: &str = "Hello, world!"; /// static ZEROES: &[u8] = &[0, 0, 0]; /// ``` - allow_elided_static: bool, + warn_elided_static: bool, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -1356,7 +1356,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { in_func_body: false, lifetime_uses: Default::default(), crate_node_id: krate.id, - allow_elided_static: false, + warn_elided_static: true, } } @@ -1568,10 +1568,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn visit_ty_allow_elided_static(&mut self, ty: &'ast Ty) { - self.allow_elided_static = true; + fn visit_ty_do_not_warn_elided_static(&mut self, ty: &'ast Ty) { + self.warn_elided_static = false; self.visit_ty(ty); - self.allow_elided_static = false; + self.warn_elided_static = true; } #[instrument(level = "debug", skip(self))] @@ -2069,7 +2069,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { debug_assert_eq!(id, missing.id); match res { LifetimeRes::Static => { - if !self.allow_elided_static { + if self.warn_elided_static { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_if_not_fake_or(self.crate_node_id), @@ -2620,7 +2620,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - this.visit_ty_allow_elided_static(ty); + this.visit_ty_do_not_warn_elided_static(ty); }); if let Some(expr) = expr { // We already forbid generic params because of the above item rib, @@ -2651,7 +2651,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Static), - |this| this.visit_ty_allow_elided_static(ty), + |this| this.visit_ty_do_not_warn_elided_static(ty), ); if let Some(expr) = expr { From bec8f581bfb927adec7511978412b558fd78cd67 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Mon, 19 Aug 2024 02:24:44 +0300 Subject: [PATCH 14/26] elided_named_lifetimes: allow elided `'static` in assoc consts' types --- compiler/rustc_resolve/src/late.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index be6f14d112574..76f827fbe995c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2978,7 +2978,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }, |this| { this.visit_generics(generics); - this.visit_ty(ty); + this.visit_ty_do_not_warn_elided_static(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. @@ -3191,7 +3191,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); this.visit_generics(generics); - this.visit_ty(ty); + this.visit_ty_do_not_warn_elided_static(ty); if let Some(expr) = expr { // We allow arbitrary const expressions inside of associated consts, // even if they are potentially not const evaluatable. From 2822affb07d1e2c59fc6e40e5586c3b31002aaab Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 22 Aug 2024 01:11:23 +0300 Subject: [PATCH 15/26] bless tests --- tests/ui/async-await/issues/issue-63388-1.rs | 2 +- .../async-await/issues/issue-63388-1.stderr | 13 ++++++++++- tests/ui/consts/min_const_fn/min_const_fn.rs | 4 ++-- .../consts/min_const_fn/min_const_fn.stderr | 22 ++++++++++++++++++- tests/ui/generics/generic-no-mangle.fixed | 2 +- tests/ui/generics/generic-no-mangle.rs | 2 +- tests/ui/impl-trait/impl-fn-hrtb-bounds.rs | 1 + .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 12 ++++++++-- .../impl-fn-predefined-lifetimes.rs | 1 + .../impl-fn-predefined-lifetimes.stderr | 14 +++++++++--- .../rpit-assoc-pair-with-lifetime.rs | 1 + .../rpit-assoc-pair-with-lifetime.stderr | 10 +++++++++ ...-return-type-requires-explicit-lifetime.rs | 1 + ...urn-type-requires-explicit-lifetime.stderr | 12 +++++++++- ...-one-existing-name-if-else-using-impl-3.rs | 1 + ...-existing-name-if-else-using-impl-3.stderr | 16 +++++++++++--- .../object-lifetime-default-elision.rs | 2 ++ .../object-lifetime-default-elision.stderr | 14 ++++++++++-- .../elision/ignore-non-reference-lifetimes.rs | 2 ++ .../ignore-non-reference-lifetimes.stderr | 16 ++++++++++++++ tests/ui/self/elision/lt-ref-self-async.fixed | 2 +- tests/ui/self/elision/lt-ref-self-async.rs | 2 +- tests/ui/self/self_lifetime-async.rs | 2 ++ tests/ui/self/self_lifetime-async.stderr | 18 +++++++++++++++ tests/ui/self/self_lifetime.rs | 2 ++ tests/ui/self/self_lifetime.stderr | 18 +++++++++++++++ .../impl-trait-missing-lifetime-gated.rs | 1 + .../impl-trait-missing-lifetime-gated.stderr | 10 ++++++++- .../missing-lifetimes-in-signature.rs | 1 + .../missing-lifetimes-in-signature.stderr | 10 ++++++++- 30 files changed, 192 insertions(+), 22 deletions(-) create mode 100644 tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr create mode 100644 tests/ui/self/elision/ignore-non-reference-lifetimes.stderr create mode 100644 tests/ui/self/self_lifetime-async.stderr create mode 100644 tests/ui/self/self_lifetime.stderr diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs index 32026a22a1616..a6f499ba94e29 100644 --- a/tests/ui/async-await/issues/issue-63388-1.rs +++ b/tests/ui/async-await/issues/issue-63388-1.rs @@ -9,7 +9,7 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( &'a self, foo: &dyn Foo - ) -> &dyn Foo + ) -> &dyn Foo //~ WARNING elided lifetime has a name { //~^ ERROR explicit lifetime required in the type of `foo` [E0621] foo diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index f7f285ad0ccda..ef74bfe32375e 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -1,3 +1,14 @@ +warning: elided lifetime has a name + --> $DIR/issue-63388-1.rs:12:10 + | +LL | async fn do_sth<'a>( + | -- lifetime `'a` declared here +LL | &'a self, foo: &dyn Foo +LL | ) -> &dyn Foo + | ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 | @@ -10,6 +21,6 @@ LL | | foo LL | | } | |_____^ lifetime `'a` required -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn.rs b/tests/ui/consts/min_const_fn/min_const_fn.rs index 76245c08ffc8c..f7663f6044eef 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn.rs @@ -44,8 +44,8 @@ impl Foo { impl<'a, T> Foo { const fn new_lt(t: T) -> Self { Foo(t) } const fn into_inner_lt(self) -> T { self.0 } //~ destructor of - const fn get_lt(&'a self) -> &T { &self.0 } - const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + const fn get_lt(&'a self) -> &T { &self.0 } //~ WARNING elided lifetime has a name + const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~ WARNING elided lifetime has a name //~^ mutable references //~| mutable references //~| mutable references diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index daa0ab2614fb1..4b348a182b87f 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -1,3 +1,23 @@ +warning: elided lifetime has a name + --> $DIR/min_const_fn.rs:47:34 + | +LL | impl<'a, T> Foo { + | -- lifetime `'a` declared here +... +LL | const fn get_lt(&'a self) -> &T { &self.0 } + | ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/min_const_fn.rs:48:42 + | +LL | impl<'a, T> Foo { + | -- lifetime `'a` declared here +... +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^ this elided lifetime gets resolved as `'a` + error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | @@ -228,7 +248,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 24 previous errors +error: aborting due to 24 previous errors; 2 warnings emitted Some errors have detailed explanations: E0493, E0658. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed index 69db712f9dc65..2776848c45fff 100644 --- a/tests/ui/generics/generic-no-mangle.fixed +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -1,5 +1,5 @@ //@ run-rustfix -#![allow(dead_code)] +#![allow(dead_code, elided_named_lifetimes)] #![deny(no_mangle_generic_items)] pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 2288b5bbe70df..5314005d31fa1 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,5 +1,5 @@ //@ run-rustfix -#![allow(dead_code)] +#![allow(dead_code, elided_named_lifetimes)] #![deny(no_mangle_generic_items)] #[no_mangle] diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs index da7530b4e7a8c..a7f38b5c16af2 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -13,6 +13,7 @@ fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + //~| WARNING elided lifetime has a name |x| x } diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 7d108b30b76ed..d0f8f7689d17c 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/impl-fn-hrtb-bounds.rs:19:38 + --> $DIR/impl-fn-hrtb-bounds.rs:20:38 | LL | fn d() -> impl Fn() -> (impl Debug + '_) { | ^^ expected named lifetime parameter @@ -10,6 +10,14 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ~~~~~~~ +warning: elided lifetime has a name + --> $DIR/impl-fn-hrtb-bounds.rs:14:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | @@ -46,7 +54,7 @@ note: lifetime declared here LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0106, E0657. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 8aba3de530b8e..2f17c0ff50861 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { //~^ ERROR cannot resolve opaque type + //~| WARNING elided lifetime has a name |x| x //~^ ERROR expected generic lifetime parameter, found `'_` } diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index c2386e8c88be0..50a9f3ebeabb8 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,9 +1,17 @@ +warning: elided lifetime has a name + --> $DIR/impl-fn-predefined-lifetimes.rs:4:48 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:6:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- this generic parameter must be used with a generic lifetime parameter -LL | +... LL | |x| x | ^ @@ -13,7 +21,7 @@ error[E0720]: cannot resolve opaque type LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | ^^^^^^^^^^^^^^^ cannot resolve opaque type -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0720, E0792. For more information about an error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs index 73c8a6c0aed9f..e48441f533d7c 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs @@ -1,6 +1,7 @@ //@ check-pass pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + //~^ WARNING elided lifetime has a name v.into_iter() } diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr new file mode 100644 index 0000000000000..bff3ffd934ac6 --- /dev/null +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -0,0 +1,10 @@ +warning: elided lifetime has a name + --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82 + | +LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs index d0a8fe795efd0..63a2c9be9ebad 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -47,5 +47,6 @@ fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } // This is ok because both `'a` are for the same parameter. fn m<'a>(_: &'a Foo<'a>) -> &str { "" } +//~^ WARNING elided lifetime has a name fn main() {} diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 23ef36888f079..f835d2655bb01 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -105,6 +105,16 @@ help: consider using the `'a` lifetime LL | fn l<'a>(_: &'a str, _: &'a str) -> &'a str { "" } | ++ -error: aborting due to 7 previous errors +warning: elided lifetime has a name + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:49:29 + | +LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs index a1126d6bb1543..598633d75768e 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -4,6 +4,7 @@ struct Foo { impl Foo { fn foo<'a>(&'a self, x: &i32) -> &i32 { + //~^ WARNING elided lifetime has a name if true { &self.field } else { x } //~ ERROR explicit lifetime diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 6dda9e61a79ca..2d5d4fb0e72ec 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -1,12 +1,22 @@ +warning: elided lifetime has a name + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:6:36 + | +LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:8:36 + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 | LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -LL | +... LL | if true { &self.field } else { x } | ^ lifetime `'a` required -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.rs b/tests/ui/object-lifetime/object-lifetime-default-elision.rs index f7c0261cfbb9c..ede6af51174b2 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.rs @@ -46,6 +46,8 @@ fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait { } fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + //~^ WARNING elided lifetime has a name + // Same as `load1` but with an explicit name thrown in for fun. ss diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index b59956879275a..b44a184c6848f 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -1,5 +1,15 @@ +warning: elided lifetime has a name + --> $DIR/object-lifetime-default-elision.rs:48:40 + | +LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error: lifetime may not live long enough - --> $DIR/object-lifetime-default-elision.rs:71:5 + --> $DIR/object-lifetime-default-elision.rs:73:5 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | -- -- lifetime `'b` defined here @@ -11,5 +21,5 @@ LL | ss | = help: consider adding the following bound: `'a: 'b` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs index f7f61b8c81063..cedc6f0f9bc62 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs @@ -4,9 +4,11 @@ struct Foo<'a>(&'a str); impl<'b> Foo<'b> { fn a<'a>(self: Self, a: &'a str) -> &str { + //~^ WARNING elided lifetime has a name a } fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { + //~^ WARNING elided lifetime has a name a } } diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr new file mode 100644 index 0000000000000..4465dbae52989 --- /dev/null +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -0,0 +1,16 @@ +warning: elided lifetime has a name + --> $DIR/ignore-non-reference-lifetimes.rs:6:41 + | +LL | fn a<'a>(self: Self, a: &'a str) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/ignore-non-reference-lifetimes.rs:10:44 + | +LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/self/elision/lt-ref-self-async.fixed b/tests/ui/self/elision/lt-ref-self-async.fixed index aa1d62012da03..914511641b894 100644 --- a/tests/ui/self/elision/lt-ref-self-async.fixed +++ b/tests/ui/self/elision/lt-ref-self-async.fixed @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-rustfix -#![allow(non_snake_case, dead_code)] +#![allow(non_snake_case, dead_code, elided_named_lifetimes)] use std::pin::Pin; diff --git a/tests/ui/self/elision/lt-ref-self-async.rs b/tests/ui/self/elision/lt-ref-self-async.rs index 38de0fd39f086..0c11b271c35a7 100644 --- a/tests/ui/self/elision/lt-ref-self-async.rs +++ b/tests/ui/self/elision/lt-ref-self-async.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-rustfix -#![allow(non_snake_case, dead_code)] +#![allow(non_snake_case, dead_code, elided_named_lifetimes)] use std::pin::Pin; diff --git a/tests/ui/self/self_lifetime-async.rs b/tests/ui/self/self_lifetime-async.rs index 7d6eb3f5eaf02..fd6902071188c 100644 --- a/tests/ui/self/self_lifetime-async.rs +++ b/tests/ui/self/self_lifetime-async.rs @@ -4,11 +4,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + //~^ WARNING elided lifetime has a name } type Alias = Foo<'static>; impl Alias { async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + //~^ WARNING elided lifetime has a name } fn main() {} diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr new file mode 100644 index 0000000000000..32de3fd18c97f --- /dev/null +++ b/tests/ui/self/self_lifetime-async.stderr @@ -0,0 +1,18 @@ +warning: elided lifetime has a name + --> $DIR/self_lifetime-async.rs:6:44 + | +LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + | -- ^ this elided lifetime gets resolved as `'b` + | | + | lifetime `'b` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/self_lifetime-async.rs:12:52 + | +LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/self/self_lifetime.rs b/tests/ui/self/self_lifetime.rs index 3f655b960b163..0607c3b9317f1 100644 --- a/tests/ui/self/self_lifetime.rs +++ b/tests/ui/self/self_lifetime.rs @@ -5,11 +5,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + //~^ WARNING elided lifetime has a name } type Alias = Foo<'static>; impl Alias { fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + //~^ WARNING elided lifetime has a name } fn main() {} diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr new file mode 100644 index 0000000000000..cd8f4d8adf8b1 --- /dev/null +++ b/tests/ui/self/self_lifetime.stderr @@ -0,0 +1,18 @@ +warning: elided lifetime has a name + --> $DIR/self_lifetime.rs:7:38 + | +LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + | -- ^ this elided lifetime gets resolved as `'b` + | | + | lifetime `'b` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/self_lifetime.rs:13:46 + | +LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs index 735efe89cba5b..daec66709b654 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -64,6 +64,7 @@ mod in_path { // This must not err, as the `&` actually resolves to `'a`. fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { + //~^ WARNING elided lifetime has a name f("f"); } diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 61a2925f582b2..30f4509d49dee 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -124,6 +124,14 @@ LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() } | +warning: elided lifetime has a name + --> $DIR/impl-trait-missing-lifetime-gated.rs:66:57 + | +LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 | @@ -244,7 +252,7 @@ help: consider introducing a named lifetime parameter LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() } | ++++ +++ -error: aborting due to 16 previous errors +error: aborting due to 16 previous errors; 1 warning emitted Some errors have detailed explanations: E0106, E0658. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index b641f5941dcef..b61bea16e3bc8 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -100,6 +100,7 @@ where // This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +//~^ WARNING elided lifetime has a name where G: Get, { diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 88a18e9d06da2..ea01dcd5020cf 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,6 +6,14 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` +warning: elided lifetime has a name + --> $DIR/missing-lifetimes-in-signature.rs:102:64 + | +LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 | @@ -125,7 +133,7 @@ help: consider adding an explicit lifetime bound LL | G: Get + 'a, | ++++ -error: aborting due to 8 previous errors +error: aborting due to 8 previous errors; 1 warning emitted Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700. For more information about an error, try `rustc --explain E0261`. From 0b37f75910a7c20ad37036f204acf3db46749047 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 22 Aug 2024 01:33:35 +0300 Subject: [PATCH 16/26] Fix ICE & bless the remaining tests --- compiler/rustc_resolve/src/late.rs | 7 ++++--- compiler/rustc_resolve/src/late/diagnostics.rs | 10 +++++----- .../type-dependent/issue-71348.full.stderr | 10 ++++++++++ .../type-dependent/issue-71348.min.stderr | 10 +++++++++- .../ui/const-generics/type-dependent/issue-71348.rs | 1 + .../type-alias-impl-trait/missing_lifetime_bound.rs | 2 +- .../missing_lifetime_bound.stderr | 12 +++++++++++- 7 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 tests/ui/const-generics/type-dependent/issue-71348.full.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 76f827fbe995c..40d649efd8672 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -702,8 +702,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// We need some "real" `NodeId` to emit /// [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES). - /// See comments in [`MissingLifetime::id_if_not_fake_or`]. + /// See comments in [`MissingLifetime::id_if_exists_in_source_or`]. crate_node_id: NodeId, + /// Don't emit [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES) /// when we are in a type annotation for a `const` or `static`. /// ```rust @@ -2072,7 +2073,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if self.warn_elided_static { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, - missing.id_if_not_fake_or(self.crate_node_id), + missing.id_if_exists_in_source_or(self.crate_node_id), missing.span, BuiltinLintDiag::ElidedIsStatic { elided }, ); @@ -2086,7 +2087,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // but `binder` sounds like a more appropriate place than the crate, // and to convert `param` from `LocalDefId` to `NodeId`, // we would have to do some additional work. - missing.id_if_not_fake_or(binder), + missing.id_if_exists_in_source_or(binder), missing.span, BuiltinLintDiag::ElidedIsParam { elided, param }, ); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ec6d66026a49e..2011c11077e2c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -117,12 +117,12 @@ impl MissingLifetime { /// in a sense that they are temporary and not get preserved down the line, /// which means that the lints for those nodes will not get emitted. /// To combat this, we can try to use some other `NodeId`s as a fallback option. - pub(super) fn id_if_not_fake_or(self, fallback: NodeId) -> NodeId { + pub(super) fn id_if_exists_in_source_or(self, fallback: NodeId) -> NodeId { match self.kind { - MissingLifetimeKind::Underscore - | MissingLifetimeKind::Comma - | MissingLifetimeKind::Brackets => self.id, - MissingLifetimeKind::Ampersand => fallback, + MissingLifetimeKind::Underscore => self.id, + MissingLifetimeKind::Ampersand + | MissingLifetimeKind::Brackets + | MissingLifetimeKind::Comma => fallback, } } } diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr new file mode 100644 index 0000000000000..177ff20fbf9ea --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -0,0 +1,10 @@ +warning: elided lifetime has a name + --> $DIR/issue-71348.rs:18:68 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 858900a500d84..5aee282952aa2 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -1,3 +1,11 @@ +warning: elided lifetime has a name + --> $DIR/issue-71348.rs:18:68 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 | @@ -30,5 +38,5 @@ help: add `#![feature(unsized_const_params)]` to the crate attributes to enable LL + #![feature(unsized_const_params)] | -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs index 2ffbd015485aa..97e786405fe39 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.rs +++ b/tests/ui/const-generics/type-dependent/issue-71348.rs @@ -17,6 +17,7 @@ trait Get<'a, const N: &'static str> { impl Foo { fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + //~^^ WARNING elided lifetime has a name where Self: Get<'a, N>, { diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs index c584a58cb32e7..c178fcf5a9142 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs @@ -2,7 +2,7 @@ type Opaque2 = impl Sized; type Opaque<'a, T> = Opaque2; -fn defining<'a, T>(x: &'a i32) -> Opaque { x } +fn defining<'a, T>(x: &'a i32) -> Opaque { x } //~ WARNING elided lifetime has a name //~^ ERROR: hidden type for `Opaque2` captures lifetime that does not appear in bounds fn main() {} diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 03cc943d50995..e2c21f1636b0c 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -1,3 +1,13 @@ +warning: elided lifetime has a name + --> $DIR/missing_lifetime_bound.rs:5:41 + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0700]: hidden type for `Opaque2` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 | @@ -9,6 +19,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } | | | hidden type `&'a i32` captures the lifetime `'a` as defined here -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0700`. From 3175fac5c9648d0e4a8b92b72d2c24c34630d852 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 23 Aug 2024 02:38:35 +0300 Subject: [PATCH 17/26] Bless clippy tests --- src/tools/clippy/tests/ui/needless_lifetimes.stderr | 13 ++++++++++++- src/tools/clippy/tests/ui/ptr_arg.stderr | 11 ++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr index f325d27b8c753..50f845e2d9291 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr @@ -1,3 +1,14 @@ +error: elided lifetime has a name + --> tests/ui/needless_lifetimes.rs:266:52 + | +LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: the following explicit lifetimes could be elided: 'a, 'b --> tests/ui/needless_lifetimes.rs:17:23 | @@ -553,5 +564,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 { LL + fn one_input(x: &u8) -> &u8 { | -error: aborting due to 46 previous errors +error: aborting due to 47 previous errors diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 1848ef80fc495..4246453e64ca7 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -1,3 +1,12 @@ +error: elided lifetime has a name + --> tests/ui/ptr_arg.rs:295:56 + | +LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:13:14 | @@ -212,5 +221,5 @@ error: using a reference to `Cow` is not recommended LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` -error: aborting due to 24 previous errors +error: aborting due to 25 previous errors From 7e74a5e857df573b7a5fd35752d3316871405250 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 23 Aug 2024 22:18:43 +0300 Subject: [PATCH 18/26] elided_named_lifetimes: add tests --- .../example-from-issue48686.rs | 12 +++++ .../example-from-issue48686.stderr | 14 ++++++ .../missing-lifetime-kind.rs | 27 +++++++++++ .../missing-lifetime-kind.stderr | 40 ++++++++++++++++ .../ui/lint/elided-named-lifetimes/static.rs | 46 +++++++++++++++++++ .../lint/elided-named-lifetimes/static.stderr | 32 +++++++++++++ 6 files changed, 171 insertions(+) create mode 100644 tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr create mode 100644 tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr create mode 100644 tests/ui/lint/elided-named-lifetimes/static.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/static.stderr diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs new file mode 100644 index 0000000000000..eac7c32a9aac6 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs @@ -0,0 +1,12 @@ +#![deny(elided_named_lifetimes)] + +struct Foo; + +impl Foo { + pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + //~^ ERROR elided lifetime has a name + unsafe { &mut *(x as *mut _) } + } +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr new file mode 100644 index 0000000000000..8c5426a60cb72 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -0,0 +1,14 @@ +error: elided lifetime has a name + --> $DIR/example-from-issue48686.rs:6:50 + | +LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/example-from-issue48686.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs new file mode 100644 index 0000000000000..2f9083ed65f6e --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs @@ -0,0 +1,27 @@ +#![deny(elided_named_lifetimes)] + +fn ampersand<'a>(x: &'a u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x +} + +struct Brackets<'a>(&'a u8); + +fn brackets<'a>(x: &'a u8) -> Brackets { + //~^ ERROR elided lifetime has a name + Brackets(x) +} + +struct Comma<'a, T>(&'a T); + +fn comma<'a>(x: &'a u8) -> Comma { + //~^ ERROR elided lifetime has a name + Comma(x) +} + +fn underscore<'a>(x: &'a u8) -> &'_ u8 { + //~^ ERROR elided lifetime has a name + x +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr new file mode 100644 index 0000000000000..249ae146b1675 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -0,0 +1,40 @@ +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:3:32 + | +LL | fn ampersand<'a>(x: &'a u8) -> &u8 { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | +note: the lint level is defined here + --> $DIR/missing-lifetime-kind.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:10:31 + | +LL | fn brackets<'a>(x: &'a u8) -> Brackets { + | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:17:33 + | +LL | fn comma<'a>(x: &'a u8) -> Comma { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:22:34 + | +LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { + | -- ^^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/elided-named-lifetimes/static.rs b/tests/ui/lint/elided-named-lifetimes/static.rs new file mode 100644 index 0000000000000..dc8222c6e6e48 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/static.rs @@ -0,0 +1,46 @@ +#![deny(elided_named_lifetimes)] + +use std::borrow::Cow; + +const A: &[u8] = &[]; +static B: &str = "hello"; + +trait Trait { + const C: &u8 = &0; +} + +impl Trait for () { + const C: &u8 = &1; +} + +fn ampersand(x: &'static u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x +} + +struct Brackets<'a>(&'a u8); + +fn brackets(x: &'static u8) -> Brackets { + //~^ ERROR elided lifetime has a name + Brackets(x) +} + +struct Comma<'a, T>(&'a T); + +fn comma(x: &'static u8) -> Comma { + //~^ ERROR elided lifetime has a name + Comma(x) +} + +fn underscore(x: &'static u8) -> &'_ u8 { + //~^ ERROR elided lifetime has a name + x +} + +const NESTED: &Vec<&Box>> = &vec![]; + +fn main() { + const HELLO: &str = "Hello"; + static WORLD: &str = "world"; + println!("{HELLO}, {WORLD}!") +} diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr new file mode 100644 index 0000000000000..d2e9776cb4f0e --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -0,0 +1,32 @@ +error: elided lifetime has a name + --> $DIR/static.rs:16:33 + | +LL | fn ampersand(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/static.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/static.rs:23:32 + | +LL | fn brackets(x: &'static u8) -> Brackets { + | ^^^^^^^^ this elided lifetime gets resolved as `'static` + +error: elided lifetime has a name + --> $DIR/static.rs:30:34 + | +LL | fn comma(x: &'static u8) -> Comma { + | ^ this elided lifetime gets resolved as `'static` + +error: elided lifetime has a name + --> $DIR/static.rs:35:35 + | +LL | fn underscore(x: &'static u8) -> &'_ u8 { + | ^^ this elided lifetime gets resolved as `'static` + +error: aborting due to 4 previous errors + From 610f1a512b3e3eb0fa63ab7c957512b7102ffbe0 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 23 Aug 2024 22:49:46 +0300 Subject: [PATCH 19/26] elided_named_lifetimes: add docs --- compiler/rustc_lint_defs/src/builtin.rs | 29 +++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 42b6d8c1da8a9..3e8b180e78b78 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1864,10 +1864,35 @@ declare_lint! { } declare_lint! { - /// TODO + /// The `elided_named_lifetimes` lint detects when an elided + /// lifetime ends up being a named lifetime, such as `'static` + /// or some lifetime parameter `'a`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(elided_named_lifetimes)] + /// struct Foo; + /// impl Foo { + /// pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + /// unsafe { &mut *(x as *mut _) } + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Lifetime elision is quite useful, because it frees you from having + /// to give each lifetime its own name, but sometimes it can produce + /// somewhat surprising resolutions. In safe code, it is mostly okay, + /// because the borrow checker prevents any unsoundness, so the worst + /// case scenario is you get a confusing error message in some other place. + /// But with `unsafe` code, such unexpected resolutions may lead to unsound code. pub ELIDED_NAMED_LIFETIMES, Warn, - "TODO" + "detects when an elided lifetime gets resolved to be `'static` or some named parameter" } declare_lint! { From bacbf467f62bec306defc2bd5065b74c31fc59f6 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 24 Aug 2024 18:28:49 +0300 Subject: [PATCH 20/26] `TyCtxt::item_name` exists --- compiler/rustc_ast_lowering/src/lib.rs | 4 ++-- compiler/rustc_hir/src/def.rs | 6 +++--- compiler/rustc_lint/src/context/diagnostics.rs | 12 +++++++----- compiler/rustc_lint_defs/src/lib.rs | 2 +- compiler/rustc_resolve/src/late.rs | 12 ++++++++---- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f379e41d24f8a..4b8c47ac4b411 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1643,7 +1643,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { for lifetime in captured_lifetimes_to_duplicate { let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); let (old_def_id, missing_kind) = match res { - LifetimeRes::Param { param: (old_def_id, _), binder: _ } => (old_def_id, None), + LifetimeRes::Param { param: old_def_id, binder: _ } => (old_def_id, None), LifetimeRes::Fresh { param, kind, .. } => { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); @@ -2061,7 +2061,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { res: LifetimeRes, ) -> &'hir hir::Lifetime { let res = match res { - LifetimeRes::Param { param: (param, _), .. } => { + LifetimeRes::Param { param, .. } => { let param = self.get_remapped_def_id(param); hir::LifetimeName::Param(param) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 44e2c163dcf54..59204d799281f 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -8,7 +8,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::kw; use rustc_span::Symbol; use crate::definitions::DefPathData; @@ -796,8 +796,8 @@ impl Res { pub enum LifetimeRes { /// Successfully linked the lifetime to a generic parameter. Param { - /// `LocalDefId` & `Ident` of the generic parameter that introduced it. - param: (LocalDefId, Ident), + /// Id of the generic parameter that introduced it. + param: LocalDefId, /// Id of the introducing place. That can be: /// - an item's id, for the item's generic parameters; /// - a TraitRef's ref_id, identifying the `for<...>` binder; diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 05f0a90d3c15e..fd43afa174383 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -446,11 +446,13 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None } .decorate_lint(diag) } - BuiltinLintDiag::ElidedIsParam { elided, param } => lints::ElidedNamedLifetime { - elided, - name: param.name, - named_declaration: Some(param.span), + BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => { + lints::ElidedNamedLifetime { + elided, + name: param_name, + named_declaration: Some(param_span), + } + .decorate_lint(diag) } - .decorate_lint(diag), } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 1863769d86ca0..a5f5ca947b31b 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -590,7 +590,7 @@ pub enum BuiltinLintDiag { }, ElidedIsParam { elided: Span, - param: Ident, + param: (Symbol, Span), }, UnknownCrateTypes { span: Span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 40d649efd8672..9b46297f8ed7a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1598,7 +1598,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) { self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named); - if let LifetimeRes::Param { param: (param, _), binder } = res { + if let LifetimeRes::Param { param, binder } = res { match self.lifetime_uses.entry(param) { Entry::Vacant(v) => { debug!("First use of {:?} at {:?}", res, ident.span); @@ -2079,7 +2079,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); } } - LifetimeRes::Param { param: (_, param), binder } => { + LifetimeRes::Param { param, binder } => { + let tcx = self.r.tcx(); self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, // It should be possible to use `self.crate_node_id` @@ -2089,7 +2090,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // we would have to do some additional work. missing.id_if_exists_in_source_or(binder), missing.span, - BuiltinLintDiag::ElidedIsParam { elided, param }, + BuiltinLintDiag::ElidedIsParam { + elided, + param: (tcx.item_name(param.into()), tcx.source_span(param)), + }, ); } LifetimeRes::Fresh { .. } @@ -2824,7 +2828,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { (&mut function_value_rib, DefKind::ConstParam) } GenericParamKind::Lifetime => { - let res = LifetimeRes::Param { param: (def_id, param.ident), binder }; + let res = LifetimeRes::Param { param: def_id, binder }; self.record_lifetime_param(param.id, res); function_lifetime_rib.bindings.insert(ident, (param.id, res)); continue; From f0c9cecf1b5c58c121a2adff4032a0803ddabfb4 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 24 Aug 2024 19:19:09 +0300 Subject: [PATCH 21/26] Move the override flag for `elided_named_lifetimes` from `LateResolutionVisitor` to `LifetimeRes::Static` --- compiler/rustc_ast_lowering/src/lib.rs | 6 +-- .../src/lifetime_collector.rs | 2 +- compiler/rustc_hir/src/def.rs | 9 +++- compiler/rustc_resolve/src/late.rs | 48 ++++++++----------- .../rustc_resolve/src/late/diagnostics.rs | 4 +- 5 files changed, 33 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4b8c47ac4b411..92209979eed22 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -838,7 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } - LifetimeRes::Static | LifetimeRes::Error => return None, + LifetimeRes::Static { .. } | LifetimeRes::Error => return None, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, ident.span @@ -1657,7 +1657,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Opaques do not capture `'static` - LifetimeRes::Static | LifetimeRes::Error => { + LifetimeRes::Static { .. } | LifetimeRes::Error => { continue; } @@ -2070,7 +2070,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::LifetimeName::Param(param) } LifetimeRes::Infer => hir::LifetimeName::Infer, - LifetimeRes::Static => hir::LifetimeName::Static, + LifetimeRes::Static { .. } => hir::LifetimeName::Static, LifetimeRes::Error => hir::LifetimeName::Error, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 77cc2a36a531d..76c957afa5461 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -27,7 +27,7 @@ impl<'ast> LifetimeCollectVisitor<'ast> { self.collected_lifetimes.insert(lifetime); } } - LifetimeRes::Static | LifetimeRes::Error => { + LifetimeRes::Static { .. } | LifetimeRes::Error => { self.collected_lifetimes.insert(lifetime); } LifetimeRes::Infer => {} diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 59204d799281f..98c7aa424e076 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -821,8 +821,13 @@ pub enum LifetimeRes { /// This variant is used for anonymous lifetimes that we did not resolve during /// late resolution. Those lifetimes will be inferred by typechecking. Infer, - /// Explicit `'static` lifetime. - Static, + /// `'static` lifetime. + Static { + /// We do not want to emit `elided_named_lifetimes` + /// when we are inside of a const item or a static, + /// because it would get too annoying. + suppress_elision_warning: bool, + }, /// Resolution failure. Error, /// HACK: This is used to recover the NodeId of an elided lifetime. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9b46297f8ed7a..c0b979b465077 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -704,14 +704,6 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES). /// See comments in [`MissingLifetime::id_if_exists_in_source_or`]. crate_node_id: NodeId, - - /// Don't emit [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES) - /// when we are in a type annotation for a `const` or `static`. - /// ```rust - /// const HELLO_WORLD: &str = "Hello, world!"; - /// static ZEROES: &[u8] = &[0, 0, 0]; - /// ``` - warn_elided_static: bool, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -1357,7 +1349,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { in_func_body: false, lifetime_uses: Default::default(), crate_node_id: krate.id, - warn_elided_static: true, } } @@ -1568,13 +1559,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ret } - #[instrument(level = "debug", skip(self))] - fn visit_ty_do_not_warn_elided_static(&mut self, ty: &'ast Ty) { - self.warn_elided_static = false; - self.visit_ty(ty); - self.warn_elided_static = true; - } - #[instrument(level = "debug", skip(self))] fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) { let ident = lifetime.ident; @@ -1582,7 +1566,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if ident.name == kw::StaticLifetime { self.record_lifetime_res( lifetime.id, - LifetimeRes::Static, + LifetimeRes::Static { suppress_elision_warning: false }, LifetimeElisionCandidate::Named, ); return; @@ -1722,7 +1706,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if lifetimes_in_scope.is_empty() { self.record_lifetime_res( lifetime.id, - LifetimeRes::Static, + // We are inside a const item, so do not warn. + LifetimeRes::Static { suppress_elision_warning: true }, elision_candidate, ); return; @@ -2069,8 +2054,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeElisionCandidate::Missing(missing @ MissingLifetime { span: elided, .. }) => { debug_assert_eq!(id, missing.id); match res { - LifetimeRes::Static => { - if self.warn_elided_static { + LifetimeRes::Static { suppress_elision_warning } => { + if !suppress_elision_warning { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_if_exists_in_source_or(self.crate_node_id), @@ -2106,7 +2091,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } match res { - LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { + LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { candidates.push((res, candidate)); } @@ -2624,9 +2609,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { self.with_static_rib(def_kind, |this| { - this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - this.visit_ty_do_not_warn_elided_static(ty); - }); + this.with_lifetime_rib( + LifetimeRibKind::Elided(LifetimeRes::Static { + suppress_elision_warning: true, + }), + |this| { + this.visit_ty(ty); + }, + ); if let Some(expr) = expr { // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. @@ -2655,8 +2645,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { this.visit_generics(generics); this.with_lifetime_rib( - LifetimeRibKind::Elided(LifetimeRes::Static), - |this| this.visit_ty_do_not_warn_elided_static(ty), + LifetimeRibKind::Elided(LifetimeRes::Static { + suppress_elision_warning: true, + }), + |this| this.visit_ty(ty), ); if let Some(expr) = expr { @@ -2983,7 +2975,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }, |this| { this.visit_generics(generics); - this.visit_ty_do_not_warn_elided_static(ty); + this.visit_ty(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. @@ -3196,7 +3188,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); this.visit_generics(generics); - this.visit_ty_do_not_warn_elided_static(ty); + this.visit_ty(ty); if let Some(expr) = expr { // We allow arbitrary const expressions inside of associated consts, // even if they are potentially not const evaluatable. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2011c11077e2c..d670aae97f4ce 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3045,7 +3045,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), - (DUMMY_NODE_ID, LifetimeRes::Static), + (DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }), )]; } } else if elided_len == 0 { @@ -3057,7 +3057,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), - (DUMMY_NODE_ID, LifetimeRes::Static), + (DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }), )]; } } else if num_params == 1 { From 3a7d0ab1c48f763765195d57d761314325ae54c0 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 25 Aug 2024 00:27:14 +0300 Subject: [PATCH 22/26] elided_named_lifetimes: get rid of `crate_node_id` --- compiler/rustc_resolve/src/late.rs | 51 +++++++++---------- .../rustc_resolve/src/late/diagnostics.rs | 24 +++------ .../not-tied-to-crate.rs | 17 +++++++ .../not-tied-to-crate.stderr | 26 ++++++++++ 4 files changed, 74 insertions(+), 44 deletions(-) create mode 100644 tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c0b979b465077..8ec0469ed6d87 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -699,11 +699,6 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Count the number of places a lifetime is used. lifetime_uses: FxHashMap, - - /// We need some "real" `NodeId` to emit - /// [`elided_named_lifetimes`](lint::builtin::ELIDED_NAMED_LIFETIMES). - /// See comments in [`MissingLifetime::id_if_exists_in_source_or`]. - crate_node_id: NodeId, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -1322,10 +1317,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { - fn new( - resolver: &'b mut Resolver<'a, 'tcx>, - krate: &Crate, - ) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { + fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; @@ -1348,7 +1340,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // errors at module scope should always be reported in_func_body: false, lifetime_uses: Default::default(), - crate_node_id: krate.id, } } @@ -1573,7 +1564,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if ident.name == kw::UnderscoreLifetime { - return self.resolve_anonymous_lifetime(lifetime, false); + return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false); } let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev(); @@ -1676,13 +1667,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) { + fn resolve_anonymous_lifetime( + &mut self, + lifetime: &Lifetime, + id_for_lint: NodeId, + elided: bool, + ) { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); let kind = if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore }; - let missing_lifetime = - MissingLifetime { id: lifetime.id, span: lifetime.ident.span, kind, count: 1 }; + let missing_lifetime = MissingLifetime { + id: lifetime.id, + span: lifetime.ident.span, + kind, + count: 1, + id_for_lint, + }; let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { debug!(?rib.kind); @@ -1810,7 +1811,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, LifetimeElisionCandidate::Ignore, ); - self.resolve_anonymous_lifetime(<, true); + self.resolve_anonymous_lifetime(<, anchor_id, true); } #[instrument(level = "debug", skip(self))] @@ -1926,6 +1927,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; let missing_lifetime = MissingLifetime { id: node_ids.start, + id_for_lint: segment_id, span: elided_lifetime_span, kind, count: expected_lifetimes, @@ -2051,32 +2053,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } match candidate { - LifetimeElisionCandidate::Missing(missing @ MissingLifetime { span: elided, .. }) => { + LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => { debug_assert_eq!(id, missing.id); match res { LifetimeRes::Static { suppress_elision_warning } => { if !suppress_elision_warning { self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, - missing.id_if_exists_in_source_or(self.crate_node_id), + missing.id_for_lint, missing.span, - BuiltinLintDiag::ElidedIsStatic { elided }, + BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, ); } } - LifetimeRes::Param { param, binder } => { + LifetimeRes::Param { param, binder: _ } => { let tcx = self.r.tcx(); self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_NAMED_LIFETIMES, - // It should be possible to use `self.crate_node_id` - // or `param`'s `NodeId` here as a fallback instead of the `binder`, - // but `binder` sounds like a more appropriate place than the crate, - // and to convert `param` from `LocalDefId` to `NodeId`, - // we would have to do some additional work. - missing.id_if_exists_in_source_or(binder), + missing.id_for_lint, missing.span, BuiltinLintDiag::ElidedIsParam { - elided, + elided: missing.span, param: (tcx.item_name(param.into()), tcx.source_span(param)), }, ); @@ -4990,7 +4987,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); - let mut late_resolution_visitor = LateResolutionVisitor::new(self, krate); + let mut late_resolution_visitor = LateResolutionVisitor::new(self); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d670aae97f4ce..8f516c2db0900 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -102,29 +102,19 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str pub(super) struct MissingLifetime { /// Used to overwrite the resolution with the suggestion, to avoid cascading errors. pub id: NodeId, - /// Where to suggest adding the lifetime. - pub span: Span, - /// How the lifetime was introduced, to have the correct space and comma. - pub kind: MissingLifetimeKind, - /// Number of elided lifetimes, used for elision in path. - pub count: usize, -} - -impl MissingLifetime { /// As we cannot yet emit lints in this crate and have to buffer them instead, /// we need to associate each lint with some `NodeId`, /// however for some `MissingLifetime`s their `NodeId`s are "fake", /// in a sense that they are temporary and not get preserved down the line, /// which means that the lints for those nodes will not get emitted. /// To combat this, we can try to use some other `NodeId`s as a fallback option. - pub(super) fn id_if_exists_in_source_or(self, fallback: NodeId) -> NodeId { - match self.kind { - MissingLifetimeKind::Underscore => self.id, - MissingLifetimeKind::Ampersand - | MissingLifetimeKind::Brackets - | MissingLifetimeKind::Comma => fallback, - } - } + pub id_for_lint: NodeId, + /// Where to suggest adding the lifetime. + pub span: Span, + /// How the lifetime was introduced, to have the correct space and comma. + pub kind: MissingLifetimeKind, + /// Number of elided lifetimes, used for elision in path. + pub count: usize, } /// Description of the lifetimes appearing in a function parameter. diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs new file mode 100644 index 0000000000000..4f9218130fbc1 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs @@ -0,0 +1,17 @@ +#![allow(elided_named_lifetimes)] + +#[warn(elided_named_lifetimes)] +mod foo { + fn bar(x: &'static u8) -> &u8 { + //~^ WARNING elided lifetime has a name + x + } + + #[deny(elided_named_lifetimes)] + fn baz(x: &'static u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x + } +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr new file mode 100644 index 0000000000000..c465aab1a03d2 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -0,0 +1,26 @@ +warning: elided lifetime has a name + --> $DIR/not-tied-to-crate.rs:5:31 + | +LL | fn bar(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/not-tied-to-crate.rs:3:8 + | +LL | #[warn(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/not-tied-to-crate.rs:11:31 + | +LL | fn baz(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/not-tied-to-crate.rs:10:12 + | +LL | #[deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + From ba24121ad6fef48793b6069e68a65a5a491272ef Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2024 13:50:07 +0200 Subject: [PATCH 23/26] tweak rustc_allow_const_fn_unstable hint, and add back test for stable-const-can-only-call-stable-const --- compiler/rustc_const_eval/messages.ftl | 2 +- .../allow_const_fn_ptr_run_pass.rs | 2 -- .../min_const_fn_libstd_stability.rs | 4 +++- .../min_const_fn_libstd_stability.stderr | 18 +++++++++++++----- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 1442f1832b9b5..d7d64180ec9c1 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -419,7 +419,7 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn const_eval_unstable_in_stable = const-stable function cannot use `#[feature({$gate})]` .unstable_sugg = if it is not part of the public API, make this function unstably const - .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks + .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) const_eval_unterminated_c_string = reading a null-terminated string starting at {$pointer} with no null found before end of allocation diff --git a/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs index a97eeadd92f4e..fe92787aec11b 100644 --- a/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs +++ b/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs @@ -1,6 +1,4 @@ //@ run-pass -#![feature(rustc_allow_const_fn_unstable)] - #![feature(rustc_attrs, staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index dc653370e5162..480b16b28a501 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -28,9 +28,11 @@ const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn // conformity is required const fn bar3() -> u32 { let x = std::cell::Cell::new(0u32); - x.get() + x.get(); //~^ ERROR const-stable function cannot use `#[feature(const_refs_to_cell)]` //~| ERROR cannot call non-const fn + foo() + //~^ ERROR is not yet stable as a const fn } // check whether this function cannot be called even with the feature gate active diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index e5f8fa25b64ab..019deda063c78 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -17,7 +17,7 @@ LL | const fn bar2() -> u32 { foo2() } error: const-stable function cannot use `#[feature(const_refs_to_cell)]` --> $DIR/min_const_fn_libstd_stability.rs:31:5 | -LL | x.get() +LL | x.get(); | ^ | help: if it is not part of the public API, make this function unstably const @@ -25,7 +25,7 @@ help: if it is not part of the public API, make this function unstably const LL + #[rustc_const_unstable(feature = "...", issue = "...")] LL | const fn bar3() -> u32 { | -help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) | LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] LL | const fn bar3() -> u32 { @@ -34,19 +34,27 @@ LL | const fn bar3() -> u32 { error[E0015]: cannot call non-const fn `Cell::::get` in constant functions --> $DIR/min_const_fn_libstd_stability.rs:31:7 | -LL | x.get() +LL | x.get(); | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +error: `foo` is not yet stable as a const fn + --> $DIR/min_const_fn_libstd_stability.rs:34:5 + | +LL | foo() + | ^^^^^ + | + = help: const-stable functions can only call other const-stable functions + error: `foo2_gated` is not yet stable as a const fn - --> $DIR/min_const_fn_libstd_stability.rs:43:32 + --> $DIR/min_const_fn_libstd_stability.rs:45:32 | LL | const fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0015`. From 8750e2424744f6365fbbfd3a42059eb51091e736 Mon Sep 17 00:00:00 2001 From: surechen Date: Thu, 22 Aug 2024 17:41:15 +0800 Subject: [PATCH 24/26] Fixing span manipulation and indentation of the suggestion introduced by #126187 According to comments: https://github.com/rust-lang/rust/pull/128084#issuecomment-2295254576 https://github.com/rust-lang/rust/pull/126187/files#r1634897691 --- .../src/error_reporting/traits/suggestions.rs | 11 +++++++--- ...turn-from-residual-sugg-issue-125997.fixed | 18 ++++++---------- ...urn-from-residual-sugg-issue-125997.stderr | 21 ++++++------------- .../ui/try-trait/try-operator-on-main.stderr | 2 -- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index a962be54c3d88..cc5b731a8d890 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4667,10 +4667,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let hir::ExprKind::Block(b, _) = body.value.kind && b.expr.is_none() { + // The span of '}' in the end of block. + let span = self.tcx.sess.source_map().end_point(b.span); sugg_spans.push(( - // The span will point to the closing curly brace `}` of the block. - b.span.shrink_to_hi().with_lo(b.span.hi() - BytePos(1)), - "\n Ok(())\n}".to_string(), + span.shrink_to_lo(), + format!( + "{}{}", + " Ok(())\n", + self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(), + ), )); } err.multipart_suggestion_verbose( diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.fixed b/tests/ui/return/return-from-residual-sugg-issue-125997.fixed index a5a133998259b..43a9907a9b496 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.fixed +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.fixed @@ -9,7 +9,6 @@ use std::io::prelude::*; fn test1() -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function - Ok(()) } @@ -17,7 +16,6 @@ fn test2() -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function println!(); - Ok(()) } @@ -27,9 +25,8 @@ macro_rules! mac { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function println!(); - - Ok(()) -} + Ok(()) + } }; } @@ -39,23 +36,20 @@ impl A { fn test4(&self) -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a method - - Ok(()) -} + Ok(()) + } fn test5(&self) -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a method println!(); - - Ok(()) -} + Ok(()) + } } fn main() -> Result<(), Box> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function mac!(); - Ok(()) } diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr index a59f38c2ec644..e22f33fd242a6 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr @@ -12,9 +12,7 @@ help: consider adding return type LL ~ fn test1() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -32,9 +30,7 @@ LL ~ fn test2() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -51,9 +47,8 @@ help: consider adding return type LL ~ fn test4(&self) -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -71,9 +66,8 @@ LL ~ fn test5(&self) -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -91,9 +85,7 @@ LL ~ fn main() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | mac!(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -115,9 +107,8 @@ LL ~ fn test3() -> Result<(), Box> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | error: aborting due to 6 previous errors diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr index d22117165c12b..311e8076ed48e 100644 --- a/tests/ui/try-trait/try-operator-on-main.stderr +++ b/tests/ui/try-trait/try-operator-on-main.stderr @@ -14,9 +14,7 @@ LL ~ fn main() -> Result<(), Box> { LL | // error for a `Try` type on a non-`Try` fn ... LL | try_trait_generic::<()>(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be applied to values that implement `Try` From 48f43fa0ed2f2e4ff2d9d53b9d72cfbc108a9034 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Aug 2024 16:02:11 -0400 Subject: [PATCH 25/26] Avoid taking reference of &TyKind --- compiler/rustc_borrowck/src/borrowck_errors.rs | 2 +- compiler/rustc_borrowck/src/places_conflict.rs | 2 +- compiler/rustc_const_eval/src/interpret/cast.rs | 6 +++--- compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 2 +- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 4 ++-- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_mir_build/src/build/expr/as_constant.rs | 2 +- compiler/rustc_mir_build/src/thir/constant.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 4 ++-- .../src/error_reporting/infer/suggest.rs | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 76e39fe94af43..70f89e80dc94d 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -290,7 +290,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { ty: Ty<'_>, is_index: Option, ) -> Diag<'infcx> { - let type_name = match (&ty.kind(), is_index) { + let type_name = match (ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 42d0c2038f8bb..311f17f15b9ee 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -201,7 +201,7 @@ fn place_components_conflict<'tcx>( let base_ty = base.ty(body, tcx).ty; - match (elem, &base_ty.kind(), access) { + match (elem, base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) | (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => { // The array length is like additional fields on the diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 4901e4b2a4158..e8c9f145eea55 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -388,7 +388,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); - match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) { + match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { let ptr = self.read_pointer(src)?; let val = Immediate::new_slice( @@ -478,9 +478,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); - match (&src.layout.ty.kind(), &cast_ty.ty.kind()) { + match (src.layout.ty.kind(), cast_ty.ty.kind()) { (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _)) - | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, *s, *c), + | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); // implies same number of fields diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index d77cbe3053653..af319fd53bde7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -608,7 +608,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); - match &self_ty.kind() { + match self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5c8ecf254a54e..d1a0da47b3d18 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1057,7 +1057,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&qself_ty.kind(), qself_res) { + let bound = match (qself_ty.kind(), qself_res) { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 703273968c5bb..11c6e65a21101 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2975,7 +2975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut suffix_suggestion = sugg.clone(); suffix_suggestion.push(( if matches!( - (&expected_ty.kind(), &checked_ty.kind()), + (expected_ty.kind(), checked_ty.kind()), (ty::Int(_) | ty::Uint(_), ty::Float(_)) ) { // Remove fractional part from literal, for example `42.0f32` into `42` @@ -3077,7 +3077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable); }; - match (&expected_ty.kind(), &checked_ty.kind()) { + match (expected_ty.kind(), checked_ty.kind()) { (ty::Int(exp), ty::Int(found)) => { let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3df32dd85052b..ffd46ea13b908 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1012,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); - match &self_ty.kind() { + match self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c4f74adb4207b..a8e5e09c8bbeb 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1336,7 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // More generally, the expected type wants a tuple variant with one field of an // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. - let missing_parentheses = match (&expected.kind(), fields, had_err) { + let missing_parentheses = match (expected.kind(), fields, had_err) { // #67037: only do this if we could successfully type-check the expected type against // the tuple struct pattern. Otherwise the args could get out of range on e.g., // `let P() = U;` where `P != U` with `struct P(T);`. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 619981bf021e4..d0a9039441dc4 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1104,7 +1104,7 @@ where } fn is_never(this: TyAndLayout<'tcx>) -> bool { - this.ty.kind() == &ty::Never + matches!(this.ty.kind(), ty::Never) } fn is_tuple(this: TyAndLayout<'tcx>) -> bool { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 045c8ad39bee2..efbccca77c1f0 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -296,7 +296,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); loop { - match (&a.kind(), &b.kind()) { + match (a.kind(), b.kind()) { (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def && a_def.is_struct() => { diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 4430aab73a819..4f1166f91118e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -127,7 +127,7 @@ fn lit_to_mir_constant<'tcx>( Ok(ConstValue::Scalar(Scalar::from_uint(result, width))) }; - let value = match (lit, &ty.kind()) { + let value = match (lit, ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 7b94867114d5a..b8877a64e47eb 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -29,7 +29,7 @@ pub(crate) fn lit_to_const<'tcx>( .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))) }; - let valtree = match (lit, &ty.kind()) { + let valtree = match (lit, ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let str_bytes = s.as_str().as_bytes(); ty::ValTree::from_raw_bytes(tcx, str_bytes) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 77f6a1e17cefc..ff4207fbefda8 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1035,9 +1035,9 @@ fn find_vtable_types_for_unsizing<'tcx>( } }; - match (&source_ty.kind(), &target_ty.kind()) { + match (source_ty.kind(), target_ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) - | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(*a, *b), + | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 35f68a56d2ddc..ba656493d462d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -382,7 +382,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if !expected_inner.is_fn() || !found_inner.is_fn() { return; } - match (&expected_inner.kind(), &found_inner.kind()) { + match (expected_inner.kind(), found_inner.kind()) { (ty::FnPtr(sig_tys, hdr), ty::FnDef(did, args)) => { let sig = sig_tys.with(*hdr); let expected_sig = &(self.normalize_fn_sig)(sig); From ecd2d115736581726ee9b77432561ea9480b3241 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 Aug 2024 15:03:51 -0400 Subject: [PATCH 26/26] Remove redundant flags that can be inferred from the HIR --- .../src/hir_ty_lowering/lint.rs | 21 +++++++++++---- .../src/hir_ty_lowering/mod.rs | 27 ++++--------------- .../src/hir_ty_lowering/object_safety.rs | 1 - .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../suggest-dyn-on-bare-trait-in-pat.rs | 14 ++++++++++ .../suggest-dyn-on-bare-trait-in-pat.stderr | 14 ++++++++++ 6 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs create mode 100644 tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 6aff518390ffc..7be45463f1512 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -15,11 +15,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty( - &self, - self_ty: &hir::Ty<'_>, - in_path: bool, - ) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = @@ -28,6 +24,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; }; + let in_path = match tcx.parent_hir_node(self_ty.hir_id) { + hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Pat(hir::Pat { + kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) if qself.hir_id == self_ty.hir_id => true, + _ => false, + }; let needs_bracket = in_path && !tcx .sess diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 73baa05bce660..010d58bfb673c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1998,16 +1998,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Lower a type from the HIR to our internal notion of a type. - pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - self.lower_ty_common(hir_ty, false, false) - } - - /// Lower a type inside of a path from the HIR to our internal notion of a type. - pub fn lower_ty_in_path(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - self.lower_ty_common(hir_ty, false, true) - } - fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { @@ -2025,7 +2015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// 2. `in_path`: Whether the type appears inside of a path. /// Used to provide correct diagnostics for bare trait object types. #[instrument(level = "debug", skip(self), ret)] - fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool) -> Ty<'tcx> { + pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match &hir_ty.kind { @@ -2035,7 +2025,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::TyKind::Ref(region, mt) => { let r = self.lower_lifetime(region, RegionInferReason::Reference); debug!(?r); - let t = self.lower_ty_common(mt.ty, true, false); + let t = self.lower_ty(mt.ty); Ty::new_ref(tcx, r, t, mt.mutbl) } hir::TyKind::Never => tcx.types.never, @@ -2064,20 +2054,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path); + self.prohibit_or_lint_bare_trait_object_ty(hir_ty); let repr = match repr { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::DynStar => ty::DynStar, }; - self.lower_trait_object_ty( - hir_ty.span, - hir_ty.hir_id, - bounds, - lifetime, - borrowed, - repr, - ) + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -2105,7 +2088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => { debug!(?qself, ?segment); - let ty = self.lower_ty_common(qself, false, true); + let ty = self.lower_ty(qself); self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false) .map(|(ty, _, _)| ty) .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 082fbb2c41835..52e167379b5dd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -30,7 +30,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_id: hir::HirId, hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], lifetime: &hir::Lifetime, - _borrowed: bool, representation: DynKind, ) -> Ty<'tcx> { let tcx = self.tcx(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b169f75796b3a..21e6ac9332cdf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -798,7 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to be object-safe. // We manually call `register_wf_obligation` in the success path // below. - let ty = self.lowerer().lower_ty_in_path(qself); + let ty = self.lowerer().lower_ty(qself); (LoweredTy::from_raw(self, span, ty), qself, segment) } QPath::LangItem(..) => { diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs new file mode 100644 index 0000000000000..19b5edb620f6b --- /dev/null +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 + +trait Trait {} + +impl dyn Trait { + const CONST: () = (); +} + +fn main() { + match () { + Trait::CONST => {} + //~^ ERROR trait objects must include the `dyn` keyword + } +} diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr new file mode 100644 index 0000000000000..4446a89b63b15 --- /dev/null +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr @@ -0,0 +1,14 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9 + | +LL | Trait::CONST => {} + | ^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | ::CONST => {} + | ++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`.