Port dead_code
lints to be translatable.
This commit is contained in:
parent
56f132565e
commit
113e8dfb72
11 changed files with 236 additions and 99 deletions
|
@ -671,3 +671,37 @@ passes_missing_const_err =
|
||||||
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
||||||
.help = make the function or method const
|
.help = make the function or method const
|
||||||
.label = attribute specified here
|
.label = attribute specified here
|
||||||
|
|
||||||
|
passes_dead_codes =
|
||||||
|
{ $multiple ->
|
||||||
|
*[true] multiple {$descr}s are
|
||||||
|
[false] { $num ->
|
||||||
|
[one] {$descr} {$name_list} is
|
||||||
|
*[other] {$descr}s {$name_list} are
|
||||||
|
}
|
||||||
|
} never {$participle}
|
||||||
|
|
||||||
|
passes_change_fields_to_be_of_unit_type =
|
||||||
|
consider changing the { $num ->
|
||||||
|
[one] field
|
||||||
|
*[other] fields
|
||||||
|
} to be of unit type to suppress this warning
|
||||||
|
while preserving the field numbering, or remove the { $num ->
|
||||||
|
[one] field
|
||||||
|
*[other] fields
|
||||||
|
}
|
||||||
|
|
||||||
|
passes_parent_info =
|
||||||
|
{$num ->
|
||||||
|
[one] {$descr}
|
||||||
|
*[other] {$descr}s
|
||||||
|
} in this {$parent_descr}
|
||||||
|
|
||||||
|
passes_ignored_derived_impls =
|
||||||
|
`{$name}` has {$trait_list_len ->
|
||||||
|
[one] a derived impl
|
||||||
|
*[other] derived impls
|
||||||
|
} for the {$trait_list_len ->
|
||||||
|
[one] trait {$trait_list}, but this is
|
||||||
|
*[other] traits {$trait_list}, but these are
|
||||||
|
} intentionally ignored during dead code analysis
|
||||||
|
|
|
@ -11,6 +11,7 @@ use rustc_target::abi::TargetDataLayoutErrors;
|
||||||
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
|
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fmt::Write;
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
@ -170,6 +171,37 @@ impl IntoDiagnosticArg for Level {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DiagnosticSymbolList(Vec<Symbol>);
|
||||||
|
|
||||||
|
impl From<Vec<Symbol>> for DiagnosticSymbolList {
|
||||||
|
fn from(v: Vec<Symbol>) -> Self {
|
||||||
|
DiagnosticSymbolList(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoDiagnosticArg for DiagnosticSymbolList {
|
||||||
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
|
// FIXME: replace the logic here with a real list formatter
|
||||||
|
let symbols = match &self.0[..] {
|
||||||
|
[symbol] => format!("`{symbol}`"),
|
||||||
|
[symbol, last] => {
|
||||||
|
format!("`{symbol}` and `{last}`",)
|
||||||
|
}
|
||||||
|
[symbols @ .., last] => {
|
||||||
|
let mut result = String::new();
|
||||||
|
for symbol in symbols {
|
||||||
|
write!(result, "`{symbol}`, ").unwrap();
|
||||||
|
}
|
||||||
|
write!(result, "and `{last}`").unwrap();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
[] => unreachable!(),
|
||||||
|
};
|
||||||
|
DiagnosticArgValue::Str(Cow::Owned(symbols))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
||||||
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
||||||
let mut diag;
|
let mut diag;
|
||||||
|
|
|
@ -376,7 +376,7 @@ pub use diagnostic::{
|
||||||
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
||||||
};
|
};
|
||||||
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
|
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
|
||||||
pub use diagnostic_impls::DiagnosticArgFromDisplay;
|
pub use diagnostic_impls::{DiagnosticArgFromDisplay, DiagnosticSymbolList};
|
||||||
use std::backtrace::Backtrace;
|
use std::backtrace::Backtrace;
|
||||||
|
|
||||||
/// A handler deals with errors and other compiler output.
|
/// A handler deals with errors and other compiler output.
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::{pluralize, Applicability, MultiSpan};
|
use rustc_errors::MultiSpan;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
@ -18,7 +18,10 @@ use rustc_session::lint;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::errors::UselessAssignment;
|
use crate::errors::{
|
||||||
|
ChangeFieldsToBeOfUnitType, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo,
|
||||||
|
UselessAssignment,
|
||||||
|
};
|
||||||
|
|
||||||
// Any local node that may call something in its body block should be
|
// Any local node that may call something in its body block should be
|
||||||
// explored. For example, if it's a live Node::Item that is a
|
// explored. For example, if it's a live Node::Item that is a
|
||||||
|
@ -698,99 +701,89 @@ impl<'tcx> DeadVisitor<'tcx> {
|
||||||
parent_item: Option<LocalDefId>,
|
parent_item: Option<LocalDefId>,
|
||||||
is_positional: bool,
|
is_positional: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(&first_id) = dead_codes.first() {
|
let Some(&first_id) = dead_codes.first() else {
|
||||||
let tcx = self.tcx;
|
return;
|
||||||
let names: Vec<_> = dead_codes
|
};
|
||||||
.iter()
|
let tcx = self.tcx;
|
||||||
.map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string())
|
let names: Vec<_> =
|
||||||
.collect();
|
dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect();
|
||||||
let spans: Vec<_> = dead_codes
|
let spans: Vec<_> = dead_codes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&def_id| match tcx.def_ident_span(def_id) {
|
.map(|&def_id| match tcx.def_ident_span(def_id) {
|
||||||
Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()),
|
Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()),
|
||||||
None => tcx.def_span(def_id),
|
None => tcx.def_span(def_id),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
||||||
|
let num = dead_codes.len();
|
||||||
|
let multiple = num > 6;
|
||||||
|
let name_list = names.into();
|
||||||
|
|
||||||
|
let lint = if is_positional {
|
||||||
|
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
|
||||||
|
} else {
|
||||||
|
lint::builtin::DEAD_CODE
|
||||||
|
};
|
||||||
|
|
||||||
|
let parent_info = if let Some(parent_item) = parent_item {
|
||||||
|
let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
|
||||||
|
Some(ParentInfo {
|
||||||
|
num,
|
||||||
|
descr,
|
||||||
|
parent_descr,
|
||||||
|
span: tcx.def_ident_span(parent_item).unwrap(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let encl_def_id = parent_item.unwrap_or(first_id);
|
||||||
|
let ignored_derived_impls =
|
||||||
|
if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
|
||||||
|
let trait_list = ign_traits
|
||||||
|
.iter()
|
||||||
|
.map(|(trait_id, _)| self.tcx.item_name(*trait_id))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let trait_list_len = trait_list.len();
|
||||||
|
Some(IgnoredDerivedImpls {
|
||||||
|
name: self.tcx.item_name(encl_def_id.to_def_id()),
|
||||||
|
trait_list: trait_list.into(),
|
||||||
|
trait_list_len,
|
||||||
})
|
})
|
||||||
.collect();
|
} else {
|
||||||
|
None
|
||||||
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
|
||||||
let span_len = dead_codes.len();
|
|
||||||
let names = match &names[..] {
|
|
||||||
_ if span_len > 6 => String::new(),
|
|
||||||
[name] => format!("`{name}` "),
|
|
||||||
[names @ .., last] => {
|
|
||||||
format!(
|
|
||||||
"{} and `{last}` ",
|
|
||||||
names.iter().map(|name| format!("`{name}`")).join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
[] => unreachable!(),
|
|
||||||
};
|
};
|
||||||
let msg = format!(
|
|
||||||
"{these}{descr}{s} {names}{are} never {participle}",
|
|
||||||
these = if span_len > 6 { "multiple " } else { "" },
|
|
||||||
s = pluralize!(span_len),
|
|
||||||
are = pluralize!("is", span_len),
|
|
||||||
);
|
|
||||||
|
|
||||||
tcx.struct_span_lint_hir(
|
let diag = if is_positional {
|
||||||
if is_positional {
|
MultipleDeadCodes::UnusedTupleStructFields {
|
||||||
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
|
multiple,
|
||||||
} else {
|
num,
|
||||||
lint::builtin::DEAD_CODE
|
descr,
|
||||||
},
|
participle,
|
||||||
tcx.hir().local_def_id_to_hir_id(first_id),
|
name_list,
|
||||||
MultiSpan::from_spans(spans.clone()),
|
change_fields_suggestion: ChangeFieldsToBeOfUnitType { num, spans: spans.clone() },
|
||||||
msg,
|
parent_info,
|
||||||
|err| {
|
ignored_derived_impls,
|
||||||
if is_positional {
|
}
|
||||||
err.multipart_suggestion(
|
} else {
|
||||||
&format!(
|
MultipleDeadCodes::DeadCodes {
|
||||||
"consider changing the field{s} to be of unit type to \
|
multiple,
|
||||||
suppress this warning while preserving the field \
|
num,
|
||||||
numbering, or remove the field{s}",
|
descr,
|
||||||
s = pluralize!(span_len)
|
participle,
|
||||||
),
|
name_list,
|
||||||
spans.iter().map(|sp| (*sp, "()".to_string())).collect(),
|
parent_info,
|
||||||
// "HasPlaceholders" because applying this fix by itself isn't
|
ignored_derived_impls,
|
||||||
// enough: All constructor calls have to be adjusted as well
|
}
|
||||||
Applicability::HasPlaceholders,
|
};
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(parent_item) = parent_item {
|
self.tcx.emit_spanned_lint(
|
||||||
let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
|
lint,
|
||||||
err.span_label(
|
tcx.hir().local_def_id_to_hir_id(first_id),
|
||||||
tcx.def_ident_span(parent_item).unwrap(),
|
MultiSpan::from_spans(spans.clone()),
|
||||||
format!("{descr}{s} in this {parent_descr}", s = pluralize!(span_len)),
|
diag,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
let encl_def_id = parent_item.unwrap_or(first_id);
|
|
||||||
if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
|
|
||||||
let traits_str = ign_traits
|
|
||||||
.iter()
|
|
||||||
.map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id)))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(" and ");
|
|
||||||
let plural_s = pluralize!(ign_traits.len());
|
|
||||||
let article = if ign_traits.len() > 1 { "" } else { "a " };
|
|
||||||
let is_are = if ign_traits.len() > 1 { "these are" } else { "this is" };
|
|
||||||
let msg = format!(
|
|
||||||
"`{}` has {}derived impl{} for the trait{} {}, but {} \
|
|
||||||
intentionally ignored during dead code analysis",
|
|
||||||
self.tcx.item_name(encl_def_id.to_def_id()),
|
|
||||||
article,
|
|
||||||
plural_s,
|
|
||||||
plural_s,
|
|
||||||
traits_str,
|
|
||||||
is_are
|
|
||||||
);
|
|
||||||
err.note(&msg);
|
|
||||||
}
|
|
||||||
err
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_dead_fields_and_variants(
|
fn warn_dead_fields_and_variants(
|
||||||
|
|
|
@ -4,12 +4,16 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustc_ast::Label;
|
use rustc_ast::Label;
|
||||||
use rustc_errors::{error_code, Applicability, ErrorGuaranteed, IntoDiagnostic, MultiSpan};
|
use rustc_errors::{
|
||||||
|
error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
|
||||||
|
};
|
||||||
use rustc_hir::{self as hir, ExprKind, Target};
|
use rustc_hir::{self as hir, ExprKind, Target};
|
||||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::{MainDefinition, Ty};
|
use rustc_middle::ty::{MainDefinition, Ty};
|
||||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||||
|
|
||||||
|
use rustc_errors::{pluralize, AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
|
||||||
|
|
||||||
use crate::lang_items::Duplicate;
|
use crate::lang_items::Duplicate;
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
|
@ -1449,3 +1453,77 @@ pub struct MissingConstErr {
|
||||||
#[label]
|
#[label]
|
||||||
pub const_span: Span,
|
pub const_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
pub enum MultipleDeadCodes<'tcx> {
|
||||||
|
#[diag(passes_dead_codes)]
|
||||||
|
DeadCodes {
|
||||||
|
multiple: bool,
|
||||||
|
num: usize,
|
||||||
|
descr: &'tcx str,
|
||||||
|
participle: &'tcx str,
|
||||||
|
name_list: DiagnosticSymbolList,
|
||||||
|
#[subdiagnostic]
|
||||||
|
parent_info: Option<ParentInfo<'tcx>>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
ignored_derived_impls: Option<IgnoredDerivedImpls>,
|
||||||
|
},
|
||||||
|
#[diag(passes_dead_codes)]
|
||||||
|
UnusedTupleStructFields {
|
||||||
|
multiple: bool,
|
||||||
|
num: usize,
|
||||||
|
descr: &'tcx str,
|
||||||
|
participle: &'tcx str,
|
||||||
|
name_list: DiagnosticSymbolList,
|
||||||
|
#[subdiagnostic]
|
||||||
|
change_fields_suggestion: ChangeFieldsToBeOfUnitType,
|
||||||
|
#[subdiagnostic]
|
||||||
|
parent_info: Option<ParentInfo<'tcx>>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
ignored_derived_impls: Option<IgnoredDerivedImpls>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[label(passes_parent_info)]
|
||||||
|
pub struct ParentInfo<'tcx> {
|
||||||
|
pub num: usize,
|
||||||
|
pub descr: &'tcx str,
|
||||||
|
pub parent_descr: &'tcx str,
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(passes_ignored_derived_impls)]
|
||||||
|
pub struct IgnoredDerivedImpls {
|
||||||
|
pub name: Symbol,
|
||||||
|
pub trait_list: DiagnosticSymbolList,
|
||||||
|
pub trait_list_len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ChangeFieldsToBeOfUnitType {
|
||||||
|
pub num: usize,
|
||||||
|
pub spans: Vec<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Replace this impl with a derive.
|
||||||
|
impl AddToDiagnostic for ChangeFieldsToBeOfUnitType {
|
||||||
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
|
diag.multipart_suggestion(
|
||||||
|
&format!(
|
||||||
|
"consider changing the field{s} to be of unit type to \
|
||||||
|
suppress this warning while preserving the field \
|
||||||
|
numbering, or remove the field{s}",
|
||||||
|
s = pluralize!(self.num)
|
||||||
|
),
|
||||||
|
self.spans.iter().map(|sp| (*sp, "()".to_string())).collect(),
|
||||||
|
// "HasPlaceholders" because applying this fix by itself isn't
|
||||||
|
// enough: All constructor calls have to be adjusted as well
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Whatever {
|
pub struct Whatever {
|
||||||
pub field0: (),
|
pub field0: (),
|
||||||
field1: (), //~ ERROR fields `field1`, `field2`, `field3` and `field4` are never read
|
field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read
|
||||||
field2: (),
|
field2: (),
|
||||||
field3: (),
|
field3: (),
|
||||||
field4: (),
|
field4: (),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: fields `field1`, `field2`, `field3` and `field4` are never read
|
error: fields `field1`, `field2`, `field3`, and `field4` are never read
|
||||||
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
|
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
|
||||||
|
|
|
|
||||||
LL | pub struct Whatever {
|
LL | pub struct Whatever {
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct Bar {
|
||||||
b: usize, //~ ERROR field `b` is never read
|
b: usize, //~ ERROR field `b` is never read
|
||||||
#[deny(dead_code)]
|
#[deny(dead_code)]
|
||||||
c: usize, //~ ERROR fields `c` and `e` are never read
|
c: usize, //~ ERROR fields `c` and `e` are never read
|
||||||
d: usize, //~ WARN fields `d`, `f` and `g` are never read
|
d: usize, //~ WARN fields `d`, `f`, and `g` are never read
|
||||||
#[deny(dead_code)]
|
#[deny(dead_code)]
|
||||||
e: usize,
|
e: usize,
|
||||||
f: usize,
|
f: usize,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
warning: fields `d`, `f` and `g` are never read
|
warning: fields `d`, `f`, and `g` are never read
|
||||||
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:10:5
|
--> $DIR/multiple-dead-codes-in-the-same-struct.rs:10:5
|
||||||
|
|
|
|
||||||
LL | struct Bar {
|
LL | struct Bar {
|
||||||
|
|
|
@ -11,7 +11,7 @@ struct SingleUnused(i32, [u8; LEN], String);
|
||||||
//~| HELP: consider changing the field to be of unit type
|
//~| HELP: consider changing the field to be of unit type
|
||||||
|
|
||||||
struct MultipleUnused(i32, f32, String, u8);
|
struct MultipleUnused(i32, f32, String, u8);
|
||||||
//~^ ERROR: fields `0`, `1`, `2` and `3` are never read
|
//~^ ERROR: fields `0`, `1`, `2`, and `3` are never read
|
||||||
//~| NOTE: fields in this struct
|
//~| NOTE: fields in this struct
|
||||||
//~| HELP: consider changing the fields to be of unit type
|
//~| HELP: consider changing the fields to be of unit type
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ help: consider changing the field to be of unit type to suppress this warning wh
|
||||||
LL | struct SingleUnused(i32, (), String);
|
LL | struct SingleUnused(i32, (), String);
|
||||||
| ~~
|
| ~~
|
||||||
|
|
||||||
error: fields `0`, `1`, `2` and `3` are never read
|
error: fields `0`, `1`, `2`, and `3` are never read
|
||||||
--> $DIR/tuple-struct-field.rs:13:23
|
--> $DIR/tuple-struct-field.rs:13:23
|
||||||
|
|
|
|
||||||
LL | struct MultipleUnused(i32, f32, String, u8);
|
LL | struct MultipleUnused(i32, f32, String, u8);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue