Auto merge of #87242 - JohnTitor:rollup-t9rmwpo, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #86763 (Add a regression test for issue-63355) - #86814 (Recover from a misplaced inner doc comment) - #86843 (Check that const parameters of trait methods have compatible types) - #86889 (rustdoc: Cleanup ExternalCrate) - #87092 (Remove nondeterminism in multiple-definitions test) - #87170 (Add diagnostic items for Clippy) - #87183 (fix typo in compile_fail doctest) - #87205 (rustc_middle: remove redundant clone) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5a8a44196b
34 changed files with 352 additions and 101 deletions
|
@ -221,9 +221,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
sess,
|
||||
&codegen_results,
|
||||
outputs,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs);
|
||||
|
||||
Ok(())
|
||||
link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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::<B>(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path)
|
||||
.build();
|
||||
link_rlib::<B>(
|
||||
sess,
|
||||
codegen_results,
|
||||
RlibFlavor::Normal,
|
||||
&out_filename,
|
||||
&path,
|
||||
)?
|
||||
.build();
|
||||
}
|
||||
CrateType::Staticlib => {
|
||||
link_staticlib::<B>(sess, codegen_results, &out_filename, &path);
|
||||
link_staticlib::<B>(sess, codegen_results, &out_filename, &path)?;
|
||||
}
|
||||
_ => {
|
||||
link_natively::<B>(
|
||||
|
@ -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<B, ErrorReported> {
|
||||
info!("preparing rlib to {:?}", out_filename);
|
||||
let mut ab = <B as ArchiveBuilder>::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<DllImport>)> {
|
||||
let mut dylib_table: FxHashMap<String, FxHashSet<DllImport>> = FxHashMap::default();
|
||||
) -> Result<Vec<(String, Vec<DllImport>)>, ErrorReported> {
|
||||
// Use index maps to preserve original order of imports and libraries.
|
||||
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::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<DllImport>)> = 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::<Vec<_>>();
|
||||
result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
|
||||
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<Symbol, DllCallingConvention> = 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::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir);
|
||||
link_rlib::<B>(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 {
|
||||
|
|
|
@ -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]> {
|
||||
|
|
|
@ -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<Symbol>,
|
||||
|
@ -75,7 +75,7 @@ pub struct NativeLib {
|
|||
pub dll_imports: Vec<DllImport>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
|
||||
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
|
||||
pub struct DllImport {
|
||||
pub name: Symbol,
|
||||
pub ordinal: Option<u16>,
|
||||
|
@ -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),
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<Span>,
|
||||
) -> 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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue