From d6de40b536f6d592de3d0a00626a4dc595d40078 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 29 Dec 2022 09:53:25 +0000 Subject: [PATCH] Make `is_object_safe` a query and move lint_object_unsafe_trait call there --- compiler/rustc_middle/src/query/mod.rs | 3 ++ compiler/rustc_middle/src/ty/mod.rs | 4 -- .../src/traits/object_safety.rs | 46 +++++++++++++------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e4df309e0089..1b9298e82d6b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1274,6 +1274,9 @@ rustc_queries! { query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] { desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) } } + query is_object_safe(trait_id: DefId) -> bool { + desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) } + } /// Gets the ParameterEnvironment for a given item; this environment /// will be in "user-facing" mode, meaning that it is suitable for diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4af29fcbfb58..8e936174c8be 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2471,10 +2471,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn is_object_safe(self, key: DefId) -> bool { - self.object_safety_violations(key).is_empty() - } - #[inline] pub fn is_const_fn_raw(self, def_id: DefId) -> bool { matches!( diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 55c2f7e2e358..a5447c012f06 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -62,6 +62,37 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object ) } +fn is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { + let violations = tcx.object_safety_violations(trait_def_id); + + if violations.is_empty() { + return true; + } + + // If the trait contains any other violations, then let the error reporting path + // report it instead of emitting a warning here. + if violations.iter().all(|violation| { + matches!( + violation, + ObjectSafetyViolation::Method(_, MethodViolationCode::WhereClauseReferencesSelf, _) + ) + }) { + for violation in violations { + if let ObjectSafetyViolation::Method( + _, + MethodViolationCode::WhereClauseReferencesSelf, + span, + ) = violation + { + lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation); + } + } + return true; + } + + false +} + /// We say a method is *vtable safe* if it can be invoked on a trait /// object. Note that object-safe traits can have some /// non-vtable-safe methods, so long as they require `Self: Sized` or @@ -93,19 +124,6 @@ fn object_safety_violations_for_trait( object_safety_violation_for_method(tcx, trait_def_id, &item) .map(|(code, span)| ObjectSafetyViolation::Method(item.name, code, span)) }) - .filter(|violation| { - if let ObjectSafetyViolation::Method( - _, - MethodViolationCode::WhereClauseReferencesSelf, - span, - ) = violation - { - lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation); - false - } else { - true - } - }) .collect(); // Check the trait itself. @@ -866,5 +884,5 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>( } pub fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { object_safety_violations, ..*providers }; + *providers = ty::query::Providers { object_safety_violations, is_object_safe, ..*providers }; }