diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2024-01-03 21:00:04 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2024-01-03 21:00:04 +0000 |
| commit | 78ef94618b037e18d01644638eaf41ecfa5def04 (patch) | |
| tree | 82a4a3620839554789539f1194fc033927935c15 /compiler/rustc_hir_analysis/src/astconv/lint.rs | |
| parent | 771966ba294be37e0613d97109f203393521e217 (diff) | |
| download | rust-78ef94618b037e18d01644638eaf41ecfa5def04.tar.gz rust-78ef94618b037e18d01644638eaf41ecfa5def04.zip | |
Account for object unsafe traits
Fix #119525.
Diffstat (limited to 'compiler/rustc_hir_analysis/src/astconv/lint.rs')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/lint.rs | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 2be172e8113..d26f3d5ee91 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -1,6 +1,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::{Diagnostic, StashKey}; use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; @@ -90,15 +91,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; + let is_object_safe = match self_ty.kind { + hir::TyKind::TraitObject(objects, ..) => { + objects.iter().all(|o| match o.trait_ref.path.res { + Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id), + _ => false, + }) + } + _ => false, + }; if let hir::FnRetTy::Return(ty) = sig.decl.output && ty.hir_id == self_ty.hir_id { - diag.multipart_suggestion_verbose( - format!("use `impl {trait_name}` to return an opaque type, as long as you return a single underlying type"), - impl_sugg, - Applicability::MachineApplicable, + let pre = if !is_object_safe { + format!("`{trait_name}` is not object safe, ") + } else { + String::new() + }; + let msg = format!( + "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \ + single underlying type", ); - if tcx.check_is_object_safe(def_id) { + diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable); + if is_object_safe { diag.multipart_suggestion_verbose( "alternatively, you can return an owned trait object", vec![ @@ -111,25 +126,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return true; } for ty in sig.decl.inputs { - if ty.hir_id == self_ty.hir_id { - let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); - if !sugg.is_empty() { - diag.multipart_suggestion_verbose( - format!("use a new generic type parameter, constrained by `{trait_name}`"), - sugg, - Applicability::MachineApplicable, - ); - diag.multipart_suggestion_verbose( - "you can also use an opaque type, but users won't be able to specify the \ - type parameter when calling the `fn`, having to rely exclusively on type \ - inference", - impl_sugg, - Applicability::MachineApplicable, - ); - } - if !tcx.check_is_object_safe(def_id) { - diag.note(format!("it is not object safe, so it can't be `dyn`")); - } + if ty.hir_id != self_ty.hir_id { + continue; + } + let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); + if !sugg.is_empty() { + diag.multipart_suggestion_verbose( + format!("use a new generic type parameter, constrained by `{trait_name}`"), + sugg, + Applicability::MachineApplicable, + ); + diag.multipart_suggestion_verbose( + "you can also use an opaque type, but users won't be able to specify the type \ + parameter when calling the `fn`, having to rely exclusively on type inference", + impl_sugg, + Applicability::MachineApplicable, + ); + } + if !is_object_safe { + diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); + } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. vec