From: Camille GILLOT Date: Sun, 5 Jan 2020 17:07:29 +0000 (+0100) Subject: Make rustc::traits::object_safety::{astconv_object_safety_violations,is_vtable_safe_m... X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=7770bce1788169e15186412b0eb035adb5c8eb4b;p=rust.git Make rustc::traits::object_safety::{astconv_object_safety_violations,is_vtable_safe_method,object_safety_violations} free functions. --- diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 1d1135ef2ed..f262672fdc8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -54,6 +54,7 @@ use crate::infer::{self, SuppressRegionErrors}; use crate::middle::region; use crate::traits::error_reporting::report_object_safety_error; +use crate::traits::object_safety_violations; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; @@ -1487,7 +1488,7 @@ pub fn report_and_explain_type_error( let failure_code = trace.cause.as_failure_code(terr); let mut diag = match failure_code { FailureCode::Error0038(did) => { - let violations = self.tcx.object_safety_violations(did); + let violations = object_safety_violations(self.tcx, did); report_object_safety_error(self.tcx, span, did, violations) } FailureCode::Error0317(failure_str) => { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7fa5a495621..172330dbc7e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -11,6 +11,7 @@ use crate::infer::{self, InferCtxt}; use crate::mir::interpret::ErrorHandled; use crate::session::DiagnosticMessageId; +use crate::traits::object_safety_violations; use crate::ty::error::ExpectedFound; use crate::ty::fast_reject; use crate::ty::fold::TypeFolder; @@ -915,7 +916,7 @@ pub fn report_selection_error( } ty::Predicate::ObjectSafe(trait_def_id) => { - let violations = self.tcx.object_safety_violations(trait_def_id); + let violations = object_safety_violations(self.tcx, trait_def_id); report_object_safety_error(self.tcx, span, trait_def_id, violations) } @@ -1079,7 +1080,7 @@ pub fn report_selection_error( } TraitNotObjectSafe(did) => { - let violations = self.tcx.object_safety_violations(did); + let violations = object_safety_violations(self.tcx, did); report_object_safety_error(self.tcx, span, did, violations) } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 3ba673d1a7d..0c315b3d6ef 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -47,6 +47,9 @@ pub use self::coherence::{OrphanCheckErr, OverlapResult}; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; +pub use self::object_safety::astconv_object_safety_violations; +pub use self::object_safety::is_vtable_safe_method; +pub use self::object_safety::object_safety_violations; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; @@ -1062,7 +1065,7 @@ fn vtable_methods<'tcx>( let def_id = trait_method.def_id; // Some methods cannot be called on an object; skip those. - if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { + if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { debug!("vtable_methods: not vtable safe"); return None; } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 3c64a46661d..bfbcb042e7a 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -108,54 +108,52 @@ pub enum MethodViolationCode { UndispatchableReceiver, } -impl<'tcx> TyCtxt<'tcx> { - /// Returns the object safety violations that affect - /// astconv -- currently, `Self` in supertraits. This is needed - /// because `object_safety_violations` can't be used during - /// type collection. - pub fn astconv_object_safety_violations( - self, - trait_def_id: DefId, - ) -> Vec { - debug_assert!(self.generics_of(trait_def_id).has_self); - let violations = traits::supertrait_def_ids(self, trait_def_id) - .filter(|&def_id| predicates_reference_self(self, def_id, true)) - .map(|_| ObjectSafetyViolation::SupertraitSelf) - .collect(); +/// Returns the object safety violations that affect +/// astconv -- currently, `Self` in supertraits. This is needed +/// because `object_safety_violations` can't be used during +/// type collection. +pub fn astconv_object_safety_violations( + tcx: TyCtxt<'_>, + trait_def_id: DefId, +) -> Vec { + debug_assert!(tcx.generics_of(trait_def_id).has_self); + let violations = traits::supertrait_def_ids(tcx, trait_def_id) + .filter(|&def_id| predicates_reference_self(tcx, def_id, true)) + .map(|_| ObjectSafetyViolation::SupertraitSelf) + .collect(); - debug!( - "astconv_object_safety_violations(trait_def_id={:?}) = {:?}", - trait_def_id, violations - ); + debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations); - violations - } + violations +} + +pub fn object_safety_violations( + tcx: TyCtxt<'_>, + trait_def_id: DefId, +) -> Vec { + debug_assert!(tcx.generics_of(trait_def_id).has_self); + debug!("object_safety_violations: {:?}", trait_def_id); - pub fn object_safety_violations(self, trait_def_id: DefId) -> Vec { - debug_assert!(self.generics_of(trait_def_id).has_self); - debug!("object_safety_violations: {:?}", trait_def_id); + traits::supertrait_def_ids(tcx, trait_def_id) + .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id)) + .collect() +} - traits::supertrait_def_ids(self, trait_def_id) - .flat_map(|def_id| object_safety_violations_for_trait(self, def_id)) - .collect() +/// 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 +/// otherwise ensure that they cannot be used when `Self = Trait`. +pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool { + debug_assert!(tcx.generics_of(trait_def_id).has_self); + debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); + // Any method that has a `Self: Sized` bound cannot be called. + if generics_require_sized_self(tcx, method.def_id) { + return 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 - /// otherwise ensure that they cannot be used when `Self = Trait`. - pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool { - debug_assert!(self.generics_of(trait_def_id).has_self); - debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); - // Any method that has a `Self: Sized` bound cannot be called. - if generics_require_sized_self(self, method.def_id) { - return false; - } - - match virtual_call_violation_for_method(self, trait_def_id, method) { - None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true, - Some(_) => false, - } + match virtual_call_violation_for_method(tcx, trait_def_id, method) { + None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true, + Some(_) => false, } } @@ -724,5 +722,5 @@ fn contains_illegal_self_type_reference<'tcx>( } pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { - tcx.object_safety_violations(trait_def_id).is_empty() + object_safety_violations(tcx, trait_def_id).is_empty() } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a7da2df9fb7..82c97af1be4 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -13,6 +13,7 @@ use rustc::hir::intravisit::Visitor; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; +use rustc::traits::astconv_object_safety_violations; use rustc::traits::error_reporting::report_object_safety_error; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; use rustc::ty::wf::object_region_bounds; @@ -1453,7 +1454,7 @@ fn conv_object_ty_poly_trait_ref( // to avoid ICEs. for item in ®ular_traits { let object_safety_violations = - tcx.astconv_object_safety_violations(item.trait_ref().def_id()); + astconv_object_safety_violations(tcx, item.trait_ref().def_id()); if !object_safety_violations.is_empty() { report_object_safety_error( tcx, diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 1a4aa089549..0be21ad58be 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -38,6 +38,7 @@ use rustc::session::Session; use rustc::traits; use rustc::traits::error_reporting::report_object_safety_error; +use rustc::traits::object_safety_violations; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::cast::{CastKind, CastTy}; use rustc::ty::error::TypeError; @@ -519,7 +520,7 @@ pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) { } fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) { - let violations = fcx.tcx.object_safety_violations(did); + let violations = object_safety_violations(fcx.tcx, did); let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations); err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty))); err.emit();