Skip to content
Merged
Show file tree
Hide file tree
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
8 changes: 6 additions & 2 deletions compiler/rustc_resolve/src/diagnostics/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1987,7 +1987,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
is_expected,
&|_| true,
);
self.add_typo_suggestion(err, suggestion, ident.span);
self.add_typo_suggestion(err, suggestion, ident.span, None);
self.detect_derive_attribute(err, ident, parent_scope, sugg_span);

let import_suggestions =
Expand Down Expand Up @@ -2271,6 +2271,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
err: &mut Diag<'_>,
suggestion: Option<TypoSuggestion>,
span: Span,
prefix: Option<Ident>,
) {
let suggestion = match suggestion {
None => return,
Expand Down Expand Up @@ -2345,7 +2346,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
format!("maybe you meant this {}", suggestion.res.descr())
}
};
(span, msg, suggestion.candidate.to_ident_string())
let candidate_str = suggestion.candidate.to_ident_string();
let sugg =
if let Some(p) = prefix { format!("{p}: {candidate_str}") } else { candidate_str };
(span, msg, sugg)
};
err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
}
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
}
}
self.r.add_typo_suggestion(err, typo_sugg, ident_span);
self.r.add_typo_suggestion(err, typo_sugg, ident_span, None);
return (true, suggested_candidates, candidates);
}

Expand Down Expand Up @@ -1244,7 +1244,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
&base_error.fallback_label,
) {
// We do this to avoid losing a secondary span when we override the main error span.
self.r.add_typo_suggestion(err, typo_sugg, ident_span);
self.r.add_typo_suggestion(err, typo_sugg, ident_span, None);
return (true, suggested_candidates, candidates);
}
}
Expand Down Expand Up @@ -1429,13 +1429,22 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
return false;
}

// Preserve the field name for struct field shorthands to avoid suggesting invalid shorthands.
let mut prefix = None;
if let PathSource::Expr(Some(ast::Expr { kind: ExprKind::Struct(expr), .. })) = source
&& let Some(ident) = path.last().map(|seg| seg.ident)
&& expr.fields.iter().any(|f| f.ident == ident && f.is_shorthand)
{
prefix = Some(ident);
}

let typo_sugg =
self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
let mut fallback = true;
let typo_sugg = typo_sugg
.to_opt_suggestion()
.filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
self.r.add_typo_suggestion(err, typo_sugg, ident_span);
self.r.add_typo_suggestion(err, typo_sugg, ident_span, prefix);

match self.diag_metadata.current_let_binding {
Some((pat_sp, Some(ty_sp), None))
Expand All @@ -1453,7 +1462,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {

// If the trait has a single item (which wasn't matched by the algorithm), suggest it
let suggestion = self.get_single_associated_item(path, &source, is_expected);
self.r.add_typo_suggestion(err, suggestion, ident_span);
self.r.add_typo_suggestion(err, suggestion, ident_span, prefix);

if self.let_binding_suggestion(err, ident_span) {
fallback = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use crate::spec::{
pub(crate) fn target() -> Target {
// Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
let pre_link_args = LinkArgs::new();
let post_link_args =
TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0", "-sWASM_BIGINT"]);
let post_link_args = TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0"]);

let opts = TargetOptions {
os: Os::Emscripten,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,15 @@ fn suggest_precise_capturing<'tcx>(
hir::GenericBound::Use(args, span) => Some((args, span)),
_ => None,
}) {
// '_ is an elision marker, not a lifetime name, so it cannot appear twice in a
// capture list. the branch for opaques with no use<..> yet already skips captured
// lifetimes; do the same here to avoid suggesting use<'_, '_>.
if args.iter().any(|arg| {
matches!(arg, hir::PreciseCapturingArg::Lifetime(lt) if lt.ident.name == new_lifetime)
}) {
return;
}

let last_lifetime_span = args.iter().rev().find_map(|arg| match arg {
hir::PreciseCapturingArg::Lifetime(lt) => Some(lt.ident.span),
_ => None,
Expand Down
56 changes: 53 additions & 3 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,8 @@ impl Dir {

/// Queries metadata about the underlying directory.
///
/// This is equivalent to `dir.metadata(".")` but can be more efficient.
///
/// # Examples
///
/// ```no_run
Expand All @@ -1645,13 +1647,13 @@ impl Dir {
///
/// fn main() -> std::io::Result<()> {
/// let dir = Dir::open("foo")?;
/// let metadata = dir.metadata()?;
/// let metadata = dir.self_metadata()?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "dirfd", issue = "120426")]
pub fn metadata(&self) -> io::Result<Metadata> {
self.inner.metadata().map(Metadata)
pub fn self_metadata(&self) -> io::Result<Metadata> {
self.inner.self_metadata().map(Metadata)
}

/// Attempts to open a file in read-only mode relative to this directory.
Expand Down Expand Up @@ -1891,6 +1893,54 @@ impl Dir {
pub fn try_clone(&self) -> io::Result<Self> {
Ok(Dir { inner: self.inner.duplicate()? })
}

/// Queries the file system to get information about a file, directory, etc. relative to this
/// directory.
///
/// This function will traverse symbolic links to query information about the destination file.
/// To query metadata about the path itself without following symbolic links, use
/// [`symlink_metadata`][Self::symlink_metadata].
///
/// # Examples
///
/// ```no_run
/// #![feature(dirfd)]
/// use std::fs::Dir;
///
/// fn main() -> std::io::Result<()> {
/// let dir = Dir::open("foo")?;
/// let metadata = dir.metadata("subdir/file.txt")?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "dirfd", issue = "120426")]
pub fn metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<Metadata> {
self.inner.metadata(path.as_ref()).map(Metadata)
}

/// Queries the file system to get information about a file, directory, etc. relative to this
/// directory.
///
/// This function will return the [`Metadata`] of the exact path without traversing symbolic
/// links to a resolved destination file. Using this function on a path that is a file or
/// directory (not a symbolic link) will behave the same as [`metadata`][Self::metadata].
///
/// # Examples
///
/// ```no_run
/// #![feature(dirfd)]
/// use std::fs::Dir;
///
/// fn main() -> std::io::Result<()> {
/// let dir = Dir::open("foo")?;
/// let metadata = dir.symlink_metadata("subdir/file.txt")?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "dirfd", issue = "120426")]
pub fn symlink_metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<Metadata> {
self.inner.symlink_metadata(path.as_ref()).map(Metadata)
}
}

impl AsInner<fs_imp::Dir> for Dir {
Expand Down
35 changes: 27 additions & 8 deletions library/std/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::os::unix::fs::symlink as symlink_file;
use crate::os::unix::fs::symlink as junction_point;
#[cfg(windows)]
use crate::os::windows::fs::{OpenOptionsExt, junction_point, symlink_dir, symlink_file};
use crate::path::Path;
use crate::path::{Path, PathBuf};
use crate::sync::Arc;
use crate::test_helpers::{TempDir, tmpdir};
use crate::time::{Duration, Instant, SystemTime};
Expand Down Expand Up @@ -655,11 +655,6 @@ fn set_get_permissions_nofollows() {
not(any(target_os = "espidf", target_os = "horizon", target_os = "wasi"))
))]
fn set_get_permissions_nofollows_symlink() {
#[cfg(not(windows))]
use crate::os::unix::fs::symlink as symlink_file;
#[cfg(windows)]
use crate::os::windows::fs::symlink_file;

let tmpdir = tmpdir();
let filename = tmpdir.join("set_get_unix_permissions_file");
let symlink_name = tmpdir.join("set_get_unix_permissions");
Expand Down Expand Up @@ -3052,10 +3047,10 @@ fn test_dir_clone() {
}

#[test]
fn test_dir_metadata() {
fn test_dir_self_metadata() {
let tmpdir = tmpdir();
let dir = check!(Dir::open(tmpdir.path()));
let metadata = check!(dir.metadata());
let metadata = check!(dir.self_metadata());
assert!(metadata.is_dir());
}

Expand Down Expand Up @@ -3143,3 +3138,27 @@ fn test_dir_open_dir() {
check!(f.read_exact(&mut buf));
assert_eq!(b"baz", &buf);
}

#[test]
fn test_dir_metadata() {
let tmpdir = tmpdir();
let dir = check!(Dir::open(tmpdir.path()));
check!(dir.create_dir("subdir"));
// FIXME: `/` does not work as path separator on Windows.
let barpath = PathBuf::from("subdir").join("bar.txt");
drop(check!(dir.open_file_with(&barpath, &OpenOptions::new().create(true).write(true))));
check!(symlink_file(&tmpdir.join("subdir/bar.txt"), &tmpdir.join("link")));

let metadata = check!(dir.metadata(&barpath));
assert!(metadata.is_file());
let metadata = check!(dir.metadata("subdir"));
assert!(metadata.is_dir());
dir.metadata("does-not-exist").unwrap_err();

let metadata = check!(dir.metadata("link"));
assert!(metadata.is_file());
assert!(!metadata.is_symlink());
let metadata = check!(dir.symlink_metadata("link"));
assert!(!metadata.is_file());
assert!(metadata.is_symlink());
}
10 changes: 9 additions & 1 deletion library/std/src/sys/fs/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl Dir {
File::open(&self.path.join(path), opts)
}

pub fn metadata(&self) -> io::Result<FileAttr> {
pub fn self_metadata(&self) -> io::Result<FileAttr> {
self.path.metadata().map(|m| m.into_inner())
}

Expand All @@ -108,6 +108,14 @@ impl Dir {
pub fn remove_dir(&self, path: &Path) -> io::Result<()> {
remove_dir(self.path.join(path))
}

pub fn metadata(&self, path: &Path) -> io::Result<FileAttr> {
self.path.join(path).metadata().map(|m| m.into_inner())
}

pub fn symlink_metadata(&self, path: &Path) -> io::Result<FileAttr> {
self.path.join(path).symlink_metadata().map(|m| m.into_inner())
}
}

impl fmt::Debug for Dir {
Expand Down
Loading
Loading