]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/traits/mod.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / compiler / rustc_middle / src / traits / mod.rs
CommitLineData
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 5mod chalk;
dfeec247 6pub mod query;
74b04a01
XL
7pub mod select;
8pub mod specialization_graph;
0731742a 9mod structural_impls;
3c0e092e 10pub mod util;
1a4d82fc 11
f9f354fc 12use crate::infer::canonical::Canonical;
c295e0f8 13use crate::thir::abstract_const::NotConstEvaluatable;
74b04a01 14use crate::ty::subst::SubstsRef;
f9f354fc 15use crate::ty::{self, AdtKind, Ty, TyCtxt};
74b04a01 16
136023e0 17use rustc_data_structures::sync::Lrc;
29967ef6 18use rustc_errors::{Applicability, DiagnosticBuilder};
dfeec247 19use rustc_hir as hir;
136023e0 20use rustc_hir::def_id::{DefId, LocalDefId};
f9f354fc 21use rustc_span::symbol::Symbol;
dfeec247 22use rustc_span::{Span, DUMMY_SP};
74b04a01 23use smallvec::SmallVec;
e9174d1e 24
74b04a01 25use std::borrow::Cow;
f035d41b 26use std::fmt;
3c0e092e 27use std::hash::{Hash, Hasher};
f035d41b 28use std::ops::Deref;
1a4d82fc 29
74b04a01 30pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
0731742a 31
1b1a35ee 32pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;
f9f354fc 33
dfeec247 34pub use self::ObligationCauseCode::*;
0531ce1d 35
1b1a35ee 36pub 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)]
41pub 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 89pub struct ObligationCause<'tcx> {
f035d41b 90 /// `None` for `ObligationCause::dummy`, `Some` otherwise.
136023e0 91 data: Option<Lrc<ObligationCauseData<'tcx>>>,
f035d41b
XL
92}
93
94const 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`.
98impl<'tcx> fmt::Debug for ObligationCause<'tcx> {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 ObligationCauseData::fmt(self, f)
101 }
102}
103
104impl 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 114pub 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
128impl 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
136impl<'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)]
180pub 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 187pub 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)]
368pub 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
384impl 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 401static_assert_size!(ObligationCauseCode<'_>, 40);
e1599b0c 402
29967ef6
XL
403#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
404pub enum StatementAsExpression {
405 CorrectType,
406 NeedsBoxing,
407}
408
409impl<'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
417pub 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)]
429pub 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
438pub 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 450pub 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
482pub 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
519pub 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 568impl<'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 678pub 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 685pub 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 694pub 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 703pub 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)]
709pub 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 723pub 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 728pub 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 742pub 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 749pub struct ImplSourceDiscriminantKindData;
f9f354fc 750
6a06907d
XL
751#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
752pub struct ImplSourcePointeeData;
753
c295e0f8
XL
754#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
755pub struct ImplSourceConstDropData;
756
3dfed10e 757#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
f035d41b 758pub 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
765pub 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
783impl 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
914pub 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}