]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/traits/mod.rs
New upstream version 1.59.0+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;
3c0e092e 26use std::hash::{Hash, Hasher};
1a4d82fc 27
74b04a01 28pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
0731742a 29
1b1a35ee 30pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;
f9f354fc 31
dfeec247 32pub use self::ObligationCauseCode::*;
0531ce1d 33
1b1a35ee 34pub 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)]
39pub 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 88pub 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.
109impl 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
116const MISC_OBLIGATION_CAUSE_CODE: ObligationCauseCode<'static> = MiscObligation;
117
74b04a01
XL
118impl<'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)]
178pub 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 185pub 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)]
372pub 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
388impl 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 405static_assert_size!(ObligationCauseCode<'_>, 40);
e1599b0c 406
29967ef6
XL
407#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
408pub enum StatementAsExpression {
409 CorrectType,
410 NeedsBoxing,
411}
412
413impl<'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
421pub 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)]
433pub 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
442pub 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 454pub 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
486pub 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
523pub 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 572impl<'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 682pub 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 689pub 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 698pub 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 707pub 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)]
713pub 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 727pub 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 732pub 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 746pub 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 753pub struct ImplSourceDiscriminantKindData;
f9f354fc 754
6a06907d
XL
755#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
756pub struct ImplSourcePointeeData;
757
c295e0f8
XL
758#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
759pub struct ImplSourceConstDropData;
760
3dfed10e 761#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
f035d41b 762pub 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
769pub 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
787impl 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
918pub 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}