Auto merge of #109346 - Dylan-DPC:rollup-vszi5bn, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #104100 (Allow using `Range` as an `Iterator` in const contexts. ) - #105793 (Add note for mismatched types because of circular dependencies) - #108798 (move default backtrace setting to sys) - #108829 (Use Edition 2021 :pat in matches macro) - #108973 (Beautify pin! docs) - #109003 (Add `useless_anonymous_reexport` lint) - #109022 (read_buf_exact: on error, all read bytes are appended to the buffer) - #109212 (fix: don't suggest similar method when unstable) - #109243 (The name of NativeLib will be presented) - #109324 (Implement FixedSizeEncoding for UnusedGenericParams.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8826b68c62
@ -358,9 +358,9 @@ fn link_rlib<'a>(
|
||||
let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
|
||||
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
|
||||
packed_bundled_libs.push(wrapper_file);
|
||||
} else if let Some(name) = lib.name {
|
||||
} else {
|
||||
let path =
|
||||
find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess);
|
||||
find_native_static_library(lib.name.as_str(), lib.verbatim, &lib_search_paths, sess);
|
||||
ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| {
|
||||
sess.emit_fatal(errors::AddNativeLibrary { library_path: path, error })});
|
||||
}
|
||||
@ -436,7 +436,7 @@ fn collate_raw_dylibs<'a, 'b>(
|
||||
for lib in used_libraries {
|
||||
if lib.kind == NativeLibKind::RawDylib {
|
||||
let ext = if lib.verbatim { "" } else { ".dll" };
|
||||
let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext);
|
||||
let name = format!("{}{}", lib.name, ext);
|
||||
let imports = dylib_table.entry(name.clone()).or_default();
|
||||
for import in &lib.dll_imports {
|
||||
if let Some(old_import) = imports.insert(import.name, import) {
|
||||
@ -1296,7 +1296,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
|
||||
.iter()
|
||||
.filter(|l| relevant_lib(sess, l))
|
||||
.filter_map(|lib| {
|
||||
let name = lib.name?;
|
||||
let name = lib.name;
|
||||
match lib.kind {
|
||||
NativeLibKind::Static { bundle: Some(false), .. }
|
||||
| NativeLibKind::Dylib { .. }
|
||||
@ -1317,6 +1317,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
|
||||
// These are included, no need to print them
|
||||
NativeLibKind::Static { bundle: None | Some(true), .. }
|
||||
| NativeLibKind::LinkArg
|
||||
| NativeLibKind::WasmImportModule
|
||||
| NativeLibKind::RawDylib => None,
|
||||
}
|
||||
})
|
||||
@ -2275,21 +2276,18 @@ fn add_native_libs_from_crate(
|
||||
|
||||
let mut last = (None, NativeLibKind::Unspecified, false);
|
||||
for lib in native_libs {
|
||||
let Some(name) = lib.name else {
|
||||
continue;
|
||||
};
|
||||
if !relevant_lib(sess, lib) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if this library is the same as the last.
|
||||
last = if (lib.name, lib.kind, lib.verbatim) == last {
|
||||
last = if (Some(lib.name), lib.kind, lib.verbatim) == last {
|
||||
continue;
|
||||
} else {
|
||||
(lib.name, lib.kind, lib.verbatim)
|
||||
(Some(lib.name), lib.kind, lib.verbatim)
|
||||
};
|
||||
|
||||
let name = name.as_str();
|
||||
let name = lib.name.as_str();
|
||||
let verbatim = lib.verbatim;
|
||||
match lib.kind {
|
||||
NativeLibKind::Static { bundle, whole_archive } => {
|
||||
@ -2346,6 +2344,7 @@ fn add_native_libs_from_crate(
|
||||
NativeLibKind::RawDylib => {
|
||||
// Handled separately in `linker_with_args`.
|
||||
}
|
||||
NativeLibKind::WasmImportModule => {}
|
||||
NativeLibKind::LinkArg => {
|
||||
if link_static {
|
||||
cmd.arg(name);
|
||||
|
@ -595,7 +595,7 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, S
|
||||
|
||||
let mut ret = FxHashMap::default();
|
||||
for (def_id, lib) in tcx.foreign_modules(cnum).iter() {
|
||||
let module = def_id_to_native_lib.get(&def_id).and_then(|s| s.wasm_import_module);
|
||||
let module = def_id_to_native_lib.get(&def_id).and_then(|s| s.wasm_import_module());
|
||||
let Some(module) = module else { continue };
|
||||
ret.extend(lib.foreign_items.iter().map(|id| {
|
||||
assert_eq!(id.krate, cnum);
|
||||
|
@ -118,7 +118,7 @@ bitflags::bitflags! {
|
||||
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
|
||||
pub struct NativeLib {
|
||||
pub kind: NativeLibKind,
|
||||
pub name: Option<Symbol>,
|
||||
pub name: Symbol,
|
||||
pub filename: Option<Symbol>,
|
||||
pub cfg: Option<ast::MetaItem>,
|
||||
pub verbatim: bool,
|
||||
|
@ -1028,6 +1028,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
true
|
||||
}
|
||||
})
|
||||
// ensure that we don't suggest unstable methods
|
||||
.filter(|candidate| {
|
||||
// note that `DUMMY_SP` is ok here because it is only used for
|
||||
// suggestions and macro stuff which isn't applicable here.
|
||||
!matches!(
|
||||
self.tcx.eval_stability(candidate.item.def_id, None, DUMMY_SP, None),
|
||||
stability::EvalResult::Deny { .. }
|
||||
)
|
||||
})
|
||||
.map(|candidate| candidate.item.ident(self.tcx))
|
||||
.filter(|&name| set.insert(name))
|
||||
.collect();
|
||||
|
@ -615,9 +615,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
let report_path_match = |err: &mut Diagnostic, did1: DefId, did2: DefId| {
|
||||
// Only external crates, if either is from a local
|
||||
// module we could have false positives
|
||||
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
|
||||
// Only report definitions from different crates. If both definitions
|
||||
// are from a local module we could have false positives, e.g.
|
||||
// let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
|
||||
if did1.krate != did2.krate {
|
||||
let abs_path =
|
||||
|def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]);
|
||||
|
||||
@ -629,10 +630,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
};
|
||||
if same_path().unwrap_or(false) {
|
||||
let crate_name = self.tcx.crate_name(did1.krate);
|
||||
err.note(&format!(
|
||||
"perhaps two different versions of crate `{}` are being used?",
|
||||
crate_name
|
||||
));
|
||||
let msg = if did1.is_local() || did2.is_local() {
|
||||
format!(
|
||||
"the crate `{crate_name}` is compiled multiple times, possibly with different configurations"
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"perhaps two different versions of crate `{crate_name}` are being used?"
|
||||
)
|
||||
};
|
||||
err.note(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -508,3 +508,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
|
||||
.specifically = this associated type bound is unsatisfied for `{$proj_ty}`
|
||||
|
||||
lint_opaque_hidden_inferred_bound_sugg = add this bound
|
||||
|
||||
lint_useless_anonymous_reexport = useless anonymous re-export
|
||||
.note = only anonymous re-exports of traits are useful, this is {$article} `{$desc}`
|
||||
|
@ -74,6 +74,7 @@ mod opaque_hidden_inferred_bound;
|
||||
mod pass_by_value;
|
||||
mod passes;
|
||||
mod redundant_semicolon;
|
||||
mod reexports;
|
||||
mod traits;
|
||||
mod types;
|
||||
mod unused;
|
||||
@ -111,6 +112,7 @@ use noop_method_call::*;
|
||||
use opaque_hidden_inferred_bound::*;
|
||||
use pass_by_value::*;
|
||||
use redundant_semicolon::*;
|
||||
use reexports::*;
|
||||
use traits::*;
|
||||
use types::*;
|
||||
use unused::*;
|
||||
@ -242,6 +244,7 @@ late_lint_methods!(
|
||||
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
|
||||
MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
|
||||
MapUnitFn: MapUnitFn,
|
||||
UselessAnonymousReexport: UselessAnonymousReexport,
|
||||
]
|
||||
]
|
||||
);
|
||||
|
@ -1528,3 +1528,11 @@ pub struct UnusedAllocationDiag;
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_unused_allocation_mut)]
|
||||
pub struct UnusedAllocationMutDiag;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_useless_anonymous_reexport)]
|
||||
#[note]
|
||||
pub struct UselessAnonymousReexportDiag {
|
||||
pub article: &'static str,
|
||||
pub desc: &'static str,
|
||||
}
|
||||
|
82
compiler/rustc_lint/src/reexports.rs
Normal file
82
compiler/rustc_lint/src/reexports.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use crate::lints::UselessAnonymousReexportDiag;
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Item, ItemKind, UseKind};
|
||||
use rustc_middle::ty::Visibility;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_lint! {
|
||||
/// The `useless_anonymous_reexport` lint checks if anonymous re-exports
|
||||
/// are re-exports of traits.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(useless_anonymous_reexport)]
|
||||
///
|
||||
/// mod sub {
|
||||
/// pub struct Bar;
|
||||
/// }
|
||||
///
|
||||
/// pub use self::sub::Bar as _;
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Anonymous re-exports are only useful if it's a re-export of a trait
|
||||
/// in case you want to give access to it. If you re-export any other kind,
|
||||
/// you won't be able to use it since its name won't be accessible.
|
||||
pub USELESS_ANONYMOUS_REEXPORT,
|
||||
Warn,
|
||||
"useless anonymous re-export"
|
||||
}
|
||||
|
||||
declare_lint_pass!(UselessAnonymousReexport => [USELESS_ANONYMOUS_REEXPORT]);
|
||||
|
||||
fn emit_err(cx: &LateContext<'_>, span: Span, def_id: DefId) {
|
||||
let article = cx.tcx.def_descr_article(def_id);
|
||||
let desc = cx.tcx.def_descr(def_id);
|
||||
cx.emit_spanned_lint(
|
||||
USELESS_ANONYMOUS_REEXPORT,
|
||||
span,
|
||||
UselessAnonymousReexportDiag { article, desc },
|
||||
);
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for UselessAnonymousReexport {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
if let ItemKind::Use(path, kind) = item.kind &&
|
||||
!matches!(kind, UseKind::Glob) &&
|
||||
item.ident.name == kw::Underscore &&
|
||||
// We only want re-exports. If it's just a `use X;`, then we ignore it.
|
||||
match cx.tcx.local_visibility(item.owner_id.def_id) {
|
||||
Visibility::Public => true,
|
||||
Visibility::Restricted(level) => {
|
||||
level != cx.tcx.parent_module_from_def_id(item.owner_id.def_id)
|
||||
}
|
||||
}
|
||||
{
|
||||
for def_id in path.res.iter().filter_map(|r| r.opt_def_id()) {
|
||||
match cx.tcx.def_kind(def_id) {
|
||||
DefKind::Trait | DefKind::TraitAlias => {}
|
||||
DefKind::TyAlias => {
|
||||
let ty = cx.tcx.type_of(def_id);
|
||||
if !ty.0.is_trait() {
|
||||
emit_err(cx, item.span, def_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
emit_err(cx, item.span, def_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ pub fn find_native_static_library(
|
||||
}
|
||||
|
||||
fn find_bundled_library(
|
||||
name: Option<Symbol>,
|
||||
name: Symbol,
|
||||
verbatim: Option<bool>,
|
||||
kind: NativeLibKind,
|
||||
has_cfg: bool,
|
||||
@ -58,7 +58,7 @@ fn find_bundled_library(
|
||||
{
|
||||
let verbatim = verbatim.unwrap_or(false);
|
||||
let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs();
|
||||
return find_native_static_library(name.unwrap().as_str(), verbatim, search_paths, sess)
|
||||
return find_native_static_library(name.as_str(), verbatim, search_paths, sess)
|
||||
.file_name()
|
||||
.and_then(|s| s.to_str())
|
||||
.map(Symbol::intern);
|
||||
@ -336,10 +336,16 @@ impl<'tcx> Collector<'tcx> {
|
||||
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
|
||||
sess.emit_err(errors::IncompatibleWasmLink { span });
|
||||
}
|
||||
} else if name.is_none() {
|
||||
sess.emit_err(errors::LinkRequiresName { span: m.span });
|
||||
}
|
||||
|
||||
if wasm_import_module.is_some() {
|
||||
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
|
||||
}
|
||||
let Some((name, name_span)) = name else {
|
||||
sess.emit_err(errors::LinkRequiresName { span: m.span });
|
||||
continue;
|
||||
};
|
||||
|
||||
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
|
||||
if let Some((_, span)) = import_name_type {
|
||||
if kind != Some(NativeLibKind::RawDylib) {
|
||||
@ -349,8 +355,8 @@ impl<'tcx> Collector<'tcx> {
|
||||
|
||||
let dll_imports = match kind {
|
||||
Some(NativeLibKind::RawDylib) => {
|
||||
if let Some((name, span)) = name && name.as_str().contains('\0') {
|
||||
sess.emit_err(errors::RawDylibNoNul { span });
|
||||
if name.as_str().contains('\0') {
|
||||
sess.emit_err(errors::RawDylibNoNul { span: name_span });
|
||||
}
|
||||
foreign_mod_items
|
||||
.iter()
|
||||
@ -389,7 +395,6 @@ impl<'tcx> Collector<'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let name = name.map(|(name, _)| name);
|
||||
let kind = kind.unwrap_or(NativeLibKind::Unspecified);
|
||||
let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess);
|
||||
self.libs.push(NativeLib {
|
||||
@ -398,7 +403,6 @@ impl<'tcx> Collector<'tcx> {
|
||||
kind,
|
||||
cfg,
|
||||
foreign_module: Some(it.owner_id.to_def_id()),
|
||||
wasm_import_module: wasm_import_module.map(|(name, _)| name),
|
||||
verbatim,
|
||||
dll_imports,
|
||||
});
|
||||
@ -415,11 +419,7 @@ impl<'tcx> Collector<'tcx> {
|
||||
self.tcx.sess.emit_err(errors::LibFrameworkApple);
|
||||
}
|
||||
if let Some(ref new_name) = lib.new_name {
|
||||
let any_duplicate = self
|
||||
.libs
|
||||
.iter()
|
||||
.filter_map(|lib| lib.name.as_ref())
|
||||
.any(|n| n.as_str() == lib.name);
|
||||
let any_duplicate = self.libs.iter().any(|n| n.name.as_str() == lib.name);
|
||||
if new_name.is_empty() {
|
||||
self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name });
|
||||
} else if !any_duplicate {
|
||||
@ -444,33 +444,28 @@ impl<'tcx> Collector<'tcx> {
|
||||
let mut existing = self
|
||||
.libs
|
||||
.drain_filter(|lib| {
|
||||
if let Some(lib_name) = lib.name {
|
||||
if lib_name.as_str() == passed_lib.name {
|
||||
// FIXME: This whole logic is questionable, whether modifiers are
|
||||
// involved or not, library reordering and kind overriding without
|
||||
// explicit `:rename` in particular.
|
||||
if lib.has_modifiers() || passed_lib.has_modifiers() {
|
||||
match lib.foreign_module {
|
||||
Some(def_id) => {
|
||||
self.tcx.sess.emit_err(errors::NoLinkModOverride {
|
||||
span: Some(self.tcx.def_span(def_id)),
|
||||
})
|
||||
}
|
||||
None => self
|
||||
.tcx
|
||||
.sess
|
||||
.emit_err(errors::NoLinkModOverride { span: None }),
|
||||
};
|
||||
}
|
||||
if passed_lib.kind != NativeLibKind::Unspecified {
|
||||
lib.kind = passed_lib.kind;
|
||||
}
|
||||
if let Some(new_name) = &passed_lib.new_name {
|
||||
lib.name = Some(Symbol::intern(new_name));
|
||||
}
|
||||
lib.verbatim = passed_lib.verbatim;
|
||||
return true;
|
||||
if lib.name.as_str() == passed_lib.name {
|
||||
// FIXME: This whole logic is questionable, whether modifiers are
|
||||
// involved or not, library reordering and kind overriding without
|
||||
// explicit `:rename` in particular.
|
||||
if lib.has_modifiers() || passed_lib.has_modifiers() {
|
||||
match lib.foreign_module {
|
||||
Some(def_id) => self.tcx.sess.emit_err(errors::NoLinkModOverride {
|
||||
span: Some(self.tcx.def_span(def_id)),
|
||||
}),
|
||||
None => {
|
||||
self.tcx.sess.emit_err(errors::NoLinkModOverride { span: None })
|
||||
}
|
||||
};
|
||||
}
|
||||
if passed_lib.kind != NativeLibKind::Unspecified {
|
||||
lib.kind = passed_lib.kind;
|
||||
}
|
||||
if let Some(new_name) = &passed_lib.new_name {
|
||||
lib.name = Symbol::intern(new_name);
|
||||
}
|
||||
lib.verbatim = passed_lib.verbatim;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
})
|
||||
@ -478,7 +473,7 @@ impl<'tcx> Collector<'tcx> {
|
||||
if existing.is_empty() {
|
||||
// Add if not found
|
||||
let new_name: Option<&str> = passed_lib.new_name.as_deref();
|
||||
let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name)));
|
||||
let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name));
|
||||
let sess = self.tcx.sess;
|
||||
let filename =
|
||||
find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess);
|
||||
@ -488,7 +483,6 @@ impl<'tcx> Collector<'tcx> {
|
||||
kind: passed_lib.kind,
|
||||
cfg: None,
|
||||
foreign_module: None,
|
||||
wasm_import_module: None,
|
||||
verbatim: passed_lib.verbatim,
|
||||
dll_imports: Vec::new(),
|
||||
});
|
||||
|
@ -226,15 +226,7 @@ provide! { tcx, def_id, other, cdata,
|
||||
lookup_default_body_stability => { table }
|
||||
lookup_deprecation_entry => { table }
|
||||
params_in_repr => { table }
|
||||
// FIXME: Could be defaulted, but `LazyValue<UnusedGenericParams>` is not `FixedSizeEncoding`..
|
||||
unused_generic_params => {
|
||||
cdata
|
||||
.root
|
||||
.tables
|
||||
.unused_generic_params
|
||||
.get(cdata, def_id.index)
|
||||
.map_or_else(|| ty::UnusedGenericParams::new_all_used(), |lazy| lazy.decode((cdata, tcx)))
|
||||
}
|
||||
unused_generic_params => { cdata.root.tables.unused_generic_params.get(cdata, def_id.index) }
|
||||
opt_def_kind => { table_direct }
|
||||
impl_parent => { table }
|
||||
impl_polarity => { table_direct }
|
||||
|
@ -1440,9 +1440,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
let instance =
|
||||
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
|
||||
let unused = tcx.unused_generic_params(instance);
|
||||
if !unused.all_used() {
|
||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
||||
}
|
||||
self.tables.unused_generic_params.set(def_id.local_def_index, unused);
|
||||
}
|
||||
|
||||
// Encode all the deduced parameter attributes for everything that has MIR, even for items
|
||||
|
@ -356,6 +356,7 @@ define_tables! {
|
||||
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
||||
associated_items_for_impl_trait_in_trait: Table<DefIndex, LazyArray<DefId>>,
|
||||
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
|
||||
unused_generic_params: Table<DefIndex, UnusedGenericParams>,
|
||||
|
||||
- optional:
|
||||
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
|
||||
@ -398,7 +399,6 @@ define_tables! {
|
||||
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
|
||||
trait_item_def_id: Table<DefIndex, RawDefId>,
|
||||
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
|
||||
unused_generic_params: Table<DefIndex, LazyValue<UnusedGenericParams>>,
|
||||
params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
|
||||
repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
|
||||
// `def_keys` and `def_path_hashes` represent a lazy version of a
|
||||
|
@ -3,7 +3,7 @@ use crate::rmeta::*;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_hir::def::{CtorKind, CtorOf};
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::ParameterizedOverTcx;
|
||||
use rustc_middle::ty::{ParameterizedOverTcx, UnusedGenericParams};
|
||||
use rustc_serialize::opaque::FileEncoder;
|
||||
use rustc_serialize::Encoder as _;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
@ -50,6 +50,16 @@ impl IsDefault for DefPathHash {
|
||||
}
|
||||
}
|
||||
|
||||
impl IsDefault for UnusedGenericParams {
|
||||
fn is_default(&self) -> bool {
|
||||
// UnusedGenericParams encodes the *un*usedness as a bitset.
|
||||
// This means that 0 corresponds to all bits used, which is indeed the default.
|
||||
let is_default = self.bits() == 0;
|
||||
debug_assert_eq!(is_default, self.all_used());
|
||||
is_default
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
|
||||
/// Used mainly for Lazy positions and lengths.
|
||||
/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
|
||||
@ -271,6 +281,21 @@ impl FixedSizeEncoding for bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl FixedSizeEncoding for UnusedGenericParams {
|
||||
type ByteArray = [u8; 4];
|
||||
|
||||
#[inline]
|
||||
fn from_bytes(b: &[u8; 4]) -> Self {
|
||||
let x: u32 = u32::from_bytes(b);
|
||||
UnusedGenericParams::from_bits(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_to_bytes(self, b: &mut [u8; 4]) {
|
||||
self.bits().write_to_bytes(b);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
|
||||
// generic `LazyValue<T>` impl, but in the general case we might not need / want
|
||||
// to fit every `usize` in `u32`.
|
||||
|
@ -781,6 +781,12 @@ fn needs_fn_once_adapter_shim(
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
|
||||
pub struct UnusedGenericParams(FiniteBitSet<u32>);
|
||||
|
||||
impl Default for UnusedGenericParams {
|
||||
fn default() -> Self {
|
||||
UnusedGenericParams::new_all_used()
|
||||
}
|
||||
}
|
||||
|
||||
impl UnusedGenericParams {
|
||||
pub fn new_all_unused(amount: u32) -> Self {
|
||||
let mut bitset = FiniteBitSet::new_empty();
|
||||
@ -807,4 +813,12 @@ impl UnusedGenericParams {
|
||||
pub fn all_used(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn bits(&self) -> u32 {
|
||||
self.0.0
|
||||
}
|
||||
|
||||
pub fn from_bits(bits: u32) -> UnusedGenericParams {
|
||||
UnusedGenericParams(FiniteBitSet(bits))
|
||||
}
|
||||
}
|
||||
|
@ -67,12 +67,11 @@ pub enum LinkagePreference {
|
||||
#[derive(Debug, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct NativeLib {
|
||||
pub kind: NativeLibKind,
|
||||
pub name: Option<Symbol>,
|
||||
pub name: Symbol,
|
||||
/// If packed_bundled_libs enabled, actual filename of library is stored.
|
||||
pub filename: Option<Symbol>,
|
||||
pub cfg: Option<ast::MetaItem>,
|
||||
pub foreign_module: Option<DefId>,
|
||||
pub wasm_import_module: Option<Symbol>,
|
||||
pub verbatim: Option<bool>,
|
||||
pub dll_imports: Vec<DllImport>,
|
||||
}
|
||||
@ -81,6 +80,10 @@ impl NativeLib {
|
||||
pub fn has_modifiers(&self) -> bool {
|
||||
self.verbatim.is_some() || self.kind.has_modifiers()
|
||||
}
|
||||
|
||||
pub fn wasm_import_module(&self) -> Option<Symbol> {
|
||||
if self.kind == NativeLibKind::WasmImportModule { Some(self.name) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
/// Different ways that the PE Format can decorate a symbol name.
|
||||
|
@ -37,6 +37,10 @@ pub enum NativeLibKind {
|
||||
/// Argument which is passed to linker, relative order with libraries and other arguments
|
||||
/// is preserved
|
||||
LinkArg,
|
||||
|
||||
/// Module imported from WebAssembly
|
||||
WasmImportModule,
|
||||
|
||||
/// The library kind wasn't specified, `Dylib` is currently used as a default.
|
||||
Unspecified,
|
||||
}
|
||||
@ -50,7 +54,10 @@ impl NativeLibKind {
|
||||
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
|
||||
as_needed.is_some()
|
||||
}
|
||||
NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false,
|
||||
NativeLibKind::RawDylib
|
||||
| NativeLibKind::Unspecified
|
||||
| NativeLibKind::LinkArg
|
||||
| NativeLibKind::WasmImportModule => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::convert::TryFrom;
|
||||
use crate::marker::Destruct;
|
||||
use crate::mem;
|
||||
use crate::ops::{self, Try};
|
||||
|
||||
@ -20,7 +21,8 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi
|
||||
/// The *successor* operation moves towards values that compare greater.
|
||||
/// The *predecessor* operation moves towards values that compare lesser.
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
pub trait Step: Clone + PartialOrd + Sized {
|
||||
#[const_trait]
|
||||
pub trait Step: ~const Clone + ~const PartialOrd + Sized {
|
||||
/// Returns the number of *successor* steps required to get from `start` to `end`.
|
||||
///
|
||||
/// Returns `None` if the number of steps would overflow `usize`
|
||||
@ -234,7 +236,8 @@ macro_rules! step_integer_impls {
|
||||
$(
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
impl Step for $u_narrower {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl const Step for $u_narrower {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
@ -266,7 +269,8 @@ macro_rules! step_integer_impls {
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
impl Step for $i_narrower {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl const Step for $i_narrower {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
@ -330,7 +334,8 @@ macro_rules! step_integer_impls {
|
||||
$(
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
impl Step for $u_wider {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl const Step for $u_wider {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
@ -355,7 +360,8 @@ macro_rules! step_integer_impls {
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
impl Step for $i_wider {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl const Step for $i_wider {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
@ -405,7 +411,8 @@ step_integer_impls! {
|
||||
}
|
||||
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
impl Step for char {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl const Step for char {
|
||||
#[inline]
|
||||
fn steps_between(&start: &char, &end: &char) -> Option<usize> {
|
||||
let start = start as u32;
|
||||
@ -423,6 +430,7 @@ impl Step for char {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_allow_const_fn_unstable(const_try)]
|
||||
fn forward_checked(start: char, count: usize) -> Option<char> {
|
||||
let start = start as u32;
|
||||
let mut res = Step::forward_checked(start, count)?;
|
||||
@ -439,6 +447,7 @@ impl Step for char {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_allow_const_fn_unstable(const_try)]
|
||||
fn backward_checked(start: char, count: usize) -> Option<char> {
|
||||
let start = start as u32;
|
||||
let mut res = Step::backward_checked(start, count)?;
|
||||
@ -514,6 +523,7 @@ macro_rules! range_incl_exact_iter_impl {
|
||||
}
|
||||
|
||||
/// Specialization implementations for `Range`.
|
||||
#[const_trait]
|
||||
trait RangeIteratorImpl {
|
||||
type Item;
|
||||
|
||||
@ -528,7 +538,7 @@ trait RangeIteratorImpl {
|
||||
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>;
|
||||
}
|
||||
|
||||
impl<A: Step> RangeIteratorImpl for ops::Range<A> {
|
||||
impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
@ -614,7 +624,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
|
||||
impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
|
||||
#[inline]
|
||||
fn spec_next(&mut self) -> Option<T> {
|
||||
if self.start < self.end {
|
||||
@ -702,7 +712,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Step> Iterator for ops::Range<A> {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl<A: ~const Step + ~const Destruct> const Iterator for ops::Range<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
@ -812,7 +823,8 @@ range_incl_exact_iter_impl! {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
self.spec_next_back()
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::marker::Destruct;
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator able to yield elements from both ends.
|
||||
@ -37,6 +38,7 @@ use crate::ops::{ControlFlow, Try};
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")]
|
||||
#[const_trait]
|
||||
pub trait DoubleEndedIterator: Iterator {
|
||||
/// Removes and returns an element from the end of the iterator.
|
||||
///
|
||||
@ -131,7 +133,10 @@ pub trait DoubleEndedIterator: Iterator {
|
||||
/// [`Err(k)`]: Err
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize>
|
||||
where
|
||||
Self::Item: ~const Destruct,
|
||||
{
|
||||
for i in 0..n {
|
||||
self.next_back().ok_or(i)?;
|
||||
}
|
||||
@ -181,6 +186,7 @@ pub trait DoubleEndedIterator: Iterator {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_nth_back", since = "1.37.0")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.advance_back_by(n).ok()?;
|
||||
self.next_back()
|
||||
@ -218,6 +224,7 @@ pub trait DoubleEndedIterator: Iterator {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
@ -289,6 +296,7 @@ pub trait DoubleEndedIterator: Iterator {
|
||||
#[doc(alias = "foldr")]
|
||||
#[inline]
|
||||
#[stable(feature = "iter_rfold", since = "1.27.0")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
@ -344,6 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_rfind", since = "1.27.0")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::array;
|
||||
use crate::cmp::{self, Ordering};
|
||||
use crate::marker::Destruct;
|
||||
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
|
||||
|
||||
use super::super::try_process;
|
||||
@ -336,8 +337,10 @@ pub trait Iterator {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize>
|
||||
where
|
||||
Self::Item: ~const Destruct,
|
||||
{
|
||||
for i in 0..n {
|
||||
self.next().ok_or(i)?;
|
||||
}
|
||||
@ -385,8 +388,10 @@ pub trait Iterator {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item>
|
||||
where
|
||||
Self::Item: ~const Destruct,
|
||||
{
|
||||
self.advance_by(n).ok()?;
|
||||
self.next()
|
||||
}
|
||||
|
@ -86,4 +86,5 @@ pub unsafe trait InPlaceIterable: Iterator {}
|
||||
/// for details. Consumers are free to rely on the invariants in unsafe code.
|
||||
#[unstable(feature = "trusted_step", issue = "85731")]
|
||||
#[rustc_specialization_trait]
|
||||
pub unsafe trait TrustedStep: Step {}
|
||||
#[const_trait]
|
||||
pub unsafe trait TrustedStep: ~const Step {}
|
||||
|
@ -123,9 +123,11 @@
|
||||
#![feature(const_index_range_slice_index)]
|
||||
#![feature(const_inherent_unchecked_arith)]
|
||||
#![feature(const_int_unchecked_arith)]
|
||||
#![feature(const_intoiterator_identity)]
|
||||
#![feature(const_intrinsic_forget)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(const_iter)]
|
||||
#![feature(const_likely)]
|
||||
#![feature(const_maybe_uninit_uninit_array)]
|
||||
#![feature(const_maybe_uninit_as_mut_ptr)]
|
||||
|
@ -340,9 +340,9 @@ pub macro debug_assert_matches($($arg:tt)*) {
|
||||
#[stable(feature = "matches_macro", since = "1.42.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")]
|
||||
macro_rules! matches {
|
||||
($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
|
||||
($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => {
|
||||
match $expression {
|
||||
$( $pattern )|+ $( if $guard )? => true,
|
||||
$pattern $(if $guard)? => true,
|
||||
_ => false
|
||||
}
|
||||
};
|
||||
|
@ -1003,22 +1003,25 @@ impl<P, U> CoerceUnsized<Pin<U>> for Pin<P> where P: CoerceUnsized<U> {}
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
|
||||
|
||||
/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning[^1] a `value: T` _locally_[^2].
|
||||
/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
|
||||
///
|
||||
/// Unlike [`Box::pin`], this does not involve a heap allocation.
|
||||
/// Unlike [`Box::pin`], this does not create a new heap allocation. As explained
|
||||
/// below, the element might still end up on the heap however.
|
||||
///
|
||||
/// [^1]: If the (type `T` of the) given value does not implement [`Unpin`], then this
|
||||
/// effectively pins the `value` in memory, where it will be unable to be moved.
|
||||
/// Otherwise, <code>[Pin]<[&mut] T></code> behaves like <code>[&mut] T</code>, and operations such
|
||||
/// as [`mem::replace()`][crate::mem::replace] will allow extracting that value, and therefore,
|
||||
/// moving it.
|
||||
/// See [the `Unpin` section of the `pin` module][self#unpin] for more info.
|
||||
/// The local pinning performed by this macro is usually dubbed "stack"-pinning.
|
||||
/// Outside of `async` contexts locals do indeed get stored on the stack. In
|
||||
/// `async` functions or blocks however, any locals crossing an `.await` point
|
||||
/// are part of the state captured by the `Future`, and will use the storage of
|
||||
/// those. That storage can either be on the heap or on the stack. Therefore,
|
||||
/// local pinning is a more accurate term.
|
||||
///
|
||||
/// [^2]: This is usually dubbed "stack"-pinning. And whilst local values are almost always located
|
||||
/// in the stack (_e.g._, when within the body of a non-`async` function), the truth is that inside
|
||||
/// the body of an `async fn` or block —more generally, the body of a generator— any locals crossing
|
||||
/// an `.await` point —a `yield` point— end up being part of the state captured by the `Future` —by
|
||||
/// the `Generator`—, and thus will be stored wherever that one is.
|
||||
/// If the type of the given value does not implement [`Unpin`], then this macro
|
||||
/// pins the value in memory in a way that prevents moves. On the other hand,
|
||||
/// if the type does implement [`Unpin`], <code>[Pin]<[&mut] T></code> behaves
|
||||
/// like <code>[&mut] T</code>, and operations such as
|
||||
/// [`mem::replace()`][crate::mem::replace] or [`mem::take()`](crate::mem::take)
|
||||
/// will allow moves of the value.
|
||||
/// See [the `Unpin` section of the `pin` module][self#unpin] for details.
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
@ -1158,9 +1161,9 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
|
||||
///
|
||||
/// If you really need to return a pinned value, consider using [`Box::pin`] instead.
|
||||
///
|
||||
/// On the other hand, pinning to the stack[<sup>2</sup>](#fn2) using [`pin!`] is likely to be
|
||||
/// cheaper than pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not
|
||||
/// even needing an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`]
|
||||
/// On the other hand, local pinning using [`pin!`] is likely to be cheaper than
|
||||
/// pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not
|
||||
/// requiring an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`]
|
||||
/// constructor.
|
||||
///
|
||||
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
|
||||
|
36
library/core/tests/iter/consts.rs
Normal file
36
library/core/tests/iter/consts.rs
Normal file
@ -0,0 +1,36 @@
|
||||
#[test]
|
||||
fn const_manual_iter() {
|
||||
struct S(bool);
|
||||
|
||||
impl const Iterator for S {
|
||||
type Item = ();
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.0 == false {
|
||||
self.0 = true;
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
const {
|
||||
let mut val = S(false);
|
||||
assert!(val.next().is_some());
|
||||
assert!(val.next().is_none());
|
||||
assert!(val.next().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn const_range() {
|
||||
const {
|
||||
let mut arr = [0; 3];
|
||||
for i in 0..arr.len() {
|
||||
arr[i] = i;
|
||||
}
|
||||
assert!(arr[0] == 0);
|
||||
assert!(arr[1] == 1);
|
||||
assert!(arr[2] == 2);
|
||||
}
|
||||
}
|
@ -20,6 +20,8 @@ mod range;
|
||||
mod sources;
|
||||
mod traits;
|
||||
|
||||
mod consts;
|
||||
|
||||
use core::cell::Cell;
|
||||
use core::convert::TryFrom;
|
||||
use core::iter::*;
|
||||
|
@ -12,8 +12,11 @@
|
||||
#![feature(const_caller_location)]
|
||||
#![feature(const_cell_into_inner)]
|
||||
#![feature(const_convert)]
|
||||
#![feature(const_for)]
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_intoiterator_identity)]
|
||||
#![feature(const_iter)]
|
||||
#![feature(const_maybe_uninit_as_mut_ptr)]
|
||||
#![feature(const_maybe_uninit_assume_init_read)]
|
||||
#![feature(const_nonnull_new)]
|
||||
|
@ -823,8 +823,22 @@ pub trait Read {
|
||||
|
||||
/// Read the exact number of bytes required to fill `cursor`.
|
||||
///
|
||||
/// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to
|
||||
/// allow use with uninitialized buffers.
|
||||
/// This is similar to the [`read_exact`](Read::read_exact) method, except
|
||||
/// that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use
|
||||
/// with uninitialized buffers.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If this function encounters an error of the kind [`ErrorKind::Interrupted`]
|
||||
/// then the error is ignored and the operation will continue.
|
||||
///
|
||||
/// If this function encounters an "end of file" before completely filling
|
||||
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
|
||||
///
|
||||
/// If any other read error is encountered then this function immediately
|
||||
/// returns.
|
||||
///
|
||||
/// If this function returns an error, all bytes read will be appended to `cursor`.
|
||||
#[unstable(feature = "read_buf", issue = "78485")]
|
||||
fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> {
|
||||
while cursor.capacity() > 0 {
|
||||
|
@ -308,8 +308,7 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> {
|
||||
BacktraceStyle::Short
|
||||
}
|
||||
})
|
||||
.unwrap_or(if cfg!(target_os = "fuchsia") {
|
||||
// Fuchsia components default to full backtrace.
|
||||
.unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT {
|
||||
BacktraceStyle::Full
|
||||
} else {
|
||||
BacktraceStyle::Off
|
||||
|
@ -76,3 +76,12 @@ cfg_if::cfg_if! {
|
||||
pub mod c;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
// Fuchsia components default to full backtrace.
|
||||
if #[cfg(target_os = "fuchsia")] {
|
||||
pub const FULL_BACKTRACE_DEFAULT: bool = true;
|
||||
} else {
|
||||
pub const FULL_BACKTRACE_DEFAULT: bool = false;
|
||||
}
|
||||
}
|
||||
|
@ -278,13 +278,15 @@ impl<'test> TestCx<'test> {
|
||||
Incremental => {
|
||||
let revision =
|
||||
self.revision.expect("incremental tests require a list of revisions");
|
||||
if revision.starts_with("rpass") || revision.starts_with("rfail") {
|
||||
if revision.starts_with("cpass")
|
||||
|| revision.starts_with("rpass")
|
||||
|| revision.starts_with("rfail")
|
||||
{
|
||||
true
|
||||
} else if revision.starts_with("cfail") {
|
||||
// FIXME: would be nice if incremental revs could start with "cpass"
|
||||
pm.is_some()
|
||||
} else {
|
||||
panic!("revision name must begin with rpass, rfail, or cfail");
|
||||
panic!("revision name must begin with cpass, rpass, rfail, or cfail");
|
||||
}
|
||||
}
|
||||
mode => panic!("unimplemented for mode {:?}", mode),
|
||||
@ -384,6 +386,20 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
fn run_cpass_test(&self) {
|
||||
let emit_metadata = self.should_emit_metadata(self.pass_mode());
|
||||
let proc_res = self.compile_test(WillExecute::No, emit_metadata);
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
}
|
||||
|
||||
// FIXME(#41968): Move this check to tidy?
|
||||
if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
|
||||
self.fatal("compile-pass tests with expected warnings should be moved to ui/");
|
||||
}
|
||||
}
|
||||
|
||||
fn run_rpass_test(&self) {
|
||||
let emit_metadata = self.should_emit_metadata(self.pass_mode());
|
||||
let should_run = self.run_if_enabled();
|
||||
@ -393,17 +409,15 @@ impl<'test> TestCx<'test> {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
}
|
||||
|
||||
// FIXME(#41968): Move this check to tidy?
|
||||
if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
|
||||
self.fatal("run-pass tests with expected warnings should be moved to ui/");
|
||||
}
|
||||
|
||||
if let WillExecute::Disabled = should_run {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME(#41968): Move this check to tidy?
|
||||
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
|
||||
assert!(
|
||||
expected_errors.is_empty(),
|
||||
"run-pass tests with expected warnings should be moved to ui/"
|
||||
);
|
||||
|
||||
let proc_res = self.exec_compiled_test();
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("test run failed!", &proc_res);
|
||||
@ -2913,10 +2927,11 @@ impl<'test> TestCx<'test> {
|
||||
fn run_incremental_test(&self) {
|
||||
// Basic plan for a test incremental/foo/bar.rs:
|
||||
// - load list of revisions rpass1, cfail2, rpass3
|
||||
// - each should begin with `rpass`, `cfail`, or `rfail`
|
||||
// - if `rpass`, expect compile and execution to succeed
|
||||
// - each should begin with `cpass`, `rpass`, `cfail`, or `rfail`
|
||||
// - if `cpass`, expect compilation to succeed, don't execute
|
||||
// - if `rpass`, expect compilation and execution to succeed
|
||||
// - if `cfail`, expect compilation to fail
|
||||
// - if `rfail`, expect execution to fail
|
||||
// - if `rfail`, expect compilation to succeed and execution to fail
|
||||
// - create a directory build/foo/bar.incremental
|
||||
// - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
|
||||
// - because name of revision starts with "rpass", expect success
|
||||
@ -2940,7 +2955,12 @@ impl<'test> TestCx<'test> {
|
||||
print!("revision={:?} props={:#?}", revision, self.props);
|
||||
}
|
||||
|
||||
if revision.starts_with("rpass") {
|
||||
if revision.starts_with("cpass") {
|
||||
if self.props.should_ice {
|
||||
self.fatal("can only use should-ice in cfail tests");
|
||||
}
|
||||
self.run_cpass_test();
|
||||
} else if revision.starts_with("rpass") {
|
||||
if self.props.should_ice {
|
||||
self.fatal("can only use should-ice in cfail tests");
|
||||
}
|
||||
@ -2953,7 +2973,7 @@ impl<'test> TestCx<'test> {
|
||||
} else if revision.starts_with("cfail") {
|
||||
self.run_cfail_test();
|
||||
} else {
|
||||
self.fatal("revision name must begin with rpass, rfail, or cfail");
|
||||
self.fatal("revision name must begin with cpass, rpass, rfail, or cfail");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,6 @@ const EXCEPTION_PATHS: &[&str] = &[
|
||||
"library/std/src/path.rs",
|
||||
"library/std/src/sys_common", // Should only contain abstractions over platforms
|
||||
"library/std/src/net/test.rs", // Utility helpers for tests
|
||||
"library/std/src/panic.rs", // fuchsia-specific panic backtrace handling
|
||||
"library/std/src/personality.rs",
|
||||
"library/std/src/personality/",
|
||||
];
|
||||
|
10
tests/incremental/auxiliary/circular-dependencies-aux.rs
Normal file
10
tests/incremental/auxiliary/circular-dependencies-aux.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// edition: 2021
|
||||
// compile-flags: --crate-type lib --extern circular_dependencies={{build-base}}/circular-dependencies/libcircular_dependencies.rmeta --emit dep-info,metadata
|
||||
|
||||
use circular_dependencies::Foo;
|
||||
|
||||
pub fn consume_foo(_: Foo) {}
|
||||
|
||||
pub fn produce_foo() -> Foo {
|
||||
Foo
|
||||
}
|
37
tests/incremental/circular-dependencies.rs
Normal file
37
tests/incremental/circular-dependencies.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// ignore-tidy-linelength
|
||||
// revisions: cpass1 cfail2
|
||||
// edition: 2021
|
||||
// [cpass1] compile-flags: --crate-type lib --emit dep-info,metadata
|
||||
// [cfail2] aux-build: circular-dependencies-aux.rs
|
||||
// [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies
|
||||
|
||||
pub struct Foo;
|
||||
//[cfail2]~^ NOTE `Foo` is defined in the current crate
|
||||
//[cfail2]~| NOTE `Foo` is defined in the current crate
|
||||
//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
|
||||
//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
|
||||
|
||||
pub fn consume_foo(_: Foo) {}
|
||||
//[cfail2]~^ NOTE function defined here
|
||||
|
||||
pub fn produce_foo() -> Foo {
|
||||
Foo
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
aux::consume_foo(produce_foo());
|
||||
//[cfail2]~^ ERROR mismatched types [E0308]
|
||||
//[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo`
|
||||
//[cfail2]~| NOTE arguments to this function are incorrect
|
||||
//[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types
|
||||
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
|
||||
//[cfail2]~| NOTE function defined here
|
||||
|
||||
consume_foo(aux::produce_foo());
|
||||
//[cfail2]~^ ERROR mismatched types [E0308]
|
||||
//[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo`
|
||||
//[cfail2]~| NOTE arguments to this function are incorrect
|
||||
//[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types
|
||||
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// run-rustfix
|
||||
#![allow(unused, nonstandard_style)]
|
||||
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||
mod m {
|
||||
|
||||
mod p {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-rustfix
|
||||
#![allow(unused, nonstandard_style)]
|
||||
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||
mod m {
|
||||
|
||||
mod p {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-rustfix
|
||||
#![allow(unused, nonstandard_style)]
|
||||
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||
mod m {
|
||||
#[macro_export]
|
||||
macro_rules! nu {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-rustfix
|
||||
#![allow(unused, nonstandard_style)]
|
||||
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||
mod m {
|
||||
#[macro_export]
|
||||
macro_rules! nu {
|
||||
|
4
tests/ui/linkage-attr/issue-109144.rs
Normal file
4
tests/ui/linkage-attr/issue-109144.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#![crate_type = "lib"]
|
||||
#[link(kind = "static", modifiers = "+whole-archive,+bundle")]
|
||||
//~^ ERROR `#[link]` attribute requires a `name = "string"` argument
|
||||
extern {}
|
9
tests/ui/linkage-attr/issue-109144.stderr
Normal file
9
tests/ui/linkage-attr/issue-109144.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0459]: `#[link]` attribute requires a `name = "string"` argument
|
||||
--> $DIR/issue-109144.rs:2:1
|
||||
|
|
||||
LL | #[link(kind = "static", modifiers = "+whole-archive,+bundle")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0459`.
|
21
tests/ui/lint/anonymous-reexport.rs
Normal file
21
tests/ui/lint/anonymous-reexport.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![deny(useless_anonymous_reexport)]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
mod my_mod {
|
||||
pub trait Foo {}
|
||||
pub type TyFoo = dyn Foo;
|
||||
pub struct Bar;
|
||||
pub type TyBar = Bar;
|
||||
}
|
||||
|
||||
pub use self::my_mod::Foo as _;
|
||||
pub use self::my_mod::TyFoo as _;
|
||||
pub use self::my_mod::Bar as _; //~ ERROR
|
||||
pub use self::my_mod::TyBar as _; //~ ERROR
|
||||
pub use self::my_mod::{Bar as _}; //~ ERROR
|
||||
pub use self::my_mod::{Bar as _, Foo as _}; //~ ERROR
|
||||
pub use self::my_mod::{Bar as _, TyBar as _};
|
||||
//~^ ERROR
|
||||
//~| ERROR
|
||||
#[allow(unused_imports)]
|
||||
use self::my_mod::TyBar as _;
|
55
tests/ui/lint/anonymous-reexport.stderr
Normal file
55
tests/ui/lint/anonymous-reexport.stderr
Normal file
@ -0,0 +1,55 @@
|
||||
error: useless anonymous re-export
|
||||
--> $DIR/anonymous-reexport.rs:13:1
|
||||
|
|
||||
LL | pub use self::my_mod::Bar as _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||
note: the lint level is defined here
|
||||
--> $DIR/anonymous-reexport.rs:1:9
|
||||
|
|
||||
LL | #![deny(useless_anonymous_reexport)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: useless anonymous re-export
|
||||
--> $DIR/anonymous-reexport.rs:14:1
|
||||
|
|
||||
LL | pub use self::my_mod::TyBar as _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: only anonymous re-exports of traits are useful, this is a `type alias`
|
||||
|
||||
error: useless anonymous re-export
|
||||
--> $DIR/anonymous-reexport.rs:15:24
|
||||
|
|
||||
LL | pub use self::my_mod::{Bar as _};
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||
|
||||
error: useless anonymous re-export
|
||||
--> $DIR/anonymous-reexport.rs:16:24
|
||||
|
|
||||
LL | pub use self::my_mod::{Bar as _, Foo as _};
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||
|
||||
error: useless anonymous re-export
|
||||
--> $DIR/anonymous-reexport.rs:17:24
|
||||
|
|
||||
LL | pub use self::my_mod::{Bar as _, TyBar as _};
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||
|
||||
error: useless anonymous re-export
|
||||
--> $DIR/anonymous-reexport.rs:17:34
|
||||
|
|
||||
LL | pub use self::my_mod::{Bar as _, TyBar as _};
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: only anonymous re-exports of traits are useful, this is a `type alias`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
@ -0,0 +1,13 @@
|
||||
#![feature(staged_api)]
|
||||
#![stable(feature = "libfoo", since = "1.0.0")]
|
||||
|
||||
#[unstable(feature = "foo", reason = "...", issue = "none")]
|
||||
pub fn foo() {}
|
||||
|
||||
#[stable(feature = "libfoo", since = "1.0.0")]
|
||||
pub struct Foo;
|
||||
|
||||
impl Foo {
|
||||
#[unstable(feature = "foo", reason = "...", issue = "none")]
|
||||
pub fn foo(&self) {}
|
||||
}
|
13
tests/ui/stability-attribute/issue-109177.rs
Normal file
13
tests/ui/stability-attribute/issue-109177.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// aux-build: similar-unstable-method.rs
|
||||
|
||||
extern crate similar_unstable_method;
|
||||
|
||||
fn main() {
|
||||
// FIXME: this function should not suggest the `foo` function.
|
||||
similar_unstable_method::foo1();
|
||||
//~^ ERROR cannot find function `foo1` in crate `similar_unstable_method` [E0425]
|
||||
|
||||
let foo = similar_unstable_method::Foo;
|
||||
foo.foo1();
|
||||
//~^ ERROR no method named `foo1` found for struct `Foo` in the current scope [E0599]
|
||||
}
|
21
tests/ui/stability-attribute/issue-109177.stderr
Normal file
21
tests/ui/stability-attribute/issue-109177.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0425]: cannot find function `foo1` in crate `similar_unstable_method`
|
||||
--> $DIR/issue-109177.rs:7:30
|
||||
|
|
||||
LL | similar_unstable_method::foo1();
|
||||
| ^^^^ help: a function with a similar name exists: `foo`
|
||||
|
|
||||
::: $DIR/auxiliary/similar-unstable-method.rs:5:1
|
||||
|
|
||||
LL | pub fn foo() {}
|
||||
| ------------ similarly named function `foo` defined here
|
||||
|
||||
error[E0599]: no method named `foo1` found for struct `Foo` in the current scope
|
||||
--> $DIR/issue-109177.rs:11:9
|
||||
|
|
||||
LL | foo.foo1();
|
||||
| ^^^^ method not found in `Foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0425, E0599.
|
||||
For more information about an error, try `rustc --explain E0425`.
|
@ -228,5 +228,4 @@ fn evens_squared(n: usize) -> _ {
|
||||
|
||||
const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||
//~^ ERROR the trait bound
|
||||
//~| ERROR the trait bound
|
||||
//~| ERROR the placeholder
|
||||
|
@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ {
|
||||
| not allowed in type signatures
|
||||
| help: replace with an appropriate return type: `impl Iterator<Item = usize>`
|
||||
|
||||
error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied
|
||||
--> $DIR/typeck_type_placeholder_item.rs:229:22
|
||||
|
|
||||
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||
| ^^^^^^ `std::ops::Range<{integer}>` is not an iterator
|
||||
|
|
||||
= help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>`
|
||||
note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const`
|
||||
--> $DIR/typeck_type_placeholder_item.rs:229:14
|
||||
|
|
||||
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied
|
||||
--> $DIR/typeck_type_placeholder_item.rs:229:45
|
||||
|
|
||||
@ -677,7 +664,7 @@ LL | const D: _ = 42;
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct type: `i32`
|
||||
|
||||
error: aborting due to 73 previous errors
|
||||
error: aborting due to 72 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0121, E0277, E0282, E0403.
|
||||
For more information about an error, try `rustc --explain E0121`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user