diff options
| author | Gary Guo <gary@garyguo.net> | 2022-12-29 09:53:25 +0000 |
|---|---|---|
| committer | Gary Guo <gary@garyguo.net> | 2023-01-28 14:49:22 +0000 |
| commit | d6de40b536f6d592de3d0a00626a4dc595d40078 (patch) | |
| tree | 08468642db4ad5245d0d0c094b7021096d60e823 | |
| parent | e144a13254a56fbfd9fc979e0886a2a70260073e (diff) | |
| download | rust-d6de40b536f6d592de3d0a00626a4dc595d40078.tar.gz rust-d6de40b536f6d592de3d0a00626a4dc595d40078.zip | |
Make `is_object_safe` a query and move lint_object_unsafe_trait call there
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/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 e4df309e008..1b9298e82d6 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 4af29fcbfb5..8e936174c8b 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 55c2f7e2e35..a5447c012f0 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 }; } |
