1 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
2 use rustc::session::Session;
3 use rustc::ty::{Ty, TypeFoldable};
6 use rustc_error_codes::*;
8 pub trait StructuredDiagnostic<'tcx> {
9 fn session(&self) -> &Session;
11 fn code(&self) -> DiagnosticId;
13 fn common(&self) -> DiagnosticBuilder<'tcx>;
15 fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
16 let err = self.common();
17 if self.session().teach(&self.code()) { self.extended(err) } else { self.regular(err) }
20 fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
24 fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
29 pub struct VariadicError<'tcx> {
36 impl<'tcx> VariadicError<'tcx> {
42 ) -> VariadicError<'tcx> {
43 VariadicError { sess, span, t, cast_ty }
47 impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
48 fn session(&self) -> &Session {
52 fn code(&self) -> DiagnosticId {
53 syntax::diagnostic_used!(E0617);
54 DiagnosticId::Error("E0617".to_owned())
57 fn common(&self) -> DiagnosticBuilder<'tcx> {
58 let mut err = if self.t.references_error() {
59 self.sess.diagnostic().struct_dummy()
61 self.sess.struct_span_fatal_with_code(
63 &format!("can't pass `{}` to variadic function", self.t),
67 if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
70 &format!("cast the value to `{}`", self.cast_ty),
71 format!("{} as {}", snippet, self.cast_ty),
72 Applicability::MachineApplicable,
75 err.help(&format!("cast the value to `{}`", self.cast_ty));
80 fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
82 "certain types, like `{}`, must be cast before passing them to a \
83 variadic function, because of arcane ABI rules dictated by the C \
91 pub struct SizedUnsizedCastError<'tcx> {
98 impl<'tcx> SizedUnsizedCastError<'tcx> {
104 ) -> SizedUnsizedCastError<'tcx> {
105 SizedUnsizedCastError { sess, span, expr_ty, cast_ty }
109 impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
110 fn session(&self) -> &Session {
114 fn code(&self) -> DiagnosticId {
115 syntax::diagnostic_used!(E0607);
116 DiagnosticId::Error("E0607".to_owned())
119 fn common(&self) -> DiagnosticBuilder<'tcx> {
120 if self.expr_ty.references_error() {
121 self.sess.diagnostic().struct_dummy()
123 self.sess.struct_span_fatal_with_code(
126 "cannot cast thin pointer `{}` to fat pointer `{}`",
127 self.expr_ty, self.cast_ty
134 fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
136 "Thin pointers are \"simple\" pointers: they are purely a reference to a
139 Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
140 called DST). DST don't have a statically known size, therefore they can
141 only exist behind some kind of pointers that contain additional
142 information. Slices and trait objects are DSTs. In the case of slices,
143 the additional information the fat pointer holds is their size.
145 To fix this error, don't try to cast directly between thin and fat
148 For more information about casts, take a look at The Book:
149 https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions",