1use std::collections::BTreeMap;
5
6use rustc_data_structures::fx::FxHashSet;
7use rustc_errors::{ErrorGuaranteed, MultiSpan};
8use rustc_hir as hir;
9use rustc_hir::ItemKind;
10use rustc_hir::def_id::{DefId, LocalDefId};
11use rustc_hir::lang_items::LangItem;
12use rustc_infer::infer::{self, RegionResolutionError, SubregionOrigin, TyCtxtInferExt};
13use rustc_infer::traits::Obligation;
14use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
15use rustc_middle::ty::print::PrintTraitRefExt as _;
16use rustc_middle::ty::{
17 self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params,
18};
19use rustc_span::{DUMMY_SP, Span, sym};
20use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
21use rustc_trait_selection::traits::misc::{
22 ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
23 type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
24};
25use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
26use tracing::debug;
27
28use crate::errors;
29
30pub(super) fn check_trait<'tcx>(
31 tcx: TyCtxt<'tcx>,
32 trait_def_id: DefId,
33 impl_def_id: LocalDefId,
34 impl_header: ty::ImplTraitHeader<'tcx>,
35) -> Result<(), ErrorGuaranteed> {
36 let lang_items = tcx.lang_items();
37 let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
38 checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
39 checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
40 checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
41 checker.check(lang_items.const_param_ty_trait(), |checker| {
42 visit_implementation_of_const_param_ty(checker)
43 })?;
44 checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
45 checker
46 .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
47 checker.check(
48 lang_items.coerce_pointee_validated_trait(),
49 visit_implementation_of_coerce_pointee_validity,
50 )?;
51 Ok(())
52}
53
54struct Checker<'tcx> {
55 tcx: TyCtxt<'tcx>,
56 trait_def_id: DefId,
57 impl_def_id: LocalDefId,
58 impl_header: ty::ImplTraitHeader<'tcx>,
59}
60
61impl<'tcx> Checker<'tcx> {
62 fn check(
63 &self,
64 trait_def_id: Option<DefId>,
65 f: impl FnOnce(&Self) -> Result<(), ErrorGuaranteed>,
66 ) -> Result<(), ErrorGuaranteed> {
67 if Some(self.trait_def_id) == trait_def_id { f(self) } else { Ok(()) }
68 }
69}
70
71fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
72 let tcx = checker.tcx;
73 let impl_did = checker.impl_def_id;
74 match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() {
76 ty::Adt(def, _) if def.did().is_local() => return Ok(()),
77 ty::Error(_) => return Ok(()),
78 _ => {}
79 }
80
81 let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
82
83 Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem {
84 span: impl_.self_ty.span,
85 trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id),
86 }))
87}
88
89fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
90 let tcx = checker.tcx;
91 let impl_header = checker.impl_header;
92 let impl_did = checker.impl_def_id;
93 debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
94
95 let self_type = impl_header.trait_ref.instantiate_identity().self_ty();
96 debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
97
98 let param_env = tcx.param_env(impl_did);
99 assert!(!self_type.has_escaping_bound_vars());
100
101 debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
102
103 if let ty::ImplPolarity::Negative = impl_header.polarity {
104 return Ok(());
105 }
106
107 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
108 match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
109 Ok(()) => Ok(()),
110 Err(CopyImplementationError::InfringingFields(fields)) => {
111 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
112 Err(infringing_fields_error(
113 tcx,
114 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
115 LangItem::Copy,
116 impl_did,
117 span,
118 ))
119 }
120 Err(CopyImplementationError::NotAnAdt) => {
121 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
122 Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
123 }
124 Err(CopyImplementationError::HasDestructor) => {
125 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
126 Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
127 }
128 Err(CopyImplementationError::HasUnsafeFields) => {
129 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
130 Err(tcx
131 .dcx()
132 .span_delayed_bug(span, format!("cannot implement `Copy` for `{}`", self_type)))
133 }
134 }
135}
136
137fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
138 let tcx = checker.tcx;
139 let header = checker.impl_header;
140 let impl_did = checker.impl_def_id;
141 let self_type = header.trait_ref.instantiate_identity().self_ty();
142 assert!(!self_type.has_escaping_bound_vars());
143
144 let param_env = tcx.param_env(impl_did);
145
146 if let ty::ImplPolarity::Negative | ty::ImplPolarity::Reservation = header.polarity {
147 return Ok(());
148 }
149
150 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
151 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
152 Ok(()) => Ok(()),
153 Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
154 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
155 Err(infringing_fields_error(
156 tcx,
157 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
158 LangItem::ConstParamTy,
159 impl_did,
160 span,
161 ))
162 }
163 Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
164 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
165 Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
166 }
167 Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
168 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
169 Err(infringing_fields_error(
170 tcx,
171 infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
172 LangItem::ConstParamTy,
173 impl_did,
174 span,
175 ))
176 }
177 Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
178 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
179 Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
180 }
181 }
182}
183
184fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
185 let tcx = checker.tcx;
186 let impl_did = checker.impl_def_id;
187 debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
188
189 tcx.ensure_ok().coerce_unsized_info(impl_did)
193}
194
195fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
196 span.ctxt()
197 .outer_expn_data()
198 .macro_def_id
199 .is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id))
200}
201
202fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
203 let tcx = checker.tcx;
204 let impl_did = checker.impl_def_id;
205 let trait_ref = checker.impl_header.trait_ref.instantiate_identity();
206 debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
207
208 let span = tcx.def_span(impl_did);
209 let trait_name = "DispatchFromDyn";
210
211 let source = trait_ref.self_ty();
212 let target = {
213 assert!(tcx.is_lang_item(trait_ref.def_id, LangItem::DispatchFromDyn));
214
215 trait_ref.args.type_at(1)
216 };
217
218 let mut res = Ok(());
221 tcx.for_each_relevant_impl(
222 tcx.require_lang_item(LangItem::CoerceUnsized, span),
223 source,
224 |impl_def_id| {
225 res = res.and(tcx.ensure_ok().coerce_unsized_info(impl_def_id));
226 },
227 );
228 res?;
229
230 debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
231
232 let param_env = tcx.param_env(impl_did);
233
234 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
235 let cause = ObligationCause::misc(span, impl_did);
236
237 match (source.kind(), target.kind()) {
246 (&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
247 if pat_a != pat_b {
248 return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
249 span,
250 trait_name,
251 pat_a: pat_a.to_string(),
252 pat_b: pat_b.to_string(),
253 }));
254 }
255 Ok(())
256 }
257
258 (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
259 if r_a == *r_b && mutbl_a == *mutbl_b =>
260 {
261 Ok(())
262 }
263 (&ty::RawPtr(_, a_mutbl), &ty::RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
264 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
265 if def_a.is_struct() && def_b.is_struct() =>
266 {
267 if def_a != def_b {
268 let source_path = tcx.def_path_str(def_a.did());
269 let target_path = tcx.def_path_str(def_b.did());
270 return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
271 span,
272 trait_name,
273 note: true,
274 source_path,
275 target_path,
276 }));
277 }
278
279 if def_a.repr().c() || def_a.repr().packed() {
280 return Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span }));
281 }
282
283 let fields = &def_a.non_enum_variant().fields;
284
285 let mut res = Ok(());
286 let coerced_fields = fields
287 .iter_enumerated()
288 .filter_map(|(i, field)| {
289 let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
291 if tcx
292 .try_normalize_erasing_regions(
293 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
294 unnormalized_ty,
295 )
296 .unwrap_or(unnormalized_ty)
297 .is_phantom_data()
298 {
299 return None;
300 }
301
302 let ty_a = field.ty(tcx, args_a);
303 let ty_b = field.ty(tcx, args_b);
304
305 if ty_a == ty_b {
307 if let Ok(layout) =
312 tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
313 && layout.is_1zst()
314 && !ty_a.has_non_region_param()
315 {
316 return None;
318 }
319
320 res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
321 span,
322 name: field.ident(tcx),
323 ty: ty_a,
324 }));
325
326 None
327 } else {
328 Some((i, ty_a, ty_b, tcx.def_span(field.did)))
329 }
330 })
331 .collect::<Vec<_>>();
332 res?;
333
334 if coerced_fields.is_empty() {
335 return Err(tcx.dcx().emit_err(errors::CoerceNoField {
336 span,
337 trait_name,
338 note: true,
339 }));
340 } else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] {
341 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
342 ocx.register_obligation(Obligation::new(
343 tcx,
344 cause.clone(),
345 param_env,
346 ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
347 ));
348 let errors = ocx.evaluate_obligations_error_on_ambiguity();
349 if !errors.is_empty() {
350 if is_from_coerce_pointee_derive(tcx, span) {
351 return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
352 span,
353 trait_name,
354 ty: trait_ref.self_ty(),
355 field_span,
356 field_ty: ty_a,
357 }));
358 } else {
359 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
360 }
361 }
362
363 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
365
366 Ok(())
367 } else {
368 return Err(tcx.dcx().emit_err(errors::CoerceMulti {
369 span,
370 trait_name,
371 number: coerced_fields.len(),
372 fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
373 }));
374 }
375 }
376 _ => Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name })),
377 }
378}
379
380pub(crate) fn coerce_unsized_info<'tcx>(
381 tcx: TyCtxt<'tcx>,
382 impl_did: LocalDefId,
383) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
384 debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
385 let span = tcx.def_span(impl_did);
386 let trait_name = "CoerceUnsized";
387
388 let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, span);
389 let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span);
390
391 let source = tcx.type_of(impl_did).instantiate_identity();
392 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity();
393
394 assert_eq!(trait_ref.def_id, coerce_unsized_trait);
395 let target = trait_ref.args.type_at(1);
396 debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
397
398 let param_env = tcx.param_env(impl_did);
399 assert!(!source.has_escaping_bound_vars());
400
401 debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
402
403 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
404 let cause = ObligationCause::misc(span, impl_did);
405 let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
406 mt_b: ty::TypeAndMut<'tcx>,
407 mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
408 if mt_a.mutbl < mt_b.mutbl {
409 infcx
410 .err_ctxt()
411 .report_mismatched_types(
412 &cause,
413 param_env,
414 mk_ptr(mt_b.ty),
415 target,
416 ty::error::TypeError::Mutability,
417 )
418 .emit();
419 }
420 (mt_a.ty, mt_b.ty, unsize_trait, None, span)
421 };
422 let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
423 (&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
424 if pat_a != pat_b {
425 return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
426 span,
427 trait_name,
428 pat_a: pat_a.to_string(),
429 pat_b: pat_b.to_string(),
430 }));
431 }
432 (ty_a, ty_b, coerce_unsized_trait, None, span)
433 }
434
435 (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
436 infcx.sub_regions(SubregionOrigin::RelateObjectBound(span), r_b, r_a);
437 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
438 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
439 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
440 }
441
442 (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
443 | (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
444 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
445 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
446 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
447 }
448
449 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
450 if def_a.is_struct() && def_b.is_struct() =>
451 {
452 if def_a != def_b {
453 let source_path = tcx.def_path_str(def_a.did());
454 let target_path = tcx.def_path_str(def_b.did());
455 return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
456 span,
457 trait_name,
458 note: true,
459 source_path,
460 target_path,
461 }));
462 }
463
464 let fields = &def_a.non_enum_variant().fields;
504 let diff_fields = fields
505 .iter_enumerated()
506 .filter_map(|(i, f)| {
507 let (a, b) = (f.ty(tcx, args_a), f.ty(tcx, args_b));
508
509 let unnormalized_ty = tcx.type_of(f.did).instantiate_identity();
511 if tcx
512 .try_normalize_erasing_regions(
513 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
514 unnormalized_ty,
515 )
516 .unwrap_or(unnormalized_ty)
517 .is_phantom_data()
518 {
519 return None;
520 }
521
522 if a == b {
532 return None;
533 }
534
535 Some((i, a, b, tcx.def_span(f.did)))
538 })
539 .collect::<Vec<_>>();
540
541 if diff_fields.is_empty() {
542 return Err(tcx.dcx().emit_err(errors::CoerceNoField {
543 span,
544 trait_name,
545 note: true,
546 }));
547 } else if diff_fields.len() > 1 {
548 let item = tcx.hir_expect_item(impl_did);
549 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
550 &item.kind
551 {
552 of_trait.trait_ref.path.span
553 } else {
554 tcx.def_span(impl_did)
555 };
556
557 return Err(tcx.dcx().emit_err(errors::CoerceMulti {
558 span,
559 trait_name,
560 number: diff_fields.len(),
561 fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
562 }));
563 }
564
565 let (i, a, b, field_span) = diff_fields[0];
566 let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
567 (a, b, coerce_unsized_trait, Some(kind), field_span)
568 }
569
570 _ => {
571 return Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name }));
572 }
573 };
574
575 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
577 let cause = traits::ObligationCause::misc(span, impl_did);
578 let obligation = Obligation::new(
579 tcx,
580 cause,
581 param_env,
582 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
583 );
584 ocx.register_obligation(obligation);
585 let errors = ocx.evaluate_obligations_error_on_ambiguity();
586
587 if !errors.is_empty() {
588 if is_from_coerce_pointee_derive(tcx, span) {
589 return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
590 span,
591 trait_name,
592 ty: trait_ref.self_ty(),
593 field_span,
594 field_ty: source,
595 }));
596 } else {
597 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
598 }
599 }
600
601 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
603
604 Ok(CoerceUnsizedInfo { custom_kind: kind })
605}
606
607fn infringing_fields_error<'tcx>(
608 tcx: TyCtxt<'tcx>,
609 infringing_tys: impl Iterator<Item = (Span, Ty<'tcx>, InfringingFieldsReason<'tcx>)>,
610 lang_item: LangItem,
611 impl_did: LocalDefId,
612 impl_span: Span,
613) -> ErrorGuaranteed {
614 let trait_did = tcx.require_lang_item(lang_item, impl_span);
615
616 let trait_name = tcx.def_path_str(trait_did);
617
618 let mut errors: BTreeMap<_, Vec<_>> = Default::default();
621 let mut bounds = vec![];
622
623 let mut seen_tys = FxHashSet::default();
624
625 let mut label_spans = Vec::new();
626
627 for (span, ty, reason) in infringing_tys {
628 if !seen_tys.insert(ty) {
630 continue;
631 }
632
633 label_spans.push(span);
634
635 match reason {
636 InfringingFieldsReason::Fulfill(fulfillment_errors) => {
637 for error in fulfillment_errors {
638 let error_predicate = error.obligation.predicate;
639 if error_predicate != error.root_obligation.predicate {
645 errors
646 .entry((ty.to_string(), error_predicate.to_string()))
647 .or_default()
648 .push(error.obligation.cause.span);
649 }
650 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
651 trait_ref,
652 polarity: ty::PredicatePolarity::Positive,
653 ..
654 })) = error_predicate.kind().skip_binder()
655 {
656 let ty = trait_ref.self_ty();
657 if let ty::Param(_) = ty.kind() {
658 bounds.push((
659 format!("{ty}"),
660 trait_ref.print_trait_sugared().to_string(),
661 Some(trait_ref.def_id),
662 ));
663 }
664 }
665 }
666 }
667 InfringingFieldsReason::Regions(region_errors) => {
668 for error in region_errors {
669 let ty = ty.to_string();
670 match error {
671 RegionResolutionError::ConcreteFailure(origin, a, b) => {
672 let predicate = format!("{b}: {a}");
673 errors
674 .entry((ty.clone(), predicate.clone()))
675 .or_default()
676 .push(origin.span());
677 if let ty::RegionKind::ReEarlyParam(ebr) = b.kind()
678 && ebr.is_named()
679 {
680 bounds.push((b.to_string(), a.to_string(), None));
681 }
682 }
683 RegionResolutionError::GenericBoundFailure(origin, a, b) => {
684 let predicate = format!("{a}: {b}");
685 errors
686 .entry((ty.clone(), predicate.clone()))
687 .or_default()
688 .push(origin.span());
689 if let infer::region_constraints::GenericKind::Param(_) = a {
690 bounds.push((a.to_string(), b.to_string(), None));
691 }
692 }
693 _ => continue,
694 }
695 }
696 }
697 }
698 }
699 let mut notes = Vec::new();
700 for ((ty, error_predicate), spans) in errors {
701 let span: MultiSpan = spans.into();
702 notes.push(errors::ImplForTyRequires {
703 span,
704 error_predicate,
705 trait_name: trait_name.clone(),
706 ty,
707 });
708 }
709
710 let mut err = tcx.dcx().create_err(errors::TraitCannotImplForTy {
711 span: impl_span,
712 trait_name,
713 label_spans,
714 notes,
715 });
716
717 suggest_constraining_type_params(
718 tcx,
719 tcx.hir_get_generics(impl_did).expect("impls always have generics"),
720 &mut err,
721 bounds
722 .iter()
723 .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
724 None,
725 );
726
727 err.emit()
728}
729
730fn visit_implementation_of_coerce_pointee_validity(
731 checker: &Checker<'_>,
732) -> Result<(), ErrorGuaranteed> {
733 let tcx = checker.tcx;
734 let self_ty = tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().self_ty();
735 let span = tcx.def_span(checker.impl_def_id);
736 if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
737 return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
738 }
739 let ty::Adt(def, _args) = self_ty.kind() else {
740 return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span }));
741 };
742 let did = def.did();
743 let span = tcx.def_span(did);
745 if !def.is_struct() {
746 return Err(tcx
747 .dcx()
748 .emit_err(errors::CoercePointeeNotStruct { span, kind: def.descr().into() }));
749 }
750 if !def.repr().transparent() {
751 return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span }));
752 }
753 if def.all_fields().next().is_none() {
754 return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span }));
755 }
756 Ok(())
757}