Skip to content

Commit 49474eb

Browse files
committed
Migrate rustc_hir_analysis to session diagnostic
Part 5: Finishing `coherence/builtin.rs` file
1 parent 33440d7 commit 49474eb

File tree

3 files changed

+205
-125
lines changed

3 files changed

+205
-125
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ 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 `CoerceUnsized` 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+
3746
hir_analysis_const_bound_for_non_const_trait =
3847
~const can only be applied to `#[const_trait]` traits
3948
@@ -57,6 +66,23 @@ hir_analysis_copy_impl_on_type_with_dtor =
5766
the trait `Copy` cannot be implemented for this type; the type has a destructor
5867
.label = `Copy` not allowed on types with destructors
5968
69+
hir_analysis_dispatch_from_dyn_coercion = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with the same definition; expected `{$source_path}`, found `{$target_path}`
70+
71+
hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
72+
.note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
73+
.coercions_note = currently, {$number} fields need coercions: {$coercions}
74+
75+
hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
76+
77+
hir_analysis_dispatch_from_dyn_same = the trait `CoerceUnsized` may only be implemented for a coercion between structures with the same definition; expected `{$source_path}`, found `{$target_path}`
78+
79+
hir_analysis_dispatch_from_dyn_single = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found
80+
81+
hir_analysis_dispatch_from_dyn_struct = the trait `DispatchFromDyn` may only be implemented for a coercion between structures
82+
83+
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
84+
.note = extra field `{$name}` of type `{$ty}` is not allowed
85+
6086
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
6187
6288
hir_analysis_drop_impl_on_wrong_item =
@@ -228,6 +254,7 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
228254
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
229255
.label = not allowed in type signatures
230256
257+
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
231258
hir_analysis_return_type_notation_conflicting_bound =
232259
ambiguous associated function `{$assoc_name}` for `{$ty_name}`
233260
.note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
@@ -295,6 +322,9 @@ hir_analysis_too_large_static = extern static is too large for the current archi
295322
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
296323
.suggestion = remove this annotation
297324
325+
hir_analysis_trait_cannot_impl_for_ty = the trait `{$trait_name}` cannot be implemented for this type
326+
.label = this field does not implement `{$trait_name}`
327+
298328
hir_analysis_trait_object_declared_with_no_traits =
299329
at least one trait is required for an object type
300330
.alias_span = this alias does not contain a trait

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 65 additions & 125 deletions
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,17 @@ 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+
source_path,
179+
target_path,
180+
});
185181

186182
return;
187183
}
188184

189185
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();
186+
tcx.sess.emit_err(errors::DispatchFromDynRepr { span });
195187
}
196188

197189
let fields = &def_a.non_enum_variant().fields;
@@ -213,16 +205,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
213205
infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
214206
{
215207
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();
208+
tcx.sess.emit_err(errors::DispatchFromDynZST {
209+
span,
210+
name: field.name,
211+
ty: ty_a,
212+
});
226213

227214
return false;
228215
}
@@ -233,36 +220,25 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
233220
.collect::<Vec<_>>();
234221

235222
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();
223+
tcx.sess.emit_err(errors::DispatchFromDynSingle { span });
242224
} 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();
225+
tcx.sess.emit_err(errors::DispatchFromDynMulti {
226+
span,
227+
coercions_note: true,
228+
number: coerced_fields.len(),
229+
coercions: coerced_fields
230+
.iter()
231+
.map(|field| {
232+
format!(
233+
"`{}` (`{}` to `{}`)",
234+
field.name,
235+
field.ty(tcx, args_a),
236+
field.ty(tcx, args_b),
237+
)
238+
})
239+
.collect::<Vec<_>>()
240+
.join(", "),
241+
});
266242
} else {
267243
let ocx = ObligationCtxt::new(&infcx);
268244
for field in coerced_fields {
@@ -288,11 +264,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
288264
}
289265
}
290266
_ => {
291-
create_err(
292-
"the trait `DispatchFromDyn` may only be implemented \
293-
for a coercion between structures",
294-
)
295-
.emit();
267+
tcx.sess.emit_err(errors::DispatchFromDynStruct { span });
296268
}
297269
}
298270
}
@@ -359,17 +331,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
359331
if def_a != def_b {
360332
let source_path = tcx.def_path_str(def_a.did());
361333
let target_path = tcx.def_path_str(def_b.did());
362-
struct_span_err!(
363-
tcx.sess,
364-
span,
365-
E0377,
366-
"the trait `CoerceUnsized` may only be implemented \
367-
for a coercion between structures with the same \
368-
definition; expected `{}`, found `{}`",
369-
source_path,
370-
target_path
371-
)
372-
.emit();
334+
tcx.sess.emit_err(errors::DispatchFromDynSame { span, source_path, target_path });
373335
return err_info;
374336
}
375337

@@ -445,15 +407,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
445407
.collect::<Vec<_>>();
446408

447409
if diff_fields.is_empty() {
448-
struct_span_err!(
449-
tcx.sess,
450-
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();
410+
tcx.sess.emit_err(errors::CoerceUnsizedOneField { span });
457411
return err_info;
458412
} else if diff_fields.len() > 1 {
459413
let item = tcx.hir().expect_item(impl_did);
@@ -463,29 +417,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
463417
tcx.def_span(impl_did)
464418
};
465419

466-
struct_span_err!(
467-
tcx.sess,
420+
tcx.sess.emit_err(errors::CoerceUnsizedMulti {
468421
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
422+
coercions_note: true,
423+
number: diff_fields.len(),
424+
coercions: diff_fields
482425
.iter()
483-
.map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) })
426+
.map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b))
484427
.collect::<Vec<_>>()
485-
.join(", ")
486-
))
487-
.span_label(span, "requires multiple coercions")
488-
.emit();
428+
.join(", "),
429+
});
430+
489431
return err_info;
490432
}
491433

@@ -495,14 +437,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
495437
}
496438

497439
_ => {
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();
440+
tcx.sess.emit_err(errors::CoerceUnsizedMay { span });
506441
return err_info;
507442
}
508443
};
@@ -540,28 +475,22 @@ fn infringing_fields_error(
540475

541476
let trait_name = tcx.def_path_str(trait_did);
542477

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-
550478
// We'll try to suggest constraining type parameters to fulfill the requirements of
551479
// their `Copy` implementation.
552480
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
553481
let mut bounds = vec![];
554482

555483
let mut seen_tys = FxHashSet::default();
556484

485+
let mut label_spans = Vec::new();
486+
557487
for (field, ty, reason) in fields {
558488
// Only report an error once per type.
559489
if !seen_tys.insert(ty) {
560490
continue;
561491
}
562492

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

566495
match reason {
567496
InfringingFieldsReason::Fulfill(fulfillment_errors) => {
@@ -625,13 +554,24 @@ fn infringing_fields_error(
625554
}
626555
}
627556
}
557+
let mut notes = Vec::new();
628558
for ((ty, error_predicate), spans) in errors {
629559
let span: MultiSpan = spans.into();
630-
err.span_note(
560+
notes.push(errors::ImplForTyRequires {
631561
span,
632-
format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"),
633-
);
562+
error_predicate,
563+
trait_name: trait_name.clone(),
564+
ty,
565+
});
634566
}
567+
568+
let mut err = tcx.sess.create_err(errors::TraitCannotImplForTy {
569+
span: impl_span,
570+
trait_name,
571+
label_spans,
572+
notes,
573+
});
574+
635575
suggest_constraining_type_params(
636576
tcx,
637577
tcx.hir().get_generics(impl_did).expect("impls always have generics"),

0 commit comments

Comments
 (0)