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