diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index cb1cb3c74dbb5..e32dae49131ab 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -221,9 +221,7 @@ impl CodegenBackend for CraneliftCodegenBackend { sess, &codegen_results, outputs, - ); - - Ok(()) + ) } } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 26fd1cfbcd08e..aa4db1622b233 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -292,9 +292,7 @@ impl CodegenBackend for LlvmCodegenBackend { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary::>(sess, &codegen_results, outputs); - - Ok(()) + link_binary::>(sess, &codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f9efa448c93fa..773a1c500b2f6 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,9 +1,9 @@ -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::Handler; +use rustc_errors::{ErrorReported, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; -use rustc_middle::middle::cstore::{DllCallingConvention, DllImport}; +use rustc_middle::middle::cstore::DllImport; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; @@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se use tempfile::Builder as TempFileBuilder; use std::ffi::OsString; -use std::iter::FromIterator; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{ascii, char, env, fmt, fs, io, mem, str}; @@ -54,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( sess: &'a Session, codegen_results: &CodegenResults, outputs: &OutputFilenames, -) { +) -> Result<(), ErrorReported> { let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); for &crate_type in sess.crate_types().iter() { @@ -95,11 +94,17 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); - link_rlib::(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path) - .build(); + link_rlib::( + sess, + codegen_results, + RlibFlavor::Normal, + &out_filename, + &path, + )? + .build(); } CrateType::Staticlib => { - link_staticlib::(sess, codegen_results, &out_filename, &path); + link_staticlib::(sess, codegen_results, &out_filename, &path)?; } _ => { link_natively::( @@ -145,6 +150,8 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( } } }); + + Ok(()) } pub fn each_linked_rlib( @@ -220,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( flavor: RlibFlavor, out_filename: &Path, tmpdir: &MaybeTempDir, -) -> B { +) -> Result { info!("preparing rlib to {:?}", out_filename); let mut ab = ::new(sess, out_filename, None); @@ -259,7 +266,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( } for (raw_dylib_name, raw_dylib_imports) in - collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries) + collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? { ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir); } @@ -312,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( } } } - return ab; + return Ok(ab); // For rlibs we "pack" rustc metadata into a dummy object file. When rustc // creates a dylib crate type it will pass `--whole-archive` (or the @@ -454,65 +461,40 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( fn collate_raw_dylibs( sess: &Session, used_libraries: &[NativeLib], -) -> Vec<(String, Vec)> { - let mut dylib_table: FxHashMap> = FxHashMap::default(); +) -> Result)>, ErrorReported> { + // Use index maps to preserve original order of imports and libraries. + let mut dylib_table = FxIndexMap::>::default(); for lib in used_libraries { if lib.kind == NativeLibKind::RawDylib { - let name = lib.name.unwrap_or_else(|| - bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier") - ); - let name = if matches!(lib.verbatim, Some(true)) { - name.to_string() - } else { - format!("{}.dll", name) - }; - dylib_table.entry(name).or_default().extend(lib.dll_imports.iter().cloned()); - } - } - - // Rustc already signals an error if we have two imports with the same name but different - // calling conventions (or function signatures), so we don't have pay attention to those - // when ordering. - // FIXME: when we add support for ordinals, figure out if we need to do anything if we - // have two DllImport values with the same name but different ordinals. - let mut result: Vec<(String, Vec)> = dylib_table - .into_iter() - .map(|(lib_name, import_table)| { - let mut imports = Vec::from_iter(import_table.into_iter()); - imports.sort_unstable_by_key(|x: &DllImport| x.name.as_str()); - (lib_name, imports) - }) - .collect::>(); - result.sort_unstable_by(|a: &(String, Vec), b: &(String, Vec)| { - a.0.cmp(&b.0) - }); - let result = result; - - // Check for multiple imports with the same name but different calling conventions or - // (when relevant) argument list sizes. Rustc only signals an error for this if the - // declarations are at the same scope level; if one shadows the other, we only get a lint - // warning. - for (library, imports) in &result { - let mut import_table: FxHashMap = FxHashMap::default(); - for import in imports { - if let Some(old_convention) = - import_table.insert(import.name, import.calling_convention) - { - if import.calling_convention != old_convention { - sess.span_fatal( - import.span, - &format!( - "multiple definitions of external function `{}` from library `{}` have different calling conventions", - import.name, - library, - )); + let ext = if matches!(lib.verbatim, Some(true)) { "" } else { ".dll" }; + let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), 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) { + // FIXME: when we add support for ordinals, figure out if we need to do anything + // if we have two DllImport values with the same name but different ordinals. + if import.calling_convention != old_import.calling_convention { + sess.span_err( + import.span, + &format!( + "multiple declarations of external function `{}` from \ + library `{}` have different calling conventions", + import.name, name, + ), + ); + } } } } } - - result + sess.compile_status()?; + Ok(dylib_table + .into_iter() + .map(|(name, imports)| { + (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) + }) + .collect()) } /// Create a static archive. @@ -531,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( codegen_results: &CodegenResults, out_filename: &Path, tempdir: &MaybeTempDir, -) { +) -> Result<(), ErrorReported> { let mut ab = - link_rlib::(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir); + link_rlib::(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?; let mut all_native_libs = vec![]; let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { @@ -581,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( print_native_static_libs(sess, &all_native_libs); } } + + Ok(()) } fn escape_stdout_stderr_string(s: &[u8]) -> String { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6877d6ef542c7..a4913a32e81ef 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1581,7 +1581,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> { empty_proc_macro!(self); let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); - self.lazy(used_libraries.iter().cloned()) + self.lazy(used_libraries.iter()) } fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index 4c35b49bcefd7..8150e67929509 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -64,7 +64,7 @@ pub enum LinkagePreference { RequireStatic, } -#[derive(Clone, Debug, Encodable, Decodable, HashStable)] +#[derive(Debug, Encodable, Decodable, HashStable)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, @@ -75,7 +75,7 @@ pub struct NativeLib { pub dll_imports: Vec, } -#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)] +#[derive(Clone, Debug, Encodable, Decodable, HashStable)] pub struct DllImport { pub name: Symbol, pub ordinal: Option, @@ -92,7 +92,7 @@ pub struct DllImport { /// /// The usize value, where present, indicates the size of the function's argument list /// in bytes. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)] +#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable)] pub enum DllCallingConvention { C, Stdcall(usize), diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index b0156daf17eff..6b51adc6aafdd 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -281,11 +281,10 @@ pub struct CaptureInfo<'tcx> { } pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { - let name = match place.base { + let mut curr_string: String = match place.base { HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), }; - let mut curr_string = name; for (i, proj) in place.projections.iter().enumerate() { match proj.kind { @@ -314,7 +313,7 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> } } - curr_string.to_string() + curr_string } #[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)] diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 8b050389078a6..e9f0038b2d65d 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -64,7 +64,14 @@ impl<'a> Parser<'a> { } self.bump(); just_parsed_doc_comment = true; - Some(attr::mk_doc_comment(comment_kind, attr_style, data, self.prev_token.span)) + // Always make an outer attribute - this allows us to recover from a misplaced + // inner attribute. + Some(attr::mk_doc_comment( + comment_kind, + ast::AttrStyle::Outer, + data, + self.prev_token.span, + )) } else { None }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 07f22159f96c8..a8f969782b22d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -122,10 +122,14 @@ symbols! { // nice to have. Symbols { Alignment, + Any, Arc, Argument, ArgumentV1, Arguments, + AsMut, + AsRef, + BTreeEntry, BTreeMap, BTreeSet, BinaryHeap, @@ -139,6 +143,7 @@ symbols! { Continue, Copy, Count, + Cow, Debug, DebugStruct, DebugTuple, @@ -146,12 +151,17 @@ symbols! { Decoder, Default, Deref, + DirBuilder, + DoubleEndedIterator, + Duration, Encodable, Encoder, Eq, Equal, Err, Error, + File, + FileType, FormatSpec, Formatter, From, @@ -162,11 +172,14 @@ symbols! { GlobalAlloc, Hash, HashMap, + HashMapEntry, HashSet, Hasher, Implied, Input, IntoIterator, + IoRead, + IoWrite, Is, ItemContext, Iterator, @@ -369,6 +382,8 @@ symbols! { closure, closure_to_fn_coercion, cmp, + cmp_max, + cmp_min, cmpxchg16b_target_feature, cmse_nonsecure_entry, coerce_unsized, @@ -674,6 +689,7 @@ symbols! { item, item_like_imports, iter, + iter_repeat, keyword, kind, kreg, @@ -740,6 +756,12 @@ symbols! { maybe_uninit, maybe_uninit_uninit, maybe_uninit_zeroed, + mem_discriminant, + mem_drop, + mem_forget, + mem_replace, + mem_size_of, + mem_size_of_val, mem_uninitialized, mem_zeroed, member_constraints, diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 12d0c14a3d51a..d35868881558e 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -66,6 +66,10 @@ crate fn compare_impl_method<'tcx>( { return; } + + if let Err(ErrorReported) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) { + return; + } } fn compare_predicate_entailment<'tcx>( @@ -929,6 +933,68 @@ fn compare_synthetic_generics<'tcx>( if error_found { Err(ErrorReported) } else { Ok(()) } } +fn compare_const_param_types<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: &ty::AssocItem, + trait_m: &ty::AssocItem, + trait_item_span: Option, +) -> Result<(), ErrorReported> { + let const_params_of = |def_id| { + tcx.generics_of(def_id).params.iter().filter_map(|param| match param.kind { + GenericParamDefKind::Const { .. } => Some(param.def_id), + _ => None, + }) + }; + let const_params_impl = const_params_of(impl_m.def_id); + let const_params_trait = const_params_of(trait_m.def_id); + + for (const_param_impl, const_param_trait) in iter::zip(const_params_impl, const_params_trait) { + let impl_ty = tcx.type_of(const_param_impl); + let trait_ty = tcx.type_of(const_param_trait); + if impl_ty != trait_ty { + let (impl_span, impl_ident) = match tcx.hir().get_if_local(const_param_impl) { + Some(hir::Node::GenericParam(hir::GenericParam { span, name, .. })) => ( + span, + match name { + hir::ParamName::Plain(ident) => Some(ident), + _ => None, + }, + ), + other => bug!( + "expected GenericParam, found {:?}", + other.map_or_else(|| "nothing".to_string(), |n| format!("{:?}", n)) + ), + }; + let trait_span = match tcx.hir().get_if_local(const_param_trait) { + Some(hir::Node::GenericParam(hir::GenericParam { span, .. })) => Some(span), + _ => None, + }; + let mut err = struct_span_err!( + tcx.sess, + *impl_span, + E0053, + "method `{}` has an incompatible const parameter type for trait", + trait_m.ident + ); + err.span_note( + trait_span.map_or_else(|| trait_item_span.unwrap_or(*impl_span), |span| *span), + &format!( + "the const parameter{} has type `{}`, but the declaration \ + in trait `{}` has type `{}`", + &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)), + impl_ty, + tcx.def_path_str(trait_m.def_id), + trait_ty + ), + ); + err.emit(); + return Err(ErrorReported); + } + } + + Ok(()) +} + crate fn compare_const_impl<'tcx>( tcx: TyCtxt<'tcx>, impl_c: &ty::AssocItem, diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 9d61b3684b82c..482a497201de6 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -177,6 +177,7 @@ where /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")] pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned, diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 6b30d95977395..5fec8dc2d1334 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -14,6 +14,7 @@ use Entry::*; /// /// [`entry`]: BTreeMap::entry #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeEntry")] pub enum Entry<'a, K: 'a, V: 'a> { /// A vacant entry. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 5e1725cfc7a63..19652106b3d01 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -108,6 +108,7 @@ use crate::intrinsics; // unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, // but we would likely want to indicate as such in documentation). #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Any")] pub trait Any: 'static { /// Gets the `TypeId` of `self`. /// diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 879deed3bed5e..79610bb409d37 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1104,6 +1104,7 @@ pub macro PartialOrd($item:item) { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")] pub fn min(v1: T, v2: T) -> T { v1.min(v2) } @@ -1166,6 +1167,7 @@ pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")] pub fn max(v1: T, v2: T) -> T { v1.max(v2) } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 65af8508a6839..1e512af48051e 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -152,6 +152,7 @@ pub const fn identity(x: T) -> T { /// is_hello(s); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")] pub trait AsRef { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] @@ -193,6 +194,7 @@ pub trait AsRef { /// /// [`Box`]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] pub trait AsMut { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index a9478041c69c4..733142ed01103 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -51,6 +51,7 @@ use crate::iter::{FusedIterator, TrustedLen}; /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "iter_repeat")] pub fn repeat(elt: T) -> Repeat { Repeat { element: elt } } diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 6d3ab788e5f48..9a9cf20077096 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -36,6 +36,7 @@ use crate::ops::{ControlFlow, Try}; /// assert_eq!(None, iter.next_back()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")] pub trait DoubleEndedIterator: Iterator { /// Removes and returns an element from the end of the iterator. /// diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 5bf47c3951da2..2c75de39ffa2f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -140,6 +140,7 @@ pub use crate::intrinsics::transmute; #[inline] #[rustc_const_stable(feature = "const_forget", since = "1.46.0")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_forget")] pub const fn forget(t: T) { let _ = ManuallyDrop::new(t); } @@ -298,6 +299,7 @@ pub fn forget_unsized(t: T) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_size_of", since = "1.24.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")] pub const fn size_of() -> usize { intrinsics::size_of::() } @@ -324,6 +326,7 @@ pub const fn size_of() -> usize { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] pub const fn size_of_val(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer unsafe { intrinsics::size_of_val(val) } @@ -814,6 +817,7 @@ pub fn take(dest: &mut T) -> T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { // SAFETY: We read from `dest` but directly write `src` into it afterwards, // such that the old value is not duplicated. Nothing is dropped and @@ -888,6 +892,7 @@ pub const fn replace(dest: &mut T, src: T) -> T { /// [`RefCell`]: crate::cell::RefCell #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_drop")] pub fn drop(_x: T) {} /// Interprets `src` as having type `&U`, and then reads `src` without moving @@ -1015,6 +1020,7 @@ impl fmt::Debug for Discriminant { /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")] pub const fn discriminant(v: &T) -> Discriminant { Discriminant(intrinsics::discriminant_value(v)) } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index b7af3ea8c1af4..c27db0767ac9d 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -356,7 +356,7 @@ //! // must have the same concrete type. //! fn make_iter(do_insert: bool) -> impl Iterator { //! // Explicit returns to illustrate return types not matching -//! match x { +//! match do_insert { //! true => return (0..4).chain(once(42)).chain(4..8), //! false => return (0..4).chain(empty()).chain(4..8), //! } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 92a4e60391894..2d8a1cb1ab016 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -61,6 +61,7 @@ const MICROS_PER_SEC: u64 = 1_000_000; /// crate to do so. #[stable(feature = "duration", since = "1.3.0")] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(not(test), rustc_diagnostic_item = "Duration")] pub struct Duration { secs: u64, nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index d7cb8a556367c..fac285c96f00d 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1829,6 +1829,7 @@ impl Debug for RawEntryBuilder<'_, K, V, S> { /// /// [`entry`]: HashMap::entry #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "HashMapEntry")] pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied entry. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index fb928ea55985f..bbe1ab40537f2 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -88,6 +88,7 @@ use crate::time::SystemTime; /// [`BufReader`]: io::BufReader /// [`sync_all`]: File::sync_all #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "File")] pub struct File { inner: fs_imp::File, } @@ -183,12 +184,14 @@ pub struct Permissions(fs_imp::FilePermissions); /// It is returned by [`Metadata::file_type`] method. #[stable(feature = "file_type", since = "1.1.0")] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[cfg_attr(not(test), rustc_diagnostic_item = "FileType")] pub struct FileType(fs_imp::FileType); /// A builder used to create directories in various manners. /// /// This builder also supports platform-specific options. #[stable(feature = "dir_builder", since = "1.6.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "DirBuilder")] #[derive(Debug)] pub struct DirBuilder { inner: fs_imp::DirBuilder, diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index ad8975c03f175..cc615b95f8625 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -514,6 +514,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ /// [`File`]: crate::fs::File #[stable(feature = "rust1", since = "1.0.0")] #[doc(notable_trait)] +#[cfg_attr(not(test), rustc_diagnostic_item = "IoRead")] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -1361,6 +1362,7 @@ impl Initializer { /// [`write_all`]: Write::write_all #[stable(feature = "rust1", since = "1.0.0")] #[doc(notable_trait)] +#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")] pub trait Write { /// Write a buffer into this writer, returning how many bytes were written. /// diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 80aaae1580114..1a2852dc6c724 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -14,7 +14,7 @@ use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::middle::resolve_lifetime as rl; @@ -85,12 +85,6 @@ impl, U> Clean> for Option { } } -impl Clean for CrateNum { - fn clean(&self, _cx: &mut DocContext<'_>) -> ExternalCrate { - ExternalCrate { crate_num: *self } - } -} - impl Clean for doctree::Module<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let mut items: Vec = vec![]; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 859746b6a2df7..2fd2d14bcabc3 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -118,7 +118,7 @@ crate struct Crate { crate name: Symbol, crate src: FileName, crate module: Item, - crate externs: Vec<(CrateNum, ExternalCrate)>, + crate externs: Vec, crate primitives: ThinVec<(DefId, PrimitiveType)>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. @@ -133,14 +133,14 @@ crate struct TraitWithExtraInfo { crate is_notable: bool, } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] crate struct ExternalCrate { crate crate_num: CrateNum, } impl ExternalCrate { #[inline] - fn def_id(&self) -> DefId { + crate fn def_id(&self) -> DefId { DefId { krate: self.crate_num, index: CRATE_DEF_INDEX } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index dea016a467d64..bdd5350aab2cb 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -1,9 +1,9 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ - inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, - Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, - Visibility, + inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, + ItemKind, Lifetime, Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, + TypeBinding, Visibility, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -35,11 +35,11 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { let mut externs = Vec::new(); for &cnum in cx.tcx.crates(()).iter() { - externs.push((cnum, cnum.clean(cx))); + externs.push(ExternalCrate { crate_num: cnum }); // Analyze doc-reachability for extern items LibEmbargoVisitor::new(cx).visit_lib(cnum); } - externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); + externs.sort_unstable_by_key(|e| e.crate_num); // Clean the crate, translating the entire librustc_ast AST to one that is // understood by rustdoc. @@ -61,7 +61,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { _ => unreachable!(), } - let local_crate = LOCAL_CRATE.clean(cx); + let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; let src = local_crate.src(cx.tcx); let name = local_crate.name(cx.tcx); let primitives = local_crate.primitives(cx.tcx); diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index e7d6e5ac2c24b..5ea2cdc2ad909 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -151,19 +151,18 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code - for &(n, ref e) in &krate.externs { + for &e in &krate.externs { let name = e.name(tcx); let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u); - let did = DefId { krate: n, index: CRATE_DEF_INDEX }; - self.extern_locations.insert(n, e.location(extern_url, &dst, tcx)); - self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module)); + self.extern_locations.insert(e.crate_num, e.location(extern_url, &dst, tcx)); + self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module)); } // Cache where all known primitives have their documentation located. // // Favor linking to as local extern as possible, so iterate all crates in // reverse topological order. - for &(_, ref e) in krate.externs.iter().rev() { + for &e in krate.externs.iter().rev() { for &(def_id, prim) in &e.primitives(tcx) { self.primitive_locations.insert(prim, def_id); } diff --git a/src/test/ui/const-generics/issue-86820.rs b/src/test/ui/const-generics/issue-86820.rs new file mode 100644 index 0000000000000..04650403c6baf --- /dev/null +++ b/src/test/ui/const-generics/issue-86820.rs @@ -0,0 +1,25 @@ +// Regression test for the ICE described in #86820. + +#![allow(unused,dead_code)] +use std::ops::BitAnd; + +const C: fn() = || is_set(); +fn is_set() { + 0xffu8.bit::<0>(); +} + +trait Bits { + fn bit(self) -> bool; + //~^ NOTE: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8` +} + +impl Bits for u8 { + fn bit(self) -> bool { + //~^ ERROR: method `bit` has an incompatible const parameter type for trait [E0053] + let i = 1 << I; + let mask = u8::from(i); + mask & self == mask + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issue-86820.stderr b/src/test/ui/const-generics/issue-86820.stderr new file mode 100644 index 0000000000000..f4396f2f2b0a2 --- /dev/null +++ b/src/test/ui/const-generics/issue-86820.stderr @@ -0,0 +1,15 @@ +error[E0053]: method `bit` has an incompatible const parameter type for trait + --> $DIR/issue-86820.rs:17:18 + | +LL | fn bit(self) -> bool { + | ^ + | +note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8` + --> $DIR/issue-86820.rs:12:18 + | +LL | fn bit(self) -> bool; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs new file mode 100644 index 0000000000000..8be1ae77738e9 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -0,0 +1,11 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +//! Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr new file mode 100644 index 0000000000000..0b2e612ee5bb9 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr @@ -0,0 +1,11 @@ +error[E0753]: expected outer doc comment + --> $DIR/issue-86781-bad-inner-doc.rs:6:1 + | +LL | //! Inner doc comment + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0753`. diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs new file mode 100644 index 0000000000000..d02bebc9d61d2 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs @@ -0,0 +1,19 @@ +// only-i686-pc-windows-msvc +// compile-flags: --crate-type lib --emit link +#![allow(clashing_extern_declarations)] +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete +#[link(name = "foo", kind = "raw-dylib")] +extern "C" { + fn f(x: i32); +} + +pub fn lib_main() { + #[link(name = "foo", kind = "raw-dylib")] + extern "stdcall" { + fn f(x: i32); + //~^ ERROR multiple declarations of external function `f` from library `foo.dll` have different calling conventions + } + + unsafe { f(42); } +} diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr new file mode 100644 index 0000000000000..a9cfd6b23f9f8 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr @@ -0,0 +1,17 @@ +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multiple-declarations.rs:4:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information + +error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions + --> $DIR/multiple-declarations.rs:14:9 + | +LL | fn f(x: i32); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs new file mode 100644 index 0000000000000..8762d189c7389 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63355.rs @@ -0,0 +1,50 @@ +#![feature(min_type_alias_impl_trait)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +pub trait Foo {} + +pub trait Bar { + type Foo: Foo; + + fn foo() -> Self::Foo; +} + +pub trait Baz { + type Foo: Foo; + type Bar: Bar; + + fn foo() -> Self::Foo; + fn bar() -> Self::Bar; +} + +impl Foo for () {} + +impl Bar for () { + type Foo = FooImpl; + + fn foo() -> Self::Foo { + () + } +} + +// FIXME(#86731): The below is illegal use of `min_type_alias_impl_trait` +// but the compiler doesn't report it, we should fix it. +pub type FooImpl = impl Foo; +pub type BarImpl = impl Bar; +//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()` + +impl Baz for () { + type Foo = FooImpl; + type Bar = BarImpl; + + fn foo() -> Self::Foo { + () + } + + fn bar() -> Self::Bar { + () + } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr new file mode 100644 index 0000000000000..dc5370a2666b7 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63355.stderr @@ -0,0 +1,14 @@ +error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()` + --> $DIR/issue-63355.rs:34:20 + | +LL | pub type FooImpl = impl Foo; + | -------- the found opaque type +LL | pub type BarImpl = impl Bar; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type + | + = note: expected unit type `()` + found opaque type `impl Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`.