1 use rustc::session::Session;
3 use errors::{Applicability, DiagnosticId, DiagnosticBuilder};
4 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()) {
24 fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
28 fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
33 pub struct VariadicError<'tcx> {
40 impl<'tcx> VariadicError<'tcx> {
41 pub fn new(sess: &'tcx Session,
44 cast_ty: &'tcx str) -> VariadicError<'tcx> {
45 VariadicError { sess, span, t, cast_ty }
49 impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
50 fn session(&self) -> &Session { self.sess }
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> {
81 err.note(&format!("certain types, like `{}`, must be cast before passing them to a \
82 variadic function, because of arcane ABI rules dictated by the C \
89 pub struct SizedUnsizedCastError<'tcx> {
96 impl<'tcx> SizedUnsizedCastError<'tcx> {
97 pub fn new(sess: &'tcx Session,
100 cast_ty: String) -> SizedUnsizedCastError<'tcx> {
101 SizedUnsizedCastError { sess, span, expr_ty, cast_ty }
105 impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
106 fn session(&self) -> &Session { self.sess }
108 fn code(&self) -> DiagnosticId {
109 syntax::diagnostic_used!(E0607);
110 DiagnosticId::Error("E0607".to_owned())
113 fn common(&self) -> DiagnosticBuilder<'tcx> {
114 if self.expr_ty.references_error() {
115 self.sess.diagnostic().struct_dummy()
117 self.sess.struct_span_fatal_with_code(
119 &format!("cannot cast thin pointer `{}` to fat pointer `{}`",
127 fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
129 "Thin pointers are \"simple\" pointers: they are purely a reference to a
132 Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
133 called DST). DST don't have a statically known size, therefore they can
134 only exist behind some kind of pointers that contain additional
135 information. Slices and trait objects are DSTs. In the case of slices,
136 the additional information the fat pointer holds is their size.
138 To fix this error, don't try to cast directly between thin and fat
141 For more information about casts, take a look at The Book:
142 https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions");