Auto merge of #137688 - fmease:rollup-gbeuj9j, r=fmease
Rollup of 10 pull requests Successful merges: - #134585 (remove `MaybeUninit::uninit_array`) - #136187 (Use less CString in the examples of CStr.) - #137201 (Teach structured errors to display short `Ty<'_>`) - #137620 (Fix `attr` cast for espidf) - #137631 (Avoid collecting associated types for undefined trait) - #137635 (Don't suggest constraining unstable associated types) - #137642 (Rustc dev guide subtree update) - #137660 (Update gcc submodule) - #137670 (revert accidental change in get_closest_merge_commit) - #137671 (Make -Z unpretty=mir suggest -Z dump-mir as well for discoverability) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
00f245915b
87 changed files with 701 additions and 329 deletions
|
@ -535,7 +535,6 @@ pub(crate) struct WhereClauseBeforeTypeAlias {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
||||
pub(crate) enum WhereClauseBeforeTypeAliasSugg {
|
||||
#[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")]
|
||||
Remove {
|
||||
|
|
|
@ -287,7 +287,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
None => "value".to_owned(),
|
||||
};
|
||||
if needs_note {
|
||||
let ty = self.infcx.tcx.short_string(ty, err.long_ty_path());
|
||||
if let Some(local) = place.as_local() {
|
||||
let span = self.body.local_decls[local].source_info.span;
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
|
|
|
@ -596,10 +596,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, place_ty, expr, None);
|
||||
}
|
||||
|
||||
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty,
|
||||
ty: place_ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
|
@ -629,10 +628,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, place_ty, expr, Some(use_spans));
|
||||
}
|
||||
|
||||
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty,
|
||||
ty: place_ty,
|
||||
place: &place_desc,
|
||||
span: use_span,
|
||||
});
|
||||
|
@ -833,10 +831,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, bind_to.ty, expr, None);
|
||||
}
|
||||
|
||||
let ty = self.infcx.tcx.short_string(bind_to.ty, err.long_ty_path());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty,
|
||||
ty: bind_to.ty,
|
||||
place: place_desc,
|
||||
span: binding_span,
|
||||
});
|
||||
|
|
|
@ -194,8 +194,8 @@ impl Display for RegionName {
|
|||
}
|
||||
|
||||
impl rustc_errors::IntoDiagArg for RegionName {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -459,17 +459,17 @@ pub(crate) enum OnClosureNote<'a> {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum TypeNoCopy<'a> {
|
||||
pub(crate) enum TypeNoCopy<'a, 'tcx> {
|
||||
#[label(borrowck_ty_no_impl_copy)]
|
||||
Label {
|
||||
is_partial_move: bool,
|
||||
ty: String,
|
||||
ty: Ty<'tcx>,
|
||||
place: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_ty_no_impl_copy)]
|
||||
Note { is_partial_move: bool, ty: String, place: &'a str },
|
||||
Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -211,7 +211,7 @@ impl fmt::Display for CguReuse {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for CguReuse {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ impl<'a> CopyPath<'a> {
|
|||
struct DebugArgPath<'a>(pub &'a Path);
|
||||
|
||||
impl IntoDiagArg for DebugArgPath<'_> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(format!("{:?}", self.0)))
|
||||
}
|
||||
}
|
||||
|
@ -1087,7 +1087,7 @@ pub enum ExpectedPointerMutability {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for ExpectedPointerMutability {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
match self {
|
||||
ExpectedPointerMutability::Mut => DiagArgValue::Str(Cow::Borrowed("*mut")),
|
||||
ExpectedPointerMutability::Not => DiagArgValue::Str(Cow::Borrowed("*_")),
|
||||
|
|
|
@ -49,10 +49,10 @@ impl MachineStopType for ConstEvalErrKind {
|
|||
| WriteThroughImmutablePointer => {}
|
||||
AssertFailure(kind) => kind.add_args(adder),
|
||||
Panic { msg, line, col, file } => {
|
||||
adder("msg".into(), msg.into_diag_arg());
|
||||
adder("file".into(), file.into_diag_arg());
|
||||
adder("line".into(), line.into_diag_arg());
|
||||
adder("col".into(), col.into_diag_arg());
|
||||
adder("msg".into(), msg.into_diag_arg(&mut None));
|
||||
adder("file".into(), file.into_diag_arg(&mut None));
|
||||
adder("line".into(), line.into_diag_arg(&mut None));
|
||||
adder("col".into(), col.into_diag_arg(&mut None));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -967,7 +967,7 @@ impl ReportErrorExt for ResourceExhaustionInfo {
|
|||
}
|
||||
|
||||
impl rustc_errors::IntoDiagArg for InternKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(match self {
|
||||
InternKind::Static(Mutability::Not) => "static",
|
||||
InternKind::Static(Mutability::Mut) => "static_mut",
|
||||
|
|
|
@ -148,11 +148,17 @@ where
|
|||
/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
|
||||
/// implement this.
|
||||
pub trait IntoDiagArg {
|
||||
fn into_diag_arg(self) -> DiagArgValue;
|
||||
/// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic.
|
||||
///
|
||||
/// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big
|
||||
/// for displaying on the terminal. This path comes from the `Diag` itself. When rendering
|
||||
/// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a
|
||||
/// value has no shortening logic that could be used, the argument can be safely ignored.
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
|
||||
}
|
||||
|
||||
impl IntoDiagArg for DiagArgValue {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +401,7 @@ impl DiagInner {
|
|||
}
|
||||
|
||||
pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
|
||||
self.args.insert(name.into(), arg.into_diag_arg());
|
||||
self.args.insert(name.into(), arg.into_diag_arg(&mut self.long_ty_path));
|
||||
}
|
||||
|
||||
/// Fields used for Hash, and PartialEq trait.
|
||||
|
|
|
@ -25,8 +25,8 @@ use crate::{
|
|||
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
|
||||
|
||||
impl IntoDiagArg for DiagArgFromDisplay<'_> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.0.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.0.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,8 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
|
|||
}
|
||||
|
||||
impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.clone().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.clone().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ macro_rules! into_diag_arg_using_display {
|
|||
($( $ty:ty ),+ $(,)?) => {
|
||||
$(
|
||||
impl IntoDiagArg for $ty {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
@ -65,13 +65,13 @@ macro_rules! into_diag_arg_for_number {
|
|||
($( $ty:ty ),+ $(,)?) => {
|
||||
$(
|
||||
impl IntoDiagArg for $ty {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
// Convert to a string if it won't fit into `Number`.
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Ok(n) = TryInto::<i32>::try_into(self) {
|
||||
DiagArgValue::Number(n)
|
||||
} else {
|
||||
self.to_string().into_diag_arg()
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,32 +98,32 @@ into_diag_arg_using_display!(
|
|||
);
|
||||
|
||||
impl IntoDiagArg for RustcVersion {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
format!("{self:?}").into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
format!("{self:?}").into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
format!("{self:?}").into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
format!("{self:?}").into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,15 +131,15 @@ impl<I: rustc_type_ir::Interner, T> IntoDiagArg for rustc_type_ir::Binder<I, T>
|
|||
where
|
||||
T: IntoDiagArg,
|
||||
{
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.skip_binder().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.skip_binder().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||
|
||||
impl IntoDiagArg for bool {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
if self {
|
||||
DiagArgValue::Str(Cow::Borrowed("true"))
|
||||
} else {
|
||||
|
@ -149,13 +149,13 @@ impl IntoDiagArg for bool {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for char {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Vec<char> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::StrListSepByAnd(
|
||||
self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
|
||||
)
|
||||
|
@ -163,49 +163,49 @@ impl IntoDiagArg for Vec<char> {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for Symbol {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_ident_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_ident_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagArg for &'a str {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for String {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagArg for Cow<'a, str> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagArg for &'a Path {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.display().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for PathBuf {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.display().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for PanicStrategy {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for hir::ConstContext {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(match self {
|
||||
hir::ConstContext::ConstFn => "const_fn",
|
||||
hir::ConstContext::Static(_) => "static",
|
||||
|
@ -215,49 +215,49 @@ impl IntoDiagArg for hir::ConstContext {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for ast::Expr {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::Path {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::token::Token {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(pprust::token_to_string(&self))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::token::TokenKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(pprust::token_kind_to_string(&self))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for FloatTy {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.name_str()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for std::ffi::CString {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ast::Visibility {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
let s = pprust::vis_to_string(&self);
|
||||
let s = s.trim_end().to_string();
|
||||
DiagArgValue::Str(Cow::Owned(s))
|
||||
|
@ -265,49 +265,49 @@ impl IntoDiagArg for ast::Visibility {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for rustc_lint_defs::Level {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id> IntoDiagArg for hir::def::Res<Id> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.descr()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for DiagLocation {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Backtrace {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Level {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ClosureKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(self.as_str().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for hir::def::Namespace {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.descr()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for ExprPrecedence {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Number(self as i32)
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ impl<S> FromIterator<S> for DiagSymbolList<S> {
|
|||
}
|
||||
|
||||
impl<S: std::fmt::Display> IntoDiagArg for DiagSymbolList<S> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::StrListSepByAnd(
|
||||
self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(),
|
||||
)
|
||||
|
|
|
@ -789,7 +789,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
Some(args.constraints.iter().filter_map(|constraint| {
|
||||
let ident = constraint.ident;
|
||||
let trait_def = path.res.def_id();
|
||||
|
||||
let Res::Def(DefKind::Trait, trait_def) = path.res else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind(
|
||||
tcx,
|
||||
ident,
|
||||
|
|
|
@ -10,6 +10,7 @@ hir_typeck_address_of_temporary_taken = cannot take address of a temporary
|
|||
hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
|
||||
.note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
|
||||
|
||||
hir_typeck_as_deref_suggestion = consider using `as_deref` here
|
||||
hir_typeck_base_expression_double_dot = base expression required after `..`
|
||||
hir_typeck_base_expression_double_dot_add_expr = add a base expression here
|
||||
hir_typeck_base_expression_double_dot_enable_default_field_values =
|
||||
|
@ -27,6 +28,9 @@ hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool`
|
|||
.help = compare with zero instead
|
||||
.label = unsupported cast
|
||||
|
||||
hir_typeck_cant_dereference = type `{$ty}` cannot be dereferenced
|
||||
hir_typeck_cant_dereference_label = can't be dereferenced
|
||||
|
||||
hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`
|
||||
|
||||
hir_typeck_cast_thin_pointer_to_wide_pointer = cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}`
|
||||
|
@ -72,6 +76,9 @@ hir_typeck_dependency_on_unit_never_type_fallback = this function depends on nev
|
|||
|
||||
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
|
||||
|
||||
hir_typeck_expected_array_or_slice = expected an array or slice, found `{$ty}`
|
||||
hir_typeck_expected_array_or_slice_label = pattern cannot match with input type `{$ty}`
|
||||
|
||||
hir_typeck_expected_default_return_type = expected `()` because of default return type
|
||||
|
||||
hir_typeck_expected_return_type = expected `{$expected}` because of return type
|
||||
|
@ -112,7 +119,11 @@ hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide
|
|||
hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata}
|
||||
hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
hir_typeck_invalid_callee = expected function, found {$ty}
|
||||
hir_typeck_invalid_callee = expected function, found {$found}
|
||||
hir_typeck_invalid_defined = `{$path}` defined here
|
||||
hir_typeck_invalid_defined_kind = {$kind} `{$path}` defined here
|
||||
hir_typeck_invalid_fn_defined = `{$func}` defined here returns `{$ty}`
|
||||
hir_typeck_invalid_local = `{$local_name}` has type `{$ty}`
|
||||
|
||||
hir_typeck_lossy_provenance_int2ptr =
|
||||
strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`
|
||||
|
@ -142,6 +153,12 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
|
|||
*[other] {" "}in the current scope
|
||||
}
|
||||
|
||||
hir_typeck_no_field_on_type = no field `{$field}` on type `{$ty}`
|
||||
|
||||
hir_typeck_no_field_on_variant = no field named `{$field}` on enum variant `{$container}::{$ident}`
|
||||
hir_typeck_no_field_on_variant_enum = this enum variant...
|
||||
hir_typeck_no_field_on_variant_field = ...does not have this field
|
||||
|
||||
hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}`
|
||||
|
||||
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
|
||||
|
@ -183,6 +200,8 @@ hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from o
|
|||
.label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
|
||||
.suggestion = replace `Self` with the actual type
|
||||
|
||||
hir_typeck_slicing_suggestion = consider slicing here
|
||||
|
||||
hir_typeck_struct_expr_non_exhaustive =
|
||||
cannot create non-exhaustive {$what} using struct expression
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use tracing::{debug, instrument};
|
|||
use super::method::MethodCallee;
|
||||
use super::method::probe::ProbeScope;
|
||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
||||
use crate::errors;
|
||||
use crate::{errors, fluent_generated};
|
||||
|
||||
/// Checks that it is legal to call methods of the trait corresponding
|
||||
/// to `trait_id` (this only cares about the trait, not the specific
|
||||
|
@ -674,13 +674,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let callee_ty = self.resolve_vars_if_possible(callee_ty);
|
||||
let mut path = None;
|
||||
let mut err = self.dcx().create_err(errors::InvalidCallee {
|
||||
span: callee_expr.span,
|
||||
ty: match &unit_variant {
|
||||
ty: callee_ty,
|
||||
found: match &unit_variant {
|
||||
Some((_, kind, path)) => format!("{kind} `{path}`"),
|
||||
None => format!("`{callee_ty}`"),
|
||||
None => format!("`{}`", self.tcx.short_string(callee_ty, &mut path)),
|
||||
},
|
||||
});
|
||||
*err.long_ty_path() = path;
|
||||
if callee_ty.references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
@ -780,27 +783,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(span) = self.tcx.hir().res_span(def) {
|
||||
let callee_ty = callee_ty.to_string();
|
||||
let label = match (unit_variant, inner_callee_path) {
|
||||
(Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
|
||||
(_, Some(hir::QPath::Resolved(_, path))) => self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(path.span)
|
||||
.ok()
|
||||
.map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
|
||||
(Some((_, kind, path)), _) => {
|
||||
err.arg("kind", kind);
|
||||
err.arg("path", path);
|
||||
Some(fluent_generated::hir_typeck_invalid_defined_kind)
|
||||
}
|
||||
(_, Some(hir::QPath::Resolved(_, path))) => {
|
||||
self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| {
|
||||
err.arg("func", p);
|
||||
fluent_generated::hir_typeck_invalid_fn_defined
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
match def {
|
||||
// Emit a different diagnostic for local variables, as they are not
|
||||
// type definitions themselves, but rather variables *of* that type.
|
||||
Res::Local(hir_id) => Some(format!(
|
||||
"`{}` has type `{}`",
|
||||
self.tcx.hir().name(hir_id),
|
||||
callee_ty
|
||||
)),
|
||||
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
|
||||
Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),))
|
||||
Res::Local(hir_id) => {
|
||||
err.arg("local_name", self.tcx.hir().name(hir_id));
|
||||
Some(fluent_generated::hir_typeck_invalid_local)
|
||||
}
|
||||
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
|
||||
err.arg("path", self.tcx.def_path_str(def_id));
|
||||
Some(fluent_generated::hir_typeck_invalid_defined)
|
||||
}
|
||||
_ => {
|
||||
err.arg("path", callee_ty);
|
||||
Some(fluent_generated::hir_typeck_invalid_defined)
|
||||
}
|
||||
_ => Some(format!("`{callee_ty}` defined here")),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -548,17 +548,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
err.emit();
|
||||
}
|
||||
CastError::SizedUnsizedCast => {
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
fcx.dcx().emit_err(errors::CastThinPointerToWidePointer {
|
||||
span: self.span,
|
||||
expr_ty: self.expr_ty,
|
||||
cast_ty: fcx.ty_to_string(self.cast_ty),
|
||||
expr_ty,
|
||||
cast_ty,
|
||||
teach: fcx.tcx.sess.teach(E0607),
|
||||
});
|
||||
}
|
||||
CastError::IntToWideCast(known_metadata) => {
|
||||
let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
let metadata = known_metadata.unwrap_or("type-specific metadata");
|
||||
let known_wide = known_metadata.is_some();
|
||||
let span = self.cast_span;
|
||||
|
@ -1164,10 +1166,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
if let Some((deref_ty, _)) = derefed {
|
||||
// Give a note about what the expr derefs to.
|
||||
if deref_ty != self.expr_ty.peel_refs() {
|
||||
err.subdiagnostic(errors::DerefImplsIsEmpty {
|
||||
span: self.expr_span,
|
||||
deref_ty: fcx.ty_to_string(deref_ty),
|
||||
});
|
||||
err.subdiagnostic(errors::DerefImplsIsEmpty { span: self.expr_span, deref_ty });
|
||||
}
|
||||
|
||||
// Create a multipart suggestion: add `!` and `.is_empty()` in
|
||||
|
@ -1175,7 +1174,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
err.subdiagnostic(errors::UseIsEmpty {
|
||||
lo: self.expr_span.shrink_to_lo(),
|
||||
hi: self.span.with_lo(self.expr_span.hi()),
|
||||
expr_ty: fcx.ty_to_string(self.expr_ty),
|
||||
expr_ty: self.expr_ty,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ pub(crate) enum ReturnLikeStatementKind {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for ReturnLikeStatementKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
let kind = match self {
|
||||
Self::Return => "return",
|
||||
Self::Become => "become",
|
||||
|
@ -454,12 +454,83 @@ impl HelpUseLatestEdition {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_no_field_on_type, code = E0609)]
|
||||
pub(crate) struct NoFieldOnType<'tcx> {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) ty: Ty<'tcx>,
|
||||
pub(crate) field: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_no_field_on_variant, code = E0609)]
|
||||
pub(crate) struct NoFieldOnVariant<'tcx> {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) container: Ty<'tcx>,
|
||||
pub(crate) ident: Ident,
|
||||
pub(crate) field: Ident,
|
||||
#[label(hir_typeck_no_field_on_variant_enum)]
|
||||
pub(crate) enum_span: Span,
|
||||
#[label(hir_typeck_no_field_on_variant_field)]
|
||||
pub(crate) field_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_cant_dereference, code = E0614)]
|
||||
pub(crate) struct CantDereference<'tcx> {
|
||||
#[primary_span]
|
||||
#[label(hir_typeck_cant_dereference_label)]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_expected_array_or_slice, code = E0529)]
|
||||
pub(crate) struct ExpectedArrayOrSlice<'tcx> {
|
||||
#[primary_span]
|
||||
#[label(hir_typeck_expected_array_or_slice_label)]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) ty: Ty<'tcx>,
|
||||
pub(crate) slice_pat_semantics: bool,
|
||||
#[subdiagnostic]
|
||||
pub(crate) as_deref: Option<AsDerefSuggestion>,
|
||||
#[subdiagnostic]
|
||||
pub(crate) slicing: Option<SlicingSuggestion>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
hir_typeck_as_deref_suggestion,
|
||||
code = ".as_deref()",
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub(crate) struct AsDerefSuggestion {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
hir_typeck_slicing_suggestion,
|
||||
code = "[..]",
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub(crate) struct SlicingSuggestion {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_invalid_callee, code = E0618)]
|
||||
pub(crate) struct InvalidCallee {
|
||||
pub(crate) struct InvalidCallee<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ty: String,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub found: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -469,7 +540,7 @@ pub(crate) struct IntToWide<'tcx> {
|
|||
#[label(hir_typeck_int_to_fat_label)]
|
||||
pub span: Span,
|
||||
pub metadata: &'tcx str,
|
||||
pub expr_ty: String,
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
#[label(hir_typeck_int_to_fat_label_nightly)]
|
||||
pub expr_if_nightly: Option<Span>,
|
||||
|
@ -581,12 +652,12 @@ pub(crate) struct UnionPatDotDot {
|
|||
applicability = "maybe-incorrect",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub(crate) struct UseIsEmpty {
|
||||
pub(crate) struct UseIsEmpty<'tcx> {
|
||||
#[suggestion_part(code = "!")]
|
||||
pub lo: Span,
|
||||
#[suggestion_part(code = ".is_empty()")]
|
||||
pub hi: Span,
|
||||
pub expr_ty: String,
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -745,10 +816,10 @@ pub(crate) struct CtorIsPrivate {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(hir_typeck_deref_is_empty)]
|
||||
pub(crate) struct DerefImplsIsEmpty {
|
||||
pub(crate) struct DerefImplsIsEmpty<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub deref_ty: String,
|
||||
pub deref_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
@ -826,7 +897,7 @@ pub(crate) struct CastThinPointerToWidePointer<'tcx> {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
pub cast_ty: String,
|
||||
pub cast_ty: Ty<'tcx>,
|
||||
#[note(hir_typeck_teach_help)]
|
||||
pub(crate) teach: bool,
|
||||
}
|
||||
|
|
|
@ -45,9 +45,10 @@ use crate::coercion::{CoerceMany, DynamicCoerceMany};
|
|||
use crate::errors::{
|
||||
AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr,
|
||||
BaseExpressionDoubleDotEnableDefaultFieldValues, BaseExpressionDoubleDotRemove,
|
||||
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
|
||||
ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive,
|
||||
TypeMismatchFruTypo, YieldExprOutsideOfCoroutine,
|
||||
CantDereference, FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
|
||||
HelpUseLatestEdition, NoFieldOnType, NoFieldOnVariant, ReturnLikeStatementKind,
|
||||
ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, TypeMismatchFruTypo,
|
||||
YieldExprOutsideOfCoroutine,
|
||||
};
|
||||
use crate::{
|
||||
BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, cast, fatally_break_rust,
|
||||
|
@ -607,13 +608,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) {
|
||||
oprnd_t = ty;
|
||||
} else {
|
||||
let mut err = type_error_struct!(
|
||||
self.dcx(),
|
||||
expr.span,
|
||||
oprnd_t,
|
||||
E0614,
|
||||
"type `{oprnd_t}` cannot be dereferenced",
|
||||
);
|
||||
let mut err =
|
||||
self.dcx().create_err(CantDereference { span: expr.span, ty: oprnd_t });
|
||||
let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None);
|
||||
if let Some(sp) =
|
||||
tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp)
|
||||
|
@ -3287,13 +3283,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let span = field.span;
|
||||
debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t);
|
||||
|
||||
let mut err = type_error_struct!(
|
||||
self.dcx(),
|
||||
span,
|
||||
expr_t,
|
||||
E0609,
|
||||
"no field `{field}` on type `{expr_t}`",
|
||||
);
|
||||
let mut err = self.dcx().create_err(NoFieldOnType { span, ty: expr_t, field });
|
||||
if expr_t.references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
||||
// try to add a suggestion in case the field is a nested field of a field of the Adt
|
||||
let mod_id = self.tcx.parent_module(id).to_def_id();
|
||||
|
@ -3867,16 +3860,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.iter_enumerated()
|
||||
.find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident)
|
||||
else {
|
||||
type_error_struct!(
|
||||
self.dcx(),
|
||||
ident.span,
|
||||
container,
|
||||
E0609,
|
||||
"no field named `{subfield}` on enum variant `{container}::{ident}`",
|
||||
)
|
||||
.with_span_label(field.span, "this enum variant...")
|
||||
.with_span_label(subident.span, "...does not have this field")
|
||||
.emit();
|
||||
self.dcx()
|
||||
.create_err(NoFieldOnVariant {
|
||||
span: ident.span,
|
||||
container,
|
||||
ident,
|
||||
field: subfield,
|
||||
enum_span: field.span,
|
||||
field_span: subident.span,
|
||||
})
|
||||
.emit_unless(container.references_error());
|
||||
break;
|
||||
};
|
||||
|
||||
|
|
|
@ -2771,16 +2771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) -> ErrorGuaranteed {
|
||||
let PatInfo { top_info: ti, current_depth, .. } = pat_info;
|
||||
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0529,
|
||||
"expected an array or slice, found `{expected_ty}`"
|
||||
);
|
||||
let mut slice_pat_semantics = false;
|
||||
let mut as_deref = None;
|
||||
let mut slicing = None;
|
||||
if let ty::Ref(_, ty, _) = expected_ty.kind()
|
||||
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
|
||||
{
|
||||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
||||
slice_pat_semantics = true;
|
||||
} else if self
|
||||
.autoderef(span, expected_ty)
|
||||
.silence_errors()
|
||||
|
@ -2797,28 +2794,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
|
||||
{
|
||||
// Slicing won't work here, but `.as_deref()` might (issue #91328).
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
"consider using `as_deref` here",
|
||||
".as_deref()",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() });
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let is_top_level = current_depth <= 1;
|
||||
if is_slice_or_array_or_vector && is_top_level {
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
"consider slicing here",
|
||||
"[..]",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() });
|
||||
}
|
||||
}
|
||||
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
|
||||
err.emit()
|
||||
self.dcx().emit_err(errors::ExpectedArrayOrSlice {
|
||||
span,
|
||||
ty: expected_ty,
|
||||
slice_pat_semantics,
|
||||
as_deref,
|
||||
slicing,
|
||||
})
|
||||
}
|
||||
|
||||
fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {
|
||||
|
|
|
@ -290,7 +290,7 @@ impl fmt::Display for CrateFlavor {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for CrateFlavor {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
match self {
|
||||
CrateFlavor::Rlib => DiagArgValue::Str(Cow::Borrowed("rlib")),
|
||||
CrateFlavor::Rmeta => DiagArgValue::Str(Cow::Borrowed("rmeta")),
|
||||
|
|
|
@ -47,10 +47,10 @@ pub struct UnsupportedUnion {
|
|||
// FIXME(autodiff): I should get used somewhere
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(middle_autodiff_unsafe_inner_const_ref)]
|
||||
pub struct AutodiffUnsafeInnerConstRef {
|
||||
pub struct AutodiffUnsafeInnerConstRef<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ty: String,
|
||||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
@ -248,7 +248,7 @@ pub enum InvalidMetaKind {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for InvalidMetaKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(match self {
|
||||
InvalidMetaKind::SliceTooBig => "slice_too_big",
|
||||
InvalidMetaKind::TooBig => "too_big",
|
||||
|
@ -282,7 +282,7 @@ pub struct Misalignment {
|
|||
macro_rules! impl_into_diag_arg_through_debug {
|
||||
($($ty:ty),*$(,)?) => {$(
|
||||
impl IntoDiagArg for $ty {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ pub enum PointerKind {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for PointerKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(
|
||||
match self {
|
||||
Self::Ref(_) => "ref",
|
||||
|
@ -666,7 +666,7 @@ macro_rules! err_ub_custom {
|
|||
msg: || $msg,
|
||||
add_args: Box::new(move |mut set_arg| {
|
||||
$($(
|
||||
set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name));
|
||||
set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None));
|
||||
)*)?
|
||||
})
|
||||
}
|
||||
|
|
|
@ -319,6 +319,7 @@ pub fn write_mir_pretty<'tcx>(
|
|||
|
||||
writeln!(w, "// WARNING: This output format is intended for human consumers only")?;
|
||||
writeln!(w, "// and is subject to change without notice. Knock yourself out.")?;
|
||||
writeln!(w, "// HINT: See also -Z dump-mir for MIR at specific points during compilation.")?;
|
||||
|
||||
let mut first = true;
|
||||
for def_id in dump_mir_def_ids(tcx, single) {
|
||||
|
|
|
@ -357,7 +357,7 @@ impl<O> AssertKind<O> {
|
|||
|
||||
macro_rules! add {
|
||||
($name: expr, $value: expr) => {
|
||||
adder($name.into(), $value.into_diag_arg());
|
||||
adder($name.into(), $value.into_diag_arg(&mut None));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ impl std::fmt::Debug for ConstInt {
|
|||
impl IntoDiagArg for ConstInt {
|
||||
// FIXME this simply uses the Debug impl, but we could probably do better by converting both
|
||||
// to an inherent method that returns `Cow`.
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(format!("{self:?}").into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,16 @@ use crate::ty::{
|
|||
TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
|
||||
impl IntoDiagArg for Ty<'_> {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
ty::tls::with(|tcx| {
|
||||
let ty = tcx.short_string(self, path);
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(ty))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
into_diag_arg_using_display! {
|
||||
Ty<'_>,
|
||||
ty::Region<'_>,
|
||||
}
|
||||
|
||||
|
|
|
@ -213,10 +213,9 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String
|
||||
pub fn string_with_limit<T>(self, p: T, length_limit: usize) -> String
|
||||
where
|
||||
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy,
|
||||
<T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
|
||||
T: Copy + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
|
||||
{
|
||||
let mut type_limit = 50;
|
||||
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
|
||||
|
@ -253,10 +252,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps
|
||||
/// the existence of a "long type" anywhere in the diagnostic, so the note telling the user
|
||||
/// where we wrote the file to is only printed once.
|
||||
pub fn short_string<'a, T>(self, p: T, path: &mut Option<PathBuf>) -> String
|
||||
pub fn short_string<T>(self, p: T, path: &mut Option<PathBuf>) -> String
|
||||
where
|
||||
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy + Hash,
|
||||
<T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
|
||||
T: Copy + Hash + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
|
||||
{
|
||||
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
|
||||
self.lift(p).expect("could not lift for printing").print(cx)
|
||||
|
|
|
@ -159,8 +159,8 @@ unsafe impl<'tcx> Sync for GenericArg<'tcx> where
|
|||
}
|
||||
|
||||
impl<'tcx> IntoDiagArg for GenericArg<'tcx> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(&mut None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -315,8 +315,8 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> IntoDiagArg for LayoutError<'tcx> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(&mut None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,15 +158,21 @@ impl<'tcx> Predicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl rustc_errors::IntoDiagArg for Predicate<'_> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
|
||||
impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
ty::tls::with(|tcx| {
|
||||
let pred = tcx.short_string(self, path);
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_errors::IntoDiagArg for Clause<'_> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
|
||||
impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
ty::tls::with(|tcx| {
|
||||
let clause = tcx.short_string(self, path);
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2898,12 +2898,15 @@ where
|
|||
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
|
||||
/// the trait path. That is, it will print `Trait<U>` instead of
|
||||
/// `<T as Trait<U>>`.
|
||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
|
||||
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
|
||||
|
||||
impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
ty::tls::with(|tcx| {
|
||||
let trait_ref = tcx.short_string(self, path);
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2915,12 +2918,15 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
|
|||
|
||||
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
|
||||
/// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds.
|
||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
|
||||
pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>);
|
||||
|
||||
impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
ty::tls::with(|tcx| {
|
||||
let trait_ref = tcx.short_string(self, path);
|
||||
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -828,7 +828,7 @@ pub(crate) struct IrrefutableLetPatternsWhileLet {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_borrow_of_moved_value)]
|
||||
pub(crate) struct BorrowOfMovedValue {
|
||||
pub(crate) struct BorrowOfMovedValue<'tcx> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label(mir_build_occurs_because_label)]
|
||||
|
@ -836,7 +836,7 @@ pub(crate) struct BorrowOfMovedValue {
|
|||
#[label(mir_build_value_borrowed_label)]
|
||||
pub(crate) conflicts_ref: Vec<Span>,
|
||||
pub(crate) name: Ident,
|
||||
pub(crate) ty: String,
|
||||
pub(crate) ty: Ty<'tcx>,
|
||||
#[suggestion(code = "ref ", applicability = "machine-applicable")]
|
||||
pub(crate) suggest_borrowing: Option<Span>,
|
||||
}
|
||||
|
|
|
@ -786,17 +786,13 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
}
|
||||
});
|
||||
if !conflicts_ref.is_empty() {
|
||||
let mut path = None;
|
||||
let ty = cx.tcx.short_string(ty, &mut path);
|
||||
let mut err = sess.dcx().create_err(BorrowOfMovedValue {
|
||||
sess.dcx().emit_err(BorrowOfMovedValue {
|
||||
binding_span: pat.span,
|
||||
conflicts_ref,
|
||||
name: Ident::new(name, pat.span),
|
||||
ty,
|
||||
suggest_borrowing: Some(pat.span.shrink_to_lo()),
|
||||
});
|
||||
*err.long_ty_path() = path;
|
||||
err.emit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -772,7 +772,6 @@ pub(crate) struct LabeledLoopInBreak {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
||||
pub(crate) enum WrapInParentheses {
|
||||
#[multipart_suggestion(
|
||||
parse_sugg_wrap_expression_in_parentheses,
|
||||
|
|
|
@ -80,13 +80,13 @@ pub(crate) enum ProcMacroKind {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for ProcMacroKind {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
match self {
|
||||
ProcMacroKind::Attribute => "attribute proc macro",
|
||||
ProcMacroKind::Derive => "derive proc macro",
|
||||
ProcMacroKind::FunctionLike => "function-like proc macro",
|
||||
}
|
||||
.into_diag_arg()
|
||||
.into_diag_arg(&mut None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1005,10 +1005,10 @@ pub(crate) struct LayoutHomogeneousAggregate {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_layout_of)]
|
||||
pub(crate) struct LayoutOf {
|
||||
pub(crate) struct LayoutOf<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub normalized_ty: String,
|
||||
pub normalized_ty: Ty<'tcx>,
|
||||
pub ty_layout: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -112,8 +112,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
|||
}
|
||||
|
||||
sym::debug => {
|
||||
let normalized_ty =
|
||||
format!("{}", tcx.normalize_erasing_regions(typing_env, ty));
|
||||
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
|
||||
// FIXME: using the `Debug` impl here isn't ideal.
|
||||
let ty_layout = format!("{:#?}", *ty_layout);
|
||||
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
|
||||
|
|
|
@ -94,7 +94,7 @@ impl PatternSource {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for PatternSource {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.descr()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2807,8 +2807,8 @@ impl fmt::Display for CrateType {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for CrateType {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg(&mut None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,8 +109,8 @@ impl Mul<usize> for Limit {
|
|||
}
|
||||
|
||||
impl rustc_errors::IntoDiagArg for Limit {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
self.to_string().into_diag_arg(&mut None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2418,7 +2418,7 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>);
|
||||
|
||||
impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
let kind = match self.0.code() {
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat",
|
||||
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat",
|
||||
|
|
|
@ -137,7 +137,7 @@ impl InferenceDiagnosticsParentData {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for UnderspecifiedArgKind {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
let kind = match self {
|
||||
Self::Type { .. } => "type",
|
||||
Self::Const { is_parameter: true } => "const_with_param",
|
||||
|
|
|
@ -31,7 +31,7 @@ impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
|
|||
where
|
||||
T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
|
||||
{
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
rustc_errors::DiagArgValue::Str(self.to_string().into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,10 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
|
|||
) {
|
||||
if hir_generics.where_clause_span.from_expansion()
|
||||
|| hir_generics.where_clause_span.desugaring_kind().is_some()
|
||||
|| projection.is_some_and(|projection| tcx.is_impl_trait_in_trait(projection.def_id))
|
||||
|| projection.is_some_and(|projection| {
|
||||
tcx.is_impl_trait_in_trait(projection.def_id)
|
||||
|| tcx.lookup_stability(projection.def_id).is_some_and(|stab| stab.is_unstable())
|
||||
})
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -784,10 +784,10 @@ pub enum TyOrSig<'tcx> {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for TyOrSig<'_> {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
match self {
|
||||
TyOrSig::Ty(ty) => ty.into_diag_arg(),
|
||||
TyOrSig::ClosureSig(sig) => sig.into_diag_arg(),
|
||||
TyOrSig::Ty(ty) => ty.into_diag_arg(path),
|
||||
TyOrSig::ClosureSig(sig) => sig.into_diag_arg(path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ pub enum SuffixKind {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for PrefixKind {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
let kind = match self {
|
||||
Self::Empty => "empty",
|
||||
Self::RefValidFor => "ref_valid_for",
|
||||
|
@ -127,7 +127,7 @@ impl IntoDiagArg for PrefixKind {
|
|||
}
|
||||
|
||||
impl IntoDiagArg for SuffixKind {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
|
||||
let kind = match self {
|
||||
Self::Empty => "empty",
|
||||
Self::Continues => "continues",
|
||||
|
|
|
@ -55,18 +55,15 @@ use crate::{fmt, ops, slice, str};
|
|||
/// Passing a Rust-originating C string:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::{CString, CStr};
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// fn work(data: &CStr) {
|
||||
/// # /* Extern functions are awkward in doc comments - fake it instead
|
||||
/// extern "C" { fn work_with(data: *const c_char); }
|
||||
/// # */ unsafe extern "C" fn work_with(s: *const c_char) {}
|
||||
///
|
||||
/// unsafe extern "C" fn work_with(s: *const c_char) {}
|
||||
/// unsafe { work_with(data.as_ptr()) }
|
||||
/// }
|
||||
///
|
||||
/// let s = CString::new("data data data data").expect("CString::new failed");
|
||||
/// let s = c"Hello world!";
|
||||
/// work(&s);
|
||||
/// ```
|
||||
///
|
||||
|
@ -384,13 +381,12 @@ impl CStr {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::{CStr, CString};
|
||||
/// use std::ffi::CStr;
|
||||
///
|
||||
/// unsafe {
|
||||
/// let cstring = CString::new("hello").expect("CString::new failed");
|
||||
/// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
|
||||
/// assert_eq!(cstr, &*cstring);
|
||||
/// }
|
||||
/// let bytes = b"Hello world!\0";
|
||||
///
|
||||
/// let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(bytes) };
|
||||
/// assert_eq!(cstr.to_bytes_with_nul(), bytes);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -449,38 +445,43 @@ impl CStr {
|
|||
/// behavior when `ptr` is used inside the `unsafe` block:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![allow(unused_must_use)]
|
||||
/// # #![expect(dangling_pointers_from_temporaries)]
|
||||
/// use std::ffi::CString;
|
||||
/// use std::ffi::{CStr, CString};
|
||||
///
|
||||
/// // Do not do this:
|
||||
/// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
|
||||
/// unsafe {
|
||||
/// // `ptr` is dangling
|
||||
/// *ptr;
|
||||
/// }
|
||||
/// // 💀 The meaning of this entire program is undefined,
|
||||
/// // 💀 and nothing about its behavior is guaranteed,
|
||||
/// // 💀 not even that its behavior resembles the code as written,
|
||||
/// // 💀 just because it contains a single instance of undefined behavior!
|
||||
///
|
||||
/// // 🚨 creates a dangling pointer to a temporary `CString`
|
||||
/// // 🚨 that is deallocated at the end of the statement
|
||||
/// let ptr = CString::new("Hi!".to_uppercase()).unwrap().as_ptr();
|
||||
///
|
||||
/// // without undefined behavior, you would expect that `ptr` equals:
|
||||
/// dbg!(CStr::from_bytes_with_nul(b"HI!\0").unwrap());
|
||||
///
|
||||
/// // 🙏 Possibly the program behaved as expected so far,
|
||||
/// // 🙏 and this just shows `ptr` is now garbage..., but
|
||||
/// // 💀 this violates `CStr::from_ptr`'s safety contract
|
||||
/// // 💀 leading to a dereference of a dangling pointer,
|
||||
/// // 💀 which is immediate undefined behavior.
|
||||
/// // 💀 *BOOM*, you're dead, you're entire program has no meaning.
|
||||
/// dbg!(unsafe { CStr::from_ptr(ptr) });
|
||||
/// ```
|
||||
///
|
||||
/// This happens because the pointer returned by `as_ptr` does not carry any
|
||||
/// lifetime information and the `CString` is deallocated immediately after
|
||||
/// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
|
||||
/// expression is evaluated.
|
||||
/// This happens because, the pointer returned by `as_ptr` does not carry any
|
||||
/// lifetime information, and the `CString` is deallocated immediately after
|
||||
/// the expression that it is part of has been evaluated.
|
||||
/// To fix the problem, bind the `CString` to a local variable:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![allow(unused_must_use)]
|
||||
/// use std::ffi::CString;
|
||||
///
|
||||
/// let hello = CString::new("Hello").expect("CString::new failed");
|
||||
/// let ptr = hello.as_ptr();
|
||||
/// unsafe {
|
||||
/// // `ptr` is valid because `hello` is in scope
|
||||
/// *ptr;
|
||||
/// }
|
||||
/// ```
|
||||
/// use std::ffi::{CStr, CString};
|
||||
///
|
||||
/// This way, the lifetime of the `CString` in `hello` encompasses
|
||||
/// the lifetime of `ptr` and the `unsafe` block.
|
||||
/// let c_str = CString::new("Hi!".to_uppercase()).unwrap();
|
||||
/// let ptr = c_str.as_ptr();
|
||||
///
|
||||
/// assert_eq!(unsafe { CStr::from_ptr(ptr) }, c"HI!");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
@ -331,42 +331,6 @@ impl<T> MaybeUninit<T> {
|
|||
MaybeUninit { uninit: () }
|
||||
}
|
||||
|
||||
/// Creates a new array of `MaybeUninit<T>` items, in an uninitialized state.
|
||||
///
|
||||
/// Note: in a future Rust version this method may become unnecessary
|
||||
/// when Rust allows
|
||||
/// [inline const expressions](https://github.com/rust-lang/rust/issues/76001).
|
||||
/// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(maybe_uninit_uninit_array, maybe_uninit_slice)]
|
||||
///
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// unsafe extern "C" {
|
||||
/// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize;
|
||||
/// }
|
||||
///
|
||||
/// /// Returns a (possibly smaller) slice of data that was actually read
|
||||
/// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
|
||||
/// unsafe {
|
||||
/// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
|
||||
/// buf[..len].assume_init_ref()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
|
||||
/// let data = read(&mut buf);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_uninit_array", issue = "96097")]
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
pub const fn uninit_array<const N: usize>() -> [Self; N] {
|
||||
[const { MaybeUninit::uninit() }; N]
|
||||
}
|
||||
|
||||
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
|
||||
/// filled with `0` bytes. It depends on `T` whether that already makes for
|
||||
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Thread {
|
|||
assert_eq!(
|
||||
libc::pthread_attr_setstacksize(
|
||||
attr.as_mut_ptr(),
|
||||
cmp::max(stack, min_stack_size(&attr))
|
||||
cmp::max(stack, min_stack_size(attr.as_ptr()))
|
||||
),
|
||||
0
|
||||
);
|
||||
|
|
|
@ -154,6 +154,7 @@ pub fn get_closest_merge_commit(
|
|||
"rev-list",
|
||||
&format!("--author={}", config.git_merge_commit_email),
|
||||
"-n1",
|
||||
"--first-parent",
|
||||
&merge_base,
|
||||
]);
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ on:
|
|||
- master
|
||||
pull_request:
|
||||
schedule:
|
||||
# Run at 18:00 UTC every day
|
||||
- cron: '0 18 * * *'
|
||||
# Run multiple times a day as the successfull cached links are not checked every time.
|
||||
- cron: '0 */8 * * *'
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
|
@ -15,7 +15,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
env:
|
||||
MDBOOK_VERSION: 0.4.21
|
||||
MDBOOK_LINKCHECK2_VERSION: 0.8.1
|
||||
MDBOOK_LINKCHECK2_VERSION: 0.9.1
|
||||
MDBOOK_MERMAID_VERSION: 0.12.6
|
||||
MDBOOK_TOC_VERSION: 0.11.2
|
||||
DEPLOY_DIR: book/html
|
||||
|
|
|
@ -111,4 +111,4 @@ jobs:
|
|||
to: 196385
|
||||
type: "stream"
|
||||
topic: "Subtree sync automation"
|
||||
content: ${{ steps.message.outputs.message }}
|
||||
content: ${{ steps.create-message.outputs.message }}
|
||||
|
|
|
@ -4,7 +4,10 @@ For each example to compile, you will need to first run the following:
|
|||
|
||||
To create an executable:
|
||||
|
||||
rustc rustc-driver-example.rs
|
||||
rustup run nightly rustc rustc-driver-example.rs
|
||||
|
||||
You might need to be more specific about the exact nightly version. See the comments at the top of
|
||||
the examples for the version they were written for.
|
||||
|
||||
To run an executable:
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Tested with nightly-2025-02-13
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_ast;
|
||||
|
@ -73,7 +75,7 @@ impl rustc_driver::Callbacks for MyCallbacks {
|
|||
let hir = tcx.hir();
|
||||
let item = hir.item(id);
|
||||
match item.kind {
|
||||
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => {
|
||||
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => {
|
||||
let name = item.ident;
|
||||
let ty = tcx.type_of(item.hir_id().owner.def_id);
|
||||
println!("{name:?}:\t{ty:?}")
|
||||
|
@ -87,5 +89,13 @@ impl rustc_driver::Callbacks for MyCallbacks {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
run_compiler(&["main.rs".to_string()], &mut MyCallbacks);
|
||||
run_compiler(
|
||||
&[
|
||||
// The first argument, which in practice contains the name of the binary being executed
|
||||
// (i.e. "rustc") is ignored by rustc.
|
||||
"ignored".to_string(),
|
||||
"main.rs".to_string(),
|
||||
],
|
||||
&mut MyCallbacks,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Tested with nightly-2025-02-13
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_ast;
|
||||
|
@ -18,7 +20,7 @@ use std::path::Path;
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast_pretty::pprust::item_to_string;
|
||||
use rustc_driver::{Compilation, run_compiler};
|
||||
use rustc_driver::{run_compiler, Compilation};
|
||||
use rustc_interface::interface::{Compiler, Config};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
|
@ -74,8 +76,8 @@ impl rustc_driver::Callbacks for MyCallbacks {
|
|||
for id in hir_krate.items() {
|
||||
let item = hir_krate.item(id);
|
||||
// Use pattern-matching to find a specific node inside the main function.
|
||||
if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind {
|
||||
let expr = &tcx.hir_body(body_id).value;
|
||||
if let rustc_hir::ItemKind::Fn { body, .. } = item.kind {
|
||||
let expr = &tcx.hir_body(body).value;
|
||||
if let rustc_hir::ExprKind::Block(block, _) = expr.kind {
|
||||
if let rustc_hir::StmtKind::Let(let_stmt) = block.stmts[0].kind {
|
||||
if let Some(expr) = let_stmt.init {
|
||||
|
@ -94,5 +96,13 @@ impl rustc_driver::Callbacks for MyCallbacks {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
run_compiler(&["main.rs".to_string()], &mut MyCallbacks);
|
||||
run_compiler(
|
||||
&[
|
||||
// The first argument, which in practice contains the name of the binary being executed
|
||||
// (i.e. "rustc") is ignored by rustc.
|
||||
"ignored".to_string(),
|
||||
"main.rs".to_string(),
|
||||
],
|
||||
&mut MyCallbacks,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Tested with nightly-2025-02-13
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_driver;
|
||||
|
@ -9,8 +11,6 @@ extern crate rustc_interface;
|
|||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_errors::registry;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_session::config;
|
||||
|
@ -56,7 +56,7 @@ fn main() {
|
|||
expanded_args: Vec::new(),
|
||||
ice_file: None,
|
||||
hash_untracked_state: None,
|
||||
using_internal_features: Arc::default(),
|
||||
using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,
|
||||
};
|
||||
rustc_interface::run_compiler(config, |compiler| {
|
||||
// Parse the program and print the syntax tree.
|
||||
|
@ -68,7 +68,7 @@ fn main() {
|
|||
let hir = tcx.hir();
|
||||
let item = hir.item(id);
|
||||
match item.kind {
|
||||
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => {
|
||||
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => {
|
||||
let name = item.ident;
|
||||
let ty = tcx.type_of(item.hir_id().owner.def_id);
|
||||
println!("{name:?}:\t{ty:?}")
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Tested with nightly-2025-02-13
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate rustc_data_structures;
|
||||
|
@ -15,7 +17,7 @@ use std::sync::{Arc, Mutex};
|
|||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::registry::{self, Registry};
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::{DiagCtxt, DiagInner, FluentBundle};
|
||||
use rustc_errors::{DiagInner, FluentBundle};
|
||||
use rustc_session::config;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
||||
|
@ -79,7 +81,7 @@ fn main() {
|
|||
expanded_args: Vec::new(),
|
||||
ice_file: None,
|
||||
hash_untracked_state: None,
|
||||
using_internal_features: Arc::default(),
|
||||
using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,
|
||||
};
|
||||
rustc_interface::run_compiler(config, |compiler| {
|
||||
let krate = rustc_interface::passes::parse(&compiler.sess);
|
||||
|
|
|
@ -1 +1 @@
|
|||
124cc92199ffa924f6b4c7cc819a85b65e0c3984
|
||||
4ecd70ddd1039a3954056c1071e40278048476fa
|
||||
|
|
|
@ -1,7 +1,46 @@
|
|||
# Debugging bootstrap
|
||||
|
||||
There are two main ways to debug bootstrap itself. The first is through println logging, and the second is through the `tracing` feature.
|
||||
|
||||
> FIXME: this section should be expanded
|
||||
|
||||
## `println` logging
|
||||
|
||||
Bootstrap has extensive unstructured logging. Most of it is gated behind the `--verbose` flag (pass `-vv` for even more detail).
|
||||
|
||||
If you want to know which `Step` ran a command, you could invoke bootstrap like so:
|
||||
|
||||
```
|
||||
$ ./x dist rustc --dry-run -vv
|
||||
learning about cargo
|
||||
running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50)
|
||||
running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/library/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50)
|
||||
> Assemble { target_compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu } }
|
||||
> Libdir { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, target: x86_64-unknown-linux-gnu }
|
||||
> Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, force_recompile: false }
|
||||
Removing sysroot /home/jyn/src/rust2/build/tmp-dry-run/x86_64-unknown-linux-gnu/stage1 to avoid caching bugs
|
||||
< Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, force_recompile: false }
|
||||
< Libdir { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, target: x86_64-unknown-linux-gnu }
|
||||
...
|
||||
```
|
||||
|
||||
This will go through all the recursive dependency calculations, where `Step`s internally call `builder.ensure()`, without actually running cargo or the compiler.
|
||||
|
||||
In some cases, even this may not be enough logging (if so, please add more!). In that case, you can omit `--dry-run`, which will show the normal output inline with the debug logging:
|
||||
|
||||
```
|
||||
c Sysroot { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu }, force_recompile: false }
|
||||
using sysroot /home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0-sysroot
|
||||
Building stage0 library artifacts (x86_64-unknown-linux-gnu)
|
||||
running: cd "/home/jyn/src/rust2" && env ... RUSTC_VERBOSE="2" RUSTC_WRAPPER="/home/jyn/src/rust2/build/bootstrap/debug/rustc" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-Zbinary-dep-depinfo" "-Zroot-dir=/home/jyn/src/rust2" "-v" "-v" "--manifest-path" "/home/jyn/src/rust2/library/sysroot/Cargo.toml" "--message-format" "json-render-diagnostics"
|
||||
0.293440230s INFO prepare_target{force=false package_id=sysroot v0.0.0 (/home/jyn/src/rust2/library/sysroot) target="sysroot"}: cargo::core::compiler::fingerprint: fingerprint error for sysroot v0.0.0 (/home/jyn/src/rust2/library/sysroot)/Build/TargetInner { name_inferred: true, ..: lib_target("sysroot", ["lib"], "/home/jyn/src/rust2/library/sysroot/src/lib.rs", Edition2021) }
|
||||
...
|
||||
```
|
||||
|
||||
In most cases this should not be necessary.
|
||||
|
||||
TODO: we should convert all this to structured logging so it's easier to control precisely.
|
||||
|
||||
## `tracing` in bootstrap
|
||||
|
||||
Bootstrap has conditional [`tracing`][tracing] setup to provide structured logging.
|
||||
|
@ -53,11 +92,11 @@ Checking stage0 bootstrap artifacts (x86_64-unknown-linux-gnu)
|
|||
Build completed successfully in 0:00:08
|
||||
```
|
||||
|
||||
#### Controlling log output
|
||||
#### Controlling tracing output
|
||||
|
||||
The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter].
|
||||
|
||||
There are two orthogonal ways to control which kind of logs you want:
|
||||
There are two orthogonal ways to control which kind of tracing logs you want:
|
||||
|
||||
1. You can specify the log **level**, e.g. `DEBUG` or `TRACE`.
|
||||
2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` vs custom targets like `CONFIG_HANDLING`.
|
||||
|
|
|
@ -120,10 +120,35 @@ create a `.vim/coc-settings.json`. The settings can be edited with
|
|||
[`src/etc/rust_analyzer_settings.json`].
|
||||
|
||||
Another way is without a plugin, and creating your own logic in your
|
||||
configuration. To do this you must translate the JSON to Lua yourself. The
|
||||
translation is 1:1 and fairly straight-forward. It must be put in the
|
||||
`["rust-analyzer"]` key of the setup table, which is [shown
|
||||
here](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer).
|
||||
configuration. The following code will work for any checkout of rust-lang/rust (newer than Febuary 2025):
|
||||
|
||||
```lua
|
||||
lspconfig.rust_analyzer.setup {
|
||||
root_dir = function()
|
||||
local default = lspconfig.rust_analyzer.config_def.default_config.root_dir()
|
||||
-- the default root detection uses the cargo workspace root.
|
||||
-- but for rust-lang/rust, the standard library is in its own workspace.
|
||||
-- use the git root instead.
|
||||
local compiler_config = vim.fs.joinpath(default, "../src/bootstrap/defaults/config.compiler.toml")
|
||||
if vim.fs.basename(default) == "library" and vim.uv.fs_stat(compiler_config) then
|
||||
return vim.fs.dirname(default)
|
||||
end
|
||||
return default
|
||||
end,
|
||||
on_init = function(client)
|
||||
local path = client.workspace_folders[1].name
|
||||
local config = vim.fs.joinpath(path, "src/etc/rust_analyzer_zed.json")
|
||||
if vim.uv.fs_stat(config) then
|
||||
-- load rust-lang/rust settings
|
||||
local file = io.open(config)
|
||||
local json = vim.json.decode(file:read("*a"))
|
||||
client.config.settings["rust-analyzer"] = json.lsp["rust-analyzer"].initialization_options
|
||||
client.notify("workspace/didChangeConfiguration", { settings = client.config.settings })
|
||||
end
|
||||
return true
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
If you would like to use the build task that is described above, you may either
|
||||
make your own command in your config, or you can install a plugin such as
|
||||
|
|
|
@ -368,7 +368,7 @@ error: layout_of(&'a u32) = Layout {
|
|||
error: aborting due to previous error
|
||||
```
|
||||
|
||||
[`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/abi/struct.Layout.html
|
||||
[`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/stable_mir/abi/struct.Layout.html
|
||||
|
||||
|
||||
## Configuring CodeLLDB for debugging `rustc`
|
||||
|
|
|
@ -52,6 +52,13 @@ you made in the beginning. But there are some things to be aware of:
|
|||
- You probably don't want incremental messing about with your
|
||||
profile. So something like `CARGO_INCREMENTAL=0` can be helpful.
|
||||
|
||||
In case to avoid the issue of `addr2line xxx/elf: could not read first record` when reading
|
||||
collected data from `cargo`, you may need use the latest version of `addr2line`:
|
||||
|
||||
```bash
|
||||
cargo install addr2line --features="bin"
|
||||
```
|
||||
|
||||
### Gathering a perf profile from a `perf.rust-lang.org` test
|
||||
|
||||
Often we want to analyze a specific test from `perf.rust-lang.org`.
|
||||
|
|
|
@ -8,7 +8,6 @@ otherwise be printed to stderr.
|
|||
To get diagnostics from the compiler,
|
||||
configure [`rustc_interface::Config`] to output diagnostic to a buffer,
|
||||
and run [`TyCtxt.analysis`].
|
||||
The following was tested with <!-- date-check: september 2024 --> `nightly-2024-09-16`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rustc-interface-getting-diagnostics.rs}}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
## Getting the type of an expression
|
||||
|
||||
To get the type of an expression, use the [`after_analysis`] callback to get a [`TyCtxt`].
|
||||
The following was tested with <!-- date-check: december 2024 --> `nightly-2024-12-15`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rustc-driver-interacting-with-the-ast.rs}}
|
||||
|
|
2
src/gcc
2
src/gcc
|
@ -1 +1 @@
|
|||
Subproject commit e607be166673a8de9fc07f6f02c60426e556c5f2
|
||||
Subproject commit 48664a6cab29d48138ffa004b7978d52ef73e3ac
|
|
@ -1,5 +1,6 @@
|
|||
// WARNING: This output format is intended for human consumers only
|
||||
// and is subject to change without notice. Knock yourself out.
|
||||
// HINT: See also -Z dump-mir for MIR at specific points during compilation.
|
||||
fn foo() -> i32 {
|
||||
let mut _0: i32;
|
||||
let mut _1: (i32, bool);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Regression test for <https://github.com/rust-lang/rust/issues/137554>.
|
||||
|
||||
fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
|
||||
//~^ ERROR `?Trait` is not permitted in trait object types
|
||||
//~| ERROR expected trait, found associated function `Iterator::advance_by`
|
||||
//~| ERROR the value of the associated type `Item` in `Iterator` must be specified
|
||||
todo!()
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
error[E0658]: `?Trait` is not permitted in trait object types
|
||||
--> $DIR/missing-associated_item_or_field_def_ids.rs:3:29
|
||||
|
|
||||
LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0404]: expected trait, found associated function `Iterator::advance_by`
|
||||
--> $DIR/missing-associated_item_or_field_def_ids.rs:3:30
|
||||
|
|
||||
LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait
|
||||
|
||||
error[E0191]: the value of the associated type `Item` in `Iterator` must be specified
|
||||
--> $DIR/missing-associated_item_or_field_def_ids.rs:3:18
|
||||
|
|
||||
LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
|
||||
| ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0191, E0404, E0658.
|
||||
For more information about an error, try `rustc --explain E0191`.
|
|
@ -0,0 +1,12 @@
|
|||
// Fix for <https://github.com/rust-lang/rust/issues/137508>.
|
||||
|
||||
trait Tr {
|
||||
type Item;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Tr + ?Foo<Assoc = ()>;
|
||||
//~^ ERROR: `?Trait` is not permitted in trait object types
|
||||
//~| ERROR: cannot find trait `Foo` in this scope
|
||||
//~| ERROR: the value of the associated type `Item` in `Tr` must be specified
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
error[E0658]: `?Trait` is not permitted in trait object types
|
||||
--> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21
|
||||
|
|
||||
LL | let _: dyn Tr + ?Foo<Assoc = ()>;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0405]: cannot find trait `Foo` in this scope
|
||||
--> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:22
|
||||
|
|
||||
LL | let _: dyn Tr + ?Foo<Assoc = ()>;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0191]: the value of the associated type `Item` in `Tr` must be specified
|
||||
--> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:16
|
||||
|
|
||||
LL | type Item;
|
||||
| --------- `Item` defined here
|
||||
...
|
||||
LL | let _: dyn Tr + ?Foo<Assoc = ()>;
|
||||
| ^^ help: specify the associated type: `Tr<Item = Type>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0191, E0405, E0658.
|
||||
For more information about an error, try `rustc --explain E0191`.
|
11
tests/ui/async-await/async-fn/suggest-constrain.rs
Normal file
11
tests/ui/async-await/async-fn/suggest-constrain.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Ensure that we don't suggest constraining `CallRefFuture` here,
|
||||
// since that isn't stable.
|
||||
|
||||
fn spawn<F: AsyncFn() + Send>(f: F) {
|
||||
check_send(f());
|
||||
//~^ ERROR cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn check_send<T: Send>(_: T) {}
|
||||
|
||||
fn main() {}
|
18
tests/ui/async-await/async-fn/suggest-constrain.stderr
Normal file
18
tests/ui/async-await/async-fn/suggest-constrain.stderr
Normal file
|
@ -0,0 +1,18 @@
|
|||
error[E0277]: `<F as AsyncFnMut<()>>::CallRefFuture<'_>` cannot be sent between threads safely
|
||||
--> $DIR/suggest-constrain.rs:5:16
|
||||
|
|
||||
LL | check_send(f());
|
||||
| ---------- ^^^ `<F as AsyncFnMut<()>>::CallRefFuture<'_>` cannot be sent between threads safely
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `<F as AsyncFnMut<()>>::CallRefFuture<'_>`
|
||||
note: required by a bound in `check_send`
|
||||
--> $DIR/suggest-constrain.rs:9:18
|
||||
|
|
||||
LL | fn check_send<T: Send>(_: T) {}
|
||||
| ^^^^ required by this bound in `check_send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -2,7 +2,7 @@ error[E0614]: type `{integer}` cannot be dereferenced
|
|||
--> $DIR/deref-non-pointer.rs:2:9
|
||||
|
|
||||
LL | match *1 {
|
||||
| ^^
|
||||
| ^^ can't be dereferenced
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
14
tests/ui/diagnostic-width/long-E0529.rs
Normal file
14
tests/ui/diagnostic-width/long-E0529.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
|
||||
// The regex below normalizes the long type file name to make it suitable for compare-modes.
|
||||
//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
|
||||
type A = (i32, i32, i32, i32);
|
||||
type B = (A, A, A, A);
|
||||
type C = (B, B, B, B);
|
||||
type D = (C, C, C, C);
|
||||
|
||||
fn foo(x: D) {
|
||||
let [] = x; //~ ERROR expected an array or slice, found `(...
|
||||
//~^ pattern cannot match with input type `(...
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/diagnostic-width/long-E0529.stderr
Normal file
12
tests/ui/diagnostic-width/long-E0529.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0529]: expected an array or slice, found `(..., ..., ..., ...)`
|
||||
--> $DIR/long-E0529.rs:10:9
|
||||
|
|
||||
LL | let [] = x;
|
||||
| ^^ pattern cannot match with input type `(..., ..., ..., ...)`
|
||||
|
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0529`.
|
13
tests/ui/diagnostic-width/long-E0609.rs
Normal file
13
tests/ui/diagnostic-width/long-E0609.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
|
||||
// The regex below normalizes the long type file name to make it suitable for compare-modes.
|
||||
//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
|
||||
type A = (i32, i32, i32, i32);
|
||||
type B = (A, A, A, A);
|
||||
type C = (B, B, B, B);
|
||||
type D = (C, C, C, C);
|
||||
|
||||
fn foo(x: D) {
|
||||
x.field; //~ ERROR no field `field` on type `(...
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/diagnostic-width/long-E0609.stderr
Normal file
12
tests/ui/diagnostic-width/long-E0609.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0609]: no field `field` on type `(..., ..., ..., ...)`
|
||||
--> $DIR/long-E0609.rs:10:7
|
||||
|
|
||||
LL | x.field;
|
||||
| ^^^^^ unknown field
|
||||
|
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0609`.
|
13
tests/ui/diagnostic-width/long-E0614.rs
Normal file
13
tests/ui/diagnostic-width/long-E0614.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
|
||||
// The regex below normalizes the long type file name to make it suitable for compare-modes.
|
||||
//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
|
||||
type A = (i32, i32, i32, i32);
|
||||
type B = (A, A, A, A);
|
||||
type C = (B, B, B, B);
|
||||
type D = (C, C, C, C);
|
||||
|
||||
fn foo(x: D) {
|
||||
*x; //~ ERROR type `(...
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/diagnostic-width/long-E0614.stderr
Normal file
12
tests/ui/diagnostic-width/long-E0614.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0614]: type `(..., ..., ..., ...)` cannot be dereferenced
|
||||
--> $DIR/long-E0614.rs:10:5
|
||||
|
|
||||
LL | *x;
|
||||
| ^^ can't be dereferenced
|
||||
|
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0614`.
|
13
tests/ui/diagnostic-width/long-E0618.rs
Normal file
13
tests/ui/diagnostic-width/long-E0618.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
|
||||
// The regex below normalizes the long type file name to make it suitable for compare-modes.
|
||||
//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
|
||||
type A = (i32, i32, i32, i32);
|
||||
type B = (A, A, A, A);
|
||||
type C = (B, B, B, B);
|
||||
type D = (C, C, C, C);
|
||||
|
||||
fn foo(x: D) { //~ `x` has type `(...
|
||||
x(); //~ ERROR expected function, found `(...
|
||||
}
|
||||
|
||||
fn main() {}
|
16
tests/ui/diagnostic-width/long-E0618.stderr
Normal file
16
tests/ui/diagnostic-width/long-E0618.stderr
Normal file
|
@ -0,0 +1,16 @@
|
|||
error[E0618]: expected function, found `(..., ..., ..., ...)`
|
||||
--> $DIR/long-E0618.rs:10:5
|
||||
|
|
||||
LL | fn foo(x: D) {
|
||||
| - `x` has type `(..., ..., ..., ...)`
|
||||
LL | x();
|
||||
| ^--
|
||||
| |
|
||||
| call expression requires function
|
||||
|
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0618`.
|
|
@ -2,7 +2,7 @@ error[E0614]: type `u32` cannot be dereferenced
|
|||
--> $DIR/E0614.rs:3:5
|
||||
|
|
||||
LL | *y;
|
||||
| ^^
|
||||
| ^^ can't be dereferenced
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0614]: type `!` cannot be dereferenced
|
|||
--> $DIR/issue-17373.rs:2:5
|
||||
|
|
||||
LL | *return
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ can't be dereferenced
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0614]: type `Foo` cannot be dereferenced
|
|||
--> $DIR/issue-9814.rs:7:13
|
||||
|
|
||||
LL | let _ = *Foo::Bar(2);
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^ can't be dereferenced
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ error[E0614]: type `{integer}` cannot be dereferenced
|
|||
--> $DIR/expr-as-stmt.rs:25:11
|
||||
|
|
||||
LL | { 3 } * 3
|
||||
| ^^^
|
||||
| ^^^ can't be dereferenced
|
||||
|
|
||||
help: parentheses are required to parse this as an expression
|
||||
|
|
||||
|
|
|
@ -2,13 +2,13 @@ error[E0614]: type `{integer}` cannot be dereferenced
|
|||
--> $DIR/nested-binding-modes-ref.rs:4:5
|
||||
|
|
||||
LL | *is_val;
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ can't be dereferenced
|
||||
|
||||
error[E0614]: type `{integer}` cannot be dereferenced
|
||||
--> $DIR/nested-binding-modes-ref.rs:9:5
|
||||
|
|
||||
LL | *is_val;
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ can't be dereferenced
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0614]: type `!` cannot be dereferenced
|
|||
--> $DIR/expr_unary.rs:8:16
|
||||
|
|
||||
LL | let x: ! = * { return; };
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^ can't be dereferenced
|
||||
|
||||
error: unreachable expression
|
||||
--> $DIR/expr_unary.rs:8:16
|
||||
|
|
|
@ -50,7 +50,7 @@ error[E0614]: type `T` cannot be dereferenced
|
|||
--> $DIR/missing_trait_impl.rs:15:13
|
||||
|
|
||||
LL | let y = *x;
|
||||
| ^^
|
||||
| ^^ can't be dereferenced
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue