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::{self, hir_ty_lowering_dyn_compatibility_violations};
15use smallvec::{SmallVec, smallvec};
16use tracing::{debug, instrument};
17
18use super::HirTyLowerer;
19use crate::hir_ty_lowering::{
20 GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
21};
22
23impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24 #[instrument(level = "debug", skip_all, ret)]
26 pub(super) fn lower_trait_object_ty(
27 &self,
28 span: Span,
29 hir_id: hir::HirId,
30 hir_bounds: &[hir::PolyTraitRef<'tcx>],
31 lifetime: &hir::Lifetime,
32 representation: DynKind,
33 ) -> Ty<'tcx> {
34 let tcx = self.tcx();
35 let dummy_self = tcx.types.trait_object_dummy_self;
36
37 let mut user_written_bounds = Vec::new();
38 let mut potential_assoc_types = Vec::new();
39 for trait_bound in hir_bounds.iter() {
40 if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
41 continue;
42 }
43 if let GenericArgCountResult {
44 correct:
45 Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
46 ..
47 } = self.lower_poly_trait_ref(
48 &trait_bound.trait_ref,
49 trait_bound.span,
50 hir::BoundConstness::Never,
51 hir::BoundPolarity::Positive,
52 dummy_self,
53 &mut user_written_bounds,
54 PredicateFilter::SelfOnly,
55 ) {
56 potential_assoc_types.extend(cur_potential_assoc_types);
57 }
58 }
59
60 let (elaborated_trait_bounds, elaborated_projection_bounds) =
61 traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
62 let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
63 .into_iter()
64 .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
65
66 if regular_traits.is_empty() && auto_traits.is_empty() {
68 let guar = self.report_trait_object_with_no_traits_error(
69 span,
70 user_written_bounds.iter().copied(),
71 );
72 return Ty::new_error(tcx, guar);
73 }
74 if regular_traits.len() > 1 {
76 let guar = self.report_trait_object_addition_traits_error(®ular_traits);
77 return Ty::new_error(tcx, guar);
78 }
79 if let Err(guar) = regular_traits.error_reported() {
81 return Ty::new_error(tcx, guar);
82 }
83
84 for (clause, span) in user_written_bounds {
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 mut projection_bounds = FxIndexMap::default();
115 for (proj, proj_span) in elaborated_projection_bounds {
116 let key = (
117 proj.skip_binder().projection_term.def_id,
118 tcx.anonymize_bound_vars(
119 proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
120 ),
121 );
122 if let Some((old_proj, old_proj_span)) =
123 projection_bounds.insert(key, (proj, proj_span))
124 && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
125 {
126 let item = tcx.item_name(proj.item_def_id());
127 self.dcx()
128 .struct_span_err(
129 span,
130 format!(
131 "conflicting associated type bounds for `{item}` when \
132 expanding trait alias"
133 ),
134 )
135 .with_span_label(
136 old_proj_span,
137 format!("`{item}` is specified to be `{}` here", old_proj.term()),
138 )
139 .with_span_label(
140 proj_span,
141 format!("`{item}` is specified to be `{}` here", proj.term()),
142 )
143 .emit();
144 }
145 }
146
147 let principal_trait = regular_traits.into_iter().next();
148
149 let mut needed_associated_types = vec![];
150 if let Some((principal_trait, ref spans)) = principal_trait {
151 let principal_trait = principal_trait.map_bound(|trait_pred| {
152 assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
153 trait_pred.trait_ref
154 });
155
156 for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
157 tcx,
158 [ClauseWithSupertraitSpan::new(
159 ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
160 *spans.last().unwrap(),
161 )],
162 )
163 .filter_only_self()
164 {
165 let clause = clause.instantiate_supertrait(tcx, principal_trait);
166 debug!("observing object predicate `{clause:?}`");
167
168 let bound_predicate = clause.kind();
169 match bound_predicate.skip_binder() {
170 ty::ClauseKind::Trait(pred) => {
171 let trait_ref =
173 tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
174 needed_associated_types.extend(
175 tcx.associated_items(pred.trait_ref.def_id)
176 .in_definition_order()
177 .filter(|item| item.kind == ty::AssocKind::Type)
179 .filter(|item| !item.is_impl_trait_in_trait())
181 .filter(|item| !tcx.generics_require_sized_self(item.def_id))
184 .map(|item| (item.def_id, trait_ref)),
185 );
186 }
187 ty::ClauseKind::Projection(pred) => {
188 let pred = bound_predicate.rebind(pred);
189 let references_self = match pred.skip_binder().term.unpack() {
192 ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
193 ty::TermKind::Const(_) => false,
195 };
196
197 if !references_self {
215 let key = (
216 pred.skip_binder().projection_term.def_id,
217 tcx.anonymize_bound_vars(
218 pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
219 ),
220 );
221 if !projection_bounds.contains_key(&key) {
222 projection_bounds.insert(key, (pred, supertrait_span));
223 }
224 }
225
226 self.check_elaborated_projection_mentions_input_lifetimes(
227 pred,
228 *spans.first().unwrap(),
229 supertrait_span,
230 );
231 }
232 _ => (),
233 }
234 }
235 }
236
237 for &(projection_bound, span) in projection_bounds.values() {
244 let def_id = projection_bound.item_def_id();
245 if tcx.generics_require_sized_self(def_id) {
246 tcx.emit_node_span_lint(
247 UNUSED_ASSOCIATED_TYPE_BOUNDS,
248 hir_id,
249 span,
250 crate::errors::UnusedAssociatedTypeBounds { span },
251 );
252 }
253 }
254
255 let mut missing_assoc_types = FxIndexSet::default();
256 let projection_bounds: Vec<_> = needed_associated_types
257 .into_iter()
258 .filter_map(|key| {
259 if let Some(assoc) = projection_bounds.get(&key) {
260 Some(*assoc)
261 } else {
262 missing_assoc_types.insert(key);
263 None
264 }
265 })
266 .collect();
267
268 if let Err(guar) = self.check_for_required_assoc_tys(
269 principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
270 missing_assoc_types,
271 potential_assoc_types,
272 hir_bounds,
273 ) {
274 return Ty::new_error(tcx, guar);
275 }
276
277 let mut duplicates = FxHashSet::default();
282 auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id()));
283
284 debug!(?principal_trait);
285 debug!(?auto_traits);
286
287 let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| {
289 trait_pred.map_bound(|trait_pred| {
290 let trait_ref = trait_pred.trait_ref;
291 assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
292 assert_eq!(trait_ref.self_ty(), dummy_self);
293
294 let span = *spans.first().unwrap();
295
296 let mut missing_type_params = vec![];
299 let generics = tcx.generics_of(trait_ref.def_id);
300 let args: Vec<_> = trait_ref
301 .args
302 .iter()
303 .enumerate()
304 .skip(1)
306 .map(|(index, arg)| {
307 if arg.walk().any(|arg| arg == dummy_self.into()) {
308 let param = &generics.own_params[index];
309 missing_type_params.push(param.name);
310 Ty::new_misc_error(tcx).into()
311 } else {
312 arg
313 }
314 })
315 .collect();
316
317 let empty_generic_args = hir_bounds.iter().any(|hir_bound| {
318 hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
319 && hir_bound.span.contains(span)
320 });
321 self.complain_about_missing_type_params(
322 missing_type_params,
323 trait_ref.def_id,
324 span,
325 empty_generic_args,
326 );
327
328 ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(
329 tcx,
330 trait_ref.def_id,
331 args,
332 ))
333 })
334 });
335
336 let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
337 bound.map_bound(|mut b| {
338 assert_eq!(b.projection_term.self_ty(), dummy_self);
339
340 let references_self = b.projection_term.args.iter().skip(1).any(|arg| {
343 if arg.walk().any(|arg| arg == dummy_self.into()) {
344 return true;
345 }
346 false
347 });
348 if references_self {
349 let guar = tcx
350 .dcx()
351 .span_delayed_bug(span, "trait object projection bounds reference `Self`");
352 b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
353 }
354
355 ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
356 tcx, b,
357 ))
358 })
359 });
360
361 let mut auto_trait_predicates: Vec<_> = auto_traits
362 .into_iter()
363 .map(|(trait_pred, _)| {
364 assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
365 assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
366
367 ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
368 })
369 .collect();
370 auto_trait_predicates.dedup();
371
372 let mut v = principal_trait_ref
375 .into_iter()
376 .chain(existential_projections)
377 .chain(auto_trait_predicates)
378 .collect::<SmallVec<[_; 8]>>();
379 v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
380 let existential_predicates = tcx.mk_poly_existential_predicates(&v);
381
382 let region_bound = if !lifetime.is_elided() {
384 self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
385 } else {
386 self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
387 if tcx.named_bound_var(lifetime.hir_id).is_some() {
389 self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
390 } else {
391 let reason =
392 if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res {
393 if let hir::Node::Ty(hir::Ty {
394 kind: hir::TyKind::Ref(parent_lifetime, _),
395 ..
396 }) = tcx.parent_hir_node(hir_id)
397 && tcx.named_bound_var(parent_lifetime.hir_id).is_none()
398 {
399 RegionInferReason::ExplicitObjectLifetime
401 } else {
402 RegionInferReason::ObjectLifetimeDefault
403 }
404 } else {
405 RegionInferReason::ExplicitObjectLifetime
406 };
407 self.re_infer(span, reason)
408 }
409 })
410 };
411 debug!(?region_bound);
412
413 Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
414 }
415
416 fn check_elaborated_projection_mentions_input_lifetimes(
421 &self,
422 pred: ty::PolyProjectionPredicate<'tcx>,
423 span: Span,
424 supertrait_span: Span,
425 ) {
426 let tcx = self.tcx();
427
428 let late_bound_in_projection_term =
436 tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
437 let late_bound_in_term =
438 tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
439 debug!(?late_bound_in_projection_term);
440 debug!(?late_bound_in_term);
441
442 self.validate_late_bound_regions(
448 late_bound_in_projection_term,
449 late_bound_in_term,
450 |br_name| {
451 let item_name = tcx.item_name(pred.item_def_id());
452 struct_span_code_err!(
453 self.dcx(),
454 span,
455 E0582,
456 "binding for associated type `{}` references {}, \
457 which does not appear in the trait input types",
458 item_name,
459 br_name
460 )
461 .with_span_label(supertrait_span, "due to this supertrait")
462 },
463 );
464 }
465}
466
467fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
468 tcx: TyCtxt<'tcx>,
469 t: T,
470 guar: ErrorGuaranteed,
471) -> T {
472 t.fold_with(&mut BottomUpFolder {
473 tcx,
474 ty_op: |ty| {
475 if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty }
476 },
477 lt_op: |lt| lt,
478 ct_op: |ct| ct,
479 })
480}