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::{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 #[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 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 if regular_traits.len() > 1 {
89 let guar = self.report_trait_object_addition_traits_error(®ular_traits);
90 return Ty::new_error(tcx, guar);
91 }
92 if let Err(guar) = regular_traits.error_reported() {
94 return Ty::new_error(tcx, guar);
95 }
96
97 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 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 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 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 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 .filter(|item| item.is_type())
212 .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 let references_self = match pred.skip_binder().term.unpack() {
222 ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
223 ty::TermKind::Const(_) => false,
225 };
226
227 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 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 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 !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 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 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 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(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 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 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 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 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 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 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 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 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}