rustc_hir_analysis/hir_ty_lowering/
dyn_compatibility.rs

1use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
2use rustc_errors::codes::*;
3use rustc_errors::struct_span_code_err;
4use rustc_hir as hir;
5use rustc_hir::LangItem;
6use rustc_hir::def::{DefKind, Res};
7use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
8use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
9use rustc_middle::ty::{
10    self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
11    TypeVisitableExt, Upcast,
12};
13use rustc_span::{ErrorGuaranteed, Span};
14use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
15use rustc_trait_selection::traits;
16use smallvec::{SmallVec, smallvec};
17use tracing::{debug, instrument};
18
19use super::HirTyLowerer;
20use crate::errors::SelfInTypeAlias;
21use crate::hir_ty_lowering::{
22    GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
23};
24
25impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26    /// Lower a trait object type from the HIR to our internal notion of a type.
27    #[instrument(level = "debug", skip_all, ret)]
28    pub(super) fn lower_trait_object_ty(
29        &self,
30        span: Span,
31        hir_id: hir::HirId,
32        hir_bounds: &[hir::PolyTraitRef<'tcx>],
33        lifetime: &hir::Lifetime,
34        representation: DynKind,
35    ) -> Ty<'tcx> {
36        let tcx = self.tcx();
37        let dummy_self = tcx.types.trait_object_dummy_self;
38
39        let mut user_written_bounds = Vec::new();
40        let mut potential_assoc_types = Vec::new();
41        for trait_bound in hir_bounds.iter() {
42            if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
43                continue;
44            }
45            if let GenericArgCountResult {
46                correct:
47                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
48                ..
49            } = self.lower_poly_trait_ref(
50                &trait_bound.trait_ref,
51                trait_bound.span,
52                hir::BoundConstness::Never,
53                hir::BoundPolarity::Positive,
54                dummy_self,
55                &mut user_written_bounds,
56                PredicateFilter::SelfOnly,
57            ) {
58                potential_assoc_types.extend(cur_potential_assoc_types);
59            }
60        }
61
62        let ast_bounds: Vec<_> =
63            hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
64
65        self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
66
67        let (elaborated_trait_bounds, elaborated_projection_bounds) =
68            traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
69        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
70            .into_iter()
71            .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
72
73        // We don't support empty trait objects.
74        if regular_traits.is_empty() && auto_traits.is_empty() {
75            let guar =
76                self.report_trait_object_with_no_traits(span, user_written_bounds.iter().copied());
77            return Ty::new_error(tcx, guar);
78        }
79        // We don't support >1 principal
80        if regular_traits.len() > 1 {
81            let guar = self.report_trait_object_addition_traits(&regular_traits);
82            return Ty::new_error(tcx, guar);
83        }
84        // We don't support `PointeeSized` principals
85        let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
86        if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) {
87            let guar = self.report_pointee_sized_trait_object(span);
88            return Ty::new_error(tcx, guar);
89        }
90
91        // Don't create a dyn trait if we have errors in the principal.
92        if let Err(guar) = regular_traits.error_reported() {
93            return Ty::new_error(tcx, guar);
94        }
95
96        // Check that there are no gross dyn-compatibility violations;
97        // most importantly, that the supertraits don't contain `Self`,
98        // to avoid ICEs.
99        for (clause, span) in user_written_bounds {
100            if let Some(trait_pred) = clause.as_trait_clause() {
101                let violations = self.dyn_compatibility_violations(trait_pred.def_id());
102                if !violations.is_empty() {
103                    let reported = report_dyn_incompatibility(
104                        tcx,
105                        span,
106                        Some(hir_id),
107                        trait_pred.def_id(),
108                        &violations,
109                    )
110                    .emit();
111                    return Ty::new_error(tcx, reported);
112                }
113            }
114        }
115
116        // Map the projection bounds onto a key that makes it easy to remove redundant
117        // bounds that are constrained by supertraits of the principal def id.
118        //
119        // Also make sure we detect conflicting bounds from expanding a trait alias and
120        // also specifying it manually, like:
121        // ```
122        // type Alias = Trait<Assoc = i32>;
123        // let _: &dyn Alias<Assoc = u32> = /* ... */;
124        // ```
125        let mut projection_bounds = FxIndexMap::default();
126        for (proj, proj_span) in elaborated_projection_bounds {
127            let proj = proj.map_bound(|mut b| {
128                if let Some(term_ty) = &b.term.as_type() {
129                    let references_self = term_ty.walk().any(|arg| arg == dummy_self.into());
130                    if references_self {
131                        // With trait alias and type alias combined, type resolver
132                        // may not be able to catch all illegal `Self` usages (issue 139082)
133                        let guar = self.dcx().emit_err(SelfInTypeAlias { span });
134                        b.term = replace_dummy_self_with_error(tcx, b.term, guar);
135                    }
136                }
137                b
138            });
139
140            let key = (
141                proj.skip_binder().projection_term.def_id,
142                tcx.anonymize_bound_vars(
143                    proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
144                ),
145            );
146            if let Some((old_proj, old_proj_span)) =
147                projection_bounds.insert(key, (proj, proj_span))
148                && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
149            {
150                let item = tcx.item_name(proj.item_def_id());
151                self.dcx()
152                    .struct_span_err(
153                        span,
154                        format!(
155                            "conflicting associated type bounds for `{item}` when \
156                            expanding trait alias"
157                        ),
158                    )
159                    .with_span_label(
160                        old_proj_span,
161                        format!("`{item}` is specified to be `{}` here", old_proj.term()),
162                    )
163                    .with_span_label(
164                        proj_span,
165                        format!("`{item}` is specified to be `{}` here", proj.term()),
166                    )
167                    .emit();
168            }
169        }
170
171        let principal_trait = regular_traits.into_iter().next();
172
173        // A stable ordering of associated types from the principal trait and all its
174        // supertraits. We use this to ensure that different substitutions of a trait
175        // don't result in `dyn Trait` types with different projections lists, which
176        // can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
177        // We achieve a stable ordering by walking over the unsubstituted principal
178        // trait ref.
179        let mut ordered_associated_types = vec![];
180
181        if let Some((principal_trait, ref spans)) = principal_trait {
182            let principal_trait = principal_trait.map_bound(|trait_pred| {
183                assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
184                trait_pred.trait_ref
185            });
186
187            for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
188                tcx,
189                [ClauseWithSupertraitSpan::new(
190                    ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
191                    *spans.last().unwrap(),
192                )],
193            )
194            .filter_only_self()
195            {
196                let clause = clause.instantiate_supertrait(tcx, principal_trait);
197                debug!("observing object predicate `{clause:?}`");
198
199                let bound_predicate = clause.kind();
200                match bound_predicate.skip_binder() {
201                    ty::ClauseKind::Trait(pred) => {
202                        // FIXME(negative_bounds): Handle this correctly...
203                        let trait_ref =
204                            tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
205                        ordered_associated_types.extend(
206                            tcx.associated_items(pred.trait_ref.def_id)
207                                .in_definition_order()
208                                // We only care about associated types.
209                                .filter(|item| item.is_type())
210                                // No RPITITs -- they're not dyn-compatible for now.
211                                .filter(|item| !item.is_impl_trait_in_trait())
212                                .map(|item| (item.def_id, trait_ref)),
213                        );
214                    }
215                    ty::ClauseKind::Projection(pred) => {
216                        let pred = bound_predicate.rebind(pred);
217                        // A `Self` within the original bound will be instantiated with a
218                        // `trait_object_dummy_self`, so check for that.
219                        let references_self = match pred.skip_binder().term.kind() {
220                            ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
221                            // FIXME(associated_const_equality): We should walk the const instead of not doing anything
222                            ty::TermKind::Const(_) => false,
223                        };
224
225                        // If the projection output contains `Self`, force the user to
226                        // elaborate it explicitly to avoid a lot of complexity.
227                        //
228                        // The "classically useful" case is the following:
229                        // ```
230                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
231                        //         type MyOutput;
232                        //     }
233                        // ```
234                        //
235                        // Here, the user could theoretically write `dyn MyTrait<MyOutput = X>`,
236                        // but actually supporting that would "expand" to an infinitely-long type
237                        // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
238                        //
239                        // Instead, we force the user to write
240                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
241                        // the discussion in #56288 for alternatives.
242                        if !references_self {
243                            let key = (
244                                pred.skip_binder().projection_term.def_id,
245                                tcx.anonymize_bound_vars(
246                                    pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
247                                ),
248                            );
249                            if !projection_bounds.contains_key(&key) {
250                                projection_bounds.insert(key, (pred, supertrait_span));
251                            }
252                        }
253
254                        self.check_elaborated_projection_mentions_input_lifetimes(
255                            pred,
256                            *spans.first().unwrap(),
257                            supertrait_span,
258                        );
259                    }
260                    _ => (),
261                }
262            }
263        }
264
265        // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where
266        // <Self as Trait>::Assoc = Foo`. So every `Projection` clause is an
267        // `Assoc = Foo` bound. `needed_associated_types` contains all associated
268        // types that we expect to be provided by the user, so the following loop
269        // removes all the associated types that have a corresponding `Projection`
270        // clause, either from expanding trait aliases or written by the user.
271        for &(projection_bound, span) in projection_bounds.values() {
272            let def_id = projection_bound.item_def_id();
273            if tcx.generics_require_sized_self(def_id) {
274                tcx.emit_node_span_lint(
275                    UNUSED_ASSOCIATED_TYPE_BOUNDS,
276                    hir_id,
277                    span,
278                    crate::errors::UnusedAssociatedTypeBounds { span },
279                );
280            }
281        }
282
283        // We compute the list of projection bounds taking the ordered associated types,
284        // and check if there was an entry in the collected `projection_bounds`. Those
285        // are computed by first taking the user-written associated types, then elaborating
286        // the principal trait ref, and only using those if there was no user-written.
287        // See note below about how we handle missing associated types with `Self: Sized`,
288        // which are not required to be provided, but are still used if they are provided.
289        let mut missing_assoc_types = FxIndexSet::default();
290        let projection_bounds: Vec<_> = ordered_associated_types
291            .into_iter()
292            .filter_map(|key| {
293                if let Some(assoc) = projection_bounds.get(&key) {
294                    Some(*assoc)
295                } else {
296                    // If the associated type has a `where Self: Sized` bound, then
297                    // we do not need to provide the associated type. This results in
298                    // a `dyn Trait` type that has a different number of projection
299                    // bounds, which may lead to type mismatches.
300                    if !tcx.generics_require_sized_self(key.0) {
301                        missing_assoc_types.insert(key);
302                    }
303                    None
304                }
305            })
306            .collect();
307
308        if let Err(guar) = self.check_for_required_assoc_tys(
309            principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
310            missing_assoc_types,
311            potential_assoc_types,
312            hir_bounds,
313        ) {
314            return Ty::new_error(tcx, guar);
315        }
316
317        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
318        // `dyn Trait + Send`.
319        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
320        // the bounds
321        let mut duplicates = FxHashSet::default();
322        auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id()));
323
324        debug!(?principal_trait);
325        debug!(?auto_traits);
326
327        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
328        let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| {
329            trait_pred.map_bound(|trait_pred| {
330                let trait_ref = trait_pred.trait_ref;
331                assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
332                assert_eq!(trait_ref.self_ty(), dummy_self);
333
334                let span = *spans.first().unwrap();
335
336                // Verify that `dummy_self` did not leak inside default type parameters. This
337                // could not be done at path creation, since we need to see through trait aliases.
338                let mut missing_type_params = vec![];
339                let generics = tcx.generics_of(trait_ref.def_id);
340                let args: Vec<_> = trait_ref
341                    .args
342                    .iter()
343                    .enumerate()
344                    // Skip `Self`
345                    .skip(1)
346                    .map(|(index, arg)| {
347                        if arg.walk().any(|arg| arg == dummy_self.into()) {
348                            let param = &generics.own_params[index];
349                            missing_type_params.push(param.name);
350                            Ty::new_misc_error(tcx).into()
351                        } else {
352                            arg
353                        }
354                    })
355                    .collect();
356
357                let empty_generic_args = hir_bounds.iter().any(|hir_bound| {
358                    hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
359                        && hir_bound.span.contains(span)
360                });
361                self.report_missing_type_params(
362                    missing_type_params,
363                    trait_ref.def_id,
364                    span,
365                    empty_generic_args,
366                );
367
368                ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(
369                    tcx,
370                    trait_ref.def_id,
371                    args,
372                ))
373            })
374        });
375
376        let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
377            bound.map_bound(|mut b| {
378                assert_eq!(b.projection_term.self_ty(), dummy_self);
379
380                // Like for trait refs, verify that `dummy_self` did not leak inside default type
381                // parameters.
382                let references_self = b.projection_term.args.iter().skip(1).any(|arg| {
383                    if arg.walk().any(|arg| arg == dummy_self.into()) {
384                        return true;
385                    }
386                    false
387                });
388                if references_self {
389                    let guar = tcx
390                        .dcx()
391                        .span_delayed_bug(span, "trait object projection bounds reference `Self`");
392                    b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
393                }
394
395                ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
396                    tcx, b,
397                ))
398            })
399        });
400
401        let mut auto_trait_predicates: Vec<_> = auto_traits
402            .into_iter()
403            .map(|(trait_pred, _)| {
404                assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
405                assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
406
407                ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
408            })
409            .collect();
410        auto_trait_predicates.dedup();
411
412        // N.b. principal, projections, auto traits
413        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
414        let mut v = principal_trait_ref
415            .into_iter()
416            .chain(existential_projections)
417            .chain(auto_trait_predicates)
418            .collect::<SmallVec<[_; 8]>>();
419        v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
420        let existential_predicates = tcx.mk_poly_existential_predicates(&v);
421
422        // Use explicitly-specified region bound, unless the bound is missing.
423        let region_bound = if !lifetime.is_elided() {
424            self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
425        } else {
426            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
427                // Curiously, we prefer object lifetime default for `+ '_`...
428                if tcx.named_bound_var(lifetime.hir_id).is_some() {
429                    self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
430                } else {
431                    let reason =
432                        if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind {
433                            if let hir::Node::Ty(hir::Ty {
434                                kind: hir::TyKind::Ref(parent_lifetime, _),
435                                ..
436                            }) = tcx.parent_hir_node(hir_id)
437                                && tcx.named_bound_var(parent_lifetime.hir_id).is_none()
438                            {
439                                // Parent lifetime must have failed to resolve. Don't emit a redundant error.
440                                RegionInferReason::ExplicitObjectLifetime
441                            } else {
442                                RegionInferReason::ObjectLifetimeDefault
443                            }
444                        } else {
445                            RegionInferReason::ExplicitObjectLifetime
446                        };
447                    self.re_infer(span, reason)
448                }
449            })
450        };
451        debug!(?region_bound);
452
453        Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
454    }
455
456    /// Check that elaborating the principal of a trait ref doesn't lead to projections
457    /// that are unconstrained. This can happen because an otherwise unconstrained
458    /// *type variable* can be substituted with a type that has late-bound regions. See
459    /// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
460    fn check_elaborated_projection_mentions_input_lifetimes(
461        &self,
462        pred: ty::PolyProjectionPredicate<'tcx>,
463        span: Span,
464        supertrait_span: Span,
465    ) {
466        let tcx = self.tcx();
467
468        // Find any late-bound regions declared in `ty` that are not
469        // declared in the trait-ref or assoc_item. These are not well-formed.
470        //
471        // Example:
472        //
473        //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
474        //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
475        let late_bound_in_projection_term =
476            tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
477        let late_bound_in_term =
478            tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
479        debug!(?late_bound_in_projection_term);
480        debug!(?late_bound_in_term);
481
482        // FIXME: point at the type params that don't have appropriate lifetimes:
483        // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
484        //                         ----  ----     ^^^^^^^
485        // NOTE(associated_const_equality): This error should be impossible to trigger
486        //                                  with associated const equality constraints.
487        self.validate_late_bound_regions(
488            late_bound_in_projection_term,
489            late_bound_in_term,
490            |br_name| {
491                let item_name = tcx.item_name(pred.item_def_id());
492                struct_span_code_err!(
493                    self.dcx(),
494                    span,
495                    E0582,
496                    "binding for associated type `{}` references {}, \
497                             which does not appear in the trait input types",
498                    item_name,
499                    br_name
500                )
501                .with_span_label(supertrait_span, "due to this supertrait")
502            },
503        );
504    }
505}
506
507fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
508    tcx: TyCtxt<'tcx>,
509    t: T,
510    guar: ErrorGuaranteed,
511) -> T {
512    t.fold_with(&mut BottomUpFolder {
513        tcx,
514        ty_op: |ty| {
515            if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty }
516        },
517        lt_op: |lt| lt,
518        ct_op: |ct| ct,
519    })
520}