use super::elaborate_predicates;
-use crate::lint;
use crate::traits::{self, Obligation, ObligationCause};
use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
+use syntax::ast;
+
use std::borrow::Cow;
use std::iter::{self};
-use syntax::ast::{self};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ObjectSafetyViolation {
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(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
- debug_assert!(self.generics_of(trait_def_id).has_self);
- debug!("object_safety_violations: {:?}", trait_def_id);
+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);
- traits::supertrait_def_ids(self, trait_def_id)
- .flat_map(|def_id| object_safety_violations_for_trait(self, def_id))
- .collect()
- }
+ traits::supertrait_def_ids(tcx, trait_def_id)
+ .flat_map(|def_id| object_safety_violations_for_trait(tcx, 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(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;
- }
+/// 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;
+ }
- 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,
}
}
{
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
// It's also hard to get a use site span, so we use the method definition span.
- tcx.lint_node_note(
- lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
+ tcx.struct_span_lint_hir(
+ WHERE_CLAUSES_OBJECT_SAFETY,
hir::CRATE_HIR_ID,
*span,
&format!(
"the trait `{}` cannot be made into an object",
tcx.def_path_str(trait_def_id)
),
- &violation.error_msg(),
- );
+ )
+ .note(&violation.error_msg())
+ .emit();
false
} else {
true
}
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()
}