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::LangItem;
6use rustc_hir::def::{DefKind, Res};
7use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
8use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
9use rustc_middle::ty::{
10 self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
11 TypeVisitableExt, Upcast,
12};
13use rustc_span::{ErrorGuaranteed, Span};
14use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
15use rustc_trait_selection::traits;
16use smallvec::{SmallVec, smallvec};
17use tracing::{debug, instrument};
18
19use super::HirTyLowerer;
20use crate::errors::SelfInTypeAlias;
21use crate::hir_ty_lowering::{
22 GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
23};
24
25impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26 #[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 = Vec::new();
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 ast_bounds: Vec<_> =
63 hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
64
65 self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
66
67 let (elaborated_trait_bounds, elaborated_projection_bounds) =
68 traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
69 let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
70 .into_iter()
71 .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
72
73 if regular_traits.is_empty() && auto_traits.is_empty() {
75 let guar =
76 self.report_trait_object_with_no_traits(span, user_written_bounds.iter().copied());
77 return Ty::new_error(tcx, guar);
78 }
79 if regular_traits.len() > 1 {
81 let guar = self.report_trait_object_addition_traits(®ular_traits);
82 return Ty::new_error(tcx, guar);
83 }
84 let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
86 if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) {
87 let guar = self.report_pointee_sized_trait_object(span);
88 return Ty::new_error(tcx, guar);
89 }
90
91 if let Err(guar) = regular_traits.error_reported() {
93 return Ty::new_error(tcx, guar);
94 }
95
96 for (clause, span) in user_written_bounds {
100 if let Some(trait_pred) = clause.as_trait_clause() {
101 let violations = self.dyn_compatibility_violations(trait_pred.def_id());
102 if !violations.is_empty() {
103 let reported = report_dyn_incompatibility(
104 tcx,
105 span,
106 Some(hir_id),
107 trait_pred.def_id(),
108 &violations,
109 )
110 .emit();
111 return Ty::new_error(tcx, reported);
112 }
113 }
114 }
115
116 let mut projection_bounds = FxIndexMap::default();
126 for (proj, proj_span) in elaborated_projection_bounds {
127 let proj = proj.map_bound(|mut b| {
128 if let Some(term_ty) = &b.term.as_type() {
129 let references_self = term_ty.walk().any(|arg| arg == dummy_self.into());
130 if references_self {
131 let guar = self.dcx().emit_err(SelfInTypeAlias { span });
134 b.term = replace_dummy_self_with_error(tcx, b.term, guar);
135 }
136 }
137 b
138 });
139
140 let key = (
141 proj.skip_binder().projection_term.def_id,
142 tcx.anonymize_bound_vars(
143 proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
144 ),
145 );
146 if let Some((old_proj, old_proj_span)) =
147 projection_bounds.insert(key, (proj, proj_span))
148 && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
149 {
150 let item = tcx.item_name(proj.item_def_id());
151 self.dcx()
152 .struct_span_err(
153 span,
154 format!(
155 "conflicting associated type bounds for `{item}` when \
156 expanding trait alias"
157 ),
158 )
159 .with_span_label(
160 old_proj_span,
161 format!("`{item}` is specified to be `{}` here", old_proj.term()),
162 )
163 .with_span_label(
164 proj_span,
165 format!("`{item}` is specified to be `{}` here", proj.term()),
166 )
167 .emit();
168 }
169 }
170
171 let principal_trait = regular_traits.into_iter().next();
172
173 let mut ordered_associated_types = vec![];
180
181 if let Some((principal_trait, ref spans)) = principal_trait {
182 let principal_trait = principal_trait.map_bound(|trait_pred| {
183 assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
184 trait_pred.trait_ref
185 });
186
187 for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
188 tcx,
189 [ClauseWithSupertraitSpan::new(
190 ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
191 *spans.last().unwrap(),
192 )],
193 )
194 .filter_only_self()
195 {
196 let clause = clause.instantiate_supertrait(tcx, principal_trait);
197 debug!("observing object predicate `{clause:?}`");
198
199 let bound_predicate = clause.kind();
200 match bound_predicate.skip_binder() {
201 ty::ClauseKind::Trait(pred) => {
202 let trait_ref =
204 tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
205 ordered_associated_types.extend(
206 tcx.associated_items(pred.trait_ref.def_id)
207 .in_definition_order()
208 .filter(|item| item.is_type())
210 .filter(|item| !item.is_impl_trait_in_trait())
212 .map(|item| (item.def_id, trait_ref)),
213 );
214 }
215 ty::ClauseKind::Projection(pred) => {
216 let pred = bound_predicate.rebind(pred);
217 let references_self = match pred.skip_binder().term.kind() {
220 ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
221 ty::TermKind::Const(_) => false,
223 };
224
225 if !references_self {
243 let key = (
244 pred.skip_binder().projection_term.def_id,
245 tcx.anonymize_bound_vars(
246 pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
247 ),
248 );
249 if !projection_bounds.contains_key(&key) {
250 projection_bounds.insert(key, (pred, supertrait_span));
251 }
252 }
253
254 self.check_elaborated_projection_mentions_input_lifetimes(
255 pred,
256 *spans.first().unwrap(),
257 supertrait_span,
258 );
259 }
260 _ => (),
261 }
262 }
263 }
264
265 for &(projection_bound, span) in projection_bounds.values() {
272 let def_id = projection_bound.item_def_id();
273 if tcx.generics_require_sized_self(def_id) {
274 tcx.emit_node_span_lint(
275 UNUSED_ASSOCIATED_TYPE_BOUNDS,
276 hir_id,
277 span,
278 crate::errors::UnusedAssociatedTypeBounds { span },
279 );
280 }
281 }
282
283 let mut missing_assoc_types = FxIndexSet::default();
290 let projection_bounds: Vec<_> = ordered_associated_types
291 .into_iter()
292 .filter_map(|key| {
293 if let Some(assoc) = projection_bounds.get(&key) {
294 Some(*assoc)
295 } else {
296 if !tcx.generics_require_sized_self(key.0) {
301 missing_assoc_types.insert(key);
302 }
303 None
304 }
305 })
306 .collect();
307
308 if let Err(guar) = self.check_for_required_assoc_tys(
309 principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
310 missing_assoc_types,
311 potential_assoc_types,
312 hir_bounds,
313 ) {
314 return Ty::new_error(tcx, guar);
315 }
316
317 let mut duplicates = FxHashSet::default();
322 auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id()));
323
324 debug!(?principal_trait);
325 debug!(?auto_traits);
326
327 let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| {
329 trait_pred.map_bound(|trait_pred| {
330 let trait_ref = trait_pred.trait_ref;
331 assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
332 assert_eq!(trait_ref.self_ty(), dummy_self);
333
334 let span = *spans.first().unwrap();
335
336 let mut missing_type_params = vec![];
339 let generics = tcx.generics_of(trait_ref.def_id);
340 let args: Vec<_> = trait_ref
341 .args
342 .iter()
343 .enumerate()
344 .skip(1)
346 .map(|(index, arg)| {
347 if arg.walk().any(|arg| arg == dummy_self.into()) {
348 let param = &generics.own_params[index];
349 missing_type_params.push(param.name);
350 Ty::new_misc_error(tcx).into()
351 } else {
352 arg
353 }
354 })
355 .collect();
356
357 let empty_generic_args = hir_bounds.iter().any(|hir_bound| {
358 hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
359 && hir_bound.span.contains(span)
360 });
361 self.report_missing_type_params(
362 missing_type_params,
363 trait_ref.def_id,
364 span,
365 empty_generic_args,
366 );
367
368 ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(
369 tcx,
370 trait_ref.def_id,
371 args,
372 ))
373 })
374 });
375
376 let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
377 bound.map_bound(|mut b| {
378 assert_eq!(b.projection_term.self_ty(), dummy_self);
379
380 let references_self = b.projection_term.args.iter().skip(1).any(|arg| {
383 if arg.walk().any(|arg| arg == dummy_self.into()) {
384 return true;
385 }
386 false
387 });
388 if references_self {
389 let guar = tcx
390 .dcx()
391 .span_delayed_bug(span, "trait object projection bounds reference `Self`");
392 b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
393 }
394
395 ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
396 tcx, b,
397 ))
398 })
399 });
400
401 let mut auto_trait_predicates: Vec<_> = auto_traits
402 .into_iter()
403 .map(|(trait_pred, _)| {
404 assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
405 assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
406
407 ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
408 })
409 .collect();
410 auto_trait_predicates.dedup();
411
412 let mut v = principal_trait_ref
415 .into_iter()
416 .chain(existential_projections)
417 .chain(auto_trait_predicates)
418 .collect::<SmallVec<[_; 8]>>();
419 v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
420 let existential_predicates = tcx.mk_poly_existential_predicates(&v);
421
422 let region_bound = if !lifetime.is_elided() {
424 self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
425 } else {
426 self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
427 if tcx.named_bound_var(lifetime.hir_id).is_some() {
429 self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
430 } else {
431 let reason =
432 if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind {
433 if let hir::Node::Ty(hir::Ty {
434 kind: hir::TyKind::Ref(parent_lifetime, _),
435 ..
436 }) = tcx.parent_hir_node(hir_id)
437 && tcx.named_bound_var(parent_lifetime.hir_id).is_none()
438 {
439 RegionInferReason::ExplicitObjectLifetime
441 } else {
442 RegionInferReason::ObjectLifetimeDefault
443 }
444 } else {
445 RegionInferReason::ExplicitObjectLifetime
446 };
447 self.re_infer(span, reason)
448 }
449 })
450 };
451 debug!(?region_bound);
452
453 Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
454 }
455
456 fn check_elaborated_projection_mentions_input_lifetimes(
461 &self,
462 pred: ty::PolyProjectionPredicate<'tcx>,
463 span: Span,
464 supertrait_span: Span,
465 ) {
466 let tcx = self.tcx();
467
468 let late_bound_in_projection_term =
476 tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
477 let late_bound_in_term =
478 tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
479 debug!(?late_bound_in_projection_term);
480 debug!(?late_bound_in_term);
481
482 self.validate_late_bound_regions(
488 late_bound_in_projection_term,
489 late_bound_in_term,
490 |br_name| {
491 let item_name = tcx.item_name(pred.item_def_id());
492 struct_span_code_err!(
493 self.dcx(),
494 span,
495 E0582,
496 "binding for associated type `{}` references {}, \
497 which does not appear in the trait input types",
498 item_name,
499 br_name
500 )
501 .with_span_label(supertrait_span, "due to this supertrait")
502 },
503 );
504 }
505}
506
507fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
508 tcx: TyCtxt<'tcx>,
509 t: T,
510 guar: ErrorGuaranteed,
511) -> T {
512 t.fold_with(&mut BottomUpFolder {
513 tcx,
514 ty_op: |ty| {
515 if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty }
516 },
517 lt_op: |lt| lt,
518 ct_op: |ct| ct,
519 })
520}