]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | //! Trait Resolution. See the [rustc dev guide] for more information on how this works. |
0531ce1d | 2 | //! |
ba9703b0 | 3 | //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html |
1a4d82fc | 4 | |
f9f354fc | 5 | mod chalk; |
dfeec247 | 6 | pub mod query; |
74b04a01 XL |
7 | pub mod select; |
8 | pub mod specialization_graph; | |
0731742a | 9 | mod structural_impls; |
3c0e092e | 10 | pub mod util; |
1a4d82fc | 11 | |
f9f354fc | 12 | use crate::infer::canonical::Canonical; |
c295e0f8 | 13 | use crate::thir::abstract_const::NotConstEvaluatable; |
74b04a01 | 14 | use crate::ty::subst::SubstsRef; |
f9f354fc | 15 | use crate::ty::{self, AdtKind, Ty, TyCtxt}; |
74b04a01 | 16 | |
136023e0 | 17 | use rustc_data_structures::sync::Lrc; |
29967ef6 | 18 | use rustc_errors::{Applicability, DiagnosticBuilder}; |
dfeec247 | 19 | use rustc_hir as hir; |
136023e0 | 20 | use rustc_hir::def_id::{DefId, LocalDefId}; |
f9f354fc | 21 | use rustc_span::symbol::Symbol; |
dfeec247 | 22 | use rustc_span::{Span, DUMMY_SP}; |
74b04a01 | 23 | use smallvec::SmallVec; |
e9174d1e | 24 | |
74b04a01 | 25 | use std::borrow::Cow; |
3c0e092e | 26 | use std::hash::{Hash, Hasher}; |
1a4d82fc | 27 | |
74b04a01 | 28 | pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; |
0731742a | 29 | |
1b1a35ee | 30 | pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>; |
f9f354fc | 31 | |
dfeec247 | 32 | pub use self::ObligationCauseCode::*; |
0531ce1d | 33 | |
1b1a35ee | 34 | pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner}; |
f9f354fc | 35 | |
74b04a01 XL |
36 | /// Depending on the stage of compilation, we want projection to be |
37 | /// more or less conservative. | |
38 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)] | |
39 | pub enum Reveal { | |
40 | /// At type-checking time, we refuse to project any associated | |
41 | /// type that is marked `default`. Non-`default` ("final") types | |
42 | /// are always projected. This is necessary in general for | |
43 | /// soundness of specialization. However, we *could* allow | |
44 | /// projections in fully-monomorphic cases. We choose not to, | |
45 | /// because we prefer for `default type` to force the type | |
46 | /// definition to be treated abstractly by any consumers of the | |
47 | /// impl. Concretely, that means that the following example will | |
48 | /// fail to compile: | |
49 | /// | |
50 | /// ``` | |
51 | /// trait Assoc { | |
52 | /// type Output; | |
53 | /// } | |
54 | /// | |
55 | /// impl<T> Assoc for T { | |
56 | /// default type Output = bool; | |
57 | /// } | |
58 | /// | |
59 | /// fn main() { | |
60 | /// let <() as Assoc>::Output = true; | |
61 | /// } | |
62 | /// ``` | |
63 | UserFacing, | |
64 | ||
65 | /// At codegen time, all monomorphic projections will succeed. | |
66 | /// Also, `impl Trait` is normalized to the concrete type, | |
67 | /// which has to be already collected by type-checking. | |
68 | /// | |
69 | /// NOTE: as `impl Trait`'s concrete type should *never* | |
70 | /// be observable directly by the user, `Reveal::All` | |
71 | /// should not be used by checks which may expose | |
72 | /// type equality or type contents to the user. | |
fc512014 | 73 | /// There are some exceptions, e.g., around auto traits and |
74b04a01 XL |
74 | /// transmute-checking, which expose some details, but |
75 | /// not the whole concrete type of the `impl Trait`. | |
76 | All, | |
1a4d82fc JJ |
77 | } |
78 | ||
9fa01778 | 79 | /// The reason why we incurred this obligation; used for error reporting. |
f035d41b | 80 | /// |
a2a8927a XL |
81 | /// Non-misc `ObligationCauseCode`s are stored on the heap. This gives the |
82 | /// best trade-off between keeping the type small (which makes copies cheaper) | |
83 | /// while not doing too many heap allocations. | |
f035d41b XL |
84 | /// |
85 | /// We do not want to intern this as there are a lot of obligation causes which | |
86 | /// only live for a short period of time. | |
3c0e092e | 87 | #[derive(Clone, Debug, PartialEq, Eq, Lift)] |
a2a8927a | 88 | pub struct ObligationCause<'tcx> { |
1a4d82fc JJ |
89 | pub span: Span, |
90 | ||
9fa01778 XL |
91 | /// The ID of the fn body that triggered this obligation. This is |
92 | /// used for region obligations to determine the precise | |
93 | /// environment in which the region obligation should be evaluated | |
94 | /// (in particular, closures can add new assumptions). See the | |
95 | /// field `region_obligations` of the `FulfillmentContext` for more | |
96 | /// information. | |
97 | pub body_id: hir::HirId, | |
1a4d82fc | 98 | |
a2a8927a XL |
99 | /// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of |
100 | /// the time). `Some` otherwise. | |
101 | code: Option<Lrc<ObligationCauseCode<'tcx>>>, | |
1a4d82fc JJ |
102 | } |
103 | ||
a2a8927a XL |
104 | // This custom hash function speeds up hashing for `Obligation` deduplication |
105 | // greatly by skipping the `code` field, which can be large and complex. That | |
106 | // shouldn't affect hash quality much since there are several other fields in | |
107 | // `Obligation` which should be unique enough, especially the predicate itself | |
108 | // which is hashed as an interned pointer. See #90996. | |
109 | impl Hash for ObligationCause<'_> { | |
3c0e092e XL |
110 | fn hash<H: Hasher>(&self, state: &mut H) { |
111 | self.body_id.hash(state); | |
112 | self.span.hash(state); | |
3c0e092e XL |
113 | } |
114 | } | |
115 | ||
a2a8927a XL |
116 | const MISC_OBLIGATION_CAUSE_CODE: ObligationCauseCode<'static> = MiscObligation; |
117 | ||
74b04a01 XL |
118 | impl<'tcx> ObligationCause<'tcx> { |
119 | #[inline] | |
120 | pub fn new( | |
121 | span: Span, | |
122 | body_id: hir::HirId, | |
123 | code: ObligationCauseCode<'tcx>, | |
124 | ) -> ObligationCause<'tcx> { | |
a2a8927a XL |
125 | ObligationCause { |
126 | span, | |
127 | body_id, | |
128 | code: if code == MISC_OBLIGATION_CAUSE_CODE { None } else { Some(Lrc::new(code)) }, | |
129 | } | |
74b04a01 XL |
130 | } |
131 | ||
132 | pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> { | |
f035d41b XL |
133 | ObligationCause::new(span, body_id, MiscObligation) |
134 | } | |
135 | ||
f035d41b | 136 | #[inline(always)] |
74b04a01 | 137 | pub fn dummy() -> ObligationCause<'tcx> { |
a2a8927a XL |
138 | ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: None } |
139 | } | |
140 | ||
141 | pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> { | |
142 | ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: None } | |
f035d41b XL |
143 | } |
144 | ||
a2a8927a XL |
145 | pub fn make_mut_code(&mut self) -> &mut ObligationCauseCode<'tcx> { |
146 | Lrc::make_mut(self.code.get_or_insert_with(|| Lrc::new(MISC_OBLIGATION_CAUSE_CODE))) | |
74b04a01 XL |
147 | } |
148 | ||
149 | pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span { | |
a2a8927a | 150 | match *self.code() { |
dfeec247 XL |
151 | ObligationCauseCode::CompareImplMethodObligation { .. } |
152 | | ObligationCauseCode::MainFunctionType | |
ba9703b0 XL |
153 | | ObligationCauseCode::StartFunctionType => { |
154 | tcx.sess.source_map().guess_head_span(self.span) | |
155 | } | |
dfeec247 XL |
156 | ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { |
157 | arm_span, | |
158 | .. | |
159 | }) => arm_span, | |
2c00a5a8 XL |
160 | _ => self.span, |
161 | } | |
162 | } | |
a2a8927a XL |
163 | |
164 | #[inline] | |
165 | pub fn code(&self) -> &ObligationCauseCode<'tcx> { | |
166 | self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE) | |
167 | } | |
168 | ||
169 | pub fn clone_code(&self) -> Lrc<ObligationCauseCode<'tcx>> { | |
170 | match &self.code { | |
171 | Some(code) => code.clone(), | |
172 | None => Lrc::new(MISC_OBLIGATION_CAUSE_CODE), | |
173 | } | |
174 | } | |
2c00a5a8 XL |
175 | } |
176 | ||
3dfed10e XL |
177 | #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] |
178 | pub struct UnifyReceiverContext<'tcx> { | |
179 | pub assoc_item: ty::AssocItem, | |
180 | pub param_env: ty::ParamEnv<'tcx>, | |
181 | pub substs: SubstsRef<'tcx>, | |
182 | } | |
183 | ||
184 | #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] | |
1a4d82fc | 185 | pub enum ObligationCauseCode<'tcx> { |
9fa01778 | 186 | /// Not well classified or should be obvious from the span. |
1a4d82fc JJ |
187 | MiscObligation, |
188 | ||
9fa01778 | 189 | /// A slice or array is WF only if `T: Sized`. |
e9174d1e SL |
190 | SliceOrArrayElem, |
191 | ||
9fa01778 | 192 | /// A tuple is WF only if its middle elements are `Sized`. |
a7813a04 XL |
193 | TupleElem, |
194 | ||
9fa01778 | 195 | /// This is the trait reference from the given projection. |
e9174d1e SL |
196 | ProjectionWf(ty::ProjectionTy<'tcx>), |
197 | ||
9fa01778 XL |
198 | /// In an impl of trait `X` for type `Y`, type `Y` must |
199 | /// also implement all supertraits of `X`. | |
e9174d1e SL |
200 | ItemObligation(DefId), |
201 | ||
e1599b0c XL |
202 | /// Like `ItemObligation`, but with extra detail on the source of the obligation. |
203 | BindingObligation(DefId, Span), | |
204 | ||
e9174d1e SL |
205 | /// A type like `&'a T` is WF only if `T: 'a`. |
206 | ReferenceOutlivesReferent(Ty<'tcx>), | |
1a4d82fc | 207 | |
c30ab7b3 | 208 | /// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`. |
7cac9316 | 209 | ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>), |
c30ab7b3 | 210 | |
1a4d82fc JJ |
211 | /// Obligation incurred due to an object cast. |
212 | ObjectCastObligation(/* Object type */ Ty<'tcx>), | |
213 | ||
e74abb32 | 214 | /// Obligation incurred due to a coercion. |
dfeec247 XL |
215 | Coercion { |
216 | source: Ty<'tcx>, | |
217 | target: Ty<'tcx>, | |
218 | }, | |
e74abb32 | 219 | |
60c5eb7d XL |
220 | /// Various cases where expressions must be `Sized` / `Copy` / etc. |
221 | /// `L = X` implies that `L` is `Sized`. | |
041b39d2 | 222 | AssignmentLhsSized, |
60c5eb7d | 223 | /// `(x1, .., xn)` must be `Sized`. |
041b39d2 | 224 | TupleInitializerSized, |
60c5eb7d | 225 | /// `S { ... }` must be `Sized`. |
041b39d2 | 226 | StructInitializerSized, |
60c5eb7d | 227 | /// Type of each variable must be `Sized`. |
dc9dc135 | 228 | VariableType(hir::HirId), |
60c5eb7d | 229 | /// Argument type must be `Sized`. |
3dfed10e | 230 | SizedArgumentType(Option<Span>), |
60c5eb7d | 231 | /// Return type must be `Sized`. |
041b39d2 | 232 | SizedReturnType, |
60c5eb7d | 233 | /// Yield type must be `Sized`. |
2c00a5a8 | 234 | SizedYieldType, |
94222f64 XL |
235 | /// Box expression result type must be `Sized`. |
236 | SizedBoxType, | |
f9f354fc XL |
237 | /// Inline asm operand type must be `Sized`. |
238 | InlineAsmSized, | |
60c5eb7d | 239 | /// `[T, ..n]` implies that `T` must be `Copy`. |
6a06907d XL |
240 | /// If the function in the array repeat expression is a `const fn`, |
241 | /// display a help message suggesting to move the function call to a | |
242 | /// new `const` item while saying that `T` doesn't implement `Copy`. | |
243 | RepeatVec(bool), | |
041b39d2 | 244 | |
b7449926 | 245 | /// Types of fields (other than the last, except for packed structs) in a struct must be sized. |
dfeec247 XL |
246 | FieldSized { |
247 | adt_kind: AdtKind, | |
3dfed10e | 248 | span: Span, |
dfeec247 XL |
249 | last: bool, |
250 | }, | |
1a4d82fc | 251 | |
041b39d2 | 252 | /// Constant expressions must be sized. |
3157f602 XL |
253 | ConstSized, |
254 | ||
60c5eb7d | 255 | /// `static` items must have `Sync` type. |
1a4d82fc JJ |
256 | SharedStatic, |
257 | ||
258 | BuiltinDerivedObligation(DerivedObligationCause<'tcx>), | |
259 | ||
260 | ImplDerivedObligation(DerivedObligationCause<'tcx>), | |
85aaf69f | 261 | |
ba9703b0 XL |
262 | DerivedObligation(DerivedObligationCause<'tcx>), |
263 | ||
c295e0f8 XL |
264 | FunctionArgumentObligation { |
265 | /// The node of the relevant argument in the function call. | |
266 | arg_hir_id: hir::HirId, | |
267 | /// The node of the function call. | |
268 | call_hir_id: hir::HirId, | |
269 | /// The obligation introduced by this argument. | |
270 | parent_code: Lrc<ObligationCauseCode<'tcx>>, | |
271 | }, | |
272 | ||
f9f354fc XL |
273 | /// Error derived when matching traits/impls; see ObligationCause for more details |
274 | CompareImplConstObligation, | |
275 | ||
e74abb32 | 276 | /// Error derived when matching traits/impls; see ObligationCause for more details |
c30ab7b3 | 277 | CompareImplMethodObligation { |
c30ab7b3 SL |
278 | impl_item_def_id: DefId, |
279 | trait_item_def_id: DefId, | |
c30ab7b3 | 280 | }, |
476ff2be | 281 | |
dfeec247 XL |
282 | /// Error derived when matching traits/impls; see ObligationCause for more details |
283 | CompareImplTypeObligation { | |
dfeec247 XL |
284 | impl_item_def_id: DefId, |
285 | trait_item_def_id: DefId, | |
286 | }, | |
287 | ||
041b39d2 | 288 | /// Checking that this expression can be assigned where it needs to be |
476ff2be SL |
289 | // FIXME(eddyb) #11161 is the original Expr required? |
290 | ExprAssignable, | |
291 | ||
041b39d2 | 292 | /// Computing common supertype in the arms of a match expression |
e1599b0c | 293 | MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>), |
0731742a | 294 | |
dfeec247 XL |
295 | /// Type error arising from type checking a pattern against an expected type. |
296 | Pattern { | |
297 | /// The span of the scrutinee or type expression which caused the `root_ty` type. | |
298 | span: Option<Span>, | |
299 | /// The root expected type induced by a scrutinee or type expression. | |
300 | root_ty: Ty<'tcx>, | |
301 | /// Whether the `Span` came from an expression or a type expression. | |
302 | origin_expr: bool, | |
303 | }, | |
476ff2be | 304 | |
e74abb32 XL |
305 | /// Constants in patterns must have `Structural` type. |
306 | ConstPatternStructural, | |
307 | ||
041b39d2 | 308 | /// Computing common supertype in an if expression |
e1599b0c | 309 | IfExpression(Box<IfExpressionCause>), |
476ff2be | 310 | |
041b39d2 | 311 | /// Computing common supertype of an if expression with no else counter-part |
476ff2be SL |
312 | IfExpressionWithNoElse, |
313 | ||
041b39d2 | 314 | /// `main` has wrong type |
476ff2be SL |
315 | MainFunctionType, |
316 | ||
041b39d2 | 317 | /// `start` has wrong type |
476ff2be SL |
318 | StartFunctionType, |
319 | ||
e74abb32 | 320 | /// Intrinsic has wrong type |
476ff2be SL |
321 | IntrinsicType, |
322 | ||
94222f64 XL |
323 | /// A let else block does not diverge |
324 | LetElse, | |
325 | ||
e74abb32 | 326 | /// Method receiver |
476ff2be | 327 | MethodReceiver, |
cc61c64b | 328 | |
3dfed10e XL |
329 | UnifyReceiver(Box<UnifyReceiverContext<'tcx>>), |
330 | ||
041b39d2 | 331 | /// `return` with no expression |
cc61c64b | 332 | ReturnNoExpression, |
041b39d2 XL |
333 | |
334 | /// `return` with an expression | |
e74abb32 XL |
335 | ReturnValue(hir::HirId), |
336 | ||
337 | /// Return type of this function | |
338 | ReturnType, | |
041b39d2 XL |
339 | |
340 | /// Block implicit return | |
532ac7d7 | 341 | BlockTailExpression(hir::HirId), |
94b46f34 XL |
342 | |
343 | /// #[feature(trivial_bounds)] is not enabled | |
344 | TrivialBound, | |
cdc7bbd5 XL |
345 | |
346 | /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` | |
347 | OpaqueType, | |
136023e0 | 348 | |
a2a8927a XL |
349 | AwaitableExpr(Option<hir::HirId>), |
350 | ||
351 | ForLoopIterator, | |
352 | ||
353 | QuestionMark, | |
354 | ||
136023e0 XL |
355 | /// Well-formed checking. If a `WellFormedLoc` is provided, |
356 | /// then it will be used to eprform HIR-based wf checking | |
357 | /// after an error occurs, in order to generate a more precise error span. | |
358 | /// This is purely for diagnostic purposes - it is always | |
359 | /// correct to use `MiscObligation` instead, or to specify | |
360 | /// `WellFormed(None)` | |
361 | WellFormed(Option<WellFormedLoc>), | |
362 | ||
363 | /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against. | |
c295e0f8 | 364 | MatchImpl(ObligationCause<'tcx>, DefId), |
136023e0 XL |
365 | } |
366 | ||
367 | /// The 'location' at which we try to perform HIR-based wf checking. | |
368 | /// This information is used to obtain an `hir::Ty`, which | |
369 | /// we can walk in order to obtain precise spans for any | |
370 | /// 'nested' types (e.g. `Foo` in `Option<Foo>`). | |
371 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] | |
372 | pub enum WellFormedLoc { | |
373 | /// Use the type of the provided definition. | |
374 | Ty(LocalDefId), | |
375 | /// Use the type of the parameter of the provided function. | |
376 | /// We cannot use `hir::Param`, since the function may | |
377 | /// not have a body (e.g. a trait method definition) | |
378 | Param { | |
379 | /// The function to lookup the parameter in | |
380 | function: LocalDefId, | |
381 | /// The index of the parameter to use. | |
382 | /// Parameters are indexed from 0, with the return type | |
383 | /// being the last 'parameter' | |
384 | param_idx: u16, | |
385 | }, | |
60c5eb7d XL |
386 | } |
387 | ||
74b04a01 XL |
388 | impl ObligationCauseCode<'_> { |
389 | // Return the base obligation, ignoring derived obligations. | |
390 | pub fn peel_derives(&self) -> &Self { | |
391 | let mut base_cause = self; | |
c295e0f8 XL |
392 | while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. }) |
393 | | ImplDerivedObligation(DerivedObligationCause { parent_code, .. }) | |
394 | | DerivedObligation(DerivedObligationCause { parent_code, .. }) | |
395 | | FunctionArgumentObligation { parent_code, .. } = base_cause | |
ba9703b0 | 396 | { |
c295e0f8 | 397 | base_cause = &parent_code; |
74b04a01 XL |
398 | } |
399 | base_cause | |
400 | } | |
401 | } | |
402 | ||
e1599b0c | 403 | // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. |
6a06907d | 404 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] |
cdc7bbd5 | 405 | static_assert_size!(ObligationCauseCode<'_>, 40); |
e1599b0c | 406 | |
29967ef6 XL |
407 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] |
408 | pub enum StatementAsExpression { | |
409 | CorrectType, | |
410 | NeedsBoxing, | |
411 | } | |
412 | ||
413 | impl<'tcx> ty::Lift<'tcx> for StatementAsExpression { | |
414 | type Lifted = StatementAsExpression; | |
415 | fn lift_to_tcx(self, _tcx: TyCtxt<'tcx>) -> Option<StatementAsExpression> { | |
416 | Some(self) | |
417 | } | |
418 | } | |
419 | ||
3dfed10e | 420 | #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] |
e1599b0c XL |
421 | pub struct MatchExpressionArmCause<'tcx> { |
422 | pub arm_span: Span, | |
29967ef6 XL |
423 | pub scrut_span: Span, |
424 | pub semi_span: Option<(Span, StatementAsExpression)>, | |
e1599b0c XL |
425 | pub source: hir::MatchSource, |
426 | pub prior_arms: Vec<Span>, | |
427 | pub last_ty: Ty<'tcx>, | |
dfeec247 | 428 | pub scrut_hir_id: hir::HirId, |
1b1a35ee | 429 | pub opt_suggest_box_span: Option<Span>, |
e1599b0c XL |
430 | } |
431 | ||
432 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | |
433 | pub struct IfExpressionCause { | |
434 | pub then: Span, | |
1b1a35ee | 435 | pub else_sp: Span, |
e1599b0c | 436 | pub outer: Option<Span>, |
29967ef6 | 437 | pub semicolon: Option<(Span, StatementAsExpression)>, |
1b1a35ee | 438 | pub opt_suggest_box_span: Option<Span>, |
e1599b0c XL |
439 | } |
440 | ||
3dfed10e | 441 | #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] |
1a4d82fc JJ |
442 | pub struct DerivedObligationCause<'tcx> { |
443 | /// The trait reference of the parent obligation that led to the | |
444 | /// current obligation. Note that only trait obligations lead to | |
445 | /// derived obligations, so we just store the trait reference here | |
446 | /// directly. | |
74b04a01 | 447 | pub parent_trait_ref: ty::PolyTraitRef<'tcx>, |
1a4d82fc | 448 | |
9fa01778 | 449 | /// The parent trait had this cause. |
136023e0 | 450 | pub parent_code: Lrc<ObligationCauseCode<'tcx>>, |
1a4d82fc JJ |
451 | } |
452 | ||
3dfed10e | 453 | #[derive(Clone, Debug, TypeFoldable, Lift)] |
1a4d82fc | 454 | pub enum SelectionError<'tcx> { |
3c0e092e | 455 | /// The trait is not implemented. |
1a4d82fc | 456 | Unimplemented, |
3c0e092e XL |
457 | /// After a closure impl has selected, its "outputs" were evaluated |
458 | /// (which for closures includes the "input" type params) and they | |
459 | /// didn't resolve. See `confirm_poly_trait_refs` for more. | |
dfeec247 XL |
460 | OutputTypeParameterMismatch( |
461 | ty::PolyTraitRef<'tcx>, | |
462 | ty::PolyTraitRef<'tcx>, | |
463 | ty::error::TypeError<'tcx>, | |
464 | ), | |
3c0e092e | 465 | /// The trait pointed by `DefId` is not object safe. |
e9174d1e | 466 | TraitNotObjectSafe(DefId), |
3c0e092e | 467 | /// A given constant couldn't be evaluated. |
cdc7bbd5 | 468 | NotConstEvaluatable(NotConstEvaluatable), |
3c0e092e | 469 | /// Exceeded the recursion depth during type projection. |
83c7162d | 470 | Overflow, |
3c0e092e XL |
471 | /// Signaling that an error has already been emitted, to avoid |
472 | /// multiple errors being shown. | |
c295e0f8 | 473 | ErrorReporting, |
3c0e092e XL |
474 | /// Multiple applicable `impl`s where found. The `DefId`s correspond to |
475 | /// all the `impl`s' Items. | |
476 | Ambiguous(Vec<DefId>), | |
1a4d82fc JJ |
477 | } |
478 | ||
1a4d82fc JJ |
479 | /// When performing resolution, it is typically the case that there |
480 | /// can be one of three outcomes: | |
481 | /// | |
482 | /// - `Ok(Some(r))`: success occurred with result `r` | |
483 | /// - `Ok(None)`: could not definitely determine anything, usually due | |
484 | /// to inconclusive type inference. | |
485 | /// - `Err(e)`: error `e` occurred | |
486 | pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>; | |
487 | ||
f035d41b XL |
488 | /// Given the successful resolution of an obligation, the `ImplSource` |
489 | /// indicates where the impl comes from. | |
1a4d82fc | 490 | /// |
f035d41b | 491 | /// For example, the obligation may be satisfied by a specific impl (case A), |
1a4d82fc JJ |
492 | /// or it may be relative to some bound that is in scope (case B). |
493 | /// | |
1a4d82fc JJ |
494 | /// ``` |
495 | /// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1 | |
496 | /// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2 | |
f035d41b | 497 | /// impl Clone for i32 { ... } // Impl_3 |
1a4d82fc | 498 | /// |
f035d41b | 499 | /// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) { |
136023e0 | 500 | /// // Case A: ImplSource points at a specific impl. Only possible when |
f035d41b | 501 | /// // type is concretely known. If the impl itself has bounded |
136023e0 XL |
502 | /// // type parameters, ImplSource will carry resolutions for those as well: |
503 | /// concrete.clone(); // ImpleSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])]) | |
1a4d82fc | 504 | /// |
f035d41b XL |
505 | /// // Case A: ImplSource points at a specific impl. Only possible when |
506 | /// // type is concretely known. If the impl itself has bounded | |
507 | /// // type parameters, ImplSource will carry resolutions for those as well: | |
508 | /// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])]) | |
1a4d82fc | 509 | /// |
f035d41b XL |
510 | /// // Case B: ImplSource must be provided by caller. This applies when |
511 | /// // type is a type parameter. | |
1b1a35ee | 512 | /// param.clone(); // ImplSource::Param |
1a4d82fc | 513 | /// |
f035d41b | 514 | /// // Case C: A mix of cases A and B. |
1b1a35ee | 515 | /// mixed.clone(); // ImplSource(Impl_1, [ImplSource::Param]) |
1a4d82fc JJ |
516 | /// } |
517 | /// ``` | |
518 | /// | |
519 | /// ### The type parameter `N` | |
520 | /// | |
f035d41b | 521 | /// See explanation on `ImplSourceUserDefinedData`. |
3dfed10e | 522 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b XL |
523 | pub enum ImplSource<'tcx, N> { |
524 | /// ImplSource identifying a particular impl. | |
1b1a35ee | 525 | UserDefined(ImplSourceUserDefinedData<'tcx, N>), |
1a4d82fc | 526 | |
f035d41b | 527 | /// ImplSource for auto trait implementations. |
c34b1796 | 528 | /// This carries the information and nested obligations with regards |
abe05a73 | 529 | /// to an auto implementation for a trait `Trait`. The nested obligations |
c34b1796 | 530 | /// ensure the trait implementation holds for all the constituent types. |
1b1a35ee | 531 | AutoImpl(ImplSourceAutoImplData<N>), |
c34b1796 | 532 | |
1a4d82fc | 533 | /// Successful resolution to an obligation provided by the caller |
85aaf69f SL |
534 | /// for some type parameter. The `Vec<N>` represents the |
535 | /// obligations incurred from normalizing the where-clause (if | |
536 | /// any). | |
94222f64 | 537 | Param(Vec<N>, ty::BoundConstness), |
1a4d82fc | 538 | |
9fa01778 | 539 | /// Virtual calls through an object. |
1b1a35ee | 540 | Object(ImplSourceObjectData<'tcx, N>), |
1a4d82fc JJ |
541 | |
542 | /// Successful resolution for a builtin trait. | |
1b1a35ee | 543 | Builtin(ImplSourceBuiltinData<N>), |
1a4d82fc | 544 | |
94222f64 XL |
545 | /// ImplSource for trait upcasting coercion |
546 | TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, N>), | |
547 | ||
f035d41b | 548 | /// ImplSource automatically generated for a closure. The `DefId` is the ID |
94222f64 | 549 | /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the |
85aaf69f | 550 | /// impl is generated by the compiler and does not appear in the source. |
1b1a35ee | 551 | Closure(ImplSourceClosureData<'tcx, N>), |
1a4d82fc | 552 | |
9fa01778 | 553 | /// Same as above, but for a function pointer type with the given signature. |
1b1a35ee | 554 | FnPointer(ImplSourceFnPointerData<'tcx, N>), |
ea8adc8c | 555 | |
f035d41b | 556 | /// ImplSource for a builtin `DeterminantKind` trait implementation. |
1b1a35ee | 557 | DiscriminantKind(ImplSourceDiscriminantKindData), |
f9f354fc | 558 | |
6a06907d XL |
559 | /// ImplSource for a builtin `Pointee` trait implementation. |
560 | Pointee(ImplSourcePointeeData), | |
561 | ||
f035d41b | 562 | /// ImplSource automatically generated for a generator. |
1b1a35ee | 563 | Generator(ImplSourceGeneratorData<'tcx, N>), |
a1dfa0c6 | 564 | |
f035d41b | 565 | /// ImplSource for a trait alias. |
1b1a35ee | 566 | TraitAlias(ImplSourceTraitAliasData<'tcx, N>), |
c295e0f8 XL |
567 | |
568 | /// ImplSource for a `const Drop` implementation. | |
569 | ConstDrop(ImplSourceConstDropData), | |
1a4d82fc JJ |
570 | } |
571 | ||
f035d41b | 572 | impl<'tcx, N> ImplSource<'tcx, N> { |
74b04a01 XL |
573 | pub fn nested_obligations(self) -> Vec<N> { |
574 | match self { | |
1b1a35ee | 575 | ImplSource::UserDefined(i) => i.nested, |
fc512014 | 576 | ImplSource::Param(n, _) => n, |
1b1a35ee XL |
577 | ImplSource::Builtin(i) => i.nested, |
578 | ImplSource::AutoImpl(d) => d.nested, | |
579 | ImplSource::Closure(c) => c.nested, | |
580 | ImplSource::Generator(c) => c.nested, | |
581 | ImplSource::Object(d) => d.nested, | |
582 | ImplSource::FnPointer(d) => d.nested, | |
6a06907d | 583 | ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) |
c295e0f8 XL |
584 | | ImplSource::Pointee(ImplSourcePointeeData) |
585 | | ImplSource::ConstDrop(ImplSourceConstDropData) => Vec::new(), | |
1b1a35ee | 586 | ImplSource::TraitAlias(d) => d.nested, |
94222f64 | 587 | ImplSource::TraitUpcasting(d) => d.nested, |
74b04a01 XL |
588 | } |
589 | } | |
590 | ||
591 | pub fn borrow_nested_obligations(&self) -> &[N] { | |
592 | match &self { | |
1b1a35ee | 593 | ImplSource::UserDefined(i) => &i.nested[..], |
a2a8927a XL |
594 | ImplSource::Param(n, _) => &n, |
595 | ImplSource::Builtin(i) => &i.nested, | |
596 | ImplSource::AutoImpl(d) => &d.nested, | |
597 | ImplSource::Closure(c) => &c.nested, | |
598 | ImplSource::Generator(c) => &c.nested, | |
599 | ImplSource::Object(d) => &d.nested, | |
600 | ImplSource::FnPointer(d) => &d.nested, | |
6a06907d | 601 | ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) |
c295e0f8 XL |
602 | | ImplSource::Pointee(ImplSourcePointeeData) |
603 | | ImplSource::ConstDrop(ImplSourceConstDropData) => &[], | |
a2a8927a XL |
604 | ImplSource::TraitAlias(d) => &d.nested, |
605 | ImplSource::TraitUpcasting(d) => &d.nested, | |
74b04a01 XL |
606 | } |
607 | } | |
608 | ||
f035d41b | 609 | pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M> |
74b04a01 XL |
610 | where |
611 | F: FnMut(N) -> M, | |
612 | { | |
613 | match self { | |
1b1a35ee | 614 | ImplSource::UserDefined(i) => ImplSource::UserDefined(ImplSourceUserDefinedData { |
74b04a01 XL |
615 | impl_def_id: i.impl_def_id, |
616 | substs: i.substs, | |
617 | nested: i.nested.into_iter().map(f).collect(), | |
618 | }), | |
fc512014 | 619 | ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), |
1b1a35ee | 620 | ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData { |
f035d41b XL |
621 | nested: i.nested.into_iter().map(f).collect(), |
622 | }), | |
1b1a35ee | 623 | ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { |
74b04a01 XL |
624 | upcast_trait_ref: o.upcast_trait_ref, |
625 | vtable_base: o.vtable_base, | |
626 | nested: o.nested.into_iter().map(f).collect(), | |
627 | }), | |
1b1a35ee | 628 | ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData { |
74b04a01 XL |
629 | trait_def_id: d.trait_def_id, |
630 | nested: d.nested.into_iter().map(f).collect(), | |
631 | }), | |
1b1a35ee | 632 | ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData { |
74b04a01 XL |
633 | closure_def_id: c.closure_def_id, |
634 | substs: c.substs, | |
635 | nested: c.nested.into_iter().map(f).collect(), | |
636 | }), | |
1b1a35ee | 637 | ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData { |
74b04a01 XL |
638 | generator_def_id: c.generator_def_id, |
639 | substs: c.substs, | |
640 | nested: c.nested.into_iter().map(f).collect(), | |
641 | }), | |
1b1a35ee | 642 | ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData { |
74b04a01 XL |
643 | fn_ty: p.fn_ty, |
644 | nested: p.nested.into_iter().map(f).collect(), | |
645 | }), | |
1b1a35ee XL |
646 | ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => { |
647 | ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) | |
f9f354fc | 648 | } |
6a06907d XL |
649 | ImplSource::Pointee(ImplSourcePointeeData) => { |
650 | ImplSource::Pointee(ImplSourcePointeeData) | |
651 | } | |
1b1a35ee | 652 | ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData { |
74b04a01 XL |
653 | alias_def_id: d.alias_def_id, |
654 | substs: d.substs, | |
655 | nested: d.nested.into_iter().map(f).collect(), | |
656 | }), | |
94222f64 XL |
657 | ImplSource::TraitUpcasting(d) => { |
658 | ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { | |
659 | upcast_trait_ref: d.upcast_trait_ref, | |
660 | vtable_vptr_slot: d.vtable_vptr_slot, | |
661 | nested: d.nested.into_iter().map(f).collect(), | |
662 | }) | |
663 | } | |
c295e0f8 XL |
664 | ImplSource::ConstDrop(ImplSourceConstDropData) => { |
665 | ImplSource::ConstDrop(ImplSourceConstDropData) | |
666 | } | |
74b04a01 XL |
667 | } |
668 | } | |
669 | } | |
670 | ||
1a4d82fc JJ |
671 | /// Identifies a particular impl in the source, along with a set of |
672 | /// substitutions from the impl's type/lifetime parameters. The | |
673 | /// `nested` vector corresponds to the nested obligations attached to | |
674 | /// the impl's type parameters. | |
675 | /// | |
676 | /// The type parameter `N` indicates the type used for "nested | |
60c5eb7d | 677 | /// obligations" that are required by the impl. During type-check, this |
94b46f34 XL |
678 | /// is `Obligation`, as one might expect. During codegen, however, this |
679 | /// is `()`, because codegen only requires a shallow resolution of an | |
1a4d82fc | 680 | /// impl, and nested obligations are satisfied later. |
3dfed10e | 681 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 682 | pub struct ImplSourceUserDefinedData<'tcx, N> { |
e9174d1e | 683 | pub impl_def_id: DefId, |
532ac7d7 | 684 | pub substs: SubstsRef<'tcx>, |
dfeec247 | 685 | pub nested: Vec<N>, |
62682a34 SL |
686 | } |
687 | ||
3dfed10e | 688 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 689 | pub struct ImplSourceGeneratorData<'tcx, N> { |
94b46f34 | 690 | pub generator_def_id: DefId, |
e74abb32 | 691 | pub substs: SubstsRef<'tcx>, |
ea8adc8c XL |
692 | /// Nested obligations. This can be non-empty if the generator |
693 | /// signature contains associated types. | |
dfeec247 | 694 | pub nested: Vec<N>, |
ea8adc8c XL |
695 | } |
696 | ||
3dfed10e | 697 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 698 | pub struct ImplSourceClosureData<'tcx, N> { |
e9174d1e | 699 | pub closure_def_id: DefId, |
e74abb32 | 700 | pub substs: SubstsRef<'tcx>, |
62682a34 SL |
701 | /// Nested obligations. This can be non-empty if the closure |
702 | /// signature contains associated types. | |
dfeec247 | 703 | pub nested: Vec<N>, |
1a4d82fc JJ |
704 | } |
705 | ||
3dfed10e | 706 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 707 | pub struct ImplSourceAutoImplData<N> { |
e9174d1e | 708 | pub trait_def_id: DefId, |
dfeec247 | 709 | pub nested: Vec<N>, |
c34b1796 AL |
710 | } |
711 | ||
94222f64 XL |
712 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
713 | pub struct ImplSourceTraitUpcastingData<'tcx, N> { | |
714 | /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. | |
715 | pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, | |
716 | ||
717 | /// The vtable is formed by concatenating together the method lists of | |
718 | /// the base object trait and all supertraits, pointers to supertrait vtable will | |
719 | /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable | |
720 | /// within that vtable. | |
721 | pub vtable_vptr_slot: Option<usize>, | |
722 | ||
723 | pub nested: Vec<N>, | |
724 | } | |
725 | ||
3dfed10e | 726 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 727 | pub struct ImplSourceBuiltinData<N> { |
dfeec247 | 728 | pub nested: Vec<N>, |
1a4d82fc JJ |
729 | } |
730 | ||
3dfed10e | 731 | #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 732 | pub struct ImplSourceObjectData<'tcx, N> { |
c34b1796 AL |
733 | /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. |
734 | pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, | |
c1a9b12d SL |
735 | |
736 | /// The vtable is formed by concatenating together the method lists of | |
94222f64 XL |
737 | /// the base object trait and all supertraits, pointers to supertrait vtable will |
738 | /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods | |
739 | /// in that vtable. | |
a7813a04 XL |
740 | pub vtable_base: usize, |
741 | ||
742 | pub nested: Vec<N>, | |
743 | } | |
744 | ||
3dfed10e | 745 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 746 | pub struct ImplSourceFnPointerData<'tcx, N> { |
ea8adc8c | 747 | pub fn_ty: Ty<'tcx>, |
dfeec247 | 748 | pub nested: Vec<N>, |
1a4d82fc JJ |
749 | } |
750 | ||
f9f354fc | 751 | // FIXME(@lcnr): This should be refactored and merged with other builtin vtables. |
3dfed10e | 752 | #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] |
f035d41b | 753 | pub struct ImplSourceDiscriminantKindData; |
f9f354fc | 754 | |
6a06907d XL |
755 | #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] |
756 | pub struct ImplSourcePointeeData; | |
757 | ||
c295e0f8 XL |
758 | #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] |
759 | pub struct ImplSourceConstDropData; | |
760 | ||
3dfed10e | 761 | #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] |
f035d41b | 762 | pub struct ImplSourceTraitAliasData<'tcx, N> { |
a1dfa0c6 | 763 | pub alias_def_id: DefId, |
532ac7d7 | 764 | pub substs: SubstsRef<'tcx>, |
a1dfa0c6 XL |
765 | pub nested: Vec<N>, |
766 | } | |
767 | ||
c295e0f8 | 768 | #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] |
74b04a01 XL |
769 | pub enum ObjectSafetyViolation { |
770 | /// `Self: Sized` declared on the trait. | |
771 | SizedSelf(SmallVec<[Span; 1]>), | |
1a4d82fc | 772 | |
74b04a01 XL |
773 | /// Supertrait reference references `Self` an in illegal location |
774 | /// (e.g., `trait Foo : Bar<Self>`). | |
775 | SupertraitSelf(SmallVec<[Span; 1]>), | |
776 | ||
777 | /// Method has something illegal. | |
f9f354fc | 778 | Method(Symbol, MethodViolationCode, Span), |
74b04a01 XL |
779 | |
780 | /// Associated const. | |
f9f354fc | 781 | AssocConst(Symbol, Span), |
cdc7bbd5 XL |
782 | |
783 | /// GAT | |
784 | GAT(Symbol, Span), | |
1a4d82fc JJ |
785 | } |
786 | ||
74b04a01 XL |
787 | impl ObjectSafetyViolation { |
788 | pub fn error_msg(&self) -> Cow<'static, str> { | |
789 | match *self { | |
790 | ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(), | |
791 | ObjectSafetyViolation::SupertraitSelf(ref spans) => { | |
792 | if spans.iter().any(|sp| *sp != DUMMY_SP) { | |
29967ef6 | 793 | "it uses `Self` as a type parameter".into() |
74b04a01 XL |
794 | } else { |
795 | "it cannot use `Self` as a type parameter in a supertrait or `where`-clause" | |
796 | .into() | |
dfeec247 | 797 | } |
a7813a04 | 798 | } |
29967ef6 | 799 | ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_, _, _), _) => { |
74b04a01 XL |
800 | format!("associated function `{}` has no `self` parameter", name).into() |
801 | } | |
802 | ObjectSafetyViolation::Method( | |
803 | name, | |
804 | MethodViolationCode::ReferencesSelfInput(_), | |
805 | DUMMY_SP, | |
806 | ) => format!("method `{}` references the `Self` type in its parameters", name).into(), | |
807 | ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => { | |
808 | format!("method `{}` references the `Self` type in this parameter", name).into() | |
809 | } | |
810 | ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => { | |
811 | format!("method `{}` references the `Self` type in its return type", name).into() | |
812 | } | |
813 | ObjectSafetyViolation::Method( | |
814 | name, | |
815 | MethodViolationCode::WhereClauseReferencesSelf, | |
816 | _, | |
817 | ) => { | |
818 | format!("method `{}` references the `Self` type in its `where` clause", name).into() | |
819 | } | |
820 | ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => { | |
821 | format!("method `{}` has generic type parameters", name).into() | |
822 | } | |
823 | ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => { | |
824 | format!("method `{}`'s `self` parameter cannot be dispatched on", name).into() | |
825 | } | |
826 | ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => { | |
827 | format!("it contains associated `const` `{}`", name).into() | |
828 | } | |
829 | ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), | |
cdc7bbd5 XL |
830 | ObjectSafetyViolation::GAT(name, _) => { |
831 | format!("it contains the generic associated type `{}`", name).into() | |
832 | } | |
dfeec247 | 833 | } |
85aaf69f | 834 | } |
c1a9b12d | 835 | |
29967ef6 XL |
836 | pub fn solution(&self, err: &mut DiagnosticBuilder<'_>) { |
837 | match *self { | |
838 | ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {} | |
839 | ObjectSafetyViolation::Method( | |
840 | name, | |
841 | MethodViolationCode::StaticMethod(sugg, self_span, has_args), | |
842 | _, | |
843 | ) => { | |
844 | err.span_suggestion( | |
845 | self_span, | |
846 | &format!( | |
847 | "consider turning `{}` into a method by giving it a `&self` argument", | |
848 | name | |
849 | ), | |
850 | format!("&self{}", if has_args { ", " } else { "" }), | |
851 | Applicability::MaybeIncorrect, | |
852 | ); | |
853 | match sugg { | |
854 | Some((sugg, span)) => { | |
855 | err.span_suggestion( | |
856 | span, | |
857 | &format!( | |
858 | "alternatively, consider constraining `{}` so it does not apply to \ | |
859 | trait objects", | |
860 | name | |
861 | ), | |
862 | sugg.to_string(), | |
863 | Applicability::MaybeIncorrect, | |
864 | ); | |
865 | } | |
866 | None => { | |
867 | err.help(&format!( | |
868 | "consider turning `{}` into a method by giving it a `&self` \ | |
869 | argument or constraining it so it does not apply to trait objects", | |
870 | name | |
871 | )); | |
872 | } | |
873 | } | |
dfeec247 | 874 | } |
74b04a01 XL |
875 | ObjectSafetyViolation::Method( |
876 | name, | |
877 | MethodViolationCode::UndispatchableReceiver, | |
878 | span, | |
29967ef6 XL |
879 | ) => { |
880 | err.span_suggestion( | |
881 | span, | |
882 | &format!( | |
883 | "consider changing method `{}`'s `self` parameter to be `&self`", | |
884 | name | |
885 | ), | |
886 | "&Self".to_string(), | |
887 | Applicability::MachineApplicable, | |
888 | ); | |
889 | } | |
74b04a01 | 890 | ObjectSafetyViolation::AssocConst(name, _) |
cdc7bbd5 | 891 | | ObjectSafetyViolation::GAT(name, _) |
74b04a01 | 892 | | ObjectSafetyViolation::Method(name, ..) => { |
29967ef6 | 893 | err.help(&format!("consider moving `{}` to another trait", name)); |
dfeec247 | 894 | } |
29967ef6 | 895 | } |
a7813a04 XL |
896 | } |
897 | ||
74b04a01 XL |
898 | pub fn spans(&self) -> SmallVec<[Span; 1]> { |
899 | // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so | |
900 | // diagnostics use a `note` instead of a `span_label`. | |
62682a34 | 901 | match self { |
74b04a01 XL |
902 | ObjectSafetyViolation::SupertraitSelf(spans) |
903 | | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(), | |
904 | ObjectSafetyViolation::AssocConst(_, span) | |
cdc7bbd5 | 905 | | ObjectSafetyViolation::GAT(_, span) |
74b04a01 XL |
906 | | ObjectSafetyViolation::Method(_, _, span) |
907 | if *span != DUMMY_SP => | |
908 | { | |
909 | smallvec![*span] | |
dfeec247 | 910 | } |
74b04a01 | 911 | _ => smallvec![], |
1a4d82fc JJ |
912 | } |
913 | } | |
914 | } | |
915 | ||
74b04a01 | 916 | /// Reasons a method might not be object-safe. |
c295e0f8 | 917 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] |
74b04a01 XL |
918 | pub enum MethodViolationCode { |
919 | /// e.g., `fn foo()` | |
29967ef6 | 920 | StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */), |
94b46f34 | 921 | |
74b04a01 XL |
922 | /// e.g., `fn foo(&self, x: Self)` |
923 | ReferencesSelfInput(usize), | |
94b46f34 | 924 | |
74b04a01 XL |
925 | /// e.g., `fn foo(&self) -> Self` |
926 | ReferencesSelfOutput, | |
94b46f34 | 927 | |
74b04a01 XL |
928 | /// e.g., `fn foo(&self) where Self: Clone` |
929 | WhereClauseReferencesSelf, | |
0731742a | 930 | |
74b04a01 XL |
931 | /// e.g., `fn foo<A>()` |
932 | Generic, | |
0731742a | 933 | |
74b04a01 XL |
934 | /// the method's receiver (`self` argument) can't be dispatched on |
935 | UndispatchableReceiver, | |
94b46f34 | 936 | } |