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 #[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 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 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.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 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 .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 let references_self = match pred.skip_binder().term.unpack() {
140 ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
141 ty::TermKind::Const(_) => false,
143 };
144
145 if !references_self {
163 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 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 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 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 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(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 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 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 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 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 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 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 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 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}