diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8bb143ed3da8d..6a0d0ca55c255 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 7b58e55dbe84a..18d17b1a0137c 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -595,7 +595,7 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap, + pub name: Symbol, pub filename: Option, pub cfg: Option, pub verbatim: bool, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 8f31a79e7b393..b6d39341fe7cc 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -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(); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index de1a2e6a577bf..fd16363a1db01 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -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); } } }; diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 68e62c9789aed..c822237413c70 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -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}` diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b3578540516d0..c2cc2fcdf551a 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -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, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 308c02929ca42..46a025f41e04a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -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, +} diff --git a/compiler/rustc_lint/src/reexports.rs b/compiler/rustc_lint/src/reexports.rs new file mode 100644 index 0000000000000..8737a57ea0264 --- /dev/null +++ b/compiler/rustc_lint/src/reexports.rs @@ -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; + } + } + } + } + } +} diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index d6f68b2e14055..b855c8e433266 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -46,7 +46,7 @@ pub fn find_native_static_library( } fn find_bundled_library( - name: Option, + name: Symbol, verbatim: Option, 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(), }); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a98433953367b..98eae70b4b708 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -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` 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 } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c778574b2c57b..19745988c5919 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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 diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e71a1c9810249..6f20ac9e5275f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -356,6 +356,7 @@ define_tables! { inherent_impls: Table>, associated_items_for_impl_trait_in_trait: Table>, opt_rpitit_info: Table>>, + unused_generic_params: Table, - optional: attributes: Table>, @@ -398,7 +399,6 @@ define_tables! { trait_def: Table>, trait_item_def_id: Table, expn_that_defined: Table>, - unused_generic_params: Table>, params_in_repr: Table>>, repr_options: Table>, // `def_keys` and `def_path_hashes` represent a lazy version of a diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index b89d48ec15ae9..364fa74ab7b45 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -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` impl, but in the general case we might not need / want // to fit every `usize` in `u32`. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index f4028a5a9f63a..5fc98f01a5470 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -781,6 +781,12 @@ fn needs_fn_once_adapter_shim( #[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)] pub struct UnusedGenericParams(FiniteBitSet); +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)) + } } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 868ffdf0f1da0..a262c06d91f03 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -67,12 +67,11 @@ pub enum LinkagePreference { #[derive(Debug, Encodable, Decodable, HashStable_Generic)] pub struct NativeLib { pub kind: NativeLibKind, - pub name: Option, + pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option, pub cfg: Option, pub foreign_module: Option, - pub wasm_import_module: Option, pub verbatim: Option, pub dll_imports: Vec, } @@ -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 { + if self.kind == NativeLibKind::WasmImportModule { Some(self.name) } else { None } + } } /// Different ways that the PE Format can decorate a symbol name. diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index b996d36a318c5..3b3d4ca5d6b21 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -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, } } diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 78e27d73065aa..f19636fba5d95 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -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 { 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 { 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 { 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 RangeIteratorImpl for ops::Range { +impl const RangeIteratorImpl for ops::Range { type Item = A; #[inline] @@ -614,7 +624,7 @@ impl RangeIteratorImpl for ops::Range { } } -impl RangeIteratorImpl for ops::Range { +impl const RangeIteratorImpl for ops::Range { #[inline] fn spec_next(&mut self) -> Option { if self.start < self.end { @@ -702,7 +712,8 @@ impl RangeIteratorImpl for ops::Range { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for ops::Range { type Item = A; #[inline] @@ -812,7 +823,8 @@ range_incl_exact_iter_impl! { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { self.spec_next_back() diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index ed23873cdde7c..7a10dea500a96 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -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.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(&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(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

(&mut self, predicate: P) -> Option where Self: Sized, diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index d48760ab3ebfa..6fc86550b63e7 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -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 { + fn nth(&mut self, n: usize) -> Option + where + Self::Item: ~const Destruct, + { self.advance_by(n).ok()?; self.next() } diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index af02848233d99..c8f60defff771 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -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 {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 526232f44ee1e..1076d357070ef 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -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)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3b026bc0e0f38..529f62f4d6cd7 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -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 } }; diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index febe57dc90bc7..c4b89a6301965 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1003,22 +1003,25 @@ impl CoerceUnsized> for Pin

where P: CoerceUnsized {} #[stable(feature = "pin", since = "1.33.0")] impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} -/// Constructs a [Pin]<[&mut] T>, by pinning[^1] a `value: T` _locally_[^2]. +/// Constructs a [Pin]<[&mut] T>, 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, [Pin]<[&mut] T> behaves like [&mut] T, 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`], [Pin]<[&mut] T> behaves +/// like [&mut] T, 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 DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// /// If you really need to return a pinned value, consider using [`Box::pin`] instead. /// -/// On the other hand, pinning to the stack[2](#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 diff --git a/library/core/tests/iter/consts.rs b/library/core/tests/iter/consts.rs new file mode 100644 index 0000000000000..d56687e48c96a --- /dev/null +++ b/library/core/tests/iter/consts.rs @@ -0,0 +1,36 @@ +#[test] +fn const_manual_iter() { + struct S(bool); + + impl const Iterator for S { + type Item = (); + + fn next(&mut self) -> Option { + 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); + } +} diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 770b6f7601fa2..cbb18e79e2d43 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -20,6 +20,8 @@ mod range; mod sources; mod traits; +mod consts; + use core::cell::Cell; use core::convert::TryFrom; use core::iter::*; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index ccb7be68eb1b2..637cc6e9f629b 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -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)] diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index b2b6d86134b62..4b31c552eedd2 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -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 { diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 9fa8f5702a843..345d72ef8678e 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -308,8 +308,7 @@ pub fn get_backtrace_style() -> Option { 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 diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index c080c176a2ace..e767b2866cb9b 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -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; + } +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a127875b55d5f..4d9010d3c4b30 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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"); } } diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 868579b4b1a8c..6b7b27fd526c3 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -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/", ]; diff --git a/tests/incremental/auxiliary/circular-dependencies-aux.rs b/tests/incremental/auxiliary/circular-dependencies-aux.rs new file mode 100644 index 0000000000000..0e74eb1b2f263 --- /dev/null +++ b/tests/incremental/auxiliary/circular-dependencies-aux.rs @@ -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 +} diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs new file mode 100644 index 0000000000000..10673066a9df0 --- /dev/null +++ b/tests/incremental/circular-dependencies.rs @@ -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 +} diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed index 0e60c73b67a44..0f688fa282356 100644 --- a/tests/ui/imports/issue-99695-b.fixed +++ b/tests/ui/imports/issue-99695-b.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { mod p { diff --git a/tests/ui/imports/issue-99695-b.rs b/tests/ui/imports/issue-99695-b.rs index 031443a1f5df8..b433997e53f6a 100644 --- a/tests/ui/imports/issue-99695-b.rs +++ b/tests/ui/imports/issue-99695-b.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { mod p { diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.fixed index 6bf228b23aad2..17ff409324e34 100644 --- a/tests/ui/imports/issue-99695.fixed +++ b/tests/ui/imports/issue-99695.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { #[macro_export] macro_rules! nu { diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs index f7199f1497ab0..b8979bcb7345c 100644 --- a/tests/ui/imports/issue-99695.rs +++ b/tests/ui/imports/issue-99695.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(unused, nonstandard_style)] +#![allow(unused, nonstandard_style, useless_anonymous_reexport)] mod m { #[macro_export] macro_rules! nu { diff --git a/tests/ui/linkage-attr/issue-109144.rs b/tests/ui/linkage-attr/issue-109144.rs new file mode 100644 index 0000000000000..2f740e5538973 --- /dev/null +++ b/tests/ui/linkage-attr/issue-109144.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] +#[link(kind = "static", modifiers = "+whole-archive,+bundle")] +//~^ ERROR `#[link]` attribute requires a `name = "string"` argument +extern {} diff --git a/tests/ui/linkage-attr/issue-109144.stderr b/tests/ui/linkage-attr/issue-109144.stderr new file mode 100644 index 0000000000000..33187cfdbb636 --- /dev/null +++ b/tests/ui/linkage-attr/issue-109144.stderr @@ -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`. diff --git a/tests/ui/lint/anonymous-reexport.rs b/tests/ui/lint/anonymous-reexport.rs new file mode 100644 index 0000000000000..5d56ae6f969b5 --- /dev/null +++ b/tests/ui/lint/anonymous-reexport.rs @@ -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 _; diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr new file mode 100644 index 0000000000000..f4f8b41c417a4 --- /dev/null +++ b/tests/ui/lint/anonymous-reexport.stderr @@ -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 + diff --git a/tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs b/tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs new file mode 100644 index 0000000000000..8804186ee1a6b --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/similar-unstable-method.rs @@ -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) {} +} diff --git a/tests/ui/stability-attribute/issue-109177.rs b/tests/ui/stability-attribute/issue-109177.rs new file mode 100644 index 0000000000000..6d052779c6d36 --- /dev/null +++ b/tests/ui/stability-attribute/issue-109177.rs @@ -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] +} diff --git a/tests/ui/stability-attribute/issue-109177.stderr b/tests/ui/stability-attribute/issue-109177.stderr new file mode 100644 index 0000000000000..9c2ac591ace05 --- /dev/null +++ b/tests/ui/stability-attribute/issue-109177.stderr @@ -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`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index a450dbb82d1bd..e6f7dc410b614 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -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 diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index bc6c9fd077993..9144ab9e3a6bd 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ { | not allowed in type signatures | help: replace with an appropriate return type: `impl Iterator` -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, [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`.