152 lines
4.3 KiB
Rust
152 lines
4.3 KiB
Rust
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
|
use rustc::session::Session;
|
|
use rustc::ty::{Ty, TypeFoldable};
|
|
use rustc_span::Span;
|
|
|
|
use rustc_error_codes::*;
|
|
|
|
pub trait StructuredDiagnostic<'tcx> {
|
|
fn session(&self) -> &Session;
|
|
|
|
fn code(&self) -> DiagnosticId;
|
|
|
|
fn common(&self) -> DiagnosticBuilder<'tcx>;
|
|
|
|
fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
|
|
let err = self.common();
|
|
if self.session().teach(&self.code()) { self.extended(err) } else { self.regular(err) }
|
|
}
|
|
|
|
fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
|
err
|
|
}
|
|
|
|
fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
|
err
|
|
}
|
|
}
|
|
|
|
pub struct VariadicError<'tcx> {
|
|
sess: &'tcx Session,
|
|
span: Span,
|
|
t: Ty<'tcx>,
|
|
cast_ty: &'tcx str,
|
|
}
|
|
|
|
impl<'tcx> VariadicError<'tcx> {
|
|
pub fn new(
|
|
sess: &'tcx Session,
|
|
span: Span,
|
|
t: Ty<'tcx>,
|
|
cast_ty: &'tcx str,
|
|
) -> VariadicError<'tcx> {
|
|
VariadicError { sess, span, t, cast_ty }
|
|
}
|
|
}
|
|
|
|
impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> {
|
|
fn session(&self) -> &Session {
|
|
self.sess
|
|
}
|
|
|
|
fn code(&self) -> DiagnosticId {
|
|
errors::error_code!(E0617)
|
|
}
|
|
|
|
fn common(&self) -> DiagnosticBuilder<'tcx> {
|
|
let mut err = if self.t.references_error() {
|
|
self.sess.diagnostic().struct_dummy()
|
|
} else {
|
|
self.sess.struct_span_fatal_with_code(
|
|
self.span,
|
|
&format!("can't pass `{}` to variadic function", self.t),
|
|
self.code(),
|
|
)
|
|
};
|
|
if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
|
|
err.span_suggestion(
|
|
self.span,
|
|
&format!("cast the value to `{}`", self.cast_ty),
|
|
format!("{} as {}", snippet, self.cast_ty),
|
|
Applicability::MachineApplicable,
|
|
);
|
|
} else {
|
|
err.help(&format!("cast the value to `{}`", self.cast_ty));
|
|
}
|
|
err
|
|
}
|
|
|
|
fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
|
err.note(&format!(
|
|
"certain types, like `{}`, must be cast before passing them to a \
|
|
variadic function, because of arcane ABI rules dictated by the C \
|
|
standard",
|
|
self.t
|
|
));
|
|
err
|
|
}
|
|
}
|
|
|
|
pub struct SizedUnsizedCastError<'tcx> {
|
|
sess: &'tcx Session,
|
|
span: Span,
|
|
expr_ty: Ty<'tcx>,
|
|
cast_ty: String,
|
|
}
|
|
|
|
impl<'tcx> SizedUnsizedCastError<'tcx> {
|
|
pub fn new(
|
|
sess: &'tcx Session,
|
|
span: Span,
|
|
expr_ty: Ty<'tcx>,
|
|
cast_ty: String,
|
|
) -> SizedUnsizedCastError<'tcx> {
|
|
SizedUnsizedCastError { sess, span, expr_ty, cast_ty }
|
|
}
|
|
}
|
|
|
|
impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> {
|
|
fn session(&self) -> &Session {
|
|
self.sess
|
|
}
|
|
|
|
fn code(&self) -> DiagnosticId {
|
|
errors::error_code!(E0607)
|
|
}
|
|
|
|
fn common(&self) -> DiagnosticBuilder<'tcx> {
|
|
if self.expr_ty.references_error() {
|
|
self.sess.diagnostic().struct_dummy()
|
|
} else {
|
|
self.sess.struct_span_fatal_with_code(
|
|
self.span,
|
|
&format!(
|
|
"cannot cast thin pointer `{}` to fat pointer `{}`",
|
|
self.expr_ty, self.cast_ty
|
|
),
|
|
self.code(),
|
|
)
|
|
}
|
|
}
|
|
|
|
fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
|
err.help(
|
|
"Thin pointers are \"simple\" pointers: they are purely a reference to a
|
|
memory address.
|
|
|
|
Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
|
|
called DST). DST don't have a statically known size, therefore they can
|
|
only exist behind some kind of pointers that contain additional
|
|
information. Slices and trait objects are DSTs. In the case of slices,
|
|
the additional information the fat pointer holds is their size.
|
|
|
|
To fix this error, don't try to cast directly between thin and fat
|
|
pointers.
|
|
|
|
For more information about casts, take a look at The Book:
|
|
https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions",
|
|
);
|
|
err
|
|
}
|
|
}
|