Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 40 additions & 103 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -193,12 +193,6 @@ dependencies = [
"object",
]

[[package]]
name = "array_tool"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"

[[package]]
name = "arrayvec"
version = "0.7.4"
@@ -237,17 +231,6 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"

[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]

[[package]]
name = "autocfg"
version = "1.1.0"
@@ -356,7 +339,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"curl",
"indexmap 2.0.0",
"indexmap",
"serde",
"serde_json",
"toml 0.5.11",
@@ -739,7 +722,7 @@ dependencies = [
"getopts",
"glob",
"home",
"indexmap 2.0.0",
"indexmap",
"lazycell",
"libc",
"miow",
@@ -1245,26 +1228,13 @@ dependencies = [
"cfg-if",
]

[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime 1.3.0",
"log",
"regex",
"termcolor",
]

[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime 2.1.0",
"humantime",
"is-terminal",
"log",
"regex",
@@ -1378,7 +1348,7 @@ dependencies = [
"intl-memoizer",
"intl_pluralrules",
"rustc-hash",
"self_cell",
"self_cell 0.10.3",
"smallvec",
"unic-langid",
]
@@ -1608,7 +1578,7 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
dependencies = [
"compiler_builtins",
"fallible-iterator",
"indexmap 2.0.0",
"indexmap",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
"stable_deref_trait",
@@ -1644,17 +1614,17 @@ dependencies = [

[[package]]
name = "h2"
version = "0.3.19"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 1.9.3",
"indexmap",
"slab",
"tokio",
"tokio-util",
@@ -1675,12 +1645,6 @@ dependencies = [
"thiserror",
]

[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"

[[package]]
name = "hashbrown"
version = "0.14.2"
@@ -1700,15 +1664,6 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"

[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]

[[package]]
name = "hermit-abi"
version = "0.3.2"
@@ -1800,15 +1755,6 @@ dependencies = [
"libm",
]

[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]

[[package]]
name = "humantime"
version = "2.1.0"
@@ -2014,24 +1960,14 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"

[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]

[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
"hashbrown 0.14.2",
"hashbrown",
"rustc-rayon",
"serde",
]
@@ -2117,7 +2053,7 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb"
dependencies = [
"hermit-abi 0.3.2",
"hermit-abi",
"rustix",
"windows-sys 0.48.0",
]
@@ -2193,12 +2129,10 @@ dependencies = [

[[package]]
name = "jsonpath_lib"
version = "0.2.6"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a"
checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f"
dependencies = [
"array_tool",
"env_logger 0.7.1",
"log",
"serde",
"serde_json",
@@ -2416,7 +2350,7 @@ dependencies = [
"clap",
"clap_complete",
"elasticlunr-rs",
"env_logger 0.10.0",
"env_logger",
"handlebars",
"log",
"memchr",
@@ -2541,7 +2475,7 @@ dependencies = [
"aes",
"colored",
"ctrlc",
"env_logger 0.10.0",
"env_logger",
"getrandom",
"lazy_static",
"libc",
@@ -2645,7 +2579,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi 0.3.2",
"hermit-abi",
"libc",
]

@@ -2664,8 +2598,8 @@ dependencies = [
"compiler_builtins",
"crc32fast",
"flate2",
"hashbrown 0.14.2",
"indexmap 2.0.0",
"hashbrown",
"indexmap",
"memchr",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
@@ -2750,11 +2684,11 @@ dependencies = [
"camino",
"clap",
"derive_builder",
"env_logger 0.10.0",
"env_logger",
"fs_extra",
"glob",
"humansize",
"humantime 2.1.0",
"humantime",
"log",
"reqwest",
"serde",
@@ -3104,12 +3038,6 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe"

[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"

[[package]]
name = "quine-mc_cluskey"
version = "0.2.4"
@@ -3357,7 +3285,7 @@ name = "rustbook"
version = "0.1.0"
dependencies = [
"clap",
"env_logger 0.10.0",
"env_logger",
"mdbook",
]

@@ -3741,7 +3669,7 @@ dependencies = [
"bitflags 1.3.2",
"elsa",
"ena",
"indexmap 2.0.0",
"indexmap",
"itertools",
"jobserver",
"libc",
@@ -4503,7 +4431,7 @@ dependencies = [
name = "rustc_serialize"
version = "0.0.0"
dependencies = [
"indexmap 2.0.0",
"indexmap",
"rustc_macros",
"smallvec",
"tempfile",
@@ -4553,7 +4481,7 @@ dependencies = [
name = "rustc_span"
version = "0.0.0"
dependencies = [
"indexmap 2.0.0",
"indexmap",
"md-5",
"rustc_arena",
"rustc_data_structures",
@@ -4712,7 +4640,7 @@ dependencies = [
"arrayvec",
"askama",
"expect-test",
"indexmap 2.0.0",
"indexmap",
"itertools",
"minifier",
"once_cell",
@@ -4902,9 +4830,18 @@ dependencies = [

[[package]]
name = "self_cell"
version = "0.10.2"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
dependencies = [
"self_cell 1.0.2",
]

[[package]]
name = "self_cell"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6"

[[package]]
name = "semver"
@@ -4941,7 +4878,7 @@ version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
dependencies = [
"indexmap 2.0.0",
"indexmap",
"itoa",
"ryu",
"serde",
@@ -5121,8 +5058,8 @@ dependencies = [
"core",
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown 0.14.2",
"hermit-abi 0.3.2",
"hashbrown",
"hermit-abi",
"libc",
"miniz_oxide",
"object",
@@ -5429,7 +5366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b"
dependencies = [
"gimli",
"hashbrown 0.14.2",
"hashbrown",
"object",
"tracing",
]
@@ -5601,7 +5538,7 @@ version = "0.19.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7"
dependencies = [
"indexmap 2.0.0",
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
4 changes: 2 additions & 2 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -47,8 +47,8 @@ Stabilized APIs
- [`core::num::Saturating`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html)
- [`impl From<io::Stdout> for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStdout%3E-for-Stdio)
- [`impl From<io::Stderr> for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio)
- [`impl From<OwnedHandle> for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio)
- [`impl From<OwnedFd> for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio)
- [`impl From<OwnedHandle> for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.ChildStderr.html#impl-From%3COwnedHandle%3E-for-ChildStderr)
- [`impl From<OwnedFd> for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.ChildStderr.html#impl-From%3COwnedFd%3E-for-ChildStderr)
- [`std::ffi::OsString::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.from_encoded_bytes_unchecked)
- [`std::ffi::OsString::into_encoded_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.into_encoded_bytes)
- [`std::ffi::OsStr::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.from_encoded_bytes_unchecked)
215 changes: 112 additions & 103 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -2191,7 +2191,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(field_name) =
find_best_match_for_name(&available_field_names, field.ident.name, None)
{
err.span_suggestion(
err.span_label(field.ident.span, "unknown field");
err.span_suggestion_verbose(
field.ident.span,
"a field with a similar name exists",
field_name,
@@ -2420,35 +2421,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
) {
let Some(output_ty) = self.get_impl_future_output_ty(ty) else {
err.span_label(field_ident.span, "unknown field");
return;
};
let mut add_label = true;
if let ty::Adt(def, _) = output_ty.kind() {
// no field access on enum type
if !def.is_enum() {
if def
.non_enum_variant()
.fields
.iter()
.any(|field| field.ident(self.tcx) == field_ident)
{
add_label = false;
err.span_label(
field_ident.span,
"field not available in `impl Future`, but it is available in its `Output`",
);
err.span_suggestion_verbose(
base.span.shrink_to_hi(),
"consider `await`ing on the `Future` and access the field of its `Output`",
".await",
Applicability::MaybeIncorrect,
);
}
}
let ty::Adt(def, _) = output_ty.kind() else {
err.span_label(field_ident.span, "unknown field");
return;
};
// no field access on enum type
if def.is_enum() {
err.span_label(field_ident.span, "unknown field");
return;
}
if add_label {
err.span_label(field_ident.span, format!("field not found in `{ty}`"));
if !def.non_enum_variant().fields.iter().any(|field| field.ident(self.tcx) == field_ident) {
err.span_label(field_ident.span, "unknown field");
return;
}
err.span_label(
field_ident.span,
"field not available in `impl Future`, but it is available in its `Output`",
);
err.span_suggestion_verbose(
base.span.shrink_to_hi(),
"consider `await`ing on the `Future` and access the field of its `Output`",
".await",
Applicability::MaybeIncorrect,
);
}

fn ban_nonexisting_field(
@@ -2471,16 +2469,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::RawPtr(..) => {
self.suggest_first_deref_field(&mut err, expr, base, ident);
}
ty::Adt(def, _) if !def.is_enum() => {
self.suggest_fields_on_recordish(&mut err, expr, def, ident);
}
ty::Param(param_ty) => {
err.span_label(ident.span, "unknown field");
self.point_at_param_definition(&mut err, param_ty);
}
ty::Alias(ty::Opaque, _) => {
self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
}
_ => {}
_ => {
err.span_label(ident.span, "unknown field");
}
}

self.suggest_fn_call(&mut err, base, base_ty, |output_ty| {
@@ -2633,34 +2631,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_label(param_span, format!("type parameter '{param_name}' declared here"));
}

fn suggest_fields_on_recordish(
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
def: ty::AdtDef<'tcx>,
field: Ident,
) {
let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]);
if let Some(suggested_field_name) =
find_best_match_for_name(&available_field_names, field.name, None)
{
err.span_suggestion(
field.span,
"a field with a similar name exists",
suggested_field_name,
Applicability::MaybeIncorrect,
);
} else {
err.span_label(field.span, "unknown field");
if !available_field_names.is_empty() {
err.note(format!(
"available fields are: {}",
self.name_series_display(available_field_names),
));
}
}
}

fn maybe_suggest_array_indexing(
&self,
err: &mut Diagnostic,
@@ -2669,6 +2639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: Ident,
len: ty::Const<'tcx>,
) {
err.span_label(field.span, "unknown field");
if let (Some(len), Ok(user_index)) =
(len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
&& let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
@@ -2691,6 +2662,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base: &hir::Expr<'_>,
field: Ident,
) {
err.span_label(field.span, "unknown field");
if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) {
let msg = format!("`{base}` is a raw pointer; try dereferencing it");
let suggestion = format!("(*{base}).{field}");
@@ -2709,18 +2681,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let mut err = type_error_struct!(
self.tcx().sess,
field.span,
span,
expr_t,
E0609,
"no field `{field}` on type `{expr_t}`",
);

// 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();
if let Some((fields, args)) =
self.get_field_candidates_considering_privacy(span, expr_t, mod_id)
let (ty, unwrap) = if let ty::Adt(def, args) = expr_t.kind()
&& (self.tcx.is_diagnostic_item(sym::Result, def.did())
|| self.tcx.is_diagnostic_item(sym::Option, def.did()))
&& let Some(arg) = args.get(0)
&& let Some(ty) = arg.as_type()
{
let candidate_fields: Vec<_> = fields
(ty, "unwrap().")
} else {
(expr_t, "")
};
for (found_fields, args) in
self.get_field_candidates_considering_privacy(span, ty, mod_id, id)
{
let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
let candidate_fields: Vec<_> = found_fields
.into_iter()
.filter_map(|candidate_field| {
self.check_for_nested_field_satisfying(
span,
@@ -2729,15 +2713,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args,
vec![],
mod_id,
id,
)
})
.map(|mut field_path| {
field_path.pop();
field_path
.iter()
.map(|id| id.name.to_ident_string())
.collect::<Vec<String>>()
.join(".")
.map(|id| format!("{}.", id.name.to_ident_string()))
.collect::<String>()
})
.collect::<Vec<_>>();

@@ -2750,9 +2734,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if len > 1 { "some" } else { "one" },
if len > 1 { "have" } else { "has" },
),
candidate_fields.iter().map(|path| format!("{path}.")),
candidate_fields.iter().map(|path| format!("{unwrap}{path}")),
Applicability::MaybeIncorrect,
);
} else {
if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) {
err.span_suggestion_verbose(
field.span,
"a field with a similar name exists",
format!("{unwrap}{}", field_name),
Applicability::MaybeIncorrect,
);
} else if !field_names.is_empty() {
let is = if field_names.len() == 1 { " is" } else { "s are" };
err.note(format!(
"available field{is}: {}",
self.name_series_display(field_names),
));
}
}
}
err
@@ -2781,33 +2780,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
base_ty: Ty<'tcx>,
mod_id: DefId,
) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, GenericArgsRef<'tcx>)> {
hir_id: hir::HirId,
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);

for (base_t, _) in self.autoderef(span, base_ty) {
match base_t.kind() {
ty::Adt(base_def, args) if !base_def.is_enum() => {
let tcx = self.tcx;
let fields = &base_def.non_enum_variant().fields;
// Some struct, e.g. some that impl `Deref`, have all private fields
// because you're expected to deref them to access the _real_ fields.
// This, for example, will help us suggest accessing a field through a `Box<T>`.
if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
continue;
self.autoderef(span, base_ty)
.filter_map(move |(base_t, _)| {
match base_t.kind() {
ty::Adt(base_def, args) if !base_def.is_enum() => {
let tcx = self.tcx;
let fields = &base_def.non_enum_variant().fields;
// Some struct, e.g. some that impl `Deref`, have all private fields
// because you're expected to deref them to access the _real_ fields.
// This, for example, will help us suggest accessing a field through a `Box<T>`.
if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
return None;
}
return Some((
fields
.iter()
.filter(move |field| {
field.vis.is_accessible_from(mod_id, tcx)
&& self.is_field_suggestable(field, hir_id, span)
})
// For compile-time reasons put a limit on number of fields we search
.take(100)
.collect::<Vec<_>>(),
*args,
));
}
return Some((
fields
.iter()
.filter(move |field| field.vis.is_accessible_from(mod_id, tcx))
// For compile-time reasons put a limit on number of fields we search
.take(100),
args,
));
_ => None,
}
_ => {}
}
}
None
})
.collect()
}

/// This method is called after we have encountered a missing field error to recursively
@@ -2820,6 +2825,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
subst: GenericArgsRef<'tcx>,
mut field_path: Vec<Ident>,
mod_id: DefId,
hir_id: HirId,
) -> Option<Vec<Ident>> {
debug!(
"check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
@@ -2835,20 +2841,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let field_ty = candidate_field.ty(self.tcx, subst);
if matches(candidate_field, field_ty) {
return Some(field_path);
} else if let Some((nested_fields, subst)) =
self.get_field_candidates_considering_privacy(span, field_ty, mod_id)
{
// recursively search fields of `candidate_field` if it's a ty::Adt
for field in nested_fields {
if let Some(field_path) = self.check_for_nested_field_satisfying(
span,
matches,
field,
subst,
field_path.clone(),
mod_id,
) {
return Some(field_path);
} else {
for (nested_fields, subst) in
self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id)
{
// recursively search fields of `candidate_field` if it's a ty::Adt
for field in nested_fields {
if let Some(field_path) = self.check_for_nested_field_satisfying(
span,
matches,
field,
subst,
field_path.clone(),
mod_id,
hir_id,
) {
return Some(field_path);
}
}
}
}
125 changes: 64 additions & 61 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -1983,69 +1983,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: Ident,
return_type: Option<Ty<'tcx>>,
) {
if let SelfSource::MethodCall(expr) = source
&& let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
&& let Some((fields, args)) =
self.get_field_candidates_considering_privacy(span, actual, mod_id)
{
let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
if let SelfSource::MethodCall(expr) = source {
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
for (fields, args) in
self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id)
{
let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));

let lang_items = self.tcx.lang_items();
let never_mention_traits = [
lang_items.clone_trait(),
lang_items.deref_trait(),
lang_items.deref_mut_trait(),
self.tcx.get_diagnostic_item(sym::AsRef),
self.tcx.get_diagnostic_item(sym::AsMut),
self.tcx.get_diagnostic_item(sym::Borrow),
self.tcx.get_diagnostic_item(sym::BorrowMut),
];
let candidate_fields: Vec<_> = fields
.filter_map(|candidate_field| {
self.check_for_nested_field_satisfying(
span,
&|_, field_ty| {
self.lookup_probe_for_diagnostic(
item_name,
field_ty,
call_expr,
ProbeScope::TraitsInScope,
return_type,
)
.is_ok_and(|pick| {
!never_mention_traits
.iter()
.flatten()
.any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
})
},
candidate_field,
args,
vec![],
mod_id,
)
})
.map(|field_path| {
field_path
.iter()
.map(|id| id.name.to_ident_string())
.collect::<Vec<String>>()
.join(".")
})
.collect();
let lang_items = self.tcx.lang_items();
let never_mention_traits = [
lang_items.clone_trait(),
lang_items.deref_trait(),
lang_items.deref_mut_trait(),
self.tcx.get_diagnostic_item(sym::AsRef),
self.tcx.get_diagnostic_item(sym::AsMut),
self.tcx.get_diagnostic_item(sym::Borrow),
self.tcx.get_diagnostic_item(sym::BorrowMut),
];
let candidate_fields: Vec<_> = fields
.iter()
.filter_map(|candidate_field| {
self.check_for_nested_field_satisfying(
span,
&|_, field_ty| {
self.lookup_probe_for_diagnostic(
item_name,
field_ty,
call_expr,
ProbeScope::TraitsInScope,
return_type,
)
.is_ok_and(|pick| {
!never_mention_traits
.iter()
.flatten()
.any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
})
},
candidate_field,
args,
vec![],
mod_id,
expr.hir_id,
)
})
.map(|field_path| {
field_path
.iter()
.map(|id| id.name.to_ident_string())
.collect::<Vec<String>>()
.join(".")
})
.collect();

let len = candidate_fields.len();
if len > 0 {
err.span_suggestions(
item_name.span.shrink_to_lo(),
format!(
"{} of the expressions' fields {} a method of the same name",
if len > 1 { "some" } else { "one" },
if len > 1 { "have" } else { "has" },
),
candidate_fields.iter().map(|path| format!("{path}.")),
Applicability::MaybeIncorrect,
);
let len = candidate_fields.len();
if len > 0 {
err.span_suggestions(
item_name.span.shrink_to_lo(),
format!(
"{} of the expressions' fields {} a method of the same name",
if len > 1 { "some" } else { "one" },
if len > 1 { "have" } else { "has" },
),
candidate_fields.iter().map(|path| format!("{path}.")),
Applicability::MaybeIncorrect,
);
}
}
}
}
10 changes: 10 additions & 0 deletions library/std/src/io/buffered/bufreader.rs
Original file line number Diff line number Diff line change
@@ -507,6 +507,16 @@ impl<R: ?Sized + Seek> Seek for BufReader<R> {
)
})
}

/// Seeks relative to the current position.
///
/// If the new position lies within the buffer, the buffer will not be
/// flushed, allowing for more efficient seeks. This method does not return
/// the location of the underlying reader, so the caller must track this
/// information themselves if it is required.
fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
self.seek_relative(offset)
}
}

impl<T: ?Sized> SizeHint for BufReader<T> {
30 changes: 30 additions & 0 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
@@ -1957,6 +1957,36 @@ pub trait Seek {
fn stream_position(&mut self) -> Result<u64> {
self.seek(SeekFrom::Current(0))
}

/// Seeks relative to the current position.
///
/// This is equivalent to `self.seek(SeekFrom::Current(offset))` but
/// doesn't return the new position which can allow some implementations
/// such as [`BufReader`] to perform more efficient seeks.
///
/// # Example
///
/// ```no_run
/// #![feature(seek_seek_relative)]
/// use std::{
/// io::{self, Seek},
/// fs::File,
/// };
///
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// f.seek_relative(10)?;
/// assert_eq!(f.stream_position()?, 10);
/// Ok(())
/// }
/// ```
///
/// [`BufReader`]: crate::io::BufReader
#[unstable(feature = "seek_seek_relative", issue = "117374")]
fn seek_relative(&mut self, offset: i64) -> Result<()> {
self.seek(SeekFrom::Current(offset))?;
Ok(())
}
}

/// Enumeration of possible methods to seek within an I/O object.
2 changes: 1 addition & 1 deletion src/tools/jsondocck/Cargo.toml
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
jsonpath_lib = "0.2"
jsonpath_lib = "0.3"
getopts = "0.2"
regex = "1.4"
shlex = "1.0"
16 changes: 9 additions & 7 deletions src/tools/suggest-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -33,13 +33,15 @@ pub fn get_suggestions<T: AsRef<str>>(modified_files: &[T]) -> Vec<Suggestion> {
let mut suggestions = Vec::new();

// static suggestions
for sug in STATIC_SUGGESTIONS.iter() {
let glob = Pattern::new(&sug.0).expect("Found invalid glob pattern!");

for file in modified_files {
if glob.matches(file.as_ref()) {
suggestions.extend_from_slice(&sug.1);
}
for (globs, sugs) in STATIC_SUGGESTIONS.iter() {
let globs = globs
.iter()
.map(|glob| Pattern::new(glob).expect("Found invalid glob pattern!"))
.collect::<Vec<_>>();
let matches_some_glob = |file: &str| globs.iter().any(|glob| glob.matches(file));

if modified_files.iter().map(AsRef::as_ref).any(matches_some_glob) {
suggestions.extend_from_slice(sugs);
}
}

31 changes: 21 additions & 10 deletions src/tools/suggest-tests/src/static_suggestions.rs
Original file line number Diff line number Diff line change
@@ -2,23 +2,34 @@ use crate::{sug, Suggestion};

// FIXME: perhaps this could use `std::lazy` when it is stablizied
macro_rules! static_suggestions {
($( $glob:expr => [ $( $suggestion:expr ),* ] ),*) => {
pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy<Vec<(&'static str, Vec<Suggestion>)>>
= ::once_cell::unsync::Lazy::new(|| vec![ $( ($glob, vec![ $($suggestion),* ]) ),*]);
($( [ $( $glob:expr ),* $(,)? ] => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => {
pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy<Vec<(Vec<&'static str>, Vec<Suggestion>)>>
= ::once_cell::unsync::Lazy::new(|| vec![ $( (vec![ $($glob),* ], vec![ $($suggestion),* ]) ),*]);
}
}

static_suggestions! {
"*.md" => [
sug!("test", 0, ["linkchecker"])
["*.md"] => [
sug!("test", 0, ["linkchecker"]),
],

"compiler/*" => [
["compiler/*"] => [
sug!("check"),
sug!("test", 1, ["tests/ui", "tests/run-make"])
sug!("test", 1, ["tests/ui", "tests/run-make"]),
],

"src/librustdoc/*" => [
sug!("test", 1, ["rustdoc"])
]
["compiler/rustc_mir_transform/*"] => [
sug!("test", 1, ["mir-opt"]),
],

[
"compiler/rustc_mir_transform/src/coverage/*",
"compiler/rustc_codegen_llvm/src/coverageinfo/*",
] => [
sug!("test", 1, ["coverage"]),
],

["src/librustdoc/*"] => [
sug!("test", 1, ["rustdoc"]),
],
}
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ fn await_on_struct_similar() {
let x = S { awai: 42 };
x.await;
//~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| HELP a field with a similar name exists
//~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP set `edition = "2021"` in `Cargo.toml`
@@ -41,6 +42,7 @@ fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
fn await_on_apit(x: impl Future<Output = ()>) {
x.await;
//~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP set `edition = "2021"` in `Cargo.toml`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
Original file line number Diff line number Diff line change
@@ -12,14 +12,18 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S`
--> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7
|
LL | x.await;
| ^^^^^ help: a field with a similar name exists: `awai`
| ^^^^^ unknown field
|
= note: to `.await` a `Future`, switch to Rust 2018 or later
= help: set `edition = "2021"` in `Cargo.toml`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
help: a field with a similar name exists
|
LL | x.awai;
| ~~~~

error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
--> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7
--> $DIR/suggest-switching-edition-on-await-cargo.rs:34:7
|
LL | x.await;
| ^^^^^ unknown field
@@ -29,10 +33,10 @@ LL | x.await;
= note: for more on editions, read https://doc.rust-lang.org/edition-guide

error[E0609]: no field `await` on type `impl Future<Output = ()>`
--> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7
--> $DIR/suggest-switching-edition-on-await-cargo.rs:43:7
|
LL | x.await;
| ^^^^^
| ^^^^^ unknown field
|
= note: to `.await` a `Future`, switch to Rust 2018 or later
= help: set `edition = "2021"` in `Cargo.toml`
2 changes: 2 additions & 0 deletions tests/ui/async-await/suggest-switching-edition-on-await.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ fn await_on_struct_similar() {
let x = S { awai: 42 };
x.await;
//~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| HELP a field with a similar name exists
//~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP pass `--edition 2021` to `rustc`
@@ -39,6 +40,7 @@ fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
fn await_on_apit(x: impl Future<Output = ()>) {
x.await;
//~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
12 changes: 8 additions & 4 deletions tests/ui/async-await/suggest-switching-edition-on-await.stderr
Original file line number Diff line number Diff line change
@@ -12,14 +12,18 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S`
--> $DIR/suggest-switching-edition-on-await.rs:22:7
|
LL | x.await;
| ^^^^^ help: a field with a similar name exists: `awai`
| ^^^^^ unknown field
|
= note: to `.await` a `Future`, switch to Rust 2018 or later
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
help: a field with a similar name exists
|
LL | x.awai;
| ~~~~

error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
--> $DIR/suggest-switching-edition-on-await.rs:31:7
--> $DIR/suggest-switching-edition-on-await.rs:32:7
|
LL | x.await;
| ^^^^^ unknown field
@@ -29,10 +33,10 @@ LL | x.await;
= note: for more on editions, read https://doc.rust-lang.org/edition-guide

error[E0609]: no field `await` on type `impl Future<Output = ()>`
--> $DIR/suggest-switching-edition-on-await.rs:40:7
--> $DIR/suggest-switching-edition-on-await.rs:41:7
|
LL | x.await;
| ^^^^^
| ^^^^^ unknown field
|
= note: to `.await` a `Future`, switch to Rust 2018 or later
= help: pass `--edition 2021` to `rustc`
7 changes: 6 additions & 1 deletion tests/ui/derived-errors/issue-30580.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `c` on type `&Foo`
--> $DIR/issue-30580.rs:12:11
|
LL | b.c;
| ^ help: a field with a similar name exists: `a`
| ^ unknown field
|
help: a field with a similar name exists
|
LL | b.a;
| ~

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ fn main() {
doc_hidden_fields::B::default().hey;
//~^ ERROR no field `hey` on type `B`
//~| NOTE unknown field
//~| NOTE available fields are: `bye`
//~| NOTE available field is: `bye`

C::default().hey;
//~^ ERROR no field `hey` on type `C`
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ error[E0609]: no field `hey` on type `B`
LL | doc_hidden_fields::B::default().hey;
| ^^^ unknown field
|
= note: available fields are: `bye`
= note: available field is: `bye`

error[E0609]: no field `hey` on type `C`
--> $DIR/dont-suggest-doc-hidden-fields.rs:34:18
6 changes: 5 additions & 1 deletion tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr
Original file line number Diff line number Diff line change
@@ -5,9 +5,13 @@ LL | environment!();
| -------------- in this macro invocation
...
LL | const CRATE: Crate = Crate { fiel: () };
| ^^^^ help: a field with a similar name exists: `field`
| ^^^^ unknown field
|
= note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info)
help: a field with a similar name exists
|
LL | const CRATE: Crate = Crate { field: () };
| ~~~~~

error[E0609]: no field `field` on type `Compound`
--> $DIR/dont-suggest-hygienic-fields.rs:24:16
7 changes: 6 additions & 1 deletion tests/ui/did_you_mean/issue-36798.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `baz` on type `Foo`
--> $DIR/issue-36798.rs:7:7
|
LL | f.baz;
| ^^^ help: a field with a similar name exists: `bar`
| ^^^ unknown field
|
help: a field with a similar name exists
|
LL | f.bar;
| ~~~

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/did_you_mean/issue-36798_unknown_field.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0609]: no field `zz` on type `Foo`
LL | f.zz;
| ^^ unknown field
|
= note: available fields are: `bar`
= note: available field is: `bar`

error: aborting due to previous error

14 changes: 12 additions & 2 deletions tests/ui/did_you_mean/issue-42599_available_fields_note.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0560]: struct `Demo` has no field named `inocently_mispellable`
--> $DIR/issue-42599_available_fields_note.rs:16:39
|
LL | Self { secret_integer: 2, inocently_mispellable: () }
| ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable`
| ^^^^^^^^^^^^^^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | Self { secret_integer: 2, innocently_misspellable: () }
| ~~~~~~~~~~~~~~~~~~~~~~~

error[E0560]: struct `Demo` has no field named `egregiously_nonexistent_field`
--> $DIR/issue-42599_available_fields_note.rs:21:39
@@ -16,7 +21,12 @@ error[E0609]: no field `inocently_mispellable` on type `Demo`
--> $DIR/issue-42599_available_fields_note.rs:32:41
|
LL | let innocent_field_misaccess = demo.inocently_mispellable;
| ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable`
| ^^^^^^^^^^^^^^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let innocent_field_misaccess = demo.innocently_misspellable;
| ~~~~~~~~~~~~~~~~~~~~~~~

error[E0609]: no field `egregiously_nonexistent_field` on type `Demo`
--> $DIR/issue-42599_available_fields_note.rs:35:42
2 changes: 1 addition & 1 deletion tests/ui/error-codes/E0609.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0609]: no field `foo` on type `Foo`
LL | let _ = x.foo;
| ^^^ unknown field
|
= note: available fields are: `x`
= note: available field is: `x`

error[E0609]: no field `1` on type `Bar`
--> $DIR/E0609.rs:11:7
7 changes: 6 additions & 1 deletion tests/ui/error-codes/ex-E0612.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `1` on type `Foo`
--> $DIR/ex-E0612.rs:5:6
|
LL | y.1;
| ^ help: a field with a similar name exists: `0`
| ^ unknown field
|
help: a field with a similar name exists
|
LL | y.0;
| ~

error: aborting due to previous error

6 changes: 4 additions & 2 deletions tests/ui/issues/issue-11004.stderr
Original file line number Diff line number Diff line change
@@ -3,15 +3,17 @@ error[E0609]: no field `x` on type `*mut A`
|
LL | let x : i32 = n.x;
| --^
| |
| | |
| | unknown field
| help: `n` is a raw pointer; try dereferencing it: `(*n).x`

error[E0609]: no field `y` on type `*mut A`
--> $DIR/issue-11004.rs:8:21
|
LL | let y : f64 = n.y;
| --^
| |
| | |
| | unknown field
| help: `n` is a raw pointer; try dereferencing it: `(*n).y`

error: aborting due to 2 previous errors
2 changes: 1 addition & 1 deletion tests/ui/issues/issue-13847.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `is_failure` on type `!`
--> $DIR/issue-13847.rs:2:12
|
LL | return.is_failure
| ^^^^^^^^^^
| ^^^^^^^^^^ unknown field

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/issues/issue-14721.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `desc` on type `&str`
--> $DIR/issue-14721.rs:3:24
|
LL | println!("{}", foo.desc);
| ^^^^
| ^^^^ unknown field

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/issues/issue-19244-1.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `1` on type `(usize,)`
--> $DIR/issue-19244-1.rs:4:24
|
LL | let a: [isize; TUP.1];
| ^
| ^ unknown field

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/issues/issue-19244-2.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0609]: no field `nonexistent_field` on type `MyStruct`
LL | let a: [isize; STRUCT.nonexistent_field];
| ^^^^^^^^^^^^^^^^^ unknown field
|
= note: available fields are: `field`
= note: available field is: `field`

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/issues/issue-23253.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `a` on type `Foo`
--> $DIR/issue-23253.rs:4:14
|
LL | Foo::Bar.a;
| ^
| ^ unknown field

error: aborting due to previous error

6 changes: 3 additions & 3 deletions tests/ui/issues/issue-24365.stderr
Original file line number Diff line number Diff line change
@@ -2,19 +2,19 @@ error[E0609]: no field `b` on type `Foo`
--> $DIR/issue-24365.rs:10:22
|
LL | println!("{}", a.b);
| ^
| ^ unknown field

error[E0609]: no field `attr_name_idx` on type `&Attribute`
--> $DIR/issue-24365.rs:17:18
|
LL | let z = (&x).attr_name_idx;
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ unknown field

error[E0609]: no field `attr_name_idx` on type `Attribute`
--> $DIR/issue-24365.rs:18:15
|
LL | let y = x.attr_name_idx;
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ unknown field

error: aborting due to 3 previous errors

2 changes: 1 addition & 1 deletion tests/ui/issues/issue-31011.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `trace` on type `&T`
--> $DIR/issue-31011.rs:3:17
|
LL | if $ctx.trace {
| ^^^^^
| ^^^^^ unknown field
...
LL | fn wrap<T>(context: &T) -> ()
| - type parameter 'T' declared here
4 changes: 2 additions & 2 deletions tests/ui/issues/issue-33525.stderr
Original file line number Diff line number Diff line change
@@ -8,13 +8,13 @@ error[E0609]: no field `lorem` on type `&'static str`
--> $DIR/issue-33525.rs:3:8
|
LL | "".lorem;
| ^^^^^
| ^^^^^ unknown field

error[E0609]: no field `ipsum` on type `&'static str`
--> $DIR/issue-33525.rs:4:8
|
LL | "".ipsum;
| ^^^^^
| ^^^^^ unknown field

error: aborting due to 3 previous errors

Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `00` on type `Verdict`
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30
|
LL | let _condemned = justice.00;
| ^^ help: a field with a similar name exists: `0`
| ^^ unknown field
|
help: a field with a similar name exists
|
LL | let _condemned = justice.0;
| ~

error[E0609]: no field `001` on type `Verdict`
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31
2 changes: 1 addition & 1 deletion tests/ui/mismatched_types/cast-rfc0401.stderr
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ error[E0609]: no field `f` on type `fn() {main}`
--> $DIR/cast-rfc0401.rs:65:18
|
LL | let _ = main.f as *const u32;
| ^
| ^ unknown field

error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/cast-rfc0401.rs:29:13
4 changes: 4 additions & 0 deletions tests/ui/offset-of/offset-of-self.stderr
Original file line number Diff line number Diff line change
@@ -54,6 +54,8 @@ error[E0609]: no field `Self` on type `S`
|
LL | offset_of!(S, Self);
| ^^^^
|
= note: available fields are: `v`, `w`

error[E0616]: field `v` of struct `T` is private
--> $DIR/offset-of-self.rs:41:30
@@ -66,6 +68,8 @@ error[E0609]: no field `self` on type `S`
|
LL | offset_of!(S, self);
| ^^^^
|
= note: available fields are: `v`, `w`

error[E0609]: no field `self` on type `u8`
--> $DIR/offset-of-self.rs:56:21
6 changes: 3 additions & 3 deletions tests/ui/parser/float-field.stderr
Original file line number Diff line number Diff line change
@@ -274,7 +274,7 @@ error[E0609]: no field `1e1` on type `(u8, u8)`
--> $DIR/float-field.rs:9:9
|
LL | s.1.1e1;
| ^^^
| ^^^ unknown field

error[E0609]: no field `0x1e1` on type `S`
--> $DIR/float-field.rs:24:7
@@ -336,13 +336,13 @@ error[E0609]: no field `f32` on type `(u8, u8)`
--> $DIR/float-field.rs:44:9
|
LL | s.1.f32;
| ^^^
| ^^^ unknown field

error[E0609]: no field `1e1` on type `(u8, u8)`
--> $DIR/float-field.rs:46:7
|
LL | s.1.1e1f32;
| ^^^^^^^^
| ^^^^^^^^ unknown field

error: aborting due to 55 previous errors

7 changes: 6 additions & 1 deletion tests/ui/rmeta/rmeta_meta_main.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0560]: struct `Foo` has no field named `field2`
--> $DIR/rmeta_meta_main.rs:13:19
|
LL | let _ = Foo { field2: 42 };
| ^^^^^^ help: a field with a similar name exists: `field`
| ^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let _ = Foo { field: 42 };
| ~~~~~

error: aborting due to previous error

7 changes: 6 additions & 1 deletion tests/ui/structs/struct-fields-hints-no-dupe.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0560]: struct `A` has no field named `bar`
--> $DIR/struct-fields-hints-no-dupe.rs:10:9
|
LL | bar : 42,
| ^^^ help: a field with a similar name exists: `barr`
| ^^^ unknown field
|
help: a field with a similar name exists
|
LL | barr : 42,
| ~~~~

error: aborting due to previous error

7 changes: 6 additions & 1 deletion tests/ui/structs/struct-fields-hints.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0560]: struct `A` has no field named `bar`
--> $DIR/struct-fields-hints.rs:10:9
|
LL | bar : 42,
| ^^^ help: a field with a similar name exists: `car`
| ^^^ unknown field
|
help: a field with a similar name exists
|
LL | car : 42,
| ~~~

error: aborting due to previous error

7 changes: 6 additions & 1 deletion tests/ui/structs/struct-fields-typo.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `baa` on type `BuildData`
--> $DIR/struct-fields-typo.rs:11:17
|
LL | let x = foo.baa;
| ^^^ help: a field with a similar name exists: `bar`
| ^^^ unknown field
|
help: a field with a similar name exists
|
LL | let x = foo.bar;
| ~~~

error: aborting due to previous error

7 changes: 6 additions & 1 deletion tests/ui/structs/struct-pat-derived-error.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `d` on type `&A`
--> $DIR/struct-pat-derived-error.rs:8:31
|
LL | let A { x, y } = self.d;
| ^ help: a field with a similar name exists: `b`
| ^ unknown field
|
help: a field with a similar name exists
|
LL | let A { x, y } = self.b;
| ~

error[E0026]: struct `A` does not have fields named `x`, `y`
--> $DIR/struct-pat-derived-error.rs:8:17
21 changes: 18 additions & 3 deletions tests/ui/structs/suggest-private-fields.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0560]: struct `B` has no field named `aa`
--> $DIR/suggest-private-fields.rs:15:9
|
LL | aa: 20,
| ^^ help: a field with a similar name exists: `a`
| ^^ unknown field
|
help: a field with a similar name exists
|
LL | a: 20,
| ~

error[E0560]: struct `B` has no field named `bb`
--> $DIR/suggest-private-fields.rs:17:9
@@ -16,13 +21,23 @@ error[E0560]: struct `A` has no field named `aa`
--> $DIR/suggest-private-fields.rs:22:9
|
LL | aa: 20,
| ^^ help: a field with a similar name exists: `a`
| ^^ unknown field
|
help: a field with a similar name exists
|
LL | a: 20,
| ~

error[E0560]: struct `A` has no field named `bb`
--> $DIR/suggest-private-fields.rs:24:9
|
LL | bb: 20,
| ^^ help: a field with a similar name exists: `b`
| ^^ unknown field
|
help: a field with a similar name exists
|
LL | b: 20,
| ~

error: aborting due to 4 previous errors

4 changes: 2 additions & 2 deletions tests/ui/suggestions/call-on-missing.stderr
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ error[E0609]: no field `i` on type `fn() -> Foo {foo}`
--> $DIR/call-on-missing.rs:16:9
|
LL | foo.i;
| ^
| ^ unknown field
|
help: use parentheses to call this function
|
@@ -62,7 +62,7 @@ LL | fn type_param<T: Fn() -> Foo>(t: T) {
| - type parameter 'T' declared here
...
LL | t.i;
| ^
| ^ unknown field
|
help: use parentheses to call this type parameter
|
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@ error[E0609]: no field `c` on type `Foo`
LL | let _test = &fooer.c;
| ^ unknown field
|
= note: available fields are: `first`, `_second`, `_third`
help: one of the expressions' fields has a field of the same name
|
LL | let _test = &fooer.first.bar.c;
@@ -16,7 +15,6 @@ error[E0609]: no field `test` on type `Foo`
LL | let _test2 = fooer.test;
| ^^^^ unknown field
|
= note: available fields are: `first`, `_second`, `_third`
help: one of the expressions' fields has a field of the same name
|
LL | let _test2 = fooer.first.bar.c.test;
5 changes: 3 additions & 2 deletions tests/ui/suggestions/parenthesized-deref-suggestion.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `opts` on type `*const Session`
--> $DIR/parenthesized-deref-suggestion.rs:7:30
|
LL | (sess as *const Session).opts;
| ^^^^
| ^^^^ unknown field
|
help: `(sess as *const Session)` is a raw pointer; try dereferencing it
|
@@ -14,7 +14,8 @@ error[E0609]: no field `0` on type `[u32; 1]`
|
LL | (x as [u32; 1]).0;
| ----------------^
| |
| | |
| | unknown field
| help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`

error: aborting due to 2 previous errors
2 changes: 1 addition & 1 deletion tests/ui/suggestions/private-field.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0609]: no field `cap` on type `S`
LL | dbg!(s.cap)
| ^^^ unknown field
|
= note: available fields are: `val`
= note: available field is: `val`

error: aborting due to previous error

21 changes: 21 additions & 0 deletions tests/ui/suggestions/suggest-field-through-deref.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// run-rustfix
#![allow(dead_code)]
use std::sync::Arc;
struct S {
long_name: (),
foo: (),
}
fn main() {
let x = Arc::new(S { long_name: (), foo: () });
let _ = x.long_name; //~ ERROR no field `longname`
let y = S { long_name: (), foo: () };
let _ = y.long_name; //~ ERROR no field `longname`
let a = Some(Arc::new(S { long_name: (), foo: () }));
let _ = a.unwrap().long_name; //~ ERROR no field `longname`
let b = Some(S { long_name: (), foo: () });
let _ = b.unwrap().long_name; //~ ERROR no field `long_name`
let c = Ok::<_, ()>(Arc::new(S { long_name: (), foo: () }));
let _ = c.unwrap().long_name; //~ ERROR no field `longname`
let d = Ok::<_, ()>(S { long_name: (), foo: () });
let _ = d.unwrap().long_name; //~ ERROR no field `long_name`
}
21 changes: 21 additions & 0 deletions tests/ui/suggestions/suggest-field-through-deref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// run-rustfix
#![allow(dead_code)]
use std::sync::Arc;
struct S {
long_name: (),
foo: (),
}
fn main() {
let x = Arc::new(S { long_name: (), foo: () });
let _ = x.longname; //~ ERROR no field `longname`
let y = S { long_name: (), foo: () };
let _ = y.longname; //~ ERROR no field `longname`
let a = Some(Arc::new(S { long_name: (), foo: () }));
let _ = a.longname; //~ ERROR no field `longname`
let b = Some(S { long_name: (), foo: () });
let _ = b.long_name; //~ ERROR no field `long_name`
let c = Ok::<_, ()>(Arc::new(S { long_name: (), foo: () }));
let _ = c.longname; //~ ERROR no field `longname`
let d = Ok::<_, ()>(S { long_name: (), foo: () });
let _ = d.long_name; //~ ERROR no field `long_name`
}
69 changes: 69 additions & 0 deletions tests/ui/suggestions/suggest-field-through-deref.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
error[E0609]: no field `longname` on type `Arc<S>`
--> $DIR/suggest-field-through-deref.rs:10:15
|
LL | let _ = x.longname;
| ^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let _ = x.long_name;
| ~~~~~~~~~

error[E0609]: no field `longname` on type `S`
--> $DIR/suggest-field-through-deref.rs:12:15
|
LL | let _ = y.longname;
| ^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let _ = y.long_name;
| ~~~~~~~~~

error[E0609]: no field `longname` on type `Option<Arc<S>>`
--> $DIR/suggest-field-through-deref.rs:14:15
|
LL | let _ = a.longname;
| ^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let _ = a.unwrap().long_name;
| ~~~~~~~~~~~~~~~~~~

error[E0609]: no field `long_name` on type `Option<S>`
--> $DIR/suggest-field-through-deref.rs:16:15
|
LL | let _ = b.long_name;
| ^^^^^^^^^ unknown field
|
help: one of the expressions' fields has a field of the same name
|
LL | let _ = b.unwrap().long_name;
| +++++++++

error[E0609]: no field `longname` on type `Result<Arc<S>, ()>`
--> $DIR/suggest-field-through-deref.rs:18:15
|
LL | let _ = c.longname;
| ^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let _ = c.unwrap().long_name;
| ~~~~~~~~~~~~~~~~~~

error[E0609]: no field `long_name` on type `Result<S, ()>`
--> $DIR/suggest-field-through-deref.rs:20:15
|
LL | let _ = d.long_name;
| ^^^^^^^^^ unknown field
|
help: one of the expressions' fields has a field of the same name
|
LL | let _ = d.unwrap().long_name;
| +++++++++

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0609`.
1 change: 0 additions & 1 deletion tests/ui/suggestions/too-many-field-suggestions.stderr
Original file line number Diff line number Diff line change
@@ -25,7 +25,6 @@ error[E0609]: no field `field` on type `Thing`
LL | t.field;
| ^^^^^ unknown field
|
= note: available fields are: `a0`, `a1`, `a2`, `a3`, `a4` ... and 5 others
help: some of the expressions' fields have a field of the same name
|
LL | t.a0.field;
Original file line number Diff line number Diff line change
@@ -24,7 +24,12 @@ error[E0560]: struct `RGB` has no field named `c`
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
|
LL | let _ = RGB { r, g, c };
| ^ help: a field with a similar name exists: `b`
| ^ unknown field
|
help: a field with a similar name exists
|
LL | let _ = RGB { r, g, b };
| ~

error: aborting due to 3 previous errors

6 changes: 3 additions & 3 deletions tests/ui/tuple/index-invalid.stderr
Original file line number Diff line number Diff line change
@@ -2,19 +2,19 @@ error[E0609]: no field `1` on type `(((),),)`
--> $DIR/index-invalid.rs:2:22
|
LL | let _ = (((),),).1.0;
| ^
| ^ unknown field

error[E0609]: no field `1` on type `((),)`
--> $DIR/index-invalid.rs:4:24
|
LL | let _ = (((),),).0.1;
| ^
| ^ unknown field

error[E0609]: no field `000` on type `(((),),)`
--> $DIR/index-invalid.rs:6:22
|
LL | let _ = (((),),).000.000;
| ^^^
| ^^^ unknown field

error: aborting due to 3 previous errors

7 changes: 6 additions & 1 deletion tests/ui/tuple/tuple-index-not-tuple.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,12 @@ error[E0609]: no field `0` on type `Point`
--> $DIR/tuple-index-not-tuple.rs:6:12
|
LL | origin.0;
| ^ help: a field with a similar name exists: `x`
| ^ unknown field
|
help: a field with a similar name exists
|
LL | origin.x;
| ~

error[E0609]: no field `0` on type `Empty`
--> $DIR/tuple-index-not-tuple.rs:8:11
9 changes: 7 additions & 2 deletions tests/ui/tuple/tuple-index-out-of-bounds.stderr
Original file line number Diff line number Diff line change
@@ -2,13 +2,18 @@ error[E0609]: no field `2` on type `Point`
--> $DIR/tuple-index-out-of-bounds.rs:7:12
|
LL | origin.2;
| ^ help: a field with a similar name exists: `0`
| ^ unknown field
|
help: a field with a similar name exists
|
LL | origin.0;
| ~

error[E0609]: no field `2` on type `({integer}, {integer})`
--> $DIR/tuple-index-out-of-bounds.rs:12:11
|
LL | tuple.2;
| ^
| ^ unknown field

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `x` on type `&Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:18
@@ -14,7 +14,7 @@ LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `y` on type `&Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:25
@@ -23,7 +23,7 @@ LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `y` on type `&Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:32
@@ -32,7 +32,7 @@ LL | fn equals_ref<Point>(a: &Point, b: &Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `x` on type `Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:11
@@ -41,7 +41,7 @@ LL | fn equals_val<Point>(a: Point, b: Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `x` on type `Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:18
@@ -50,7 +50,7 @@ LL | fn equals_val<Point>(a: Point, b: Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `y` on type `Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:25
@@ -59,7 +59,7 @@ LL | fn equals_val<Point>(a: Point, b: Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error[E0609]: no field `y` on type `Point`
--> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:32
@@ -68,7 +68,7 @@ LL | fn equals_val<Point>(a: Point, b: Point) -> bool
| ----- type parameter 'Point' declared here
LL | {
LL | a.x == b.x && a.y == b.y
| ^
| ^ unknown field

error: aborting due to 8 previous errors

3 changes: 2 additions & 1 deletion tests/ui/typeck/issue-53712.stderr
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@ error[E0609]: no field `0` on type `[{integer}; 5]`
|
LL | arr.0;
| ----^
| |
| | |
| | unknown field
| help: instead of using tuple indexing, use array indexing: `arr[0]`

error: aborting due to previous error
2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-65611.stderr
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ error[E0609]: no field `0` on type `&_`
--> $DIR/issue-65611.rs:59:36
|
LL | let x = buffer.last().unwrap().0.clone();
| ^
| ^ unknown field

error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-87181/tuple-field.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `0` on type `fn(char, u16) -> Foo {Foo}`
--> $DIR/tuple-field.rs:12:15
|
LL | thing.bar.0;
| ^
| ^ unknown field
|
help: use parentheses to construct this tuple struct
|
2 changes: 1 addition & 1 deletion tests/ui/typeck/issue-96738.stderr
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ error[E0609]: no field `nonexistent_field` on type `fn(_) -> Option<_> {Option::
--> $DIR/issue-96738.rs:3:10
|
LL | Some.nonexistent_field;
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^ unknown field

error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion tests/ui/typeck/no-type-for-node-ice.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0609]: no field `homura` on type `&'static str`
--> $DIR/no-type-for-node-ice.rs:4:8
|
LL | "".homura[""];
| ^^^^^^
| ^^^^^^ unknown field

error: aborting due to previous error

14 changes: 12 additions & 2 deletions tests/ui/union/union-suggest-field.mirunsafeck.stderr
Original file line number Diff line number Diff line change
@@ -2,13 +2,23 @@ error[E0560]: union `U` has no field named `principle`
--> $DIR/union-suggest-field.rs:13:17
|
LL | let u = U { principle: 0 };
| ^^^^^^^^^ help: a field with a similar name exists: `principal`
| ^^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let u = U { principal: 0 };
| ~~~~~~~~~

error[E0609]: no field `principial` on type `U`
--> $DIR/union-suggest-field.rs:17:15
|
LL | let w = u.principial;
| ^^^^^^^^^^ help: a field with a similar name exists: `principal`
| ^^^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let w = u.principal;
| ~~~~~~~~~

error[E0615]: attempted to take value of method `calculate` on type `U`
--> $DIR/union-suggest-field.rs:21:15
14 changes: 12 additions & 2 deletions tests/ui/union/union-suggest-field.thirunsafeck.stderr
Original file line number Diff line number Diff line change
@@ -2,13 +2,23 @@ error[E0560]: union `U` has no field named `principle`
--> $DIR/union-suggest-field.rs:13:17
|
LL | let u = U { principle: 0 };
| ^^^^^^^^^ help: a field with a similar name exists: `principal`
| ^^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let u = U { principal: 0 };
| ~~~~~~~~~

error[E0609]: no field `principial` on type `U`
--> $DIR/union-suggest-field.rs:17:15
|
LL | let w = u.principial;
| ^^^^^^^^^^ help: a field with a similar name exists: `principal`
| ^^^^^^^^^^ unknown field
|
help: a field with a similar name exists
|
LL | let w = u.principal;
| ~~~~~~~~~

error[E0615]: attempted to take value of method `calculate` on type `U`
--> $DIR/union-suggest-field.rs:21:15
3 changes: 2 additions & 1 deletion tests/ui/unsafe/unsafe-fn-autoderef.stderr
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@ error[E0609]: no field `f` on type `*const Rec`
|
LL | return p.f;
| --^
| |
| | |
| | unknown field
| help: `p` is a raw pointer; try dereferencing it: `(*p).f`

error: aborting due to previous error