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