| use std::borrow::Cow; | |
| use rustc_abi::TargetDataLayoutErrors; | |
| use rustc_error_messages::{DiagArgValue, IntoDiagArg}; | |
| use rustc_macros::Subdiagnostic; | |
| use rustc_span::{Span, Symbol}; | |
| use crate::diagnostic::DiagLocation; | |
| use crate::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, msg}; | |
| impl IntoDiagArg for DiagLocation { | |
| fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { | |
| DiagArgValue::Str(Cow::from(self.to_string())) | |
| } | |
| } | |
| #[derive(Clone)] | |
| pub struct DiagSymbolList<S = Symbol>(Vec<S>); | |
| impl<S> From<Vec<S>> for DiagSymbolList<S> { | |
| fn from(v: Vec<S>) -> Self { | |
| DiagSymbolList(v) | |
| } | |
| } | |
| impl<S> FromIterator<S> for DiagSymbolList<S> { | |
| fn from_iter<T: IntoIterator<Item = S>>(iter: T) -> Self { | |
| iter.into_iter().collect::<Vec<_>>().into() | |
| } | |
| } | |
| impl<S: std::fmt::Display> IntoDiagArg for DiagSymbolList<S> { | |
| fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { | |
| DiagArgValue::StrListSepByAnd( | |
| self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(), | |
| ) | |
| } | |
| } | |
| impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { | |
| fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { | |
| match self { | |
| TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { | |
| Diag::new(dcx, level, msg!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}")) | |
| .with_arg("addr_space", addr_space) | |
| .with_arg("cause", cause) | |
| .with_arg("err", err) | |
| } | |
| TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { | |
| Diag::new(dcx, level, msg!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}")) | |
| .with_arg("kind", kind) | |
| .with_arg("bit", bit) | |
| .with_arg("cause", cause) | |
| .with_arg("err", err) | |
| } | |
| TargetDataLayoutErrors::MissingAlignment { cause } => { | |
| Diag::new(dcx, level, msg!("missing alignment for `{$cause}` in \"data-layout\"")) | |
| .with_arg("cause", cause) | |
| } | |
| TargetDataLayoutErrors::InvalidAlignment { cause, err } => { | |
| Diag::new(dcx, level, msg!( | |
| "invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind -> | |
| [not_power_of_two] not a power of 2 | |
| [too_large] too large | |
| *[other] {\"\"} | |
| }" | |
| )) | |
| .with_arg("cause", cause) | |
| .with_arg("err_kind", err.diag_ident()) | |
| .with_arg("align", err.align()) | |
| } | |
| TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { | |
| Diag::new(dcx, level, msg!( | |
| "inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`" | |
| )) | |
| .with_arg("dl", dl).with_arg("target", target) | |
| } | |
| TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { | |
| Diag::new(dcx, level, msg!( | |
| "inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`" | |
| )).with_arg("pointer_size", pointer_size).with_arg("target", target) | |
| } | |
| TargetDataLayoutErrors::InvalidBitsSize { err } => { | |
| Diag::new(dcx, level, msg!("{$err}")).with_arg("err", err) | |
| } | |
| TargetDataLayoutErrors::UnknownPointerSpecification { err } => { | |
| Diag::new(dcx, level, msg!("unknown pointer specification `{$err}` in datalayout string")) | |
| .with_arg("err", err) | |
| } | |
| } | |
| } | |
| } | |
| /// Utility struct used to apply a single label while highlighting multiple spans | |
| pub struct SingleLabelManySpans { | |
| pub spans: Vec<Span>, | |
| pub label: &'static str, | |
| } | |
| impl Subdiagnostic for SingleLabelManySpans { | |
| fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { | |
| diag.span_labels(self.spans, self.label); | |
| } | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[label( | |
| "expected lifetime {$count -> | |
| [1] parameter | |
| *[other] parameters | |
| }" | |
| )] | |
| pub struct ExpectedLifetimeParameter { | |
| #[primary_span] | |
| pub span: Span, | |
| pub count: usize, | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[suggestion( | |
| "indicate the anonymous {$count -> | |
| [1] lifetime | |
| *[other] lifetimes | |
| }", | |
| code = "{suggestion}", | |
| style = "verbose" | |
| )] | |
| pub struct IndicateAnonymousLifetime { | |
| #[primary_span] | |
| pub span: Span, | |
| pub count: usize, | |
| pub suggestion: String, | |
| } | |
| #[derive(Subdiagnostic)] | |
| pub struct ElidedLifetimeInPathSubdiag { | |
| #[subdiagnostic] | |
| pub expected: ExpectedLifetimeParameter, | |
| #[subdiagnostic] | |
| pub indicate: Option<IndicateAnonymousLifetime>, | |
| } |