rustc_hir_analysis/hir_ty_lowering/
dyn_compatibility.rs1use 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 #[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 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 if regular_traits.len() > 1 {
69 let guar = self.report_trait_object_addition_traits(®ular_traits);
70 return Ty::new_error(tcx, guar);
71 }
72 if let Err(guar) = regular_traits.error_reported() {
74 return Ty::new_error(tcx, guar);
75 }
76
77 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 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 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 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 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 .filter(|item| item.is_type())
191 .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 let references_self = match pred.skip_binder().term.kind() {
201 ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
202 ty::TermKind::Const(_) => false,
204 };
205
206 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 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 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 !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 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 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 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(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 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 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 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 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 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 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 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 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}