1
Fork 0

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:
bors 2025-02-26 20:21:40 +00:00
commit 00f245915b
87 changed files with 701 additions and 329 deletions

View file

@ -535,7 +535,6 @@ pub(crate) struct WhereClauseBeforeTypeAlias {
}
#[derive(Subdiagnostic)]
pub(crate) enum WhereClauseBeforeTypeAliasSugg {
#[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")]
Remove {

View file

@ -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 {

View file

@ -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,
});

View file

@ -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)
}
}

View file

@ -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)]

View file

@ -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()))
}
}

View file

@ -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("*_")),

View file

@ -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));
}
}
}

View file

@ -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",

View file

@ -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.

View file

@ -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(),
)

View file

@ -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,

View file

@ -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

View file

@ -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")),
}
}
};

View file

@ -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,
});
}
}

View file

@ -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,
}

View file

@ -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;
};

View file

@ -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>) {

View file

@ -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")),

View file

@ -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)]

View file

@ -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));
)*)?
})
}

View file

@ -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) {

View file

@ -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));
};
}

View file

@ -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())
}
}

View file

@ -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<'_>,
}

View file

@ -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)

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -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))
})
}
}

View file

@ -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))
})
}
}

View file

@ -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>,
}

View file

@ -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;
}

View file

@ -772,7 +772,6 @@ pub(crate) struct LabeledLoopInBreak {
}
#[derive(Subdiagnostic)]
pub(crate) enum WrapInParentheses {
#[multipart_suggestion(
parse_sugg_wrap_expression_in_parentheses,

View file

@ -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)
}
}

View file

@ -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,
}

View file

@ -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 });

View file

@ -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()))
}
}

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -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",

View file

@ -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",

View file

@ -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())
}
}

View file

@ -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;
}

View file

@ -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),
}
}
}

View file

@ -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",

View file

@ -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")]

View file

@ -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,

View file

@ -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
);

View file

@ -154,6 +154,7 @@ pub fn get_closest_merge_commit(
"rev-list",
&format!("--author={}", config.git_merge_commit_email),
"-n1",
"--first-parent",
&merge_base,
]);

View file

@ -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

View file

@ -111,4 +111,4 @@ jobs:
to: 196385
type: "stream"
topic: "Subtree sync automation"
content: ${{ steps.message.outputs.message }}
content: ${{ steps.create-message.outputs.message }}

View file

@ -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:

View file

@ -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,
);
}

View file

@ -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,
);
}

View file

@ -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:?}")

View file

@ -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);

View file

@ -1 +1 @@
124cc92199ffa924f6b4c7cc819a85b65e0c3984
4ecd70ddd1039a3954056c1071e40278048476fa

View file

@ -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`.

View file

@ -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

View file

@ -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`

View file

@ -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`.

View file

@ -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}}

View file

@ -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}}

@ -1 +1 @@
Subproject commit e607be166673a8de9fc07f6f02c60426e556c5f2
Subproject commit 48664a6cab29d48138ffa004b7978d52ef73e3ac

View file

@ -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);

View file

@ -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!()
}

View file

@ -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`.

View file

@ -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
}

View file

@ -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`.

View 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() {}

View 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`.

View file

@ -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

View 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() {}

View 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`.

View 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() {}

View 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`.

View 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() {}

View 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`.

View 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() {}

View 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`.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
|

View file

@ -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

View file

@ -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

View file

@ -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