]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_infer/traits/object_safety.rs
Update const_forget.rs
[rust.git] / src / librustc_infer / traits / object_safety.rs
index d36d66e4e2555cc7940aa06bb77bc9fb982154e8..f5bab7cfac9767ac469dc5fd07af40639065f661 100644 (file)
 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 smallvec::{smallvec, SmallVec};
-use syntax::ast;
+use rustc_span::Span;
+use smallvec::SmallVec;
 
-use std::borrow::Cow;
-use std::iter::{self};
+use std::iter;
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum ObjectSafetyViolation {
-    /// `Self: Sized` declared on the trait.
-    SizedSelf(SmallVec<[Span; 1]>),
-
-    /// Supertrait reference references `Self` an in illegal location
-    /// (e.g., `trait Foo : Bar<Self>`).
-    SupertraitSelf(SmallVec<[Span; 1]>),
-
-    /// Method has something illegal.
-    Method(ast::Name, MethodViolationCode, Span),
-
-    /// Associated const.
-    AssocConst(ast::Name, Span),
-}
-
-impl ObjectSafetyViolation {
-    pub fn error_msg(&self) -> Cow<'static, str> {
-        match *self {
-            ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
-            ObjectSafetyViolation::SupertraitSelf(ref spans) => {
-                if spans.iter().any(|sp| *sp != DUMMY_SP) {
-                    "it uses `Self` as a type parameter in this".into()
-                } else {
-                    "it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
-                        .into()
-                }
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
-                format!("associated function `{}` has no `self` parameter", name).into()
-            }
-            ObjectSafetyViolation::Method(
-                name,
-                MethodViolationCode::ReferencesSelfInput(_),
-                DUMMY_SP,
-            ) => format!("method `{}` references the `Self` type in its parameters", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => {
-                format!("method `{}` references the `Self` type in this parameter", name).into()
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => {
-                format!("method `{}` references the `Self` type in its return type", name).into()
-            }
-            ObjectSafetyViolation::Method(
-                name,
-                MethodViolationCode::WhereClauseReferencesSelf,
-                _,
-            ) => {
-                format!("method `{}` references the `Self` type in its `where` clause", name).into()
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => {
-                format!("method `{}` has generic type parameters", name).into()
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => {
-                format!("method `{}`'s `self` parameter cannot be dispatched on", name).into()
-            }
-            ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => {
-                format!("it contains associated `const` `{}`", name).into()
-            }
-            ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(),
-        }
-    }
-
-    pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> {
-        Some(match *self {
-            ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {
-                return None;
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => (
-                format!(
-                    "consider turning `{}` into a method by giving it a `&self` argument or \
-                     constraining it so it does not apply to trait objects",
-                    name
-                ),
-                sugg.map(|(sugg, sp)| (sugg.to_string(), sp)),
-            ),
-            ObjectSafetyViolation::Method(
-                name,
-                MethodViolationCode::UndispatchableReceiver,
-                span,
-            ) => (
-                format!("consider changing method `{}`'s `self` parameter to be `&self`", name)
-                    .into(),
-                Some(("&Self".to_string(), span)),
-            ),
-            ObjectSafetyViolation::AssocConst(name, _)
-            | ObjectSafetyViolation::Method(name, ..) => {
-                (format!("consider moving `{}` to another trait", name), None)
-            }
-        })
-    }
-
-    pub fn spans(&self) -> SmallVec<[Span; 1]> {
-        // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
-        // diagnostics use a `note` instead of a `span_label`.
-        match self {
-            ObjectSafetyViolation::SupertraitSelf(spans)
-            | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
-            ObjectSafetyViolation::AssocConst(_, span)
-            | ObjectSafetyViolation::Method(_, _, span)
-                if *span != DUMMY_SP =>
-            {
-                smallvec![*span]
-            }
-            _ => smallvec![],
-        }
-    }
-}
-
-/// Reasons a method might not be object-safe.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum MethodViolationCode {
-    /// e.g., `fn foo()`
-    StaticMethod(Option<(&'static str, Span)>),
-
-    /// e.g., `fn foo(&self, x: Self)`
-    ReferencesSelfInput(usize),
-
-    /// e.g., `fn foo(&self) -> Self`
-    ReferencesSelfOutput,
-
-    /// e.g., `fn foo(&self) where Self: Clone`
-    WhereClauseReferencesSelf,
-
-    /// e.g., `fn foo<A>()`
-    Generic,
-
-    /// the method's receiver (`self` argument) can't be dispatched on
-    UndispatchableReceiver,
-}
+pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
 
 /// Returns the object safety violations that affect
 /// astconv -- currently, `Self` in supertraits. This is needed
@@ -176,10 +46,7 @@ pub fn astconv_object_safety_violations(
     violations
 }
 
-pub fn object_safety_violations(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-) -> Vec<ObjectSafetyViolation> {
+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);
 
@@ -213,7 +80,7 @@ fn object_safety_violations_for_trait(
     // Check methods for violations.
     let mut violations: Vec<_> = tcx
         .associated_items(trait_def_id)
-        .iter()
+        .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Method)
         .filter_map(|item| {
             object_safety_violation_for_method(tcx, trait_def_id, &item)
@@ -289,7 +156,7 @@ fn object_safety_violations_for_trait(
 
     violations.extend(
         tcx.associated_items(trait_def_id)
-            .iter()
+            .in_definition_order()
             .filter(|item| item.kind == ty::AssocKind::Const)
             .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
     );
@@ -646,7 +513,7 @@ fn object_ty_for_trait<'tcx>(
     let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
         .flat_map(|super_trait_ref| {
             tcx.associated_items(super_trait_ref.def_id())
-                .iter()
+                .in_definition_order()
                 .map(move |item| (super_trait_ref, item))
         })
         .filter(|(_, item)| item.kind == ty::AssocKind::Type)
@@ -905,6 +772,6 @@ fn contains_illegal_self_type_reference<'tcx>(
     error
 }
 
-pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
-    object_safety_violations(tcx, trait_def_id).is_empty()
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers { object_safety_violations, ..*providers };
 }