1 use rustc::session::Session;
3 use errors::{Applicability, DiagnosticId, DiagnosticBuilder};
4 use rustc::ty::{Ty, TypeFoldable};
6 pub trait StructuredDiagnostic<'tcx> {
7 fn session(&self) -> &Session;
9 fn code(&self) -> DiagnosticId;
11 fn common(&self) -> DiagnosticBuilder<'tcx>;
13 fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
14 let err = self.common();
15 if self.session().teach(&self.code()) {
22 fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
26 fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
31 pub struct VariadicError<'tcx> {
38 impl<'tcx> VariadicError<'tcx> {
39 pub fn new(sess: &'tcx Session,
42 cast_ty: &'tcx str) -> VariadicError<'tcx> {
43 VariadicError { sess, span, t, cast_ty }
47 impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
48 fn session(&self) -> &Session { self.sess }
50 fn code(&self) -> DiagnosticId {
51 __diagnostic_used!(E0617);
52 DiagnosticId::Error("E0617".to_owned())
55 fn common(&self) -> DiagnosticBuilder<'tcx> {
56 let mut err = if self.t.references_error() {
57 self.sess.diagnostic().struct_dummy()
59 self.sess.struct_span_fatal_with_code(
61 &format!("can't pass `{}` to variadic function", self.t),
65 if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
66 err.span_suggestion_with_applicability(
68 &format!("cast the value to `{}`", self.cast_ty),
69 format!("{} as {}", snippet, self.cast_ty),
70 Applicability::MachineApplicable,
73 err.help(&format!("cast the value to `{}`", self.cast_ty));
78 fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
79 err.note(&format!("certain types, like `{}`, must be cast before passing them to a \
80 variadic function, because of arcane ABI rules dictated by the C \
87 pub struct SizedUnsizedCastError<'tcx> {
94 impl<'tcx> SizedUnsizedCastError<'tcx> {
95 pub fn new(sess: &'tcx Session,
98 cast_ty: String) -> SizedUnsizedCastError<'tcx> {
99 SizedUnsizedCastError { sess, span, expr_ty, cast_ty }
103 impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
104 fn session(&self) -> &Session { self.sess }
106 fn code(&self) -> DiagnosticId {
107 __diagnostic_used!(E0607);
108 DiagnosticId::Error("E0607".to_owned())
111 fn common(&self) -> DiagnosticBuilder<'tcx> {
112 if self.expr_ty.references_error() {
113 self.sess.diagnostic().struct_dummy()
115 self.sess.struct_span_fatal_with_code(
117 &format!("cannot cast thin pointer `{}` to fat pointer `{}`",
125 fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
127 "Thin pointers are \"simple\" pointers: they are purely a reference to a
130 Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
131 called DST). DST don't have a statically known size, therefore they can
132 only exist behind some kind of pointers that contain additional
133 information. Slices and trait objects are DSTs. In the case of slices,
134 the additional information the fat pointer holds is their size.
136 To fix this error, don't try to cast directly between thin and fat
139 For more information about casts, take a look at The Book:
140 https://doc.rust-lang.org/book/first-edition/casting-between-types.html");