]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/traits/object_safety.rs
Auto merge of #107443 - cjgillot:generator-less-query, r=compiler-errors
[rust.git] / compiler / rustc_trait_selection / src / traits / object_safety.rs
1 //! "Object safety" refers to the ability for a trait to be converted
2 //! to an object. In general, traits may only be converted to an
3 //! object if all of their methods meet certain criteria. In particular,
4 //! they must:
5 //!
6 //!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
7 //!     that doesn't contain the vtable;
8 //!   - not reference the erased type `Self` except for in this receiver;
9 //!   - not have generic type parameters.
10
11 use super::{elaborate_predicates, elaborate_trait_ref};
12
13 use crate::infer::TyCtxtInferExt;
14 use crate::traits::query::evaluate_obligation::InferCtxtExt;
15 use crate::traits::{self, Obligation, ObligationCause};
16 use hir::def::DefKind;
17 use rustc_errors::{DelayDm, FatalError, MultiSpan};
18 use rustc_hir as hir;
19 use rustc_hir::def_id::DefId;
20 use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
21 use rustc_middle::ty::{
22     self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
23 };
24 use rustc_middle::ty::{Predicate, ToPredicate};
25 use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
26 use rustc_span::symbol::Symbol;
27 use rustc_span::Span;
28 use smallvec::SmallVec;
29
30 use std::iter;
31 use std::ops::ControlFlow;
32
33 pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
34
35 /// Returns the object safety violations that affect
36 /// astconv -- currently, `Self` in supertraits. This is needed
37 /// because `object_safety_violations` can't be used during
38 /// type collection.
39 pub fn astconv_object_safety_violations(
40     tcx: TyCtxt<'_>,
41     trait_def_id: DefId,
42 ) -> Vec<ObjectSafetyViolation> {
43     debug_assert!(tcx.generics_of(trait_def_id).has_self);
44     let violations = traits::supertrait_def_ids(tcx, trait_def_id)
45         .map(|def_id| predicates_reference_self(tcx, def_id, true))
46         .filter(|spans| !spans.is_empty())
47         .map(ObjectSafetyViolation::SupertraitSelf)
48         .collect();
49
50     debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations);
51
52     violations
53 }
54
55 fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [ObjectSafetyViolation] {
56     debug_assert!(tcx.generics_of(trait_def_id).has_self);
57     debug!("object_safety_violations: {:?}", trait_def_id);
58
59     tcx.arena.alloc_from_iter(
60         traits::supertrait_def_ids(tcx, trait_def_id)
61             .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id)),
62     )
63 }
64
65 fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
66     let violations = tcx.object_safety_violations(trait_def_id);
67
68     if violations.is_empty() {
69         return true;
70     }
71
72     // If the trait contains any other violations, then let the error reporting path
73     // report it instead of emitting a warning here.
74     if violations.iter().all(|violation| {
75         matches!(
76             violation,
77             ObjectSafetyViolation::Method(_, MethodViolationCode::WhereClauseReferencesSelf, _)
78         )
79     }) {
80         for violation in violations {
81             if let ObjectSafetyViolation::Method(
82                 _,
83                 MethodViolationCode::WhereClauseReferencesSelf,
84                 span,
85             ) = violation
86             {
87                 lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation);
88             }
89         }
90         return true;
91     }
92
93     false
94 }
95
96 /// We say a method is *vtable safe* if it can be invoked on a trait
97 /// object. Note that object-safe traits can have some
98 /// non-vtable-safe methods, so long as they require `Self: Sized` or
99 /// otherwise ensure that they cannot be used when `Self = Trait`.
100 pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
101     debug_assert!(tcx.generics_of(trait_def_id).has_self);
102     debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
103     // Any method that has a `Self: Sized` bound cannot be called.
104     if generics_require_sized_self(tcx, method.def_id) {
105         return false;
106     }
107
108     match virtual_call_violation_for_method(tcx, trait_def_id, method) {
109         None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
110         Some(_) => false,
111     }
112 }
113
114 fn object_safety_violations_for_trait(
115     tcx: TyCtxt<'_>,
116     trait_def_id: DefId,
117 ) -> Vec<ObjectSafetyViolation> {
118     // Check methods for violations.
119     let mut violations: Vec<_> = tcx
120         .associated_items(trait_def_id)
121         .in_definition_order()
122         .filter(|item| item.kind == ty::AssocKind::Fn)
123         .filter_map(|item| {
124             object_safety_violation_for_method(tcx, trait_def_id, &item)
125                 .map(|(code, span)| ObjectSafetyViolation::Method(item.name, code, span))
126         })
127         .collect();
128
129     // Check the trait itself.
130     if trait_has_sized_self(tcx, trait_def_id) {
131         // We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
132         let spans = get_sized_bounds(tcx, trait_def_id);
133         violations.push(ObjectSafetyViolation::SizedSelf(spans));
134     }
135     let spans = predicates_reference_self(tcx, trait_def_id, false);
136     if !spans.is_empty() {
137         violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
138     }
139     let spans = bounds_reference_self(tcx, trait_def_id);
140     if !spans.is_empty() {
141         violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
142     }
143
144     violations.extend(
145         tcx.associated_items(trait_def_id)
146             .in_definition_order()
147             .filter(|item| item.kind == ty::AssocKind::Const)
148             .map(|item| {
149                 let ident = item.ident(tcx);
150                 ObjectSafetyViolation::AssocConst(ident.name, ident.span)
151             }),
152     );
153
154     if !tcx.features().generic_associated_types_extended {
155         violations.extend(
156             tcx.associated_items(trait_def_id)
157                 .in_definition_order()
158                 .filter(|item| item.kind == ty::AssocKind::Type)
159                 .filter(|item| !tcx.generics_of(item.def_id).params.is_empty())
160                 .map(|item| {
161                     let ident = item.ident(tcx);
162                     ObjectSafetyViolation::GAT(ident.name, ident.span)
163                 }),
164         );
165     }
166
167     debug!(
168         "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
169         trait_def_id, violations
170     );
171
172     violations
173 }
174
175 /// Lint object-unsafe trait.
176 fn lint_object_unsafe_trait(
177     tcx: TyCtxt<'_>,
178     span: Span,
179     trait_def_id: DefId,
180     violation: &ObjectSafetyViolation,
181 ) {
182     // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
183     // It's also hard to get a use site span, so we use the method definition span.
184     tcx.struct_span_lint_hir(
185         WHERE_CLAUSES_OBJECT_SAFETY,
186         hir::CRATE_HIR_ID,
187         span,
188         DelayDm(|| format!("the trait `{}` cannot be made into an object", tcx.def_path_str(trait_def_id))),
189         |err| {
190             let node = tcx.hir().get_if_local(trait_def_id);
191             let mut spans = MultiSpan::from_span(span);
192             if let Some(hir::Node::Item(item)) = node {
193                 spans.push_span_label(
194                     item.ident.span,
195                     "this trait cannot be made into an object...",
196                 );
197                 spans.push_span_label(span, format!("...because {}", violation.error_msg()));
198             } else {
199                 spans.push_span_label(
200                     span,
201                     format!(
202                         "the trait cannot be made into an object because {}",
203                         violation.error_msg()
204                     ),
205                 );
206             };
207             err.span_note(
208                 spans,
209                 "for a trait to be \"object safe\" it needs to allow building a vtable to allow the \
210                 call to be resolvable dynamically; for more information visit \
211                 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
212             );
213             if node.is_some() {
214                 // Only provide the help if its a local trait, otherwise it's not
215                 violation.solution(err);
216             }
217             err
218         },
219     );
220 }
221
222 fn sized_trait_bound_spans<'tcx>(
223     tcx: TyCtxt<'tcx>,
224     bounds: hir::GenericBounds<'tcx>,
225 ) -> impl 'tcx + Iterator<Item = Span> {
226     bounds.iter().filter_map(move |b| match b {
227         hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
228             if trait_has_sized_self(
229                 tcx,
230                 trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
231             ) =>
232         {
233             // Fetch spans for supertraits that are `Sized`: `trait T: Super`
234             Some(trait_ref.span)
235         }
236         _ => None,
237     })
238 }
239
240 fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
241     tcx.hir()
242         .get_if_local(trait_def_id)
243         .and_then(|node| match node {
244             hir::Node::Item(hir::Item {
245                 kind: hir::ItemKind::Trait(.., generics, bounds, _),
246                 ..
247             }) => Some(
248                 generics
249                     .predicates
250                     .iter()
251                     .filter_map(|pred| {
252                         match pred {
253                             hir::WherePredicate::BoundPredicate(pred)
254                                 if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
255                             {
256                                 // Fetch spans for trait bounds that are Sized:
257                                 // `trait T where Self: Pred`
258                                 Some(sized_trait_bound_spans(tcx, pred.bounds))
259                             }
260                             _ => None,
261                         }
262                     })
263                     .flatten()
264                     // Fetch spans for supertraits that are `Sized`: `trait T: Super`.
265                     .chain(sized_trait_bound_spans(tcx, bounds))
266                     .collect::<SmallVec<[Span; 1]>>(),
267             ),
268             _ => None,
269         })
270         .unwrap_or_else(SmallVec::new)
271 }
272
273 fn predicates_reference_self(
274     tcx: TyCtxt<'_>,
275     trait_def_id: DefId,
276     supertraits_only: bool,
277 ) -> SmallVec<[Span; 1]> {
278     let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
279     let predicates = if supertraits_only {
280         tcx.super_predicates_of(trait_def_id)
281     } else {
282         tcx.predicates_of(trait_def_id)
283     };
284     predicates
285         .predicates
286         .iter()
287         .map(|&(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
288         .filter_map(|predicate| predicate_references_self(tcx, predicate))
289         .collect()
290 }
291
292 fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
293     tcx.associated_items(trait_def_id)
294         .in_definition_order()
295         .filter(|item| item.kind == ty::AssocKind::Type)
296         .flat_map(|item| tcx.explicit_item_bounds(item.def_id))
297         .filter_map(|pred_span| predicate_references_self(tcx, *pred_span))
298         .collect()
299 }
300
301 fn predicate_references_self<'tcx>(
302     tcx: TyCtxt<'tcx>,
303     (predicate, sp): (ty::Predicate<'tcx>, Span),
304 ) -> Option<Span> {
305     let self_ty = tcx.types.self_param;
306     let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into());
307     match predicate.kind().skip_binder() {
308         ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
309             // In the case of a trait predicate, we can skip the "self" type.
310             if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
311         }
312         ty::PredicateKind::Clause(ty::Clause::Projection(ref data)) => {
313             // And similarly for projections. This should be redundant with
314             // the previous check because any projection should have a
315             // matching `Trait` predicate with the same inputs, but we do
316             // the check to be safe.
317             //
318             // It's also won't be redundant if we allow type-generic associated
319             // types for trait objects.
320             //
321             // Note that we *do* allow projection *outputs* to contain
322             // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
323             // we just require the user to specify *both* outputs
324             // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
325             //
326             // This is ALT2 in issue #56288, see that for discussion of the
327             // possible alternatives.
328             if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
329         }
330         ty::PredicateKind::WellFormed(..)
331         | ty::PredicateKind::ObjectSafe(..)
332         | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
333         | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
334         | ty::PredicateKind::ClosureKind(..)
335         | ty::PredicateKind::Subtype(..)
336         | ty::PredicateKind::Coerce(..)
337         | ty::PredicateKind::ConstEvaluatable(..)
338         | ty::PredicateKind::ConstEquate(..)
339         | ty::PredicateKind::Ambiguous
340         | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
341     }
342 }
343
344 fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
345     generics_require_sized_self(tcx, trait_def_id)
346 }
347
348 fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
349     let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
350         return false; /* No Sized trait, can't require it! */
351     };
352
353     // Search for a predicate like `Self : Sized` amongst the trait bounds.
354     let predicates = tcx.predicates_of(def_id);
355     let predicates = predicates.instantiate_identity(tcx).predicates;
356     elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
357         match obligation.predicate.kind().skip_binder() {
358             ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => {
359                 trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
360             }
361             ty::PredicateKind::Clause(ty::Clause::Projection(..))
362             | ty::PredicateKind::Subtype(..)
363             | ty::PredicateKind::Coerce(..)
364             | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
365             | ty::PredicateKind::WellFormed(..)
366             | ty::PredicateKind::ObjectSafe(..)
367             | ty::PredicateKind::ClosureKind(..)
368             | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
369             | ty::PredicateKind::ConstEvaluatable(..)
370             | ty::PredicateKind::ConstEquate(..)
371             | ty::PredicateKind::Ambiguous
372             | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
373         }
374     })
375 }
376
377 /// Returns `Some(_)` if this method makes the containing trait not object safe.
378 fn object_safety_violation_for_method(
379     tcx: TyCtxt<'_>,
380     trait_def_id: DefId,
381     method: &ty::AssocItem,
382 ) -> Option<(MethodViolationCode, Span)> {
383     debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
384     // Any method that has a `Self : Sized` requisite is otherwise
385     // exempt from the regulations.
386     if generics_require_sized_self(tcx, method.def_id) {
387         return None;
388     }
389
390     let violation = virtual_call_violation_for_method(tcx, trait_def_id, method);
391     // Get an accurate span depending on the violation.
392     violation.map(|v| {
393         let node = tcx.hir().get_if_local(method.def_id);
394         let span = match (&v, node) {
395             (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
396             (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
397             (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
398             (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
399                 node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span())
400             }
401             _ => method.ident(tcx).span,
402         };
403         (v, span)
404     })
405 }
406
407 /// Returns `Some(_)` if this method cannot be called on a trait
408 /// object; this does not necessarily imply that the enclosing trait
409 /// is not object safe, because the method might have a where clause
410 /// `Self:Sized`.
411 fn virtual_call_violation_for_method<'tcx>(
412     tcx: TyCtxt<'tcx>,
413     trait_def_id: DefId,
414     method: &ty::AssocItem,
415 ) -> Option<MethodViolationCode> {
416     let sig = tcx.fn_sig(method.def_id).subst_identity();
417
418     // The method's first parameter must be named `self`
419     if !method.fn_has_self_parameter {
420         let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
421             generics,
422             kind: hir::TraitItemKind::Fn(sig, _),
423             ..
424         })) = tcx.hir().get_if_local(method.def_id).as_ref()
425         {
426             let sm = tcx.sess.source_map();
427             Some((
428                 (
429                     format!("&self{}", if sig.decl.inputs.is_empty() { "" } else { ", " }),
430                     sm.span_through_char(sig.span, '(').shrink_to_hi(),
431                 ),
432                 (
433                     format!("{} Self: Sized", generics.add_where_or_trailing_comma()),
434                     generics.tail_span_for_predicate_suggestion(),
435                 ),
436             ))
437         } else {
438             None
439         };
440         return Some(MethodViolationCode::StaticMethod(sugg));
441     }
442
443     for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
444         if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) {
445             let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
446                 kind: hir::TraitItemKind::Fn(sig, _),
447                 ..
448             })) = tcx.hir().get_if_local(method.def_id).as_ref()
449             {
450                 Some(sig.decl.inputs[i].span)
451             } else {
452                 None
453             };
454             return Some(MethodViolationCode::ReferencesSelfInput(span));
455         }
456     }
457     if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
458         return Some(MethodViolationCode::ReferencesSelfOutput);
459     }
460     if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
461         return Some(code);
462     }
463
464     // We can't monomorphize things like `fn foo<A>(...)`.
465     let own_counts = tcx.generics_of(method.def_id).own_counts();
466     if own_counts.types + own_counts.consts != 0 {
467         return Some(MethodViolationCode::Generic);
468     }
469
470     let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
471
472     // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
473     // However, this is already considered object-safe. We allow it as a special case here.
474     // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
475     // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
476     if receiver_ty != tcx.types.self_param {
477         if !receiver_is_dispatchable(tcx, method, receiver_ty) {
478             let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
479                 kind: hir::TraitItemKind::Fn(sig, _),
480                 ..
481             })) = tcx.hir().get_if_local(method.def_id).as_ref()
482             {
483                 Some(sig.decl.inputs[0].span)
484             } else {
485                 None
486             };
487             return Some(MethodViolationCode::UndispatchableReceiver(span));
488         } else {
489             // Do sanity check to make sure the receiver actually has the layout of a pointer.
490
491             use rustc_target::abi::Abi;
492
493             let param_env = tcx.param_env(method.def_id);
494
495             let abi_of_ty = |ty: Ty<'tcx>| -> Option<Abi> {
496                 match tcx.layout_of(param_env.and(ty)) {
497                     Ok(layout) => Some(layout.abi),
498                     Err(err) => {
499                         // #78372
500                         tcx.sess.delay_span_bug(
501                             tcx.def_span(method.def_id),
502                             &format!("error: {}\n while computing layout for type {:?}", err, ty),
503                         );
504                         None
505                     }
506                 }
507             };
508
509             // e.g., `Rc<()>`
510             let unit_receiver_ty =
511                 receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
512
513             match abi_of_ty(unit_receiver_ty) {
514                 Some(Abi::Scalar(..)) => (),
515                 abi => {
516                     tcx.sess.delay_span_bug(
517                         tcx.def_span(method.def_id),
518                         &format!(
519                             "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
520                             abi
521                         ),
522                     );
523                 }
524             }
525
526             let trait_object_ty =
527                 object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
528
529             // e.g., `Rc<dyn Trait>`
530             let trait_object_receiver =
531                 receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
532
533             match abi_of_ty(trait_object_receiver) {
534                 Some(Abi::ScalarPair(..)) => (),
535                 abi => {
536                     tcx.sess.delay_span_bug(
537                         tcx.def_span(method.def_id),
538                         &format!(
539                             "receiver when `Self = {}` should have a ScalarPair ABI; found {:?}",
540                             trait_object_ty, abi
541                         ),
542                     );
543                 }
544             }
545         }
546     }
547
548     // NOTE: This check happens last, because it results in a lint, and not a
549     // hard error.
550     if tcx
551         .predicates_of(method.def_id)
552         .predicates
553         .iter()
554         // A trait object can't claim to live more than the concrete type,
555         // so outlives predicates will always hold.
556         .cloned()
557         .filter(|(p, _)| p.to_opt_type_outlives().is_none())
558         .any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
559     {
560         return Some(MethodViolationCode::WhereClauseReferencesSelf);
561     }
562
563     None
564 }
565
566 /// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
567 /// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
568 fn receiver_for_self_ty<'tcx>(
569     tcx: TyCtxt<'tcx>,
570     receiver_ty: Ty<'tcx>,
571     self_ty: Ty<'tcx>,
572     method_def_id: DefId,
573 ) -> Ty<'tcx> {
574     debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
575     let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
576         if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
577     });
578
579     let result = EarlyBinder(receiver_ty).subst(tcx, substs);
580     debug!(
581         "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
582         receiver_ty, self_ty, method_def_id, result
583     );
584     result
585 }
586
587 /// Creates the object type for the current trait. For example,
588 /// if the current trait is `Deref`, then this will be
589 /// `dyn Deref<Target = Self::Target> + 'static`.
590 #[instrument(level = "trace", skip(tcx), ret)]
591 fn object_ty_for_trait<'tcx>(
592     tcx: TyCtxt<'tcx>,
593     trait_def_id: DefId,
594     lifetime: ty::Region<'tcx>,
595 ) -> Ty<'tcx> {
596     let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
597     debug!(?trait_ref);
598
599     let trait_predicate = trait_ref.map_bound(|trait_ref| {
600         ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref))
601     });
602     debug!(?trait_predicate);
603
604     let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
605         .filter_map(|obligation| {
606             debug!(?obligation);
607             let pred = obligation.predicate.to_opt_poly_projection_pred()?;
608             Some(pred.map_bound(|p| {
609                 ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
610                     def_id: p.projection_ty.def_id,
611                     substs: p.projection_ty.substs,
612                     term: p.term,
613                 })
614             }))
615         })
616         .collect();
617     // NOTE: Since #37965, the existential predicates list has depended on the
618     // list of predicates to be sorted. This is mostly to enforce that the primary
619     // predicate comes first.
620     elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
621     elaborated_predicates.dedup();
622
623     let existential_predicates = tcx
624         .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates));
625     debug!(?existential_predicates);
626
627     tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn)
628 }
629
630 /// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
631 /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
632 /// in the following way:
633 /// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
634 /// - require the following bound:
635 ///
636 ///   ```ignore (not-rust)
637 ///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
638 ///   ```
639 ///
640 ///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
641 ///   (substitution notation).
642 ///
643 /// Some examples of receiver types and their required obligation:
644 /// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
645 /// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
646 /// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
647 ///
648 /// The only case where the receiver is not dispatchable, but is still a valid receiver
649 /// type (just not object-safe), is when there is more than one level of pointer indirection.
650 /// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
651 /// is no way, or at least no inexpensive way, to coerce the receiver from the version where
652 /// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
653 /// contained by the trait object, because the object that needs to be coerced is behind
654 /// a pointer.
655 ///
656 /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
657 /// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
658 /// is stabilized, see tracking issue <https://github.com/rust-lang/rust/issues/43561>).
659 /// Instead, we fudge a little by introducing a new type parameter `U` such that
660 /// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
661 /// Written as a chalk-style query:
662 /// ```ignore (not-rust)
663 /// forall (U: Trait + ?Sized) {
664 ///     if (Self: Unsize<U>) {
665 ///         Receiver: DispatchFromDyn<Receiver[Self => U]>
666 ///     }
667 /// }
668 /// ```
669 /// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
670 /// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
671 /// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
672 //
673 // FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
674 // fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
675 // `self: Wrapper<Self>`.
676 #[allow(dead_code)]
677 fn receiver_is_dispatchable<'tcx>(
678     tcx: TyCtxt<'tcx>,
679     method: &ty::AssocItem,
680     receiver_ty: Ty<'tcx>,
681 ) -> bool {
682     debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
683
684     let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
685     let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
686         debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
687         return false;
688     };
689
690     // the type `U` in the query
691     // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
692     // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
693     // replace this with `dyn Trait`
694     let unsized_self_ty: Ty<'tcx> =
695         tcx.mk_ty_param(u32::MAX, Symbol::intern("RustaceansAreAwesome"));
696
697     // `Receiver[Self => U]`
698     let unsized_receiver_ty =
699         receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
700
701     // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
702     // `U: ?Sized` is already implied here
703     let param_env = {
704         let param_env = tcx.param_env(method.def_id);
705
706         // Self: Unsize<U>
707         let unsize_predicate = ty::Binder::dummy(
708             tcx.mk_trait_ref(unsize_did, [tcx.types.self_param, unsized_self_ty]),
709         )
710         .without_const()
711         .to_predicate(tcx);
712
713         // U: Trait<Arg1, ..., ArgN>
714         let trait_predicate = {
715             let trait_def_id = method.trait_container(tcx).unwrap();
716             let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
717                 if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
718             });
719
720             ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
721         };
722
723         let caller_bounds: Vec<Predicate<'tcx>> =
724             param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect();
725
726         ty::ParamEnv::new(
727             tcx.intern_predicates(&caller_bounds),
728             param_env.reveal(),
729             param_env.constness(),
730         )
731     };
732
733     // Receiver: DispatchFromDyn<Receiver[Self => U]>
734     let obligation = {
735         let predicate = ty::Binder::dummy(
736             tcx.mk_trait_ref(dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]),
737         );
738
739         Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
740     };
741
742     let infcx = tcx.infer_ctxt().build();
743     // the receiver is dispatchable iff the obligation holds
744     infcx.predicate_must_hold_modulo_regions(&obligation)
745 }
746
747 fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
748     tcx: TyCtxt<'tcx>,
749     trait_def_id: DefId,
750     value: T,
751 ) -> bool {
752     // This is somewhat subtle. In general, we want to forbid
753     // references to `Self` in the argument and return types,
754     // since the value of `Self` is erased. However, there is one
755     // exception: it is ok to reference `Self` in order to access
756     // an associated type of the current trait, since we retain
757     // the value of those associated types in the object type
758     // itself.
759     //
760     // ```rust
761     // trait SuperTrait {
762     //     type X;
763     // }
764     //
765     // trait Trait : SuperTrait {
766     //     type Y;
767     //     fn foo(&self, x: Self) // bad
768     //     fn foo(&self) -> Self // bad
769     //     fn foo(&self) -> Option<Self> // bad
770     //     fn foo(&self) -> Self::Y // OK, desugars to next example
771     //     fn foo(&self) -> <Self as Trait>::Y // OK
772     //     fn foo(&self) -> Self::X // OK, desugars to next example
773     //     fn foo(&self) -> <Self as SuperTrait>::X // OK
774     // }
775     // ```
776     //
777     // However, it is not as simple as allowing `Self` in a projected
778     // type, because there are illegal ways to use `Self` as well:
779     //
780     // ```rust
781     // trait Trait : SuperTrait {
782     //     ...
783     //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
784     // }
785     // ```
786     //
787     // Here we will not have the type of `X` recorded in the
788     // object type, and we cannot resolve `Self as SomeOtherTrait`
789     // without knowing what `Self` is.
790
791     struct IllegalSelfTypeVisitor<'tcx> {
792         tcx: TyCtxt<'tcx>,
793         trait_def_id: DefId,
794         supertraits: Option<Vec<DefId>>,
795     }
796
797     impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
798         type BreakTy = ();
799
800         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
801             match t.kind() {
802                 ty::Param(_) => {
803                     if t == self.tcx.types.self_param {
804                         ControlFlow::Break(())
805                     } else {
806                         ControlFlow::Continue(())
807                     }
808                 }
809                 ty::Alias(ty::Projection, ref data)
810                     if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder =>
811                 {
812                     // We'll deny these later in their own pass
813                     ControlFlow::Continue(())
814                 }
815                 ty::Alias(ty::Projection, ref data) => {
816                     // This is a projected type `<Foo as SomeTrait>::X`.
817
818                     // Compute supertraits of current trait lazily.
819                     if self.supertraits.is_none() {
820                         let trait_ref = ty::TraitRef::identity(self.tcx, self.trait_def_id);
821                         self.supertraits = Some(
822                             traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(),
823                         );
824                     }
825
826                     // Determine whether the trait reference `Foo as
827                     // SomeTrait` is in fact a supertrait of the
828                     // current trait. In that case, this type is
829                     // legal, because the type `X` will be specified
830                     // in the object type. Note that we can just use
831                     // direct equality here because all of these types
832                     // are part of the formal parameter listing, and
833                     // hence there should be no inference variables.
834                     let is_supertrait_of_current_trait = self
835                         .supertraits
836                         .as_ref()
837                         .unwrap()
838                         .contains(&data.trait_ref(self.tcx).def_id);
839
840                     if is_supertrait_of_current_trait {
841                         ControlFlow::Continue(()) // do not walk contained types, do not report error, do collect $200
842                     } else {
843                         t.super_visit_with(self) // DO walk contained types, POSSIBLY reporting an error
844                     }
845                 }
846                 _ => t.super_visit_with(self), // walk contained types, if any
847             }
848         }
849
850         fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
851             // Constants can only influence object safety if they are generic and reference `Self`.
852             // This is only possible for unevaluated constants, so we walk these here.
853             self.tcx.expand_abstract_consts(ct).super_visit_with(self)
854         }
855     }
856
857     value
858         .visit_with(&mut IllegalSelfTypeVisitor { tcx, trait_def_id, supertraits: None })
859         .is_break()
860 }
861
862 pub fn contains_illegal_impl_trait_in_trait<'tcx>(
863     tcx: TyCtxt<'tcx>,
864     fn_def_id: DefId,
865     ty: ty::Binder<'tcx, Ty<'tcx>>,
866 ) -> Option<MethodViolationCode> {
867     // This would be caught below, but rendering the error as a separate
868     // `async-specific` message is better.
869     if tcx.asyncness(fn_def_id).is_async() {
870         return Some(MethodViolationCode::AsyncFn);
871     }
872
873     // FIXME(RPITIT): Perhaps we should use a visitor here?
874     ty.skip_binder().walk().find_map(|arg| {
875         if let ty::GenericArgKind::Type(ty) = arg.unpack()
876             && let ty::Alias(ty::Projection, proj) = ty.kind()
877             && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
878         {
879             Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
880         } else {
881             None
882         }
883     })
884 }
885
886 pub fn provide(providers: &mut ty::query::Providers) {
887     *providers =
888         ty::query::Providers { object_safety_violations, check_is_object_safe, ..*providers };
889 }