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