Auto merge of #146350 - cuviper:beta-next, r=cuviper
[beta] backports - Rust build fails on OpenBSD after using file_lock feature rust-lang/rust#145511 - Revert suggestions for missing methods in tuples rust-lang/rust#145765 - When determining if a trait has no entries for the purposes of omitting vptrs from subtrait vtables, consider its transitive supertraits' entries, instead of just its own entries. rust-lang/rust#145807 - Ship LLVM tools for the correct target when cross-compiling rust-lang/rust#145763 - bootstrap: vendor `clippy_test_deps` too rust-lang/rust#145861 r? cuviper
This commit is contained in:
commit
1c785abde7
18 changed files with 373 additions and 258 deletions
|
|
@ -13,9 +13,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagStyledString, MultiSpan, StashKey, pluralize, struct_span_code_err,
|
||||
};
|
||||
use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -1572,11 +1570,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh()
|
||||
|| restrict_type_params
|
||||
|| suggested_derive
|
||||
|| self.lookup_alternative_tuple_impls(&mut err, &unsatisfied_predicates)
|
||||
{
|
||||
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
|
||||
} else {
|
||||
self.suggest_traits_to_import(
|
||||
&mut err,
|
||||
|
|
@ -1753,119 +1747,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.emit()
|
||||
}
|
||||
|
||||
/// If the predicate failure is caused by an unmet bound on a tuple, recheck if the bound would
|
||||
/// succeed if all the types on the tuple had no borrows. This is a common problem for libraries
|
||||
/// like Bevy and ORMs, which rely heavily on traits being implemented on tuples.
|
||||
fn lookup_alternative_tuple_impls(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
unsatisfied_predicates: &[(
|
||||
ty::Predicate<'tcx>,
|
||||
Option<ty::Predicate<'tcx>>,
|
||||
Option<ObligationCause<'tcx>>,
|
||||
)],
|
||||
) -> bool {
|
||||
let mut found_tuple = false;
|
||||
for (pred, root, _ob) in unsatisfied_predicates {
|
||||
let mut preds = vec![pred];
|
||||
if let Some(root) = root {
|
||||
// We will look at both the current predicate and the root predicate that caused it
|
||||
// to be needed. If calling something like `<(A, &B)>::default()`, then `pred` is
|
||||
// `&B: Default` and `root` is `(A, &B): Default`, which is the one we are checking
|
||||
// for further down, so we check both.
|
||||
preds.push(root);
|
||||
}
|
||||
for pred in preds {
|
||||
if let Some(clause) = pred.as_clause()
|
||||
&& let Some(clause) = clause.as_trait_clause()
|
||||
&& let ty = clause.self_ty().skip_binder()
|
||||
&& let ty::Tuple(types) = ty.kind()
|
||||
{
|
||||
let path = clause.skip_binder().trait_ref.print_only_trait_path();
|
||||
let def_id = clause.def_id();
|
||||
let ty = Ty::new_tup(
|
||||
self.tcx,
|
||||
self.tcx.mk_type_list_from_iter(types.iter().map(|ty| ty.peel_refs())),
|
||||
);
|
||||
let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| {
|
||||
if param.index == 0 {
|
||||
ty.into()
|
||||
} else {
|
||||
self.infcx.var_for_def(DUMMY_SP, param)
|
||||
}
|
||||
});
|
||||
if self
|
||||
.infcx
|
||||
.type_implements_trait(def_id, args, self.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
// "`Trait` is implemented for `(A, B)` but not for `(A, &B)`"
|
||||
let mut msg = DiagStyledString::normal(format!("`{path}` "));
|
||||
msg.push_highlighted("is");
|
||||
msg.push_normal(" implemented for `(");
|
||||
let len = types.len();
|
||||
for (i, t) in types.iter().enumerate() {
|
||||
msg.push(
|
||||
format!("{}", with_forced_trimmed_paths!(t.peel_refs())),
|
||||
t.peel_refs() != t,
|
||||
);
|
||||
if i < len - 1 {
|
||||
msg.push_normal(", ");
|
||||
}
|
||||
}
|
||||
msg.push_normal(")` but ");
|
||||
msg.push_highlighted("not");
|
||||
msg.push_normal(" for `(");
|
||||
for (i, t) in types.iter().enumerate() {
|
||||
msg.push(
|
||||
format!("{}", with_forced_trimmed_paths!(t)),
|
||||
t.peel_refs() != t,
|
||||
);
|
||||
if i < len - 1 {
|
||||
msg.push_normal(", ");
|
||||
}
|
||||
}
|
||||
msg.push_normal(")`");
|
||||
|
||||
// Find the span corresponding to the impl that was found to point at it.
|
||||
if let Some(impl_span) = self
|
||||
.tcx
|
||||
.all_impls(def_id)
|
||||
.filter(|&impl_def_id| {
|
||||
let header = self.tcx.impl_trait_header(impl_def_id).unwrap();
|
||||
let trait_ref = header.trait_ref.instantiate(
|
||||
self.tcx,
|
||||
self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
|
||||
);
|
||||
|
||||
let value = ty::fold_regions(self.tcx, ty, |_, _| {
|
||||
self.tcx.lifetimes.re_erased
|
||||
});
|
||||
// FIXME: Don't bother dealing with non-lifetime binders here...
|
||||
if value.has_escaping_bound_vars() {
|
||||
return false;
|
||||
}
|
||||
self.infcx.can_eq(ty::ParamEnv::empty(), trait_ref.self_ty(), value)
|
||||
&& header.polarity == ty::ImplPolarity::Positive
|
||||
})
|
||||
.map(|impl_def_id| self.tcx.def_span(impl_def_id))
|
||||
.next()
|
||||
{
|
||||
err.highlighted_span_note(impl_span, msg.0);
|
||||
} else {
|
||||
err.highlighted_note(msg.0);
|
||||
}
|
||||
found_tuple = true;
|
||||
}
|
||||
// If `pred` was already on the tuple, we don't need to look at the root
|
||||
// obligation too.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
found_tuple
|
||||
}
|
||||
|
||||
/// If an appropriate error source is not found, check method chain for possible candidates
|
||||
fn lookup_segments_chain_for_no_match_method(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -153,7 +153,12 @@ fn prepare_vtable_segments_inner<'tcx, T>(
|
|||
|
||||
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
|
||||
while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
|
||||
let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id);
|
||||
// We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a
|
||||
// vptr for supertraits that have no methods, but that themselves have supertraits
|
||||
// with methods, so we check if any transitive supertrait has entries here (this includes
|
||||
// the trait itself).
|
||||
let has_entries = ty::elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id)
|
||||
.any(|def_id| has_own_existential_vtable_entries(tcx, def_id));
|
||||
|
||||
segment_visitor(VtblSegment::TraitOwnEntries {
|
||||
trait_ref: inner_most_trait_ref,
|
||||
|
|
|
|||
|
|
@ -1263,6 +1263,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
|
|
@ -1275,6 +1276,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
)))]
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
|
|
@ -1286,6 +1288,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
|
|
@ -1298,6 +1301,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
)))]
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
|
|
@ -1309,6 +1313,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub fn try_lock(&self) -> Result<(), TryLockError> {
|
||||
|
|
@ -1329,6 +1334,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
)))]
|
||||
pub fn try_lock(&self) -> Result<(), TryLockError> {
|
||||
|
|
@ -1343,6 +1349,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
|
||||
|
|
@ -1363,6 +1370,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
)))]
|
||||
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
|
||||
|
|
@ -1377,6 +1385,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
|
|
@ -1389,6 +1398,7 @@ impl File {
|
|||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_vendor = "apple",
|
||||
)))]
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
|
|
|
|||
|
|
@ -1416,8 +1416,8 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
|
|||
if builder.config.llvm_enzyme {
|
||||
cargo.env("LLVM_ENZYME", "1");
|
||||
}
|
||||
let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
|
||||
cargo.env("LLVM_CONFIG", &llvm_config);
|
||||
let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
|
||||
cargo.env("LLVM_CONFIG", &host_llvm_config);
|
||||
|
||||
// Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script
|
||||
// expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by
|
||||
|
|
@ -2012,14 +2012,52 @@ impl Step for Assemble {
|
|||
if builder.config.llvm_enabled(target_compiler.host) {
|
||||
trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
|
||||
|
||||
let llvm::LlvmResult { llvm_config, .. } =
|
||||
builder.ensure(llvm::Llvm { target: target_compiler.host });
|
||||
let target = target_compiler.host;
|
||||
let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
|
||||
if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
|
||||
trace!("LLVM tools enabled");
|
||||
|
||||
let llvm_bin_dir =
|
||||
command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
|
||||
let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
|
||||
let host_llvm_bin_dir = command(&host_llvm_config)
|
||||
.arg("--bindir")
|
||||
.run_capture_stdout(builder)
|
||||
.stdout()
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
let llvm_bin_dir = if target == builder.host_target {
|
||||
PathBuf::from(host_llvm_bin_dir)
|
||||
} else {
|
||||
// If we're cross-compiling, we cannot run the target llvm-config in order to
|
||||
// figure out where binaries are located. We thus have to guess.
|
||||
let external_llvm_config = builder
|
||||
.config
|
||||
.target_config
|
||||
.get(&target)
|
||||
.and_then(|t| t.llvm_config.clone());
|
||||
if let Some(external_llvm_config) = external_llvm_config {
|
||||
// If we have an external LLVM, just hope that the bindir is the directory
|
||||
// where the LLVM config is located
|
||||
external_llvm_config.parent().unwrap().to_path_buf()
|
||||
} else {
|
||||
// If we have built LLVM locally, then take the path of the host bindir
|
||||
// relative to its output build directory, and then apply it to the target
|
||||
// LLVM output build directory.
|
||||
let host_llvm_out = builder.llvm_out(builder.host_target);
|
||||
let target_llvm_out = builder.llvm_out(target);
|
||||
if let Ok(relative_path) =
|
||||
Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
|
||||
{
|
||||
target_llvm_out.join(relative_path)
|
||||
} else {
|
||||
// This is the most desperate option, just replace the host target with
|
||||
// the actual target in the directory path...
|
||||
PathBuf::from(
|
||||
host_llvm_bin_dir
|
||||
.replace(&*builder.host_target.triple, &target.triple),
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Since we've already built the LLVM tools, install them to the sysroot.
|
||||
// This is the equivalent of installing the `llvm-tools-preview` component via
|
||||
|
|
|
|||
|
|
@ -2176,11 +2176,12 @@ fn maybe_install_llvm(
|
|||
builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
|
||||
}
|
||||
!builder.config.dry_run()
|
||||
} else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
|
||||
llvm::prebuilt_llvm_config(builder, target, true)
|
||||
} else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
|
||||
host_llvm_config, ..
|
||||
}) = llvm::prebuilt_llvm_config(builder, target, true)
|
||||
{
|
||||
trace!("LLVM already built, installing LLVM files");
|
||||
let mut cmd = command(llvm_config);
|
||||
let mut cmd = command(host_llvm_config);
|
||||
cmd.arg("--libfiles");
|
||||
builder.verbose(|| println!("running {cmd:?}"));
|
||||
let files = cmd.run_capture_stdout(builder).stdout();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ use crate::{CLang, GitRepo, Kind, trace};
|
|||
pub struct LlvmResult {
|
||||
/// Path to llvm-config binary.
|
||||
/// NB: This is always the host llvm-config!
|
||||
pub llvm_config: PathBuf,
|
||||
pub host_llvm_config: PathBuf,
|
||||
/// Path to LLVM cmake directory for the target.
|
||||
pub llvm_cmake_dir: PathBuf,
|
||||
}
|
||||
|
|
@ -111,14 +111,14 @@ pub fn prebuilt_llvm_config(
|
|||
&& let Some(ref s) = config.llvm_config
|
||||
{
|
||||
check_llvm_version(builder, s);
|
||||
let llvm_config = s.to_path_buf();
|
||||
let mut llvm_cmake_dir = llvm_config.clone();
|
||||
let host_llvm_config = s.to_path_buf();
|
||||
let mut llvm_cmake_dir = host_llvm_config.clone();
|
||||
llvm_cmake_dir.pop();
|
||||
llvm_cmake_dir.pop();
|
||||
llvm_cmake_dir.push("lib");
|
||||
llvm_cmake_dir.push("cmake");
|
||||
llvm_cmake_dir.push("llvm");
|
||||
return LlvmBuildStatus::AlreadyBuilt(LlvmResult { llvm_config, llvm_cmake_dir });
|
||||
return LlvmBuildStatus::AlreadyBuilt(LlvmResult { host_llvm_config, llvm_cmake_dir });
|
||||
}
|
||||
|
||||
if handle_submodule_when_needed {
|
||||
|
|
@ -143,7 +143,7 @@ pub fn prebuilt_llvm_config(
|
|||
};
|
||||
|
||||
let llvm_cmake_dir = out_dir.join("lib/cmake/llvm");
|
||||
let res = LlvmResult { llvm_config: build_llvm_config, llvm_cmake_dir };
|
||||
let res = LlvmResult { host_llvm_config: build_llvm_config, llvm_cmake_dir };
|
||||
|
||||
static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
|
||||
let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
|
||||
|
|
@ -488,11 +488,11 @@ impl Step for Llvm {
|
|||
|
||||
// https://llvm.org/docs/HowToCrossCompileLLVM.html
|
||||
if !builder.config.is_host_target(target) {
|
||||
let LlvmResult { llvm_config, .. } =
|
||||
let LlvmResult { host_llvm_config, .. } =
|
||||
builder.ensure(Llvm { target: builder.config.host_target });
|
||||
if !builder.config.dry_run() {
|
||||
let llvm_bindir =
|
||||
command(&llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
|
||||
command(&host_llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
|
||||
let host_bin = Path::new(llvm_bindir.trim());
|
||||
cfg.define(
|
||||
"LLVM_TABLEGEN",
|
||||
|
|
@ -501,7 +501,7 @@ impl Step for Llvm {
|
|||
// LLVM_NM is required for cross compiling using MSVC
|
||||
cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION));
|
||||
}
|
||||
cfg.define("LLVM_CONFIG_PATH", llvm_config);
|
||||
cfg.define("LLVM_CONFIG_PATH", host_llvm_config);
|
||||
if builder.config.llvm_clang {
|
||||
let build_bin =
|
||||
builder.llvm_out(builder.config.host_target).join("build").join("bin");
|
||||
|
|
@ -543,7 +543,7 @@ impl Step for Llvm {
|
|||
|
||||
// Helper to find the name of LLVM's shared library on darwin and linux.
|
||||
let find_llvm_lib_name = |extension| {
|
||||
let major = get_llvm_version_major(builder, &res.llvm_config);
|
||||
let major = get_llvm_version_major(builder, &res.host_llvm_config);
|
||||
match &llvm_version_suffix {
|
||||
Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.{extension}"),
|
||||
None => format!("libLLVM-{major}.{extension}"),
|
||||
|
|
@ -929,7 +929,7 @@ impl Step for Enzyme {
|
|||
}
|
||||
let target = self.target;
|
||||
|
||||
let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: self.target });
|
||||
let LlvmResult { host_llvm_config, .. } = builder.ensure(Llvm { target: self.target });
|
||||
|
||||
static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
|
||||
let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
|
||||
|
|
@ -983,7 +983,7 @@ impl Step for Enzyme {
|
|||
|
||||
cfg.out_dir(&out_dir)
|
||||
.profile(profile)
|
||||
.env("LLVM_CONFIG_REAL", &llvm_config)
|
||||
.env("LLVM_CONFIG_REAL", &host_llvm_config)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", "ON")
|
||||
.define("ENZYME_EXTERNAL_SHARED_LIB", "ON")
|
||||
.define("LLVM_DIR", builder.llvm_out(target));
|
||||
|
|
@ -1019,13 +1019,13 @@ impl Step for Lld {
|
|||
}
|
||||
let target = self.target;
|
||||
|
||||
let LlvmResult { llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target });
|
||||
let LlvmResult { host_llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target });
|
||||
|
||||
// The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path
|
||||
// we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin`
|
||||
// subfolder. We check if that's the case, and if LLD's binary already exists there next to
|
||||
// `llvm-config`: if so, we can use it instead of building LLVM/LLD from source.
|
||||
let ci_llvm_bin = llvm_config.parent().unwrap();
|
||||
let ci_llvm_bin = host_llvm_config.parent().unwrap();
|
||||
if ci_llvm_bin.is_dir() && ci_llvm_bin.file_name().unwrap() == "bin" {
|
||||
let lld_path = ci_llvm_bin.join(exe("lld", target));
|
||||
if lld_path.exists() {
|
||||
|
|
@ -1108,7 +1108,7 @@ impl Step for Lld {
|
|||
// Use the host llvm-tblgen binary.
|
||||
cfg.define(
|
||||
"LLVM_TABLEGEN_EXE",
|
||||
llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
|
||||
host_llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1149,7 +1149,7 @@ impl Step for Sanitizers {
|
|||
return runtimes;
|
||||
}
|
||||
|
||||
let LlvmResult { llvm_config, .. } =
|
||||
let LlvmResult { host_llvm_config, .. } =
|
||||
builder.ensure(Llvm { target: builder.config.host_target });
|
||||
|
||||
static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
|
||||
|
|
@ -1189,7 +1189,7 @@ impl Step for Sanitizers {
|
|||
cfg.define("COMPILER_RT_BUILD_XRAY", "OFF");
|
||||
cfg.define("COMPILER_RT_DEFAULT_TARGET_ONLY", "ON");
|
||||
cfg.define("COMPILER_RT_USE_LIBCXX", "OFF");
|
||||
cfg.define("LLVM_CONFIG_PATH", &llvm_config);
|
||||
cfg.define("LLVM_CONFIG_PATH", &host_llvm_config);
|
||||
|
||||
if self.target.contains("ohos") {
|
||||
cfg.define("COMPILER_RT_USE_BUILTINS_LIBRARY", "ON");
|
||||
|
|
|
|||
|
|
@ -1976,12 +1976,14 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
let mut llvm_components_passed = false;
|
||||
let mut copts_passed = false;
|
||||
if builder.config.llvm_enabled(compiler.host) {
|
||||
let llvm::LlvmResult { llvm_config, .. } =
|
||||
let llvm::LlvmResult { host_llvm_config, .. } =
|
||||
builder.ensure(llvm::Llvm { target: builder.config.host_target });
|
||||
if !builder.config.dry_run() {
|
||||
let llvm_version = get_llvm_version(builder, &llvm_config);
|
||||
let llvm_components =
|
||||
command(&llvm_config).arg("--components").run_capture_stdout(builder).stdout();
|
||||
let llvm_version = get_llvm_version(builder, &host_llvm_config);
|
||||
let llvm_components = command(&host_llvm_config)
|
||||
.arg("--components")
|
||||
.run_capture_stdout(builder)
|
||||
.stdout();
|
||||
// Remove trailing newline from llvm-config output.
|
||||
cmd.arg("--llvm-version")
|
||||
.arg(llvm_version.trim())
|
||||
|
|
@ -1999,7 +2001,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
// rustc args as a workaround.
|
||||
if !builder.config.dry_run() && suite.ends_with("fulldeps") {
|
||||
let llvm_libdir =
|
||||
command(&llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
|
||||
command(&host_llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
|
||||
let link_llvm = if target.is_msvc() {
|
||||
format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
|
||||
} else {
|
||||
|
|
@ -2013,7 +2015,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
// tools. Pass the path to run-make tests so they can use them.
|
||||
// (The coverage-run tests also need these tools to process
|
||||
// coverage reports.)
|
||||
let llvm_bin_path = llvm_config
|
||||
let llvm_bin_path = host_llvm_config
|
||||
.parent()
|
||||
.expect("Expected llvm-config to be contained in directory");
|
||||
assert!(llvm_bin_path.is_dir());
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ pub const VENDOR_DIR: &str = "vendor";
|
|||
pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'static str>)> {
|
||||
[
|
||||
("src/tools/cargo/Cargo.toml", vec!["src/tools/cargo"]),
|
||||
("src/tools/clippy/clippy_test_deps/Cargo.toml", vec![]),
|
||||
("src/tools/rust-analyzer/Cargo.toml", vec![]),
|
||||
("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]),
|
||||
("compiler/rustc_codegen_gcc/Cargo.toml", vec![]),
|
||||
|
|
|
|||
|
|
@ -1613,11 +1613,15 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
///
|
||||
/// Note that this returns `None` if LLVM is disabled, or if we're in a
|
||||
/// check build or dry-run, where there's no need to build all of LLVM.
|
||||
///
|
||||
/// FIXME(@kobzol)
|
||||
/// **WARNING**: This actually returns the **HOST** LLVM config, not LLVM config for the given
|
||||
/// *target*.
|
||||
pub fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
|
||||
if self.config.llvm_enabled(target) && self.kind != Kind::Check && !self.config.dry_run() {
|
||||
let llvm::LlvmResult { llvm_config, .. } = self.ensure(llvm::Llvm { target });
|
||||
if llvm_config.is_file() {
|
||||
return Some(llvm_config);
|
||||
let llvm::LlvmResult { host_llvm_config, .. } = self.ensure(llvm::Llvm { target });
|
||||
if host_llvm_config.is_file() {
|
||||
return Some(host_llvm_config);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
|||
|
|
@ -494,14 +494,14 @@ fn test_prebuilt_llvm_config_path_resolution() {
|
|||
false,
|
||||
)
|
||||
.llvm_result()
|
||||
.llvm_config
|
||||
.host_llvm_config
|
||||
.clone();
|
||||
let actual = drop_win_disk_prefix_if_present(actual);
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
let actual = prebuilt_llvm_config(&builder, builder.config.host_target, false)
|
||||
.llvm_result()
|
||||
.llvm_config
|
||||
.host_llvm_config
|
||||
.clone();
|
||||
let actual = drop_win_disk_prefix_if_present(actual);
|
||||
assert_eq!(expected, actual);
|
||||
|
|
@ -519,7 +519,7 @@ fn test_prebuilt_llvm_config_path_resolution() {
|
|||
|
||||
let actual = prebuilt_llvm_config(&builder, builder.config.host_target, false)
|
||||
.llvm_result()
|
||||
.llvm_config
|
||||
.host_llvm_config
|
||||
.clone();
|
||||
let expected = builder
|
||||
.out
|
||||
|
|
@ -542,7 +542,7 @@ fn test_prebuilt_llvm_config_path_resolution() {
|
|||
|
||||
let actual = prebuilt_llvm_config(&builder, builder.config.host_target, false)
|
||||
.llvm_result()
|
||||
.llvm_config
|
||||
.host_llvm_config
|
||||
.clone();
|
||||
let expected = builder
|
||||
.out
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
trait WorksOnDefault {
|
||||
fn do_something() {}
|
||||
}
|
||||
|
||||
impl<T: Default> WorksOnDefault for T {}
|
||||
//~^ NOTE the following trait bounds were not satisfied
|
||||
//~| NOTE unsatisfied trait bound introduced here
|
||||
|
||||
trait Foo {}
|
||||
|
||||
trait WorksOnFoo {
|
||||
fn do_be_do() {}
|
||||
}
|
||||
|
||||
impl<T: Foo> WorksOnFoo for T {}
|
||||
//~^ NOTE the following trait bounds were not satisfied
|
||||
//~| NOTE unsatisfied trait bound introduced here
|
||||
|
||||
impl<A: Foo, B: Foo, C: Foo> Foo for (A, B, C) {}
|
||||
//~^ NOTE `Foo` is implemented for `(i32, u32, String)`
|
||||
impl Foo for i32 {}
|
||||
impl Foo for &i32 {}
|
||||
impl Foo for u32 {}
|
||||
impl Foo for String {}
|
||||
|
||||
fn main() {
|
||||
let _success = <(i32, u32, String)>::do_something();
|
||||
let _failure = <(i32, &u32, String)>::do_something(); //~ ERROR E0599
|
||||
//~^ NOTE `Default` is implemented for `(i32, u32, String)`
|
||||
//~| NOTE function or associated item cannot be called on
|
||||
let _success = <(i32, u32, String)>::do_be_do();
|
||||
let _failure = <(i32, &u32, String)>::do_be_do(); //~ ERROR E0599
|
||||
//~^ NOTE function or associated item cannot be called on
|
||||
let _success = <(i32, u32, String)>::default();
|
||||
let _failure = <(i32, &u32, String)>::default(); //~ ERROR E0599
|
||||
//~^ NOTE `Default` is implemented for `(i32, u32, String)`
|
||||
//~| NOTE function or associated item cannot be called on
|
||||
//~| NOTE the following trait bounds were not satisfied
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
error[E0599]: the function or associated item `do_something` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied
|
||||
--> $DIR/missing-bound-on-tuple.rs:28:43
|
||||
|
|
||||
LL | let _failure = <(i32, &u32, String)>::do_something();
|
||||
| ^^^^^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`&(i32, &u32, String): Default`
|
||||
`&mut (i32, &u32, String): Default`
|
||||
`(i32, &u32, String): Default`
|
||||
--> $DIR/missing-bound-on-tuple.rs:5:9
|
||||
|
|
||||
LL | impl<T: Default> WorksOnDefault for T {}
|
||||
| ^^^^^^^ -------------- -
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: `Default` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)`
|
||||
--> $SRC_DIR/core/src/tuple.rs:LL:COL
|
||||
= note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0599]: the function or associated item `do_be_do` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied
|
||||
--> $DIR/missing-bound-on-tuple.rs:32:43
|
||||
|
|
||||
LL | let _failure = <(i32, &u32, String)>::do_be_do();
|
||||
| ^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`&(i32, &u32, String): Foo`
|
||||
`&mut (i32, &u32, String): Foo`
|
||||
`(i32, &u32, String): Foo`
|
||||
--> $DIR/missing-bound-on-tuple.rs:15:9
|
||||
|
|
||||
LL | impl<T: Foo> WorksOnFoo for T {}
|
||||
| ^^^ ---------- -
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: `Foo` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)`
|
||||
--> $DIR/missing-bound-on-tuple.rs:19:1
|
||||
|
|
||||
LL | impl<A: Foo, B: Foo, C: Foo> Foo for (A, B, C) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0599]: the function or associated item `default` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied
|
||||
--> $DIR/missing-bound-on-tuple.rs:35:43
|
||||
|
|
||||
LL | let _failure = <(i32, &u32, String)>::default();
|
||||
| ^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`&u32: Default`
|
||||
which is required by `(i32, &u32, String): Default`
|
||||
note: `Default` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)`
|
||||
--> $SRC_DIR/core/src/tuple.rs:LL:COL
|
||||
= note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
48
tests/ui/methods/tuple-suggestions-issue-142488.rs
Normal file
48
tests/ui/methods/tuple-suggestions-issue-142488.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// Regression test for issue #142488, a diagnostics ICE when trying to suggest missing methods
|
||||
// present in similar tuple types.
|
||||
// This is a few of the MCVEs from the issues and its many duplicates.
|
||||
|
||||
// 1
|
||||
fn main() {
|
||||
for a in x {
|
||||
//~^ ERROR: cannot find value `x` in this scope
|
||||
(a,).to_string()
|
||||
//~^ ERROR: the method `to_string` exists for tuple
|
||||
}
|
||||
}
|
||||
|
||||
// 2
|
||||
trait Trait {
|
||||
fn meth(self);
|
||||
}
|
||||
|
||||
impl<T, U: Trait> Trait for (T, U) {
|
||||
fn meth(self) {}
|
||||
}
|
||||
|
||||
fn mcve2() {
|
||||
((), std::collections::HashMap::new()).meth()
|
||||
//~^ ERROR: the method `meth` exists for tuple
|
||||
}
|
||||
|
||||
// 3
|
||||
trait I {}
|
||||
|
||||
struct Struct;
|
||||
impl I for Struct {}
|
||||
|
||||
trait Tr {
|
||||
fn f<A>(self) -> (A,)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Tr for T where T: I {}
|
||||
|
||||
fn mcve3() {
|
||||
Struct.f().f();
|
||||
//~^ ERROR: the method `f` exists for tuple
|
||||
}
|
||||
61
tests/ui/methods/tuple-suggestions-issue-142488.stderr
Normal file
61
tests/ui/methods/tuple-suggestions-issue-142488.stderr
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
error[E0425]: cannot find value `x` in this scope
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:7:14
|
||||
|
|
||||
LL | for a in x {
|
||||
| ^ not found in this scope
|
||||
|
||||
error[E0599]: the method `to_string` exists for tuple `(_,)`, but its trait bounds were not satisfied
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:9:14
|
||||
|
|
||||
LL | (a,).to_string()
|
||||
| ^^^^^^^^^ method cannot be called on `(_,)` due to unsatisfied trait bounds
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`(_,): std::fmt::Display`
|
||||
which is required by `(_,): ToString`
|
||||
|
||||
error[E0599]: the method `meth` exists for tuple `((), HashMap<_, _>)`, but its trait bounds were not satisfied
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:24:44
|
||||
|
|
||||
LL | ((), std::collections::HashMap::new()).meth()
|
||||
| ^^^^ method cannot be called on `((), HashMap<_, _>)` due to unsatisfied trait bounds
|
||||
|
|
||||
note: trait bound `HashMap<_, _>: Trait` was not satisfied
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:19:12
|
||||
|
|
||||
LL | impl<T, U: Trait> Trait for (T, U) {
|
||||
| ^^^^^ ----- ------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `Trait` defines an item `meth`, perhaps you need to implement it
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:15:1
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error[E0599]: the method `f` exists for tuple `(_,)`, but its trait bounds were not satisfied
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:46:16
|
||||
|
|
||||
LL | Struct.f().f();
|
||||
| ^ method cannot be called on `(_,)` due to unsatisfied trait bounds
|
||||
|
|
||||
note: the following trait bounds were not satisfied:
|
||||
`&(_,): I`
|
||||
`&mut (_,): I`
|
||||
`(_,): I`
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:43:27
|
||||
|
|
||||
LL | impl<T> Tr for T where T: I {}
|
||||
| -- - ^ unsatisfied trait bound introduced here
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `Tr` defines an item `f`, perhaps you need to implement it
|
||||
--> $DIR/tuple-suggestions-issue-142488.rs:34:1
|
||||
|
|
||||
LL | trait Tr {
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0425, E0599.
|
||||
For more information about an error, try `rustc --explain E0425`.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
error: vtable entries: [
|
||||
MetadataDropInPlace,
|
||||
MetadataSize,
|
||||
MetadataAlign,
|
||||
Method(<dyn OneTwo as One>::one - shim(reify)),
|
||||
Method(<dyn OneTwo as Two>::two - shim(reify)),
|
||||
TraitVPtr(<dyn OneTwo as Two>),
|
||||
TraitVPtr(<dyn OneTwo as TwoAgain>),
|
||||
]
|
||||
--> $DIR/empty-supertrait-with-nonempty-supersupertrait.rs:40:1
|
||||
|
|
||||
LL | type T = dyn OneTwo;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
//@ revisions: run dump
|
||||
//@[run] run-pass
|
||||
//@[dump] check-fail
|
||||
//! Regression test for #145752
|
||||
//! Ensure that `OneTwo` contains a vptr for `TwoAgain`
|
||||
#![allow(unused)]
|
||||
#![cfg_attr(dump, feature(rustc_attrs))]
|
||||
|
||||
trait One {
|
||||
fn one(&self) {
|
||||
panic!("don't call this");
|
||||
}
|
||||
}
|
||||
impl One for () {}
|
||||
|
||||
trait Two {
|
||||
fn two(&self) {
|
||||
println!("good");
|
||||
}
|
||||
}
|
||||
impl Two for () {}
|
||||
|
||||
trait TwoAgain: Two {}
|
||||
impl<T: Two> TwoAgain for T {}
|
||||
|
||||
trait OneTwo: One + TwoAgain {}
|
||||
impl<T: One + Two> OneTwo for T {}
|
||||
|
||||
fn main() {
|
||||
(&()).two();
|
||||
(&() as &dyn OneTwo).two();
|
||||
(&() as &dyn OneTwo as &dyn Two).two();
|
||||
|
||||
// these two used to panic because they called `one` due to #145752
|
||||
(&() as &dyn OneTwo as &dyn TwoAgain).two();
|
||||
(&() as &dyn OneTwo as &dyn TwoAgain as &dyn Two).two();
|
||||
}
|
||||
|
||||
#[cfg_attr(dump, rustc_dump_vtable)]
|
||||
type T = dyn OneTwo;
|
||||
//[dump]~^ ERROR vtable entries: [
|
||||
//[dump]~| ERROR MetadataDropInPlace,
|
||||
//[dump]~| ERROR MetadataSize,
|
||||
//[dump]~| ERROR MetadataAlign,
|
||||
//[dump]~| ERROR Method(<dyn OneTwo as One>::one - shim(reify)),
|
||||
//[dump]~| ERROR Method(<dyn OneTwo as Two>::two - shim(reify)),
|
||||
//[dump]~| ERROR TraitVPtr(<dyn OneTwo as Two>),
|
||||
//[dump]~| ERROR TraitVPtr(<dyn OneTwo as TwoAgain>),
|
||||
//[dump]~| ERROR ]
|
||||
50
tests/ui/traits/vtable/multiple-auto.rs
Normal file
50
tests/ui/traits/vtable/multiple-auto.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Related to <https://github.com/rust-lang/rust/issues/113840>
|
||||
//
|
||||
// This test makes sure that multiple auto traits can reuse the
|
||||
// same pointer for upcasting (e.g. `Send`/`Sync`)
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(rustc_attrs, auto_traits)]
|
||||
|
||||
// Markers
|
||||
auto trait M0 {}
|
||||
auto trait M1 {}
|
||||
auto trait M2 {}
|
||||
|
||||
// Just a trait with a method
|
||||
trait T {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
trait A: M0 + M1 + M2 + T {}
|
||||
|
||||
trait B: M0 + M1 + T + M2 {}
|
||||
|
||||
trait C: M0 + T + M1 + M2 {}
|
||||
|
||||
trait D: T + M0 + M1 + M2 {}
|
||||
|
||||
struct S;
|
||||
|
||||
impl M0 for S {}
|
||||
impl M1 for S {}
|
||||
impl M2 for S {}
|
||||
impl T for S {}
|
||||
|
||||
#[rustc_dump_vtable]
|
||||
impl A for S {}
|
||||
//~^ ERROR vtable entries
|
||||
|
||||
#[rustc_dump_vtable]
|
||||
impl B for S {}
|
||||
//~^ ERROR vtable entries
|
||||
|
||||
#[rustc_dump_vtable]
|
||||
impl C for S {}
|
||||
//~^ ERROR vtable entries
|
||||
|
||||
#[rustc_dump_vtable]
|
||||
impl D for S {}
|
||||
//~^ ERROR vtable entries
|
||||
|
||||
fn main() {}
|
||||
46
tests/ui/traits/vtable/multiple-auto.stderr
Normal file
46
tests/ui/traits/vtable/multiple-auto.stderr
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
error: vtable entries: [
|
||||
MetadataDropInPlace,
|
||||
MetadataSize,
|
||||
MetadataAlign,
|
||||
Method(<S as T>::method),
|
||||
]
|
||||
--> $DIR/multiple-auto.rs:35:1
|
||||
|
|
||||
LL | impl A for S {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: vtable entries: [
|
||||
MetadataDropInPlace,
|
||||
MetadataSize,
|
||||
MetadataAlign,
|
||||
Method(<S as T>::method),
|
||||
]
|
||||
--> $DIR/multiple-auto.rs:39:1
|
||||
|
|
||||
LL | impl B for S {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: vtable entries: [
|
||||
MetadataDropInPlace,
|
||||
MetadataSize,
|
||||
MetadataAlign,
|
||||
Method(<S as T>::method),
|
||||
]
|
||||
--> $DIR/multiple-auto.rs:43:1
|
||||
|
|
||||
LL | impl C for S {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: vtable entries: [
|
||||
MetadataDropInPlace,
|
||||
MetadataSize,
|
||||
MetadataAlign,
|
||||
Method(<S as T>::method),
|
||||
]
|
||||
--> $DIR/multiple-auto.rs:47:1
|
||||
|
|
||||
LL | impl D for S {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue