Skip to content

Rollup of 10 pull requests #93921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Feb 12, 2022
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
69803f7
Make `span_extend_to_prev_str()` more robust
FabianWolff Jan 15, 2022
71ff16b
Update test output for `ui/asm/aarch64/parse-error.rs`
FabianWolff Jan 31, 2022
2d0bb0d
jsondocck: Improved error messages for invalid json value and failed …
aDotInTheVoid Feb 4, 2022
bf0e862
rustdoc-json: Add some tests for `typealias` item
aDotInTheVoid Feb 4, 2022
1115f15
windows: Map `ERROR_INVALID_NAME` as `InvalidInput`
JohnTitor Nov 16, 2021
755e475
Rename `FilenameTooLong` to `FilenameInvalid`
JohnTitor Jan 31, 2022
cc94079
Map `ERROR_INVALID_NAME` to `FilenameInvalid`
JohnTitor Jan 31, 2022
861f3c7
Fix description of FilenameInvalid
joshtriplett Jan 31, 2022
a898b31
Rename to `InvalidFilename`
JohnTitor Feb 10, 2022
d39a637
Split PAuth target feature
adamgemmell Jan 31, 2022
20e6c1d
Fix incorrect register conflict detection in asm!
Amanieu Feb 10, 2022
1f98ef7
Implement `AsFd` for `&T` and `&mut T`.
sunfishcode Feb 11, 2022
22a24c9
Add missing platform-specific information on current_dir and set_curr…
GuillaumeGomez Feb 3, 2022
45dc8eb
fix mention of moved function in `rustc_hir` docs
rosefromthedead Feb 11, 2022
f9cb01f
Fix typo: explicitely->explicitly
saschanaz Feb 11, 2022
55ceed8
Remove the alt_std_name option
bjorn3 Jan 14, 2022
7ba4110
Make two functions private
bjorn3 Jun 25, 2021
ce4df92
Rollup merge of #90955 - JohnTitor:os-error-123-as-invalid-input, r=m…
matthiaskrgr Feb 11, 2022
b7c48b4
Rollup merge of #91607 - FabianWolff:issue-91560-const-span, r=jackh726
matthiaskrgr Feb 11, 2022
642414e
Rollup merge of #92895 - bjorn3:simplifications, r=jackh726
matthiaskrgr Feb 11, 2022
15d71cf
Rollup merge of #93635 - GuillaumeGomez:missing-platform-spec-info, r…
matthiaskrgr Feb 11, 2022
ffa8d6b
Rollup merge of #93660 - aDotInTheVoid:rustdoc-type-tests, r=CraftSpider
matthiaskrgr Feb 11, 2022
13d636d
Rollup merge of #93782 - adamgemmell:dev/adagem01/split-pauth, r=Amanieu
matthiaskrgr Feb 11, 2022
db71248
Rollup merge of #93868 - Amanieu:asm_reg_conflict, r=cjgillot
matthiaskrgr Feb 11, 2022
34997f0
Rollup merge of #93888 - sunfishcode:sunfishcode/impl-asfd-for-ref, r…
matthiaskrgr Feb 11, 2022
0986b2d
Rollup merge of #93909 - saschanaz:patch-2, r=petrochenkov
matthiaskrgr Feb 11, 2022
de0feb3
Rollup merge of #93910 - rosehuds:master, r=cjgillot
matthiaskrgr Feb 11, 2022
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
4 changes: 3 additions & 1 deletion compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
@@ -373,7 +373,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
err.emit();
}
Entry::Vacant(v) => {
v.insert(idx);
if r == reg {
v.insert(idx);
}
}
}
};
Original file line number Diff line number Diff line change
@@ -11,7 +11,6 @@ pub fn inject(
mut krate: ast::Crate,
resolver: &mut dyn ResolverExpand,
sess: &Session,
alt_std_name: Option<Symbol>,
) -> ast::Crate {
let edition = sess.parse_sess.edition;

@@ -53,7 +52,7 @@ pub fn inject(
span,
ident,
vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
ast::ItemKind::ExternCrate(alt_std_name),
ast::ItemKind::ExternCrate(None),
),
);
}
31 changes: 26 additions & 5 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
@@ -322,12 +322,33 @@ pub fn from_fn_attrs<'ll, 'tcx>(
// The target doesn't care; the subtarget reads our attribute.
apply_tune_cpu_attr(cx, llfn);

let mut function_features = codegen_fn_attrs
.target_features
let function_features =
codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::<Vec<&str>>();

if let Some(f) = llvm_util::check_tied_features(
cx.tcx.sess,
&function_features.iter().map(|f| (*f, true)).collect(),
) {
let span = cx
.tcx
.get_attrs(instance.def_id())
.iter()
.find(|a| a.has_name(rustc_span::sym::target_feature))
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
let msg = format!(
"the target features {} must all be either enabled or disabled together",
f.join(", ")
);
let mut err = cx.tcx.sess.struct_span_err(span, &msg);
err.help("add the missing features in a `target_feature` attribute");
err.emit();
return;
}

let mut function_features = function_features
.iter()
.flat_map(|f| {
let feature = f.as_str();
llvm_util::to_llvm_feature(cx.tcx.sess, feature)
.flat_map(|feat| {
llvm_util::to_llvm_feature(cx.tcx.sess, feat)
.into_iter()
.map(|f| format!("+{}", f))
.collect::<Vec<String>>()
49 changes: 41 additions & 8 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ use crate::back::write::create_informational_target_machine;
use crate::{llvm, llvm_util};
use libc::c_int;
use libloading::Library;
use rustc_codegen_ssa::target_features::supported_target_features;
use rustc_data_structures::fx::FxHashSet;
use rustc_codegen_ssa::target_features::{supported_target_features, tied_target_features};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_fs_util::path_to_c_string;
use rustc_middle::bug;
use rustc_session::config::PrintRequest;
@@ -191,10 +191,30 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
("aarch64", "frintts") => vec!["fptoint"],
("aarch64", "fcma") => vec!["complxnum"],
("aarch64", "pmuv3") => vec!["perfmon"],
("aarch64", "paca") => vec!["pauth"],
("aarch64", "pacg") => vec!["pauth"],
(_, s) => vec![s],
}
}

// Given a map from target_features to whether they are enabled or disabled,
// ensure only valid combinations are allowed.
pub fn check_tied_features(
sess: &Session,
features: &FxHashMap<&str, bool>,
) -> Option<&'static [&'static str]> {
for tied in tied_target_features(sess) {
// Tied features must be set to the same value, or not set at all
let mut tied_iter = tied.iter();
let enabled = features.get(tied_iter.next().unwrap());

if tied_iter.any(|f| enabled != features.get(f)) {
return Some(tied);
}
}
None
}

pub fn target_features(sess: &Session) -> Vec<Symbol> {
let target_machine = create_informational_target_machine(sess);
supported_target_features(sess)
@@ -395,15 +415,19 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
Some(_) | None => {}
};

fn strip(s: &str) -> &str {
s.strip_prefix(&['+', '-']).unwrap_or(s)
}

let filter = |s: &str| {
if s.is_empty() {
return vec![];
}
let feature = if s.starts_with('+') || s.starts_with('-') {
&s[1..]
} else {
let feature = strip(s);
if feature == s {
return vec![s.to_string()];
};
}

// Rustc-specific feature requests like `+crt-static` or `-crt-static`
// are not passed down to LLVM.
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
@@ -420,8 +444,17 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
features.extend(sess.target.features.split(',').flat_map(&filter));

// -Ctarget-features
features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));

let feats: Vec<&str> = sess.opts.cg.target_feature.split(',').collect();
// LLVM enables based on the last occurence of a feature
if let Some(f) =
check_tied_features(sess, &feats.iter().map(|f| (strip(f), !f.starts_with("-"))).collect())
{
sess.err(&format!(
"Target features {} must all be enabled or disabled together",
f.join(", ")
));
}
features.extend(feats.iter().flat_map(|&f| filter(f)));
features
}

15 changes: 13 additions & 2 deletions compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
@@ -74,8 +74,10 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("ssbs", Some(sym::aarch64_target_feature)),
// FEAT_SB
("sb", Some(sym::aarch64_target_feature)),
// FEAT_PAUTH
("pauth", Some(sym::aarch64_target_feature)),
// FEAT_PAUTH (address authentication)
("paca", Some(sym::aarch64_target_feature)),
// FEAT_PAUTH (generic authentication)
("pacg", Some(sym::aarch64_target_feature)),
// FEAT_DPB
("dpb", Some(sym::aarch64_target_feature)),
// FEAT_DPB2
@@ -137,6 +139,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("v8.7a", Some(sym::aarch64_target_feature)),
];

const AARCH64_TIED_FEATURES: &[&[&str]] = &[&["paca", "pacg"]];

const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("adx", Some(sym::adx_target_feature)),
("aes", None),
@@ -256,6 +260,13 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
}
}

pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]] {
match &*sess.target.arch {
"aarch64" => AARCH64_TIED_FEATURES,
_ => &[],
}
}

pub(crate) fn provide(providers: &mut Providers) {
providers.supported_target_features = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
8 changes: 4 additions & 4 deletions compiler/rustc_hir/src/itemlikevisit.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ use super::{ForeignItem, ImplItem, Item, TraitItem};
///
/// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
/// - Example: find all items with a `#[foo]` attribute on them.
/// - How: Implement `ItemLikeVisitor` and call `tcx.hir().krate().visit_all_item_likes()`.
/// - How: Implement `ItemLikeVisitor` and call `tcx.hir().visit_all_item_likes()`.
/// - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves.
/// - Con: Don't get information about nesting
/// - Con: Don't have methods for specific bits of HIR, like "on
@@ -19,9 +19,9 @@ use super::{ForeignItem, ImplItem, Item, TraitItem};
/// - Example: Examine each expression to look for its type and do some check or other.
/// - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method
/// to return `NestedVisitorMap::OnlyBodies` and use
/// `tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within
/// your `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget
/// to invoke `intravisit::walk_expr()` to keep walking the subparts).
/// `tcx.hir().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within your
/// `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke
/// `intravisit::walk_expr()` to keep walking the subparts).
/// - Pro: Visitor methods for any kind of HIR node, not just item-like things.
/// - Pro: Integrates well into dependency tracking.
/// - Con: Don't get information about nesting between items
3 changes: 1 addition & 2 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
@@ -286,8 +286,7 @@ pub fn configure_and_expand(
rustc_builtin_macros::register_builtin_macros(resolver);

krate = sess.time("crate_injection", || {
let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess, alt_std_name)
rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess)
});

util::check_attr_crate_type(sess, &krate.attrs, &mut resolver.lint_buffer());
4 changes: 2 additions & 2 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ fn get_stack_size() -> Option<usize> {
/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
/// for `'static` bounds.
#[cfg(not(parallel_compiler))]
pub fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
// SAFETY: join() is called immediately, so any closure captures are still
// alive.
match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() {
@@ -379,7 +379,7 @@ fn sysroot_candidates() -> Vec<PathBuf> {
}
}

pub fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> MakeBackendFn {
fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> MakeBackendFn {
// For now we only allow this function to be called once as it'll dlopen a
// few things, which seems to work best if we only do that once. In
// general this assertion never trips due to the once guard in `get_codegen_backend`,
38 changes: 19 additions & 19 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -453,28 +453,28 @@ impl<'a> Resolver<'a> {
// edit:
// only do this if the const and usage of the non-constant value are on the same line
// the further the two are apart, the higher the chance of the suggestion being wrong
// also make sure that the pos for the suggestion is not 0 (ICE #90878)

let sp =
self.session.source_map().span_extend_to_prev_str(ident.span, current, true);

let pos_for_suggestion = sp.lo().0.saturating_sub(current.len() as u32);
let sp = self
.session
.source_map()
.span_extend_to_prev_str(ident.span, current, true, false);

if sp.lo().0 == 0
|| pos_for_suggestion == 0
|| self.session.source_map().is_multiline(sp)
{
err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
} else {
let sp = sp.with_lo(BytePos(pos_for_suggestion));
err.span_suggestion(
sp,
&format!("consider using `{}` instead of `{}`", sugg, current),
format!("{} {}", sugg, ident),
Applicability::MaybeIncorrect,
);
err.span_label(span, "non-constant value");
match sp {
Some(sp) if !self.session.source_map().is_multiline(sp) => {
let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32)));
err.span_suggestion(
sp,
&format!("consider using `{}` instead of `{}`", sugg, current),
format!("{} {}", sugg, ident),
Applicability::MaybeIncorrect,
);
err.span_label(span, "non-constant value");
}
_ => {
err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
}
}

err
}
ResolutionError::BindingShadowsSomethingUnacceptable {
2 changes: 0 additions & 2 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
@@ -770,7 +770,6 @@ impl Default for Options {
externs: Externs(BTreeMap::new()),
extern_dep_specs: ExternDepSpecs(BTreeMap::new()),
crate_name: None,
alt_std_name: None,
libs: Vec::new(),
unstable_features: UnstableFeatures::Disallow,
debug_assertions: true,
@@ -2382,7 +2381,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
extern_dep_specs,
crate_name,
alt_std_name: None,
libs,
debug_assertions,
actually_rustdoc: false,
4 changes: 0 additions & 4 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
@@ -184,10 +184,6 @@ top_level_options!(
externs: Externs [UNTRACKED],
extern_dep_specs: ExternDepSpecs [UNTRACKED],
crate_name: Option<String> [TRACKED],
/// An optional name to use as the crate for std during std injection,
/// written `extern crate name as std`. Defaults to `std`. Used by
/// out-of-tree drivers.
alt_std_name: Option<String> [TRACKED],
/// Indicates how the compiler should treat unstable features.
unstable_features: UnstableFeatures [TRACKED],

40 changes: 27 additions & 13 deletions compiler/rustc_span/src/source_map.rs
Original file line number Diff line number Diff line change
@@ -629,26 +629,41 @@ impl SourceMap {
}

/// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by
/// whitespace. Returns the same span if no character could be found or if an error occurred
/// while retrieving the code snippet.
pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool) -> Span {
/// whitespace. Returns None if the pattern could not be found or if an error occurred while
/// retrieving the code snippet.
pub fn span_extend_to_prev_str(
&self,
sp: Span,
pat: &str,
accept_newlines: bool,
include_whitespace: bool,
) -> Option<Span> {
// assure that the pattern is delimited, to avoid the following
// fn my_fn()
// ^^^^ returned span without the check
// ---------- correct span
let prev_source = self.span_to_prev_source(sp).ok()?;
for ws in &[" ", "\t", "\n"] {
let pat = pat.to_owned() + ws;
if let Ok(prev_source) = self.span_to_prev_source(sp) {
let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start();
if prev_source.is_empty() && sp.lo().0 != 0 {
return sp.with_lo(BytePos(sp.lo().0 - 1));
} else if accept_newlines || !prev_source.contains('\n') {
return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
if let Some(pat_pos) = prev_source.rfind(&pat) {
let just_after_pat_pos = pat_pos + pat.len() - 1;
let just_after_pat_plus_ws = if include_whitespace {
just_after_pat_pos
+ prev_source[just_after_pat_pos..]
.find(|c: char| !c.is_whitespace())
.unwrap_or(0)
} else {
just_after_pat_pos
};
let len = prev_source.len() - just_after_pat_plus_ws;
let prev_source = &prev_source[just_after_pat_plus_ws..];
if accept_newlines || !prev_source.trim_start().contains('\n') {
return Some(sp.with_lo(BytePos(sp.lo().0 - len as u32)));
}
}
}

sp
None
}

/// Returns the source snippet as `String` after the given `Span`.
@@ -927,7 +942,7 @@ impl SourceMap {
}

pub fn generate_fn_name_span(&self, span: Span) -> Option<Span> {
let prev_span = self.span_extend_to_prev_str(span, "fn", true);
let prev_span = self.span_extend_to_prev_str(span, "fn", true, true).unwrap_or(span);
if let Ok(snippet) = self.span_to_snippet(prev_span) {
debug!(
"generate_fn_name_span: span={:?}, prev_span={:?}, snippet={:?}",
@@ -968,8 +983,7 @@ impl SourceMap {
pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> {
// Try to extend the span to the previous "fn" keyword to retrieve the function
// signature.
let sugg_span = self.span_extend_to_prev_str(span, "fn", false);
if sugg_span != span {
if let Some(sugg_span) = self.span_extend_to_prev_str(span, "fn", false, true) {
if let Ok(snippet) = self.span_to_snippet(sugg_span) {
// Consume the function name.
let mut offset = snippet
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -1819,15 +1819,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
[] => {}
[trait_info] => {
let msg = format!(
"the trait `{}` defines an item `{}`, but is explicitely unimplemented",
"the trait `{}` defines an item `{}`, but is explicitly unimplemented",
self.tcx.def_path_str(trait_info.def_id),
item_name
);
err.note(&msg);
}
trait_infos => {
let mut msg = format!(
"the following traits define an item `{}`, but are explicitely unimplemented:",
"the following traits define an item `{}`, but are explicitly unimplemented:",
item_name
);
for trait_info in trait_infos {
10 changes: 10 additions & 0 deletions library/std/src/env.rs
Original file line number Diff line number Diff line change
@@ -23,6 +23,11 @@ use crate::sys::os as os_imp;

/// Returns the current working directory as a [`PathBuf`].
///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `getcwd` function on Unix
/// and the `GetCurrentDirectoryW` function on Windows.
///
/// # Errors
///
/// Returns an [`Err`] if the current working directory value is invalid.
@@ -49,6 +54,11 @@ pub fn current_dir() -> io::Result<PathBuf> {

/// Changes the current working directory to the specified path.
///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `chdir` function on Unix
/// and the `SetCurrentDirectoryW` function on Windows.
///
/// Returns an [`Err`] if the operation fails.
///
/// # Examples
9 changes: 4 additions & 5 deletions library/std/src/io/error.rs
Original file line number Diff line number Diff line change
@@ -296,12 +296,11 @@ pub enum ErrorKind {
/// The filesystem does not support making so many hardlinks to the same file.
#[unstable(feature = "io_error_more", issue = "86442")]
TooManyLinks,
/// Filename too long.
/// A filename was invalid.
///
/// The limit might be from the underlying filesystem or API, or an administratively imposed
/// resource limit.
/// This error can also cause if it exceeded the filename length limit.
#[unstable(feature = "io_error_more", issue = "86442")]
FilenameTooLong,
InvalidFilename,
/// Program argument list too long.
///
/// When trying to run an external program, a system or process limit on the size of the
@@ -382,12 +381,12 @@ impl ErrorKind {
DirectoryNotEmpty => "directory not empty",
ExecutableFileBusy => "executable file busy",
FileTooLarge => "file too large",
FilenameTooLong => "filename too long",
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
FilesystemQuotaExceeded => "filesystem quota exceeded",
HostUnreachable => "host unreachable",
Interrupted => "operation interrupted",
InvalidData => "invalid data",
InvalidFilename => "invalid filename",
InvalidInput => "invalid input parameter",
IsADirectory => "is a directory",
NetworkDown => "network down",
2 changes: 1 addition & 1 deletion library/std/src/io/error/repr_bitpacked.rs
Original file line number Diff line number Diff line change
@@ -315,7 +315,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
Deadlock,
CrossesDevices,
TooManyLinks,
FilenameTooLong,
InvalidFilename,
ArgumentListTooLong,
Interrupted,
Other,
16 changes: 16 additions & 0 deletions library/std/src/os/fd/owned.rs
Original file line number Diff line number Diff line change
@@ -200,6 +200,22 @@ pub trait AsFd {
fn as_fd(&self) -> BorrowedFd<'_>;
}

#[unstable(feature = "io_safety", issue = "87074")]
impl<T: AsFd> AsFd for &T {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
T::as_fd(self)
}
}

#[unstable(feature = "io_safety", issue = "87074")]
impl<T: AsFd> AsFd for &mut T {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
T::as_fd(self)
}
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for BorrowedFd<'_> {
#[inline]
2 changes: 1 addition & 1 deletion library/std/src/os/unix/fs.rs
Original file line number Diff line number Diff line change
@@ -966,7 +966,7 @@ pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::
///
/// fn main() -> std::io::Result<()> {
/// let f = std::fs::File::open("/file")?;
/// fs::fchown(f, Some(0), Some(0))?;
/// fs::fchown(&f, Some(0), Some(0))?;
/// Ok(())
/// }
/// ```
16 changes: 16 additions & 0 deletions library/std/src/os/windows/io/handle.rs
Original file line number Diff line number Diff line change
@@ -316,6 +316,22 @@ pub trait AsHandle {
fn as_handle(&self) -> BorrowedHandle<'_>;
}

#[unstable(feature = "io_safety", issue = "87074")]
impl<T: AsHandle> AsHandle for &T {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
T::as_handle(self)
}
}

#[unstable(feature = "io_safety", issue = "87074")]
impl<T: AsHandle> AsHandle for &mut T {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
T::as_handle(self)
}
}

impl AsHandle for BorrowedHandle<'_> {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
16 changes: 16 additions & 0 deletions library/std/src/os/windows/io/socket.rs
Original file line number Diff line number Diff line change
@@ -210,6 +210,22 @@ pub trait AsSocket {
fn as_socket(&self) -> BorrowedSocket<'_>;
}

#[unstable(feature = "io_safety", issue = "87074")]
impl<T: AsSocket> AsSocket for &T {
#[inline]
fn as_socket(&self) -> BorrowedSocket<'_> {
T::as_socket(self)
}
}

#[unstable(feature = "io_safety", issue = "87074")]
impl<T: AsSocket> AsSocket for &mut T {
#[inline]
fn as_socket(&self) -> BorrowedSocket<'_> {
T::as_socket(self)
}
}

impl AsSocket for BorrowedSocket<'_> {
#[inline]
fn as_socket(&self) -> BorrowedSocket<'_> {
2 changes: 1 addition & 1 deletion library/std/src/sys/unix/mod.rs
Original file line number Diff line number Diff line change
@@ -159,7 +159,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => FilenameTooLong,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
3 changes: 2 additions & 1 deletion library/std/src/sys/windows/mod.rs
Original file line number Diff line number Diff line change
@@ -71,6 +71,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
c::ERROR_FILE_NOT_FOUND => return NotFound,
c::ERROR_PATH_NOT_FOUND => return NotFound,
c::ERROR_NO_DATA => return BrokenPipe,
c::ERROR_INVALID_NAME => return InvalidFilename,
c::ERROR_INVALID_PARAMETER => return InvalidInput,
c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory,
c::ERROR_SEM_TIMEOUT
@@ -104,7 +105,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
c::ERROR_POSSIBLE_DEADLOCK => return Deadlock,
c::ERROR_NOT_SAME_DEVICE => return CrossesDevices,
c::ERROR_TOO_MANY_LINKS => return TooManyLinks,
c::ERROR_FILENAME_EXCED_RANGE => return FilenameTooLong,
c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename,
_ => {}
}

21 changes: 21 additions & 0 deletions src/test/rustdoc-json/type/dyn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ignore-tidy-linelength

// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items" 1
// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id"
// @is - "$.index[*][?(@.name=='dyn')].inner.items[0]" $sync_int_gen

// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.name" \"Fn\"
// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[*]" 3
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[0].trait_bound.trait.inner.name" \"Send\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[1].trait_bound.trait.inner.name" \"Sync\"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[2]" "{\"outlives\": \"'static\"}"
// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
28 changes: 28 additions & 0 deletions src/test/rustdoc-json/type/fn_lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// ignore-tidy-linelength

// @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"

// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1
// @is - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
// @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\"
// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0
// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1
// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"

pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;

// @is fn_lifetime.json "$.index[*][?(@.name=='ForAll')].kind" \"typedef\"
// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0
// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0
// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1
// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\"
// @has - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime"
// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0
// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1
// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
33 changes: 33 additions & 0 deletions src/test/rustdoc-json/type/generic_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// ignore-tidy-linelength

// @set result = generic_default.json "$.index[*][?(@.name=='Result')].id"
pub enum Result<T, E> {
Ok(T),
Err(E),
}

// @set my_error = - "$.index[*][?(@.name=='MyError')].id"
pub struct MyError {}

// @is - "$.index[*][?(@.name=='MyResult')].kind" \"typedef\"
// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0
// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2
// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\"
// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type"
// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type"
// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0
// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0
// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null
// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error
// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" []
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\"
// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\"
pub type MyResult<T, E = MyError> = Result<T, E>;
14 changes: 7 additions & 7 deletions src/test/ui/asm/aarch64/parse-error.stderr
Original file line number Diff line number Diff line change
@@ -382,7 +382,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:39:37
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
| ----------- help: consider using `const` instead of `let`: `const foo`
...
LL | asm!("{}", options(), const foo);
| ^^^ non-constant value
@@ -391,7 +391,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:48:44
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
| ----------- help: consider using `const` instead of `let`: `const foo`
...
LL | asm!("{}", clobber_abi("C"), const foo);
| ^^^ non-constant value
@@ -400,7 +400,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:55:31
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
| ----------- help: consider using `const` instead of `let`: `const foo`
...
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^ non-constant value
@@ -409,7 +409,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:55:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^ non-constant value
@@ -418,7 +418,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:62:45
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{a}", in("x0") foo, a = const bar);
| ^^^ non-constant value
@@ -427,7 +427,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:65:45
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{a}", in("x0") foo, a = const bar);
| ^^^ non-constant value
@@ -436,7 +436,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:68:41
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{1}", in("x0") foo, const bar);
| ^^^ non-constant value
20 changes: 20 additions & 0 deletions src/test/ui/asm/reg-conflict.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// compile-flags: --target armv7-unknown-linux-gnueabihf
// needs-llvm-components: arm

#![feature(no_core, lang_items, rustc_attrs)]
#![no_core]

#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
#[lang = "sized"]
trait Sized {}

fn main() {
unsafe {
asm!("", out("d0") _, out("d1") _);
asm!("", out("d0") _, out("s1") _);
//~^ ERROR register `s1` conflicts with register `d0`
}
}
10 changes: 10 additions & 0 deletions src/test/ui/asm/reg-conflict.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: register `s1` conflicts with register `d0`
--> $DIR/reg-conflict.rs:17:31
|
LL | asm!("", out("d0") _, out("s1") _);
| ----------- ^^^^^^^^^^^ register `s1`
| |
| register `d0`

error: aborting due to previous error

14 changes: 7 additions & 7 deletions src/test/ui/asm/x86_64/parse-error.stderr
Original file line number Diff line number Diff line change
@@ -394,7 +394,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:39:37
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
| ----------- help: consider using `const` instead of `let`: `const foo`
...
LL | asm!("{}", options(), const foo);
| ^^^ non-constant value
@@ -403,7 +403,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:50:44
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
| ----------- help: consider using `const` instead of `let`: `const foo`
...
LL | asm!("{}", clobber_abi("C"), const foo);
| ^^^ non-constant value
@@ -412,7 +412,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:57:31
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
| ----------- help: consider using `const` instead of `let`: `const foo`
...
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^ non-constant value
@@ -421,7 +421,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:57:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^ non-constant value
@@ -430,7 +430,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:64:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{a}", in("eax") foo, a = const bar);
| ^^^ non-constant value
@@ -439,7 +439,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:67:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{a}", in("eax") foo, a = const bar);
| ^^^ non-constant value
@@ -448,7 +448,7 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:70:42
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
| ----------- help: consider using `const` instead of `let`: `const bar`
...
LL | asm!("{1}", in("eax") foo, const bar);
| ^^^ non-constant value
21 changes: 21 additions & 0 deletions src/test/ui/consts/issue-91560.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Regression test for issue #91560.

// run-rustfix

#![allow(unused,non_upper_case_globals)]

fn foo() {
const length: usize = 2;
//~^ HELP: consider using `const`
let arr = [0; length];
//~^ ERROR: attempt to use a non-constant value in a constant [E0435]
}

fn bar() {
const length: usize = 2;
//~^ HELP: consider using `const`
let arr = [0; length];
//~^ ERROR: attempt to use a non-constant value in a constant [E0435]
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/consts/issue-91560.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Regression test for issue #91560.

// run-rustfix

#![allow(unused,non_upper_case_globals)]

fn foo() {
let mut length: usize = 2;
//~^ HELP: consider using `const`
let arr = [0; length];
//~^ ERROR: attempt to use a non-constant value in a constant [E0435]
}

fn bar() {
let length: usize = 2;
//~^ HELP: consider using `const`
let arr = [0; length];
//~^ ERROR: attempt to use a non-constant value in a constant [E0435]
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/consts/issue-91560.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-91560.rs:10:19
|
LL | let mut length: usize = 2;
| -------------- help: consider using `const` instead of `let`: `const length`
LL |
LL | let arr = [0; length];
| ^^^^^^ non-constant value

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-91560.rs:17:19
|
LL | let length: usize = 2;
| ------------ help: consider using `const` instead of `let`: `const length`
LL |
LL | let arr = [0; length];
| ^^^^^^ non-constant value

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0435`.
4 changes: 4 additions & 0 deletions src/test/ui/target-feature/tied-features-cli.one.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
error: Target features paca, pacg must all be enabled or disabled together

error: aborting due to previous error

9 changes: 9 additions & 0 deletions src/test/ui/target-feature/tied-features-cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// only-aarch64
// revisions: one two three four
//[one] compile-flags: -C target-feature=+paca
//[two] compile-flags: -C target-feature=-pacg,+pacg
//[three] compile-flags: -C target-feature=+paca,+pacg,-paca
//[four] check-pass
//[four] compile-flags: -C target-feature=-paca,+pacg -C target-feature=+paca

fn main() {}
4 changes: 4 additions & 0 deletions src/test/ui/target-feature/tied-features-cli.three.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
error: Target features paca, pacg must all be enabled or disabled together

error: aborting due to previous error

4 changes: 4 additions & 0 deletions src/test/ui/target-feature/tied-features-cli.two.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
error: Target features paca, pacg must all be enabled or disabled together

error: aborting due to previous error

29 changes: 29 additions & 0 deletions src/test/ui/target-feature/tied-features.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// only-aarch64
// build-fail

#![feature(aarch64_target_feature, target_feature_11)]

fn main() {
#[target_feature(enable = "pacg")]
//~^ ERROR must all be either enabled or disabled together
unsafe fn inner() {}

unsafe {
foo();
bar();
baz();
inner();
}
}

#[target_feature(enable = "paca")]
//~^ ERROR must all be either enabled or disabled together
unsafe fn foo() {}


#[target_feature(enable = "paca,pacg")]
unsafe fn bar() {}

#[target_feature(enable = "paca")]
#[target_feature(enable = "pacg")]
unsafe fn baz() {}
18 changes: 18 additions & 0 deletions src/test/ui/target-feature/tied-features.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: the target features paca, pacg must all be either enabled or disabled together
--> $DIR/tied-features.rs:7:5
|
LL | #[target_feature(enable = "pacg")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add the missing features in a `target_feature` attribute

error: the target features paca, pacg must all be either enabled or disabled together
--> $DIR/tied-features.rs:19:1
|
LL | #[target_feature(enable = "paca")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add the missing features in a `target_feature` attribute

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
@@ -34,20 +34,20 @@ fn main() {
Qux.clone();
//~^ ERROR no method named `clone` found for struct `Qux`
//~| NOTE method not found in `Qux`
//~| NOTE `Clone` defines an item `clone`, but is explicitely unimplemented
//~| NOTE `Clone` defines an item `clone`, but is explicitly unimplemented

0_u32.bar();
//~^ ERROR no method named `bar` found for type `u32`
//~| NOTE method not found in `u32`
//~| NOTE `Bar` defines an item `bar`, but is explicitely unimplemented
//~| NOTE `Bar` defines an item `bar`, but is explicitly unimplemented

Qux.foo();
//~^ ERROR no method named `foo` found for struct `Qux`
//~| NOTE method not found in `Qux`
//~| NOTE the following traits define an item `foo`, but are explicitely unimplemented
//~| NOTE the following traits define an item `foo`, but are explicitly unimplemented

0_u32.foo();
//~^ ERROR no method named `foo` found for type `u32`
//~| NOTE method not found in `u32`
//~| NOTE `FooBar` defines an item `foo`, but is explicitely unimplemented
//~| NOTE `FooBar` defines an item `foo`, but is explicitly unimplemented
}
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ LL | Qux.clone();
| ^^^^^ method not found in `Qux`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented
= note: the trait `Clone` defines an item `clone`, but is explicitly unimplemented

error[E0599]: no method named `bar` found for type `u32` in the current scope
--> $DIR/explicitly-unimplemented-error-message.rs:39:11
@@ -17,7 +17,7 @@ LL | 0_u32.bar();
| ^^^ method not found in `u32`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the trait `Bar` defines an item `bar`, but is explicitely unimplemented
= note: the trait `Bar` defines an item `bar`, but is explicitly unimplemented

error[E0599]: no method named `foo` found for struct `Qux` in the current scope
--> $DIR/explicitly-unimplemented-error-message.rs:44:9
@@ -29,7 +29,7 @@ LL | Qux.foo();
| ^^^ method not found in `Qux`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `foo`, but are explicitely unimplemented:
= note: the following traits define an item `foo`, but are explicitly unimplemented:
Foo
FooBar

@@ -45,7 +45,7 @@ note: `Foo` defines an item `foo`, perhaps you need to implement it
|
LL | trait Foo {
| ^^^^^^^^^
= note: the trait `FooBar` defines an item `foo`, but is explicitely unimplemented
= note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented

error: aborting due to 4 previous errors

18 changes: 16 additions & 2 deletions src/tools/jsondocck/src/main.rs
Original file line number Diff line number Diff line change
@@ -231,7 +231,21 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {

let val = cache.get_value(&command.args[0])?;
let results = select(&val, &command.args[1]).unwrap();
results.len() == expected
let eq = results.len() == expected;
if !command.negated && !eq {
return Err(CkError::FailedCheck(
format!(
"`{}` matched to `{:?}` with length {}, but expected length {}",
&command.args[1],
results,
results.len(),
expected
),
command,
));
} else {
eq
}
}
CommandKind::Is => {
// @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
@@ -317,6 +331,6 @@ fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> {
panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.variables)
}))
} else {
Cow::Owned(serde_json::from_str(s).unwrap())
Cow::Owned(serde_json::from_str(s).expect(&format!("Cannot convert `{}` to json", s)))
}
}