]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_analysis/src/coherence/builtin.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / compiler / rustc_hir_analysis / src / coherence / builtin.rs
CommitLineData
2b03887a
FG
1//! Check properties that are required by built-in traits and set
2//! up data structures required by type-checking/codegen.
3
781aab86
FG
4use crate::errors;
5
353b0b11 6use rustc_data_structures::fx::FxHashSet;
781aab86 7use rustc_errors::{ErrorGuaranteed, MultiSpan};
2b03887a
FG
8use rustc_hir as hir;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_hir::lang_items::LangItem;
11use rustc_hir::ItemKind;
2b03887a 12use rustc_infer::infer::outlives::env::OutlivesEnvironment;
e8be2606 13use rustc_infer::infer::TyCtxtInferExt;
9c376795 14use rustc_infer::infer::{self, RegionResolutionError};
353b0b11 15use rustc_infer::traits::Obligation;
2b03887a 16use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
31ef2f64 17use rustc_middle::ty::print::PrintTraitRefExt as _;
9ffffee4 18use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
c620b35d 19use rustc_span::{Span, DUMMY_SP};
2b03887a 20use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
9c376795 21use rustc_trait_selection::traits::misc::{
49aad941
FG
22 type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
23 ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
9c376795 24};
353b0b11 25use rustc_trait_selection::traits::ObligationCtxt;
2b03887a
FG
26use rustc_trait_selection::traits::{self, ObligationCause};
27use std::collections::BTreeMap;
28
c620b35d
FG
29pub(super) fn check_trait<'tcx>(
30 tcx: TyCtxt<'tcx>,
31 trait_def_id: DefId,
32 impl_def_id: LocalDefId,
33 impl_header: ty::ImplTraitHeader<'tcx>,
34) -> Result<(), ErrorGuaranteed> {
2b03887a 35 let lang_items = tcx.lang_items();
c620b35d 36 let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
c0240ec0
FG
37 let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop);
38 res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
39 res = res.and(
40 checker.check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty),
41 );
42 res = res.and(
43 checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized),
44 );
45 res.and(
46 checker
47 .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn),
48 )
2b03887a
FG
49}
50
51struct Checker<'tcx> {
52 tcx: TyCtxt<'tcx>,
53 trait_def_id: DefId,
c620b35d
FG
54 impl_def_id: LocalDefId,
55 impl_header: ty::ImplTraitHeader<'tcx>,
2b03887a
FG
56}
57
58impl<'tcx> Checker<'tcx> {
c620b35d
FG
59 fn check(
60 &self,
61 trait_def_id: Option<DefId>,
62 f: impl FnOnce(&Self) -> Result<(), ErrorGuaranteed>,
63 ) -> Result<(), ErrorGuaranteed> {
64 if Some(self.trait_def_id) == trait_def_id { f(self) } else { Ok(()) }
2b03887a
FG
65 }
66}
67
c620b35d
FG
68fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
69 let tcx = checker.tcx;
70 let impl_did = checker.impl_def_id;
2b03887a 71 // Destructors only work on local ADT types.
c620b35d 72 match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() {
c0240ec0
FG
73 ty::Adt(def, _) if def.did().is_local() => return Ok(()),
74 ty::Error(_) => return Ok(()),
2b03887a
FG
75 _ => {}
76 }
77
9ffffee4 78 let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
2b03887a 79
c0240ec0 80 Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }))
2b03887a
FG
81}
82
c620b35d
FG
83fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
84 let tcx = checker.tcx;
85 let impl_header = checker.impl_header;
86 let impl_did = checker.impl_def_id;
2b03887a
FG
87 debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
88
c620b35d 89 let self_type = impl_header.trait_ref.instantiate_identity().self_ty();
2b03887a
FG
90 debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
91
92 let param_env = tcx.param_env(impl_did);
93 assert!(!self_type.has_escaping_bound_vars());
94
95 debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
96
c620b35d
FG
97 if let ty::ImplPolarity::Negative = impl_header.polarity {
98 return Ok(());
99 }
2b03887a 100
c620b35d 101 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
9c376795 102 match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
c0240ec0 103 Ok(()) => Ok(()),
49aad941 104 Err(CopyImplementationError::InfringingFields(fields)) => {
c620b35d 105 let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
c0240ec0 106 Err(infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span))
2b03887a
FG
107 }
108 Err(CopyImplementationError::NotAnAdt) => {
c620b35d 109 let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
c0240ec0 110 Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
2b03887a
FG
111 }
112 Err(CopyImplementationError::HasDestructor) => {
c620b35d 113 let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
c0240ec0 114 Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
2b03887a
FG
115 }
116 }
117}
118
c620b35d
FG
119fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
120 let tcx = checker.tcx;
121 let header = checker.impl_header;
122 let impl_did = checker.impl_def_id;
123 let self_type = header.trait_ref.instantiate_identity().self_ty();
49aad941
FG
124 assert!(!self_type.has_escaping_bound_vars());
125
126 let param_env = tcx.param_env(impl_did);
127
c620b35d
FG
128 if let ty::ImplPolarity::Negative = header.polarity {
129 return Ok(());
130 }
49aad941 131
c620b35d 132 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
49aad941 133 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
c0240ec0 134 Ok(()) => Ok(()),
49aad941 135 Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
c620b35d 136 let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
c0240ec0 137 Err(infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span))
49aad941
FG
138 }
139 Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
c620b35d 140 let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
c0240ec0 141 Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
49aad941
FG
142 }
143 }
144}
145
c620b35d
FG
146fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
147 let tcx = checker.tcx;
148 let impl_did = checker.impl_def_id;
2b03887a
FG
149 debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
150
151 // Just compute this for the side-effects, in particular reporting
152 // errors; other parts of the code may demand it for the info of
153 // course.
154 let span = tcx.def_span(impl_did);
c0240ec0 155 tcx.at(span).ensure().coerce_unsized_info(impl_did)
2b03887a
FG
156}
157
c620b35d
FG
158fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
159 let tcx = checker.tcx;
160 let impl_did = checker.impl_def_id;
161 let trait_ref = checker.impl_header.trait_ref.instantiate_identity();
2b03887a
FG
162 debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
163
9ffffee4 164 let span = tcx.def_span(impl_did);
2b03887a
FG
165
166 let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
167
c620b35d 168 let source = trait_ref.self_ty();
2b03887a
FG
169 assert!(!source.has_escaping_bound_vars());
170 let target = {
2b03887a
FG
171 assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
172
add651ee 173 trait_ref.args.type_at(1)
2b03887a
FG
174 };
175
176 debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
177
178 let param_env = tcx.param_env(impl_did);
179
2b03887a 180 let infcx = tcx.infer_ctxt().build();
9ffffee4 181 let cause = ObligationCause::misc(span, impl_did);
2b03887a 182
781aab86
FG
183 // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw
184 // pointers. This is enforced here: we only allow impls for references, raw pointers, and things
185 // that are effectively repr(transparent) newtypes around types that already hav a
186 // DispatchedFromDyn impl. We cannot literally use repr(transparent) on those tpyes since some
187 // of them support an allocator, but we ensure that for the cases where the type implements this
188 // trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else
189 // in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
190 // even if they do not carry that attribute.
ed00b5ec 191 use rustc_type_ir::TyKind::*;
2b03887a 192 match (source.kind(), target.kind()) {
e8be2606 193 (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) if r_a == *r_b && mutbl_a == *mutbl_b => {
c0240ec0
FG
194 Ok(())
195 }
e8be2606 196 (&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
add651ee 197 (&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => {
2b03887a
FG
198 if def_a != def_b {
199 let source_path = tcx.def_path_str(def_a.did());
200 let target_path = tcx.def_path_str(def_b.did());
201
c0240ec0 202 return Err(tcx.dcx().emit_err(errors::DispatchFromDynCoercion {
781aab86
FG
203 span,
204 trait_name: "DispatchFromDyn",
205 note: true,
206 source_path,
207 target_path,
c0240ec0 208 }));
2b03887a
FG
209 }
210
c0240ec0 211 let mut res = Ok(());
2b03887a 212 if def_a.repr().c() || def_a.repr().packed() {
c0240ec0 213 res = Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span }));
2b03887a
FG
214 }
215
216 let fields = &def_a.non_enum_variant().fields;
217
218 let coerced_fields = fields
219 .iter()
220 .filter(|field| {
add651ee
FG
221 let ty_a = field.ty(tcx, args_a);
222 let ty_b = field.ty(tcx, args_b);
2b03887a
FG
223
224 if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
781aab86
FG
225 if layout.is_1zst() {
226 // ignore 1-ZST fields
2b03887a
FG
227 return false;
228 }
229 }
230
e8be2606
FG
231 if ty_a == ty_b {
232 res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
233 span,
234 name: field.name,
235 ty: ty_a,
236 }));
2b03887a 237
e8be2606 238 return false;
2b03887a
FG
239 }
240
241 return true;
242 })
243 .collect::<Vec<_>>();
244
245 if coerced_fields.is_empty() {
c0240ec0 246 res = Err(tcx.dcx().emit_err(errors::DispatchFromDynSingle {
781aab86
FG
247 span,
248 trait_name: "DispatchFromDyn",
249 note: true,
c0240ec0 250 }));
2b03887a 251 } else if coerced_fields.len() > 1 {
c0240ec0 252 res = Err(tcx.dcx().emit_err(errors::DispatchFromDynMulti {
781aab86
FG
253 span,
254 coercions_note: true,
255 number: coerced_fields.len(),
256 coercions: coerced_fields
257 .iter()
258 .map(|field| {
259 format!(
260 "`{}` (`{}` to `{}`)",
261 field.name,
262 field.ty(tcx, args_a),
263 field.ty(tcx, args_b),
264 )
265 })
266 .collect::<Vec<_>>()
267 .join(", "),
c0240ec0 268 }));
2b03887a 269 } else {
31ef2f64 270 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
353b0b11
FG
271 for field in coerced_fields {
272 ocx.register_obligation(Obligation::new(
273 tcx,
274 cause.clone(),
275 param_env,
49aad941
FG
276 ty::TraitRef::new(
277 tcx,
2b03887a 278 dispatch_from_dyn_trait,
add651ee 279 [field.ty(tcx, args_a), field.ty(tcx, args_b)],
49aad941 280 ),
353b0b11
FG
281 ));
282 }
283 let errors = ocx.select_all_or_error();
2b03887a 284 if !errors.is_empty() {
c0240ec0 285 res = Err(infcx.err_ctxt().report_fulfillment_errors(errors));
2b03887a
FG
286 }
287
288 // Finally, resolve all regions.
289 let outlives_env = OutlivesEnvironment::new(param_env);
c0240ec0 290 res = res.and(ocx.resolve_regions_and_report_errors(impl_did, &outlives_env));
2b03887a 291 }
c0240ec0 292 res
2b03887a 293 }
c0240ec0
FG
294 _ => Err(tcx
295 .dcx()
296 .emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" })),
2b03887a
FG
297 }
298}
299
c0240ec0
FG
300pub fn coerce_unsized_info<'tcx>(
301 tcx: TyCtxt<'tcx>,
302 impl_did: LocalDefId,
303) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
2b03887a 304 debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
2b03887a
FG
305 let span = tcx.def_span(impl_did);
306
307 let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
308
49aad941 309 let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
2b03887a 310
add651ee
FG
311 let source = tcx.type_of(impl_did).instantiate_identity();
312 let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
2b03887a 313 assert_eq!(trait_ref.def_id, coerce_unsized_trait);
add651ee 314 let target = trait_ref.args.type_at(1);
2b03887a
FG
315 debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
316
317 let param_env = tcx.param_env(impl_did);
318 assert!(!source.has_escaping_bound_vars());
319
2b03887a
FG
320 debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
321
322 let infcx = tcx.infer_ctxt().build();
9ffffee4 323 let cause = ObligationCause::misc(span, impl_did);
2b03887a
FG
324 let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
325 mt_b: ty::TypeAndMut<'tcx>,
326 mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
487cf647 327 if mt_a.mutbl < mt_b.mutbl {
2b03887a
FG
328 infcx
329 .err_ctxt()
330 .report_mismatched_types(
331 &cause,
332 mk_ptr(mt_b.ty),
333 target,
334 ty::error::TypeError::Mutability,
335 )
336 .emit();
337 }
338 (mt_a.ty, mt_b.ty, unsize_trait, None)
339 };
340 let (source, target, trait_def_id, kind) = match (source.kind(), target.kind()) {
341 (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
342 infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
343 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
344 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
fe692bf9 345 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
2b03887a
FG
346 }
347
e8be2606
FG
348 (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
349 ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
350 ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
351 &|ty| Ty::new_imm_ptr(tcx, ty),
352 ),
2b03887a 353
e8be2606
FG
354 (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
355 ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
356 ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
357 &|ty| Ty::new_imm_ptr(tcx, ty),
358 ),
2b03887a 359
add651ee 360 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
2b03887a
FG
361 if def_a.is_struct() && def_b.is_struct() =>
362 {
363 if def_a != def_b {
364 let source_path = tcx.def_path_str(def_a.did());
365 let target_path = tcx.def_path_str(def_b.did());
c0240ec0 366 return Err(tcx.dcx().emit_err(errors::DispatchFromDynSame {
2b03887a 367 span,
781aab86
FG
368 trait_name: "CoerceUnsized",
369 note: true,
2b03887a 370 source_path,
781aab86 371 target_path,
c0240ec0 372 }));
2b03887a
FG
373 }
374
375 // Here we are considering a case of converting
9ffffee4 376 // `S<P0...Pn>` to `S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
2b03887a
FG
377 // which acts like a pointer to `U`, but carries along some extra data of type `T`:
378 //
379 // struct Foo<T, U> {
380 // extra: T,
381 // ptr: *mut U,
382 // }
383 //
384 // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
385 // to `Foo<T, [i32]>`. That impl would look like:
386 //
387 // impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
388 //
389 // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
390 // when this coercion occurs, we would be changing the
391 // field `ptr` from a thin pointer of type `*mut [i32;
392 // 3]` to a fat pointer of type `*mut [i32]` (with
9c376795 393 // extra data `3`). **The purpose of this check is to
2b03887a
FG
394 // make sure that we know how to do this conversion.**
395 //
396 // To check if this impl is legal, we would walk down
397 // the fields of `Foo` and consider their types with
c620b35d 398 // both generic parameters. We are looking to find that
2b03887a
FG
399 // exactly one (non-phantom) field has changed its
400 // type, which we will expect to be the pointer that
401 // is becoming fat (we could probably generalize this
402 // to multiple thin pointers of the same type becoming
403 // fat, but we don't). In this case:
404 //
405 // - `extra` has type `T` before and type `T` after
406 // - `ptr` has type `*mut U` before and type `*mut V` after
407 //
408 // Since just one field changed, we would then check
409 // that `*mut U: CoerceUnsized<*mut V>` is implemented
410 // (in other words, that we know how to do this
411 // conversion). This will work out because `U:
412 // Unsize<V>`, and we have a builtin rule that `*mut
413 // U` can be coerced to `*mut V` if `U: Unsize<V>`.
414 let fields = &def_a.non_enum_variant().fields;
415 let diff_fields = fields
353b0b11 416 .iter_enumerated()
2b03887a 417 .filter_map(|(i, f)| {
add651ee 418 let (a, b) = (f.ty(tcx, args_a), f.ty(tcx, args_b));
2b03887a 419
add651ee 420 if tcx.type_of(f.did).instantiate_identity().is_phantom_data() {
2b03887a
FG
421 // Ignore PhantomData fields
422 return None;
423 }
424
425 // Ignore fields that aren't changed; it may
426 // be that we could get away with subtyping or
427 // something more accepting, but we use
428 // equality because we want to be able to
429 // perform this check without computing
e8be2606
FG
430 // variance or constraining opaque types' hidden types.
431 // (This is because we may have to evaluate constraint
2b03887a
FG
432 // expressions in the course of execution.)
433 // See e.g., #41936.
e8be2606
FG
434 if a == b {
435 return None;
2b03887a
FG
436 }
437
438 // Collect up all fields that were significantly changed
439 // i.e., those that contain T in coerce_unsized T -> U
440 Some((i, a, b))
441 })
442 .collect::<Vec<_>>();
443
444 if diff_fields.is_empty() {
c0240ec0 445 return Err(tcx.dcx().emit_err(errors::CoerceUnsizedOneField {
2b03887a 446 span,
781aab86
FG
447 trait_name: "CoerceUnsized",
448 note: true,
c0240ec0 449 }));
2b03887a
FG
450 } else if diff_fields.len() > 1 {
451 let item = tcx.hir().expect_item(impl_did);
9c376795
FG
452 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(t), .. }) = &item.kind {
453 t.path.span
454 } else {
455 tcx.def_span(impl_did)
456 };
2b03887a 457
c0240ec0 458 return Err(tcx.dcx().emit_err(errors::CoerceUnsizedMulti {
2b03887a 459 span,
781aab86
FG
460 coercions_note: true,
461 number: diff_fields.len(),
462 coercions: diff_fields
2b03887a 463 .iter()
781aab86 464 .map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b))
2b03887a 465 .collect::<Vec<_>>()
781aab86 466 .join(", "),
c0240ec0 467 }));
2b03887a
FG
468 }
469
470 let (i, a, b) = diff_fields[0];
471 let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
472 (a, b, coerce_unsized_trait, Some(kind))
473 }
474
475 _ => {
c0240ec0
FG
476 return Err(tcx
477 .dcx()
478 .emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" }));
2b03887a
FG
479 }
480 };
481
482 // Register an obligation for `A: Trait<B>`.
31ef2f64 483 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
9ffffee4 484 let cause = traits::ObligationCause::misc(span, impl_did);
49aad941
FG
485 let obligation = Obligation::new(
486 tcx,
487 cause,
488 param_env,
489 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
490 );
353b0b11
FG
491 ocx.register_obligation(obligation);
492 let errors = ocx.select_all_or_error();
2b03887a 493 if !errors.is_empty() {
ed00b5ec 494 infcx.err_ctxt().report_fulfillment_errors(errors);
2b03887a
FG
495 }
496
497 // Finally, resolve all regions.
498 let outlives_env = OutlivesEnvironment::new(param_env);
353b0b11 499 let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
2b03887a 500
c0240ec0 501 Ok(CoerceUnsizedInfo { custom_kind: kind })
2b03887a 502}
49aad941
FG
503
504fn infringing_fields_error(
505 tcx: TyCtxt<'_>,
506 fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>,
507 lang_item: LangItem,
508 impl_did: LocalDefId,
509 impl_span: Span,
510) -> ErrorGuaranteed {
511 let trait_did = tcx.require_lang_item(lang_item, Some(impl_span));
512
513 let trait_name = tcx.def_path_str(trait_did);
514
49aad941
FG
515 // We'll try to suggest constraining type parameters to fulfill the requirements of
516 // their `Copy` implementation.
517 let mut errors: BTreeMap<_, Vec<_>> = Default::default();
518 let mut bounds = vec![];
519
520 let mut seen_tys = FxHashSet::default();
521
781aab86
FG
522 let mut label_spans = Vec::new();
523
49aad941
FG
524 for (field, ty, reason) in fields {
525 // Only report an error once per type.
526 if !seen_tys.insert(ty) {
527 continue;
528 }
529
781aab86 530 label_spans.push(tcx.def_span(field.did));
49aad941
FG
531
532 match reason {
533 InfringingFieldsReason::Fulfill(fulfillment_errors) => {
534 for error in fulfillment_errors {
535 let error_predicate = error.obligation.predicate;
536 // Only note if it's not the root obligation, otherwise it's trivial and
537 // should be self-explanatory (i.e. a field literally doesn't implement Copy).
538
539 // FIXME: This error could be more descriptive, especially if the error_predicate
540 // contains a foreign type or if it's a deeply nested type...
541 if error_predicate != error.root_obligation.predicate {
542 errors
543 .entry((ty.to_string(), error_predicate.to_string()))
544 .or_default()
545 .push(error.obligation.cause.span);
546 }
fe692bf9 547 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
49aad941 548 trait_ref,
e8be2606 549 polarity: ty::PredicatePolarity::Positive,
49aad941
FG
550 ..
551 })) = error_predicate.kind().skip_binder()
552 {
553 let ty = trait_ref.self_ty();
554 if let ty::Param(_) = ty.kind() {
555 bounds.push((
556 format!("{ty}"),
31ef2f64 557 trait_ref.print_trait_sugared().to_string(),
49aad941
FG
558 Some(trait_ref.def_id),
559 ));
560 }
561 }
562 }
563 }
564 InfringingFieldsReason::Regions(region_errors) => {
565 for error in region_errors {
566 let ty = ty.to_string();
567 match error {
568 RegionResolutionError::ConcreteFailure(origin, a, b) => {
569 let predicate = format!("{b}: {a}");
570 errors
571 .entry((ty.clone(), predicate.clone()))
572 .or_default()
573 .push(origin.span());
4b012472 574 if let ty::RegionKind::ReEarlyParam(ebr) = *b
ed00b5ec
FG
575 && ebr.has_name()
576 {
577 bounds.push((b.to_string(), a.to_string(), None));
578 }
49aad941
FG
579 }
580 RegionResolutionError::GenericBoundFailure(origin, a, b) => {
581 let predicate = format!("{a}: {b}");
582 errors
583 .entry((ty.clone(), predicate.clone()))
584 .or_default()
585 .push(origin.span());
586 if let infer::region_constraints::GenericKind::Param(_) = a {
587 bounds.push((a.to_string(), b.to_string(), None));
588 }
589 }
590 _ => continue,
591 }
592 }
593 }
594 }
595 }
781aab86 596 let mut notes = Vec::new();
49aad941
FG
597 for ((ty, error_predicate), spans) in errors {
598 let span: MultiSpan = spans.into();
781aab86 599 notes.push(errors::ImplForTyRequires {
49aad941 600 span,
781aab86
FG
601 error_predicate,
602 trait_name: trait_name.clone(),
603 ty,
604 });
49aad941 605 }
781aab86 606
c0240ec0 607 let mut err = tcx.dcx().create_err(errors::TraitCannotImplForTy {
781aab86
FG
608 span: impl_span,
609 trait_name,
610 label_spans,
611 notes,
612 });
613
49aad941
FG
614 suggest_constraining_type_params(
615 tcx,
616 tcx.hir().get_generics(impl_did).expect("impls always have generics"),
617 &mut err,
618 bounds
619 .iter()
620 .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
621 None,
622 );
623
624 err.emit()
625}