Skip to content

Commit

Permalink
Make rustc::traits::object_safety::{astconv_object_safety_violations,…
Browse files Browse the repository at this point in the history
…is_vtable_safe_method,object_safety_violations} free functions.
  • Loading branch information
cjgillot committed Jan 7, 2020
1 parent 0b1521e commit 7770bce
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 49 deletions.
3 changes: 2 additions & 1 deletion src/librustc/infer/error_reporting/mod.rs
Expand Up @@ -54,6 +54,7 @@ use crate::infer::opaque_types;
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,
};
Expand Down Expand Up @@ -1487,7 +1488,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
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) => {
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/traits/error_reporting.rs
Expand Up @@ -11,6 +11,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
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;
Expand Down Expand Up @@ -915,7 +916,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

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)
}

Expand Down Expand Up @@ -1079,7 +1080,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

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)
}

Expand Down
5 changes: 4 additions & 1 deletion src/librustc/traits/mod.rs
Expand Up @@ -47,6 +47,9 @@ pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}
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};
Expand Down Expand Up @@ -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;
}
Expand Down
84 changes: 41 additions & 43 deletions src/librustc/traits/object_safety.rs
Expand Up @@ -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<ObjectSafetyViolation> {
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<ObjectSafetyViolation> {
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<ObjectSafetyViolation> {
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<ObjectSafetyViolation> {
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,
}
}

Expand Down Expand Up @@ -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()
}
3 changes: 2 additions & 1 deletion src/librustc_typeck/astconv.rs
Expand Up @@ -13,6 +13,7 @@ use errors::{Applicability, DiagnosticId};
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;
Expand Down Expand Up @@ -1453,7 +1454,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// to avoid ICEs.
for item in &regular_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,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/cast.rs
Expand Up @@ -38,6 +38,7 @@ use rustc::middle::lang_items;
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;
Expand Down Expand Up @@ -519,7 +520,7 @@ impl<'a, 'tcx> CastCheck<'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();
Expand Down

0 comments on commit 7770bce

Please sign in to comment.