1 //! Trait Resolution. See the [rustc dev guide] for more information on how this works.
3 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
8 pub mod specialization_graph
;
11 use crate::infer
::canonical
::Canonical
;
12 use crate::mir
::interpret
::ErrorHandled
;
13 use crate::ty
::subst
::SubstsRef
;
14 use crate::ty
::{self, AdtKind, Ty, TyCtxt}
;
17 use rustc_hir
::def_id
::DefId
;
18 use rustc_span
::symbol
::Symbol
;
19 use rustc_span
::{Span, DUMMY_SP}
;
20 use smallvec
::SmallVec
;
27 pub use self::select
::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}
;
29 pub type ChalkCanonicalGoal
<'tcx
> = Canonical
<'tcx
, ChalkEnvironmentAndGoal
<'tcx
>>;
31 pub use self::ImplSource
::*;
32 pub use self::ObligationCauseCode
::*;
34 pub use self::chalk
::{
35 ChalkEnvironmentAndGoal
, ChalkEnvironmentClause
, RustInterner
as ChalkRustInterner
,
38 /// Depending on the stage of compilation, we want projection to be
39 /// more or less conservative.
40 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
42 /// At type-checking time, we refuse to project any associated
43 /// type that is marked `default`. Non-`default` ("final") types
44 /// are always projected. This is necessary in general for
45 /// soundness of specialization. However, we *could* allow
46 /// projections in fully-monomorphic cases. We choose not to,
47 /// because we prefer for `default type` to force the type
48 /// definition to be treated abstractly by any consumers of the
49 /// impl. Concretely, that means that the following example will
57 /// impl<T> Assoc for T {
58 /// default type Output = bool;
62 /// let <() as Assoc>::Output = true;
67 /// At codegen time, all monomorphic projections will succeed.
68 /// Also, `impl Trait` is normalized to the concrete type,
69 /// which has to be already collected by type-checking.
71 /// NOTE: as `impl Trait`'s concrete type should *never*
72 /// be observable directly by the user, `Reveal::All`
73 /// should not be used by checks which may expose
74 /// type equality or type contents to the user.
75 /// There are some exceptions, e.g., around OIBITS and
76 /// transmute-checking, which expose some details, but
77 /// not the whole concrete type of the `impl Trait`.
81 /// The reason why we incurred this obligation; used for error reporting.
83 /// As the happy path does not care about this struct, storing this on the heap
84 /// ends up increasing performance.
86 /// We do not want to intern this as there are a lot of obligation causes which
87 /// only live for a short period of time.
88 #[derive(Clone, PartialEq, Eq, Hash, Lift)]
89 pub struct ObligationCause
<'tcx
> {
90 /// `None` for `ObligationCause::dummy`, `Some` otherwise.
91 data
: Option
<Rc
<ObligationCauseData
<'tcx
>>>,
94 const DUMMY_OBLIGATION_CAUSE_DATA
: ObligationCauseData
<'
static> =
95 ObligationCauseData { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation }
;
97 // Correctly format `ObligationCause::dummy`.
98 impl<'tcx
> fmt
::Debug
for ObligationCause
<'tcx
> {
99 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
100 ObligationCauseData
::fmt(self, f
)
104 impl Deref
for ObligationCause
<'tcx
> {
105 type Target
= ObligationCauseData
<'tcx
>;
108 fn deref(&self) -> &Self::Target
{
109 self.data
.as_deref().unwrap_or(&DUMMY_OBLIGATION_CAUSE_DATA
)
113 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
114 pub struct ObligationCauseData
<'tcx
> {
117 /// The ID of the fn body that triggered this obligation. This is
118 /// used for region obligations to determine the precise
119 /// environment in which the region obligation should be evaluated
120 /// (in particular, closures can add new assumptions). See the
121 /// field `region_obligations` of the `FulfillmentContext` for more
123 pub body_id
: hir
::HirId
,
125 pub code
: ObligationCauseCode
<'tcx
>,
128 impl<'tcx
> ObligationCause
<'tcx
> {
133 code
: ObligationCauseCode
<'tcx
>,
134 ) -> ObligationCause
<'tcx
> {
135 ObligationCause { data: Some(Rc::new(ObligationCauseData { span, body_id, code }
)) }
138 pub fn misc(span
: Span
, body_id
: hir
::HirId
) -> ObligationCause
<'tcx
> {
139 ObligationCause
::new(span
, body_id
, MiscObligation
)
142 pub fn dummy_with_span(span
: Span
) -> ObligationCause
<'tcx
> {
143 ObligationCause
::new(span
, hir
::CRATE_HIR_ID
, MiscObligation
)
147 pub fn dummy() -> ObligationCause
<'tcx
> {
148 ObligationCause { data: None }
151 pub fn make_mut(&mut self) -> &mut ObligationCauseData
<'tcx
> {
152 Rc
::make_mut(self.data
.get_or_insert_with(|| Rc
::new(DUMMY_OBLIGATION_CAUSE_DATA
)))
155 pub fn span(&self, tcx
: TyCtxt
<'tcx
>) -> Span
{
157 ObligationCauseCode
::CompareImplMethodObligation { .. }
158 | ObligationCauseCode
::MainFunctionType
159 | ObligationCauseCode
::StartFunctionType
=> {
160 tcx
.sess
.source_map().guess_head_span(self.span
)
162 ObligationCauseCode
::MatchExpressionArm(box MatchExpressionArmCause
{
171 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
172 pub struct UnifyReceiverContext
<'tcx
> {
173 pub assoc_item
: ty
::AssocItem
,
174 pub param_env
: ty
::ParamEnv
<'tcx
>,
175 pub substs
: SubstsRef
<'tcx
>,
178 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
179 pub enum ObligationCauseCode
<'tcx
> {
180 /// Not well classified or should be obvious from the span.
183 /// A slice or array is WF only if `T: Sized`.
186 /// A tuple is WF only if its middle elements are `Sized`.
189 /// This is the trait reference from the given projection.
190 ProjectionWf(ty
::ProjectionTy
<'tcx
>),
192 /// In an impl of trait `X` for type `Y`, type `Y` must
193 /// also implement all supertraits of `X`.
194 ItemObligation(DefId
),
196 /// Like `ItemObligation`, but with extra detail on the source of the obligation.
197 BindingObligation(DefId
, Span
),
199 /// A type like `&'a T` is WF only if `T: 'a`.
200 ReferenceOutlivesReferent(Ty
<'tcx
>),
202 /// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
203 ObjectTypeBound(Ty
<'tcx
>, ty
::Region
<'tcx
>),
205 /// Obligation incurred due to an object cast.
206 ObjectCastObligation(/* Object type */ Ty
<'tcx
>),
208 /// Obligation incurred due to a coercion.
214 /// Various cases where expressions must be `Sized` / `Copy` / etc.
215 /// `L = X` implies that `L` is `Sized`.
217 /// `(x1, .., xn)` must be `Sized`.
218 TupleInitializerSized
,
219 /// `S { ... }` must be `Sized`.
220 StructInitializerSized
,
221 /// Type of each variable must be `Sized`.
222 VariableType(hir
::HirId
),
223 /// Argument type must be `Sized`.
224 SizedArgumentType(Option
<Span
>),
225 /// Return type must be `Sized`.
227 /// Yield type must be `Sized`.
229 /// Inline asm operand type must be `Sized`.
231 /// `[T, ..n]` implies that `T` must be `Copy`.
232 /// If `true`, suggest `const_in_array_repeat_expressions` feature flag.
235 /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
242 /// Constant expressions must be sized.
245 /// `static` items must have `Sync` type.
248 BuiltinDerivedObligation(DerivedObligationCause
<'tcx
>),
250 ImplDerivedObligation(DerivedObligationCause
<'tcx
>),
252 DerivedObligation(DerivedObligationCause
<'tcx
>),
254 /// Error derived when matching traits/impls; see ObligationCause for more details
255 CompareImplConstObligation
,
257 /// Error derived when matching traits/impls; see ObligationCause for more details
258 CompareImplMethodObligation
{
260 impl_item_def_id
: DefId
,
261 trait_item_def_id
: DefId
,
264 /// Error derived when matching traits/impls; see ObligationCause for more details
265 CompareImplTypeObligation
{
267 impl_item_def_id
: DefId
,
268 trait_item_def_id
: DefId
,
271 /// Checking that this expression can be assigned where it needs to be
272 // FIXME(eddyb) #11161 is the original Expr required?
275 /// Computing common supertype in the arms of a match expression
276 MatchExpressionArm(Box
<MatchExpressionArmCause
<'tcx
>>),
278 /// Type error arising from type checking a pattern against an expected type.
280 /// The span of the scrutinee or type expression which caused the `root_ty` type.
282 /// The root expected type induced by a scrutinee or type expression.
284 /// Whether the `Span` came from an expression or a type expression.
288 /// Constants in patterns must have `Structural` type.
289 ConstPatternStructural
,
291 /// Computing common supertype in an if expression
292 IfExpression(Box
<IfExpressionCause
>),
294 /// Computing common supertype of an if expression with no else counter-part
295 IfExpressionWithNoElse
,
297 /// `main` has wrong type
300 /// `start` has wrong type
303 /// Intrinsic has wrong type
309 UnifyReceiver(Box
<UnifyReceiverContext
<'tcx
>>),
311 /// `return` with no expression
314 /// `return` with an expression
315 ReturnValue(hir
::HirId
),
317 /// Return type of this function
320 /// Block implicit return
321 BlockTailExpression(hir
::HirId
),
323 /// #[feature(trivial_bounds)] is not enabled
327 impl ObligationCauseCode
<'_
> {
328 // Return the base obligation, ignoring derived obligations.
329 pub fn peel_derives(&self) -> &Self {
330 let mut base_cause
= self;
331 while let BuiltinDerivedObligation(cause
)
332 | ImplDerivedObligation(cause
)
333 | DerivedObligation(cause
) = base_cause
335 base_cause
= &cause
.parent_code
;
341 // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
342 #[cfg(target_arch = "x86_64")]
343 static_assert_size
!(ObligationCauseCode
<'_
>, 32);
345 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
346 pub struct MatchExpressionArmCause
<'tcx
> {
348 pub semi_span
: Option
<Span
>,
349 pub source
: hir
::MatchSource
,
350 pub prior_arms
: Vec
<Span
>,
351 pub last_ty
: Ty
<'tcx
>,
352 pub scrut_hir_id
: hir
::HirId
,
355 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
356 pub struct IfExpressionCause
{
358 pub outer
: Option
<Span
>,
359 pub semicolon
: Option
<Span
>,
362 #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
363 pub struct DerivedObligationCause
<'tcx
> {
364 /// The trait reference of the parent obligation that led to the
365 /// current obligation. Note that only trait obligations lead to
366 /// derived obligations, so we just store the trait reference here
368 pub parent_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
370 /// The parent trait had this cause.
371 pub parent_code
: Rc
<ObligationCauseCode
<'tcx
>>,
374 #[derive(Clone, Debug, TypeFoldable, Lift)]
375 pub enum SelectionError
<'tcx
> {
377 OutputTypeParameterMismatch(
378 ty
::PolyTraitRef
<'tcx
>,
379 ty
::PolyTraitRef
<'tcx
>,
380 ty
::error
::TypeError
<'tcx
>,
382 TraitNotObjectSafe(DefId
),
383 ConstEvalFailure(ErrorHandled
),
387 /// When performing resolution, it is typically the case that there
388 /// can be one of three outcomes:
390 /// - `Ok(Some(r))`: success occurred with result `r`
391 /// - `Ok(None)`: could not definitely determine anything, usually due
392 /// to inconclusive type inference.
393 /// - `Err(e)`: error `e` occurred
394 pub type SelectionResult
<'tcx
, T
> = Result
<Option
<T
>, SelectionError
<'tcx
>>;
396 /// Given the successful resolution of an obligation, the `ImplSource`
397 /// indicates where the impl comes from.
399 /// For example, the obligation may be satisfied by a specific impl (case A),
400 /// or it may be relative to some bound that is in scope (case B).
403 /// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
404 /// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
405 /// impl Clone for i32 { ... } // Impl_3
407 /// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
408 /// // Case A: Vtable points at a specific impl. Only possible when
409 /// // type is concretely known. If the impl itself has bounded
410 /// // type parameters, Vtable will carry resolutions for those as well:
411 /// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
413 /// // Case A: ImplSource points at a specific impl. Only possible when
414 /// // type is concretely known. If the impl itself has bounded
415 /// // type parameters, ImplSource will carry resolutions for those as well:
416 /// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
418 /// // Case B: ImplSource must be provided by caller. This applies when
419 /// // type is a type parameter.
420 /// param.clone(); // ImplSourceParam
422 /// // Case C: A mix of cases A and B.
423 /// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
427 /// ### The type parameter `N`
429 /// See explanation on `ImplSourceUserDefinedData`.
430 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
431 pub enum ImplSource
<'tcx
, N
> {
432 /// ImplSource identifying a particular impl.
433 ImplSourceUserDefined(ImplSourceUserDefinedData
<'tcx
, N
>),
435 /// ImplSource for auto trait implementations.
436 /// This carries the information and nested obligations with regards
437 /// to an auto implementation for a trait `Trait`. The nested obligations
438 /// ensure the trait implementation holds for all the constituent types.
439 ImplSourceAutoImpl(ImplSourceAutoImplData
<N
>),
441 /// Successful resolution to an obligation provided by the caller
442 /// for some type parameter. The `Vec<N>` represents the
443 /// obligations incurred from normalizing the where-clause (if
445 ImplSourceParam(Vec
<N
>),
447 /// Virtual calls through an object.
448 ImplSourceObject(ImplSourceObjectData
<'tcx
, N
>),
450 /// Successful resolution for a builtin trait.
451 ImplSourceBuiltin(ImplSourceBuiltinData
<N
>),
453 /// ImplSource automatically generated for a closure. The `DefId` is the ID
454 /// of the closure expression. This is a `ImplSourceUserDefined` in spirit, but the
455 /// impl is generated by the compiler and does not appear in the source.
456 ImplSourceClosure(ImplSourceClosureData
<'tcx
, N
>),
458 /// Same as above, but for a function pointer type with the given signature.
459 ImplSourceFnPointer(ImplSourceFnPointerData
<'tcx
, N
>),
461 /// ImplSource for a builtin `DeterminantKind` trait implementation.
462 ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData
),
464 /// ImplSource automatically generated for a generator.
465 ImplSourceGenerator(ImplSourceGeneratorData
<'tcx
, N
>),
467 /// ImplSource for a trait alias.
468 ImplSourceTraitAlias(ImplSourceTraitAliasData
<'tcx
, N
>),
471 impl<'tcx
, N
> ImplSource
<'tcx
, N
> {
472 pub fn nested_obligations(self) -> Vec
<N
> {
474 ImplSourceUserDefined(i
) => i
.nested
,
475 ImplSourceParam(n
) => n
,
476 ImplSourceBuiltin(i
) => i
.nested
,
477 ImplSourceAutoImpl(d
) => d
.nested
,
478 ImplSourceClosure(c
) => c
.nested
,
479 ImplSourceGenerator(c
) => c
.nested
,
480 ImplSourceObject(d
) => d
.nested
,
481 ImplSourceFnPointer(d
) => d
.nested
,
482 ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData
) => Vec
::new(),
483 ImplSourceTraitAlias(d
) => d
.nested
,
487 pub fn borrow_nested_obligations(&self) -> &[N
] {
489 ImplSourceUserDefined(i
) => &i
.nested
[..],
490 ImplSourceParam(n
) => &n
[..],
491 ImplSourceBuiltin(i
) => &i
.nested
[..],
492 ImplSourceAutoImpl(d
) => &d
.nested
[..],
493 ImplSourceClosure(c
) => &c
.nested
[..],
494 ImplSourceGenerator(c
) => &c
.nested
[..],
495 ImplSourceObject(d
) => &d
.nested
[..],
496 ImplSourceFnPointer(d
) => &d
.nested
[..],
497 ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData
) => &[],
498 ImplSourceTraitAlias(d
) => &d
.nested
[..],
502 pub fn map
<M
, F
>(self, f
: F
) -> ImplSource
<'tcx
, M
>
507 ImplSourceUserDefined(i
) => ImplSourceUserDefined(ImplSourceUserDefinedData
{
508 impl_def_id
: i
.impl_def_id
,
510 nested
: i
.nested
.into_iter().map(f
).collect(),
512 ImplSourceParam(n
) => ImplSourceParam(n
.into_iter().map(f
).collect()),
513 ImplSourceBuiltin(i
) => ImplSourceBuiltin(ImplSourceBuiltinData
{
514 nested
: i
.nested
.into_iter().map(f
).collect(),
516 ImplSourceObject(o
) => ImplSourceObject(ImplSourceObjectData
{
517 upcast_trait_ref
: o
.upcast_trait_ref
,
518 vtable_base
: o
.vtable_base
,
519 nested
: o
.nested
.into_iter().map(f
).collect(),
521 ImplSourceAutoImpl(d
) => ImplSourceAutoImpl(ImplSourceAutoImplData
{
522 trait_def_id
: d
.trait_def_id
,
523 nested
: d
.nested
.into_iter().map(f
).collect(),
525 ImplSourceClosure(c
) => ImplSourceClosure(ImplSourceClosureData
{
526 closure_def_id
: c
.closure_def_id
,
528 nested
: c
.nested
.into_iter().map(f
).collect(),
530 ImplSourceGenerator(c
) => ImplSourceGenerator(ImplSourceGeneratorData
{
531 generator_def_id
: c
.generator_def_id
,
533 nested
: c
.nested
.into_iter().map(f
).collect(),
535 ImplSourceFnPointer(p
) => ImplSourceFnPointer(ImplSourceFnPointerData
{
537 nested
: p
.nested
.into_iter().map(f
).collect(),
539 ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData
) => {
540 ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData
)
542 ImplSourceTraitAlias(d
) => ImplSourceTraitAlias(ImplSourceTraitAliasData
{
543 alias_def_id
: d
.alias_def_id
,
545 nested
: d
.nested
.into_iter().map(f
).collect(),
551 /// Identifies a particular impl in the source, along with a set of
552 /// substitutions from the impl's type/lifetime parameters. The
553 /// `nested` vector corresponds to the nested obligations attached to
554 /// the impl's type parameters.
556 /// The type parameter `N` indicates the type used for "nested
557 /// obligations" that are required by the impl. During type-check, this
558 /// is `Obligation`, as one might expect. During codegen, however, this
559 /// is `()`, because codegen only requires a shallow resolution of an
560 /// impl, and nested obligations are satisfied later.
561 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
562 pub struct ImplSourceUserDefinedData
<'tcx
, N
> {
563 pub impl_def_id
: DefId
,
564 pub substs
: SubstsRef
<'tcx
>,
568 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
569 pub struct ImplSourceGeneratorData
<'tcx
, N
> {
570 pub generator_def_id
: DefId
,
571 pub substs
: SubstsRef
<'tcx
>,
572 /// Nested obligations. This can be non-empty if the generator
573 /// signature contains associated types.
577 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
578 pub struct ImplSourceClosureData
<'tcx
, N
> {
579 pub closure_def_id
: DefId
,
580 pub substs
: SubstsRef
<'tcx
>,
581 /// Nested obligations. This can be non-empty if the closure
582 /// signature contains associated types.
586 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
587 pub struct ImplSourceAutoImplData
<N
> {
588 pub trait_def_id
: DefId
,
592 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
593 pub struct ImplSourceBuiltinData
<N
> {
597 #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
598 pub struct ImplSourceObjectData
<'tcx
, N
> {
599 /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
600 pub upcast_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
602 /// The vtable is formed by concatenating together the method lists of
603 /// the base object trait and all supertraits; this is the start of
604 /// `upcast_trait_ref`'s methods in that vtable.
605 pub vtable_base
: usize,
610 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
611 pub struct ImplSourceFnPointerData
<'tcx
, N
> {
616 // FIXME(@lcnr): This should be refactored and merged with other builtin vtables.
617 #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
618 pub struct ImplSourceDiscriminantKindData
;
620 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
621 pub struct ImplSourceTraitAliasData
<'tcx
, N
> {
622 pub alias_def_id
: DefId
,
623 pub substs
: SubstsRef
<'tcx
>,
627 #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
628 pub enum ObjectSafetyViolation
{
629 /// `Self: Sized` declared on the trait.
630 SizedSelf(SmallVec
<[Span
; 1]>),
632 /// Supertrait reference references `Self` an in illegal location
633 /// (e.g., `trait Foo : Bar<Self>`).
634 SupertraitSelf(SmallVec
<[Span
; 1]>),
636 /// Method has something illegal.
637 Method(Symbol
, MethodViolationCode
, Span
),
639 /// Associated const.
640 AssocConst(Symbol
, Span
),
643 impl ObjectSafetyViolation
{
644 pub fn error_msg(&self) -> Cow
<'
static, str> {
646 ObjectSafetyViolation
::SizedSelf(_
) => "it requires `Self: Sized`".into(),
647 ObjectSafetyViolation
::SupertraitSelf(ref spans
) => {
648 if spans
.iter().any(|sp
| *sp
!= DUMMY_SP
) {
649 "it uses `Self` as a type parameter in this".into()
651 "it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
655 ObjectSafetyViolation
::Method(name
, MethodViolationCode
::StaticMethod(_
), _
) => {
656 format
!("associated function `{}` has no `self` parameter", name
).into()
658 ObjectSafetyViolation
::Method(
660 MethodViolationCode
::ReferencesSelfInput(_
),
662 ) => format
!("method `{}` references the `Self` type in its parameters", name
).into(),
663 ObjectSafetyViolation
::Method(name
, MethodViolationCode
::ReferencesSelfInput(_
), _
) => {
664 format
!("method `{}` references the `Self` type in this parameter", name
).into()
666 ObjectSafetyViolation
::Method(name
, MethodViolationCode
::ReferencesSelfOutput
, _
) => {
667 format
!("method `{}` references the `Self` type in its return type", name
).into()
669 ObjectSafetyViolation
::Method(
671 MethodViolationCode
::WhereClauseReferencesSelf
,
674 format
!("method `{}` references the `Self` type in its `where` clause", name
).into()
676 ObjectSafetyViolation
::Method(name
, MethodViolationCode
::Generic
, _
) => {
677 format
!("method `{}` has generic type parameters", name
).into()
679 ObjectSafetyViolation
::Method(name
, MethodViolationCode
::UndispatchableReceiver
, _
) => {
680 format
!("method `{}`'s `self` parameter cannot be dispatched on", name
).into()
682 ObjectSafetyViolation
::AssocConst(name
, DUMMY_SP
) => {
683 format
!("it contains associated `const` `{}`", name
).into()
685 ObjectSafetyViolation
::AssocConst(..) => "it contains this associated `const`".into(),
689 pub fn solution(&self) -> Option
<(String
, Option
<(String
, Span
)>)> {
691 ObjectSafetyViolation
::SizedSelf(_
) | ObjectSafetyViolation
::SupertraitSelf(_
) => {
694 ObjectSafetyViolation
::Method(name
, MethodViolationCode
::StaticMethod(sugg
), _
) => (
696 "consider turning `{}` into a method by giving it a `&self` argument or \
697 constraining it so it does not apply to trait objects",
700 sugg
.map(|(sugg
, sp
)| (sugg
.to_string(), sp
)),
702 ObjectSafetyViolation
::Method(
704 MethodViolationCode
::UndispatchableReceiver
,
707 format
!("consider changing method `{}`'s `self` parameter to be `&self`", name
),
708 Some(("&Self".to_string(), span
)),
710 ObjectSafetyViolation
::AssocConst(name
, _
)
711 | ObjectSafetyViolation
::Method(name
, ..) => {
712 (format
!("consider moving `{}` to another trait", name
), None
)
717 pub fn spans(&self) -> SmallVec
<[Span
; 1]> {
718 // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
719 // diagnostics use a `note` instead of a `span_label`.
721 ObjectSafetyViolation
::SupertraitSelf(spans
)
722 | ObjectSafetyViolation
::SizedSelf(spans
) => spans
.clone(),
723 ObjectSafetyViolation
::AssocConst(_
, span
)
724 | ObjectSafetyViolation
::Method(_
, _
, span
)
725 if *span
!= DUMMY_SP
=>
734 /// Reasons a method might not be object-safe.
735 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
736 pub enum MethodViolationCode
{
738 StaticMethod(Option
<(&'
static str, Span
)>),
740 /// e.g., `fn foo(&self, x: Self)`
741 ReferencesSelfInput(usize),
743 /// e.g., `fn foo(&self) -> Self`
744 ReferencesSelfOutput
,
746 /// e.g., `fn foo(&self) where Self: Clone`
747 WhereClauseReferencesSelf
,
749 /// e.g., `fn foo<A>()`
752 /// the method's receiver (`self` argument) can't be dispatched on
753 UndispatchableReceiver
,