Skip to content

Commit dd79ee6

Browse files
committed
Migrate rustc_hir_analysis to session diagnostic
Part 5: Finishing `coherence/builtin.rs` file
1 parent df99bc1 commit dd79ee6

File tree

6 files changed

+235
-125
lines changed

6 files changed

+235
-125
lines changed

compiler/rustc_hir_analysis/messages.ftl

+27
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr
3434
hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
3535
.label = `for<...>` is here
3636
37+
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
38+
39+
hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions
40+
.note = `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
41+
.coercions_note = currently, {$number} fields need coercions: {$coercions}
42+
.label = requires multiple coercions
43+
44+
hir_analysis_coerce_unsized_one_field = the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found
45+
46+
hir_analysis_coercion_between_struct_same_note = the same definition; expected `{$source_path}`, found `{$target_path}`
47+
48+
hir_analysis_coercion_between_struct_single_note = a single field being coerced, none found
49+
3750
hir_analysis_const_bound_for_non_const_trait =
3851
~const can only be applied to `#[const_trait]` traits
3952
@@ -57,6 +70,15 @@ hir_analysis_copy_impl_on_type_with_dtor =
5770
the trait `Copy` cannot be implemented for this type; the type has a destructor
5871
.label = `Copy` not allowed on types with destructors
5972
73+
hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
74+
.note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
75+
.coercions_note = currently, {$number} fields need coercions: {$coercions}
76+
77+
hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
78+
79+
hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
80+
.note = extra field `{$name}` of type `{$ty}` is not allowed
81+
6082
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
6183
6284
hir_analysis_drop_impl_on_wrong_item =
@@ -228,6 +250,8 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
228250
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
229251
.label = not allowed in type signatures
230252
253+
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
254+
231255
hir_analysis_return_type_notation_conflicting_bound =
232256
ambiguous associated function `{$assoc_name}` for `{$ty_name}`
233257
.note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
@@ -295,6 +319,9 @@ hir_analysis_too_large_static = extern static is too large for the current archi
295319
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
296320
.suggestion = remove this annotation
297321
322+
hir_analysis_trait_cannot_impl_for_ty = the trait `{$trait_name}` cannot be implemented for this type
323+
.label = this field does not implement `{$trait_name}`
324+
298325
hir_analysis_trait_object_declared_with_no_traits =
299326
at least one trait is required for an object type
300327
.alias_span = this alias does not contain a trait

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+78-122
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//! Check properties that are required by built-in traits and set
22
//! up data structures required by type-checking/codegen.
33
4-
use crate::errors::{
5-
ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem,
6-
};
4+
use crate::errors;
5+
76
use rustc_data_structures::fx::FxHashSet;
8-
use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
7+
use rustc_errors::{ErrorGuaranteed, MultiSpan};
98
use rustc_hir as hir;
109
use rustc_hir::def_id::{DefId, LocalDefId};
1110
use rustc_hir::lang_items::LangItem;
@@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
6564

6665
let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
6766

68-
tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span });
67+
tcx.sess.emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span });
6968
}
7069

7170
fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
@@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9190
infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span);
9291
}
9392
Err(CopyImplementationError::NotAnAdt) => {
94-
tcx.sess.emit_err(CopyImplOnNonAdt { span });
93+
tcx.sess.emit_err(errors::CopyImplOnNonAdt { span });
9594
}
9695
Err(CopyImplementationError::HasDestructor) => {
97-
tcx.sess.emit_err(CopyImplOnTypeWithDtor { span });
96+
tcx.sess.emit_err(errors::CopyImplOnTypeWithDtor { span });
9897
}
9998
}
10099
}
@@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId)
117116
infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span);
118117
}
119118
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
120-
tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span });
119+
tcx.sess.emit_err(errors::ConstParamTyImplOnNonAdt { span });
121120
}
122121
}
123122
}
@@ -152,8 +151,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
152151

153152
let param_env = tcx.param_env(impl_did);
154153

155-
let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg);
156-
157154
let infcx = tcx.infer_ctxt().build();
158155
let cause = ObligationCause::misc(span, impl_did);
159156

@@ -176,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
176173
let source_path = tcx.def_path_str(def_a.did());
177174
let target_path = tcx.def_path_str(def_b.did());
178175

179-
create_err(&format!(
180-
"the trait `DispatchFromDyn` may only be implemented \
181-
for a coercion between structures with the same \
182-
definition; expected `{source_path}`, found `{target_path}`",
183-
))
184-
.emit();
176+
tcx.sess.emit_err(errors::DispatchFromDynCoercion {
177+
span,
178+
trait_name: "DispatchFromDyn",
179+
note: true,
180+
source_path,
181+
target_path,
182+
});
185183

186184
return;
187185
}
188186

189187
if def_a.repr().c() || def_a.repr().packed() {
190-
create_err(
191-
"structs implementing `DispatchFromDyn` may not have \
192-
`#[repr(packed)]` or `#[repr(C)]`",
193-
)
194-
.emit();
188+
tcx.sess.emit_err(errors::DispatchFromDynRepr { span });
195189
}
196190

197191
let fields = &def_a.non_enum_variant().fields;
@@ -213,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
213207
infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
214208
{
215209
if ok.obligations.is_empty() {
216-
create_err(
217-
"the trait `DispatchFromDyn` may only be implemented \
218-
for structs containing the field being coerced, \
219-
ZST fields with 1 byte alignment, and nothing else",
220-
)
221-
.note(format!(
222-
"extra field `{}` of type `{}` is not allowed",
223-
field.name, ty_a,
224-
))
225-
.emit();
210+
tcx.sess.emit_err(errors::DispatchFromDynZST {
211+
span,
212+
name: field.name,
213+
ty: ty_a,
214+
});
226215

227216
return false;
228217
}
@@ -233,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
233222
.collect::<Vec<_>>();
234223

235224
if coerced_fields.is_empty() {
236-
create_err(
237-
"the trait `DispatchFromDyn` may only be implemented \
238-
for a coercion between structures with a single field \
239-
being coerced, none found",
240-
)
241-
.emit();
225+
tcx.sess.emit_err(errors::DispatchFromDynSingle {
226+
span,
227+
trait_name: "DispatchFromDyn",
228+
note: true,
229+
});
242230
} else if coerced_fields.len() > 1 {
243-
create_err("implementing the `DispatchFromDyn` trait requires multiple coercions")
244-
.note(
245-
"the trait `DispatchFromDyn` may only be implemented \
246-
for a coercion between structures with a single field \
247-
being coerced",
248-
)
249-
.note(format!(
250-
"currently, {} fields need coercions: {}",
251-
coerced_fields.len(),
252-
coerced_fields
253-
.iter()
254-
.map(|field| {
255-
format!(
256-
"`{}` (`{}` to `{}`)",
257-
field.name,
258-
field.ty(tcx, args_a),
259-
field.ty(tcx, args_b),
260-
)
261-
})
262-
.collect::<Vec<_>>()
263-
.join(", ")
264-
))
265-
.emit();
231+
tcx.sess.emit_err(errors::DispatchFromDynMulti {
232+
span,
233+
coercions_note: true,
234+
number: coerced_fields.len(),
235+
coercions: coerced_fields
236+
.iter()
237+
.map(|field| {
238+
format!(
239+
"`{}` (`{}` to `{}`)",
240+
field.name,
241+
field.ty(tcx, args_a),
242+
field.ty(tcx, args_b),
243+
)
244+
})
245+
.collect::<Vec<_>>()
246+
.join(", "),
247+
});
266248
} else {
267249
let ocx = ObligationCtxt::new(&infcx);
268250
for field in coerced_fields {
@@ -288,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
288270
}
289271
}
290272
_ => {
291-
create_err(
292-
"the trait `DispatchFromDyn` may only be implemented \
293-
for a coercion between structures",
294-
)
295-
.emit();
273+
tcx.sess.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" });
296274
}
297275
}
298276
}
@@ -359,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
359337
if def_a != def_b {
360338
let source_path = tcx.def_path_str(def_a.did());
361339
let target_path = tcx.def_path_str(def_b.did());
362-
struct_span_err!(
363-
tcx.sess,
340+
tcx.sess.emit_err(errors::DispatchFromDynSame {
364341
span,
365-
E0377,
366-
"the trait `CoerceUnsized` may only be implemented \
367-
for a coercion between structures with the same \
368-
definition; expected `{}`, found `{}`",
342+
trait_name: "CoerceUnsized",
343+
note: true,
369344
source_path,
370-
target_path
371-
)
372-
.emit();
345+
target_path,
346+
});
373347
return err_info;
374348
}
375349

@@ -445,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
445419
.collect::<Vec<_>>();
446420

447421
if diff_fields.is_empty() {
448-
struct_span_err!(
449-
tcx.sess,
422+
tcx.sess.emit_err(errors::CoerceUnsizedOneField {
450423
span,
451-
E0374,
452-
"the trait `CoerceUnsized` may only be implemented \
453-
for a coercion between structures with one field \
454-
being coerced, none found"
455-
)
456-
.emit();
424+
trait_name: "CoerceUnsized",
425+
note: true,
426+
});
457427
return err_info;
458428
} else if diff_fields.len() > 1 {
459429
let item = tcx.hir().expect_item(impl_did);
@@ -463,29 +433,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
463433
tcx.def_span(impl_did)
464434
};
465435

466-
struct_span_err!(
467-
tcx.sess,
436+
tcx.sess.emit_err(errors::CoerceUnsizedMulti {
468437
span,
469-
E0375,
470-
"implementing the trait \
471-
`CoerceUnsized` requires multiple \
472-
coercions"
473-
)
474-
.note(
475-
"`CoerceUnsized` may only be implemented for \
476-
a coercion between structures with one field being coerced",
477-
)
478-
.note(format!(
479-
"currently, {} fields need coercions: {}",
480-
diff_fields.len(),
481-
diff_fields
438+
coercions_note: true,
439+
number: diff_fields.len(),
440+
coercions: diff_fields
482441
.iter()
483-
.map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) })
442+
.map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b))
484443
.collect::<Vec<_>>()
485-
.join(", ")
486-
))
487-
.span_label(span, "requires multiple coercions")
488-
.emit();
444+
.join(", "),
445+
});
446+
489447
return err_info;
490448
}
491449

@@ -495,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
495453
}
496454

497455
_ => {
498-
struct_span_err!(
499-
tcx.sess,
500-
span,
501-
E0376,
502-
"the trait `CoerceUnsized` may only be implemented \
503-
for a coercion between structures"
504-
)
505-
.emit();
456+
tcx.sess.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" });
506457
return err_info;
507458
}
508459
};
@@ -540,28 +491,22 @@ fn infringing_fields_error(
540491

541492
let trait_name = tcx.def_path_str(trait_did);
542493

543-
let mut err = struct_span_err!(
544-
tcx.sess,
545-
impl_span,
546-
E0204,
547-
"the trait `{trait_name}` cannot be implemented for this type"
548-
);
549-
550494
// We'll try to suggest constraining type parameters to fulfill the requirements of
551495
// their `Copy` implementation.
552496
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
553497
let mut bounds = vec![];
554498

555499
let mut seen_tys = FxHashSet::default();
556500

501+
let mut label_spans = Vec::new();
502+
557503
for (field, ty, reason) in fields {
558504
// Only report an error once per type.
559505
if !seen_tys.insert(ty) {
560506
continue;
561507
}
562508

563-
let field_span = tcx.def_span(field.did);
564-
err.span_label(field_span, format!("this field does not implement `{trait_name}`"));
509+
label_spans.push(tcx.def_span(field.did));
565510

566511
match reason {
567512
InfringingFieldsReason::Fulfill(fulfillment_errors) => {
@@ -625,13 +570,24 @@ fn infringing_fields_error(
625570
}
626571
}
627572
}
573+
let mut notes = Vec::new();
628574
for ((ty, error_predicate), spans) in errors {
629575
let span: MultiSpan = spans.into();
630-
err.span_note(
576+
notes.push(errors::ImplForTyRequires {
631577
span,
632-
format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"),
633-
);
578+
error_predicate,
579+
trait_name: trait_name.clone(),
580+
ty,
581+
});
634582
}
583+
584+
let mut err = tcx.sess.create_err(errors::TraitCannotImplForTy {
585+
span: impl_span,
586+
trait_name,
587+
label_spans,
588+
notes,
589+
});
590+
635591
suggest_constraining_type_params(
636592
tcx,
637593
tcx.hir().get_generics(impl_did).expect("impls always have generics"),

0 commit comments

Comments
 (0)