rustc_hir_analysis/hir_ty_lowering/
dyn_compatibility.rs

1use rustc_data_structures::fx::{FxHashSet, 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::fold::BottomUpFolder;
8use rustc_middle::ty::{
9    self, 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 rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
16use smallvec::{SmallVec, smallvec};
17use tracing::{debug, instrument};
18
19use super::HirTyLowerer;
20use crate::bounds::Bounds;
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 = Bounds::default();
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 (trait_bounds, mut projection_bounds) =
63            traits::expand_trait_aliases(tcx, user_written_bounds.clauses());
64        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds
65            .into_iter()
66            .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
67
68        // We  don't support empty trait objects.
69        if regular_traits.is_empty() && auto_traits.is_empty() {
70            let guar =
71                self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses());
72            return Ty::new_error(tcx, guar);
73        }
74        // We don't support >1 principal
75        if regular_traits.len() > 1 {
76            let guar = self.report_trait_object_addition_traits_error(&regular_traits);
77            return Ty::new_error(tcx, guar);
78        }
79        // Don't create a dyn trait if we have errors in the principal.
80        if let Err(guar) = regular_traits.error_reported() {
81            return Ty::new_error(tcx, guar);
82        }
83
84        // Check that there are no gross dyn-compatibility violations;
85        // most importantly, that the supertraits don't contain `Self`,
86        // to avoid ICEs.
87        for (clause, span) in user_written_bounds.clauses() {
88            if let Some(trait_pred) = clause.as_trait_clause() {
89                let violations =
90                    hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id());
91                if !violations.is_empty() {
92                    let reported = report_dyn_incompatibility(
93                        tcx,
94                        span,
95                        Some(hir_id),
96                        trait_pred.def_id(),
97                        &violations,
98                    )
99                    .emit();
100                    return Ty::new_error(tcx, reported);
101                }
102            }
103        }
104
105        let principal_trait = regular_traits.into_iter().next();
106
107        let mut needed_associated_types = FxIndexSet::default();
108        if let Some((principal_trait, spans)) = &principal_trait {
109            let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx);
110            for ClauseWithSupertraitSpan { pred, supertrait_span } in traits::elaborate(
111                tcx,
112                [ClauseWithSupertraitSpan::new(pred, *spans.last().unwrap())],
113            )
114            .filter_only_self()
115            {
116                debug!("observing object predicate `{pred:?}`");
117
118                let bound_predicate = pred.kind();
119                match bound_predicate.skip_binder() {
120                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
121                        // FIXME(negative_bounds): Handle this correctly...
122                        let trait_ref =
123                            tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
124                        needed_associated_types.extend(
125                            tcx.associated_items(trait_ref.def_id())
126                                .in_definition_order()
127                                .filter(|item| item.kind == ty::AssocKind::Type)
128                                .filter(|item| !item.is_impl_trait_in_trait())
129                                // If the associated type has a `where Self: Sized` bound,
130                                // we do not need to constrain the associated type.
131                                .filter(|item| !tcx.generics_require_sized_self(item.def_id))
132                                .map(|item| (item.def_id, trait_ref)),
133                        );
134                    }
135                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
136                        let pred = bound_predicate.rebind(pred);
137                        // A `Self` within the original bound will be instantiated with a
138                        // `trait_object_dummy_self`, so check for that.
139                        let references_self = match pred.skip_binder().term.unpack() {
140                            ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
141                            // FIXME(associated_const_equality): We should walk the const instead of not doing anything
142                            ty::TermKind::Const(_) => false,
143                        };
144
145                        // If the projection output contains `Self`, force the user to
146                        // elaborate it explicitly to avoid a lot of complexity.
147                        //
148                        // The "classically useful" case is the following:
149                        // ```
150                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
151                        //         type MyOutput;
152                        //     }
153                        // ```
154                        //
155                        // Here, the user could theoretically write `dyn MyTrait<MyOutput = X>`,
156                        // but actually supporting that would "expand" to an infinitely-long type
157                        // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
158                        //
159                        // Instead, we force the user to write
160                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
161                        // the discussion in #56288 for alternatives.
162                        if !references_self {
163                            // Include projections defined on supertraits.
164                            projection_bounds.push((pred, supertrait_span));
165                        }
166
167                        self.check_elaborated_projection_mentions_input_lifetimes(
168                            pred,
169                            *spans.first().unwrap(),
170                            supertrait_span,
171                        );
172                    }
173                    _ => (),
174                }
175            }
176        }
177
178        // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where
179        // <Self as Trait>::Assoc = Foo`. So every `Projection` clause is an
180        // `Assoc = Foo` bound. `needed_associated_types` contains all associated
181        // types that we expect to be provided by the user, so the following loop
182        // removes all the associated types that have a corresponding `Projection`
183        // clause, either from expanding trait aliases or written by the user.
184        for &(projection_bound, span) in &projection_bounds {
185            let def_id = projection_bound.item_def_id();
186            let trait_ref = tcx.anonymize_bound_vars(
187                projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
188            );
189            needed_associated_types.swap_remove(&(def_id, trait_ref));
190            if tcx.generics_require_sized_self(def_id) {
191                tcx.emit_node_span_lint(
192                    UNUSED_ASSOCIATED_TYPE_BOUNDS,
193                    hir_id,
194                    span,
195                    crate::errors::UnusedAssociatedTypeBounds { span },
196                );
197            }
198        }
199
200        if let Err(guar) = self.check_for_required_assoc_tys(
201            principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
202            needed_associated_types,
203            potential_assoc_types,
204            hir_bounds,
205        ) {
206            return Ty::new_error(tcx, guar);
207        }
208
209        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
210        // `dyn Trait + Send`.
211        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
212        // the bounds
213        let mut duplicates = FxHashSet::default();
214        auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id()));
215
216        debug!(?principal_trait);
217        debug!(?auto_traits);
218
219        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
220        let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| {
221            trait_pred.map_bound(|trait_pred| {
222                let trait_ref = trait_pred.trait_ref;
223                assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
224                assert_eq!(trait_ref.self_ty(), dummy_self);
225
226                let span = *spans.first().unwrap();
227
228                // Verify that `dummy_self` did not leak inside default type parameters. This
229                // could not be done at path creation, since we need to see through trait aliases.
230                let mut missing_type_params = vec![];
231                let generics = tcx.generics_of(trait_ref.def_id);
232                let args: Vec<_> = trait_ref
233                    .args
234                    .iter()
235                    .enumerate()
236                    // Skip `Self`
237                    .skip(1)
238                    .map(|(index, arg)| {
239                        if arg.walk().any(|arg| arg == dummy_self.into()) {
240                            let param = &generics.own_params[index];
241                            missing_type_params.push(param.name);
242                            Ty::new_misc_error(tcx).into()
243                        } else {
244                            arg
245                        }
246                    })
247                    .collect();
248
249                let empty_generic_args = hir_bounds.iter().any(|hir_bound| {
250                    hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
251                        && hir_bound.span.contains(span)
252                });
253                self.complain_about_missing_type_params(
254                    missing_type_params,
255                    trait_ref.def_id,
256                    span,
257                    empty_generic_args,
258                );
259
260                ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(
261                    tcx,
262                    trait_ref.def_id,
263                    args,
264                ))
265            })
266        });
267
268        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
269            bound.map_bound(|mut b| {
270                assert_eq!(b.projection_term.self_ty(), dummy_self);
271
272                // Like for trait refs, verify that `dummy_self` did not leak inside default type
273                // parameters.
274                let references_self = b.projection_term.args.iter().skip(1).any(|arg| {
275                    if arg.walk().any(|arg| arg == dummy_self.into()) {
276                        return true;
277                    }
278                    false
279                });
280                if references_self {
281                    let guar = tcx
282                        .dcx()
283                        .span_delayed_bug(span, "trait object projection bounds reference `Self`");
284                    b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
285                }
286
287                ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
288                    tcx, b,
289                ))
290            })
291        });
292
293        let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| {
294            assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
295            assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
296
297            ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
298        });
299
300        // N.b. principal, projections, auto traits
301        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
302        let mut v = principal_trait_ref
303            .into_iter()
304            .chain(existential_projections)
305            .chain(auto_trait_predicates)
306            .collect::<SmallVec<[_; 8]>>();
307        v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
308        v.dedup();
309        let existential_predicates = tcx.mk_poly_existential_predicates(&v);
310
311        // Use explicitly-specified region bound, unless the bound is missing.
312        let region_bound = if !lifetime.is_elided() {
313            self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
314        } else {
315            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
316                // Curiously, we prefer object lifetime default for `+ '_`...
317                if tcx.named_bound_var(lifetime.hir_id).is_some() {
318                    self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
319                } else {
320                    let reason =
321                        if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res {
322                            if let hir::Node::Ty(hir::Ty {
323                                kind: hir::TyKind::Ref(parent_lifetime, _),
324                                ..
325                            }) = tcx.parent_hir_node(hir_id)
326                                && tcx.named_bound_var(parent_lifetime.hir_id).is_none()
327                            {
328                                // Parent lifetime must have failed to resolve. Don't emit a redundant error.
329                                RegionInferReason::ExplicitObjectLifetime
330                            } else {
331                                RegionInferReason::ObjectLifetimeDefault
332                            }
333                        } else {
334                            RegionInferReason::ExplicitObjectLifetime
335                        };
336                    self.re_infer(span, reason)
337                }
338            })
339        };
340        debug!(?region_bound);
341
342        Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
343    }
344
345    /// Check that elaborating the principal of a trait ref doesn't lead to projections
346    /// that are unconstrained. This can happen because an otherwise unconstrained
347    /// *type variable* can be substituted with a type that has late-bound regions. See
348    /// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
349    fn check_elaborated_projection_mentions_input_lifetimes(
350        &self,
351        pred: ty::PolyProjectionPredicate<'tcx>,
352        span: Span,
353        supertrait_span: Span,
354    ) {
355        let tcx = self.tcx();
356
357        // Find any late-bound regions declared in `ty` that are not
358        // declared in the trait-ref or assoc_item. These are not well-formed.
359        //
360        // Example:
361        //
362        //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
363        //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
364        let late_bound_in_projection_term =
365            tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
366        let late_bound_in_term =
367            tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
368        debug!(?late_bound_in_projection_term);
369        debug!(?late_bound_in_term);
370
371        // FIXME: point at the type params that don't have appropriate lifetimes:
372        // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
373        //                         ----  ----     ^^^^^^^
374        // NOTE(associated_const_equality): This error should be impossible to trigger
375        //                                  with associated const equality constraints.
376        self.validate_late_bound_regions(
377            late_bound_in_projection_term,
378            late_bound_in_term,
379            |br_name| {
380                let item_name = tcx.item_name(pred.item_def_id());
381                struct_span_code_err!(
382                    self.dcx(),
383                    span,
384                    E0582,
385                    "binding for associated type `{}` references {}, \
386                             which does not appear in the trait input types",
387                    item_name,
388                    br_name
389                )
390                .with_span_label(supertrait_span, "due to this supertrait")
391            },
392        );
393    }
394}
395
396fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
397    tcx: TyCtxt<'tcx>,
398    t: T,
399    guar: ErrorGuaranteed,
400) -> T {
401    t.fold_with(&mut BottomUpFolder {
402        tcx,
403        ty_op: |ty| {
404            if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty }
405        },
406        lt_op: |lt| lt,
407        ct_op: |ct| ct,
408    })
409}