mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Auto merge of #128796 - matthiaskrgr:rollup-r7l68ph, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #128221 (Add implied target features to target_feature attribute) - #128261 (impl `Default` for collection iterators that don't already have it) - #128353 (Change generate-copyright to generate HTML, with cargo dependencies included) - #128679 (codegen: better centralize function declaration attribute computation) - #128732 (make `import.vis` is immutable) - #128755 (Integrate crlf directly into related test file instead via of .gitattributes) - #128772 (rustc_codegen_ssa: Set architecture for object crate for 32-bit SPARC) - #128782 (unused_parens: do not lint against parens around &raw) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8b3870784f
@ -1406,8 +1406,11 @@ name = "generate-copyright"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"cargo_metadata 0.18.1",
|
||||||
|
"rinja",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3094,7 +3097,10 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d3762e3740cdbf2fd2be465cc2c26d643ad17353cc2e0223d211c1b096118bd"
|
checksum = "6d3762e3740cdbf2fd2be465cc2c26d643ad17353cc2e0223d211c1b096118bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"humansize",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"num-traits",
|
||||||
|
"percent-encoding",
|
||||||
"rinja_derive",
|
"rinja_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ SPDX-License-Identifier = "MIT OR Apache-2.0"
|
|||||||
path = "src/llvm-project/**"
|
path = "src/llvm-project/**"
|
||||||
precedence = "override"
|
precedence = "override"
|
||||||
SPDX-FileCopyrightText = [
|
SPDX-FileCopyrightText = [
|
||||||
"2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)",
|
"2003-2019 by the contributors listed in CREDITS.TXT (https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)",
|
||||||
"2010 Apple Inc",
|
"2010 Apple Inc",
|
||||||
"2003-2019 University of Illinois at Urbana-Champaign.",
|
"2003-2019 University of Illinois at Urbana-Champaign.",
|
||||||
]
|
]
|
||||||
|
@ -75,7 +75,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||||||
let function_features = codegen_fn_attrs
|
let function_features = codegen_fn_attrs
|
||||||
.target_features
|
.target_features
|
||||||
.iter()
|
.iter()
|
||||||
.map(|features| features.as_str())
|
.map(|features| features.name.as_str())
|
||||||
.collect::<Vec<&str>>();
|
.collect::<Vec<&str>>();
|
||||||
|
|
||||||
if let Some(features) = check_tied_features(
|
if let Some(features) = check_tied_features(
|
||||||
|
@ -65,8 +65,8 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||||||
|
|
||||||
let feature = backend_feature_name(s)?;
|
let feature = backend_feature_name(s)?;
|
||||||
// Warn against use of GCC specific feature names on the CLI.
|
// Warn against use of GCC specific feature names on the CLI.
|
||||||
if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) {
|
if diagnostics && !supported_features.iter().any(|&(v, _, _)| v == feature) {
|
||||||
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
|
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| {
|
||||||
let gcc_features = to_gcc_features(sess, rust_feature);
|
let gcc_features = to_gcc_features(sess, rust_feature);
|
||||||
if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
|
if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
|
||||||
Some(rust_feature)
|
Some(rust_feature)
|
||||||
|
@ -486,7 +486,7 @@ pub fn target_features(
|
|||||||
sess.target
|
sess.target
|
||||||
.supported_target_features()
|
.supported_target_features()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|&(feature, gate)| {
|
.filter_map(|&(feature, gate, _)| {
|
||||||
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
|
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
|
||||||
Some(feature)
|
Some(feature)
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,10 +5,10 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
|||||||
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::MemFlags;
|
use rustc_codegen_ssa::MemFlags;
|
||||||
use rustc_middle::bug;
|
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
use rustc_middle::{bug, ty};
|
||||||
use rustc_session::config;
|
use rustc_session::config;
|
||||||
pub use rustc_target::abi::call::*;
|
pub use rustc_target::abi::call::*;
|
||||||
use rustc_target::abi::{self, HasDataLayout, Int, Size};
|
use rustc_target::abi::{self, HasDataLayout, Int, Size};
|
||||||
@ -16,6 +16,7 @@ pub use rustc_target::spec::abi::Abi;
|
|||||||
use rustc_target::spec::SanitizerSet;
|
use rustc_target::spec::SanitizerSet;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
use crate::attributes::llfn_attrs_from_instance;
|
||||||
use crate::builder::Builder;
|
use crate::builder::Builder;
|
||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
use crate::llvm::{self, Attribute, AttributePlace};
|
use crate::llvm::{self, Attribute, AttributePlace};
|
||||||
@ -310,7 +311,16 @@ pub trait FnAbiLlvmExt<'ll, 'tcx> {
|
|||||||
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
||||||
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
|
||||||
fn llvm_cconv(&self) -> llvm::CallConv;
|
fn llvm_cconv(&self) -> llvm::CallConv;
|
||||||
fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
|
|
||||||
|
/// Apply attributes to a function declaration/definition.
|
||||||
|
fn apply_attrs_llfn(
|
||||||
|
&self,
|
||||||
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
|
llfn: &'ll Value,
|
||||||
|
instance: Option<ty::Instance<'tcx>>,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Apply attributes to a function call.
|
||||||
fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value);
|
fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +406,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
self.conv.into()
|
self.conv.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
|
fn apply_attrs_llfn(
|
||||||
|
&self,
|
||||||
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
|
llfn: &'ll Value,
|
||||||
|
instance: Option<ty::Instance<'tcx>>,
|
||||||
|
) {
|
||||||
let mut func_attrs = SmallVec::<[_; 3]>::new();
|
let mut func_attrs = SmallVec::<[_; 3]>::new();
|
||||||
if self.ret.layout.abi.is_uninhabited() {
|
if self.ret.layout.abi.is_uninhabited() {
|
||||||
func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
|
func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
|
||||||
@ -477,6 +492,11 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the declaration has an associated instance, compute extra attributes based on that.
|
||||||
|
if let Some(instance) = instance {
|
||||||
|
llfn_attrs_from_instance(cx, llfn, instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) {
|
fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) {
|
||||||
|
@ -324,9 +324,10 @@ fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute {
|
|||||||
llvm::CreateAttrStringValue(llcx, "alloc-family", "__rust_alloc")
|
llvm::CreateAttrStringValue(llcx, "alloc-family", "__rust_alloc")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for `FnAbi::apply_attrs_llfn`:
|
||||||
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
|
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
|
||||||
/// attributes.
|
/// attributes.
|
||||||
pub fn from_fn_attrs<'ll, 'tcx>(
|
pub fn llfn_attrs_from_instance<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
llfn: &'ll Value,
|
llfn: &'ll Value,
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
@ -496,7 +497,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||||||
to_add.extend(tune_cpu_attr(cx));
|
to_add.extend(tune_cpu_attr(cx));
|
||||||
|
|
||||||
let function_features =
|
let function_features =
|
||||||
codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::<Vec<&str>>();
|
codegen_fn_attrs.target_features.iter().map(|f| f.name.as_str()).collect::<Vec<&str>>();
|
||||||
|
|
||||||
if let Some(f) = llvm_util::check_tied_features(
|
if let Some(f) = llvm_util::check_tied_features(
|
||||||
cx.tcx.sess,
|
cx.tcx.sess,
|
||||||
|
@ -95,11 +95,14 @@ pub fn write_output_file<'ll>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine {
|
pub fn create_informational_target_machine(
|
||||||
|
sess: &Session,
|
||||||
|
only_base_features: bool,
|
||||||
|
) -> OwnedTargetMachine {
|
||||||
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
|
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
|
||||||
// Can't use query system here quite yet because this function is invoked before the query
|
// Can't use query system here quite yet because this function is invoked before the query
|
||||||
// system/tcx is set up.
|
// system/tcx is set up.
|
||||||
let features = llvm_util::global_llvm_features(sess, false);
|
let features = llvm_util::global_llvm_features(sess, false, only_base_features);
|
||||||
target_machine_factory(sess, config::OptLevel::No, &features)(config)
|
target_machine_factory(sess, config::OptLevel::No, &features)(config)
|
||||||
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
|
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@ use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
|||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
|
use crate::llvm;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{attributes, llvm};
|
|
||||||
|
|
||||||
/// Codegens a reference to a fn/method item, monomorphizing and
|
/// Codegens a reference to a fn/method item, monomorphizing and
|
||||||
/// inlining as it goes.
|
/// inlining as it goes.
|
||||||
@ -78,8 +78,6 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
|
|||||||
};
|
};
|
||||||
debug!("get_fn: not casting pointer!");
|
debug!("get_fn: not casting pointer!");
|
||||||
|
|
||||||
attributes::from_fn_attrs(cx, llfn, instance);
|
|
||||||
|
|
||||||
// Apply an appropriate linkage/visibility value to our item that we
|
// Apply an appropriate linkage/visibility value to our item that we
|
||||||
// just declared.
|
// just declared.
|
||||||
//
|
//
|
||||||
|
@ -149,7 +149,7 @@ pub unsafe fn create_module<'ll>(
|
|||||||
|
|
||||||
// Ensure the data-layout values hardcoded remain the defaults.
|
// Ensure the data-layout values hardcoded remain the defaults.
|
||||||
{
|
{
|
||||||
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
|
let tm = crate::back::write::create_informational_target_machine(tcx.sess, false);
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||||||
llvm::Visibility::Default,
|
llvm::Visibility::Default,
|
||||||
fn_abi.llvm_type(self),
|
fn_abi.llvm_type(self),
|
||||||
);
|
);
|
||||||
fn_abi.apply_attrs_llfn(self, llfn);
|
fn_abi.apply_attrs_llfn(self, llfn, instance);
|
||||||
|
|
||||||
if self.tcx.sess.is_sanitizer_cfi_enabled() {
|
if self.tcx.sess.is_sanitizer_cfi_enabled() {
|
||||||
if let Some(instance) = instance {
|
if let Some(instance) = instance {
|
||||||
|
@ -269,7 +269,7 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||||||
|
|
||||||
fn provide(&self, providers: &mut Providers) {
|
fn provide(&self, providers: &mut Providers) {
|
||||||
providers.global_backend_features =
|
providers.global_backend_features =
|
||||||
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
|
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
|
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
|
||||||
@ -434,7 +434,7 @@ impl ModuleLlvm {
|
|||||||
ModuleLlvm {
|
ModuleLlvm {
|
||||||
llmod_raw,
|
llmod_raw,
|
||||||
llcx,
|
llcx,
|
||||||
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
|
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use libc::c_int;
|
|||||||
use rustc_codegen_ssa::base::wants_wasm_eh;
|
use rustc_codegen_ssa::base::wants_wasm_eh;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
|
use rustc_data_structures::unord::UnordSet;
|
||||||
use rustc_fs_util::path_to_c_string;
|
use rustc_fs_util::path_to_c_string;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_session::config::{PrintKind, PrintRequest};
|
use rustc_session::config::{PrintKind, PrintRequest};
|
||||||
@ -239,40 +240,8 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> {
|
|||||||
}
|
}
|
||||||
// In LLVM neon implicitly enables fp, but we manually enable
|
// In LLVM neon implicitly enables fp, but we manually enable
|
||||||
// neon when a feature only implicitly enables fp
|
// neon when a feature only implicitly enables fp
|
||||||
("aarch64", "f32mm") => {
|
("aarch64", "fhm") => LLVMFeature::new("fp16fml"),
|
||||||
LLVMFeature::with_dependency("f32mm", TargetFeatureFoldStrength::EnableOnly("neon"))
|
("aarch64", "fp16") => LLVMFeature::new("fullfp16"),
|
||||||
}
|
|
||||||
("aarch64", "f64mm") => {
|
|
||||||
LLVMFeature::with_dependency("f64mm", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "fhm") => {
|
|
||||||
LLVMFeature::with_dependency("fp16fml", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "fp16") => {
|
|
||||||
LLVMFeature::with_dependency("fullfp16", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "jsconv") => {
|
|
||||||
LLVMFeature::with_dependency("jsconv", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "sve") => {
|
|
||||||
LLVMFeature::with_dependency("sve", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "sve2") => {
|
|
||||||
LLVMFeature::with_dependency("sve2", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "sve2-aes") => {
|
|
||||||
LLVMFeature::with_dependency("sve2-aes", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "sve2-sm4") => {
|
|
||||||
LLVMFeature::with_dependency("sve2-sm4", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "sve2-sha3") => {
|
|
||||||
LLVMFeature::with_dependency("sve2-sha3", TargetFeatureFoldStrength::EnableOnly("neon"))
|
|
||||||
}
|
|
||||||
("aarch64", "sve2-bitperm") => LLVMFeature::with_dependency(
|
|
||||||
"sve2-bitperm",
|
|
||||||
TargetFeatureFoldStrength::EnableOnly("neon"),
|
|
||||||
),
|
|
||||||
// In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called
|
// In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called
|
||||||
// `fast-unaligned-access`. In LLVM 19, it was split back out.
|
// `fast-unaligned-access`. In LLVM 19, it was split back out.
|
||||||
("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
|
("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
|
||||||
@ -308,18 +277,15 @@ pub fn check_tied_features(
|
|||||||
/// Used to generate cfg variables and apply features
|
/// Used to generate cfg variables and apply features
|
||||||
/// Must express features in the way Rust understands them
|
/// Must express features in the way Rust understands them
|
||||||
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||||
let target_machine = create_informational_target_machine(sess);
|
let mut features = vec![];
|
||||||
|
|
||||||
|
// Add base features for the target
|
||||||
|
let target_machine = create_informational_target_machine(sess, true);
|
||||||
|
features.extend(
|
||||||
sess.target
|
sess.target
|
||||||
.supported_target_features()
|
.supported_target_features()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|&(feature, gate)| {
|
.filter(|(feature, _, _)| {
|
||||||
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
|
|
||||||
Some(feature)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(|feature| {
|
|
||||||
// skip checking special features, as LLVM may not understands them
|
// skip checking special features, as LLVM may not understands them
|
||||||
if RUSTC_SPECIAL_FEATURES.contains(feature) {
|
if RUSTC_SPECIAL_FEATURES.contains(feature) {
|
||||||
return true;
|
return true;
|
||||||
@ -333,6 +299,40 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||||||
}
|
}
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
|
.map(|(feature, _, _)| Symbol::intern(feature)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add enabled features
|
||||||
|
for (enabled, feature) in
|
||||||
|
sess.opts.cg.target_feature.split(',').filter_map(|s| match s.chars().next() {
|
||||||
|
Some('+') => Some((true, Symbol::intern(&s[1..]))),
|
||||||
|
Some('-') => Some((false, Symbol::intern(&s[1..]))),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if enabled {
|
||||||
|
features.extend(sess.target.implied_target_features(std::iter::once(feature)));
|
||||||
|
} else {
|
||||||
|
features.retain(|f| {
|
||||||
|
!sess.target.implied_target_features(std::iter::once(*f)).contains(&feature)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter enabled features based on feature gates
|
||||||
|
sess.target
|
||||||
|
.supported_target_features()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|&(feature, gate, _)| {
|
||||||
|
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
|
||||||
|
Some(feature)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(|feature| {
|
||||||
|
RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
|
||||||
|
})
|
||||||
.map(|feature| Symbol::intern(feature))
|
.map(|feature| Symbol::intern(feature))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -386,7 +386,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
|
|||||||
.target
|
.target
|
||||||
.supported_target_features()
|
.supported_target_features()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(feature, _gate)| {
|
.map(|(feature, _gate, _implied)| {
|
||||||
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
|
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
|
||||||
let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name;
|
let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name;
|
||||||
let desc =
|
let desc =
|
||||||
@ -440,7 +440,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
|
|||||||
|
|
||||||
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
||||||
require_inited();
|
require_inited();
|
||||||
let tm = create_informational_target_machine(sess);
|
let tm = create_informational_target_machine(sess, false);
|
||||||
match req.kind {
|
match req.kind {
|
||||||
PrintKind::TargetCPUs => {
|
PrintKind::TargetCPUs => {
|
||||||
// SAFETY generate a C compatible string from a byte slice to pass
|
// SAFETY generate a C compatible string from a byte slice to pass
|
||||||
@ -488,7 +488,11 @@ pub fn target_cpu(sess: &Session) -> &str {
|
|||||||
|
|
||||||
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
|
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
|
||||||
/// `--target` and similar).
|
/// `--target` and similar).
|
||||||
pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<String> {
|
pub(crate) fn global_llvm_features(
|
||||||
|
sess: &Session,
|
||||||
|
diagnostics: bool,
|
||||||
|
only_base_features: bool,
|
||||||
|
) -> Vec<String> {
|
||||||
// Features that come earlier are overridden by conflicting features later in the string.
|
// Features that come earlier are overridden by conflicting features later in the string.
|
||||||
// Typically we'll want more explicit settings to override the implicit ones, so:
|
// Typically we'll want more explicit settings to override the implicit ones, so:
|
||||||
//
|
//
|
||||||
@ -548,14 +552,30 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -Ctarget-features
|
// -Ctarget-features
|
||||||
|
if !only_base_features {
|
||||||
let supported_features = sess.target.supported_target_features();
|
let supported_features = sess.target.supported_target_features();
|
||||||
let (llvm_major, _, _) = get_version();
|
let (llvm_major, _, _) = get_version();
|
||||||
let mut featsmap = FxHashMap::default();
|
let mut featsmap = FxHashMap::default();
|
||||||
let feats = sess
|
|
||||||
.opts
|
// insert implied features
|
||||||
.cg
|
let mut all_rust_features = vec![];
|
||||||
.target_feature
|
for feature in sess.opts.cg.target_feature.split(',') {
|
||||||
.split(',')
|
match feature.strip_prefix('+') {
|
||||||
|
Some(feature) => all_rust_features.extend(
|
||||||
|
UnordSet::from(
|
||||||
|
sess.target
|
||||||
|
.implied_target_features(std::iter::once(Symbol::intern(feature))),
|
||||||
|
)
|
||||||
|
.to_sorted_stable_ord()
|
||||||
|
.iter()
|
||||||
|
.map(|s| format!("+{}", s.as_str())),
|
||||||
|
),
|
||||||
|
_ => all_rust_features.push(feature.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let feats = all_rust_features
|
||||||
|
.iter()
|
||||||
.filter_map(|s| {
|
.filter_map(|s| {
|
||||||
let enable_disable = match s.chars().next() {
|
let enable_disable = match s.chars().next() {
|
||||||
None => return None,
|
None => return None,
|
||||||
@ -571,11 +591,13 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
let feature = backend_feature_name(sess, s)?;
|
let feature = backend_feature_name(sess, s)?;
|
||||||
// Warn against use of LLVM specific feature names and unstable features on the CLI.
|
// Warn against use of LLVM specific feature names and unstable features on the CLI.
|
||||||
if diagnostics {
|
if diagnostics {
|
||||||
let feature_state = supported_features.iter().find(|&&(v, _)| v == feature);
|
let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
|
||||||
if feature_state.is_none() {
|
if feature_state.is_none() {
|
||||||
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
|
let rust_feature =
|
||||||
|
supported_features.iter().find_map(|&(rust_feature, _, _)| {
|
||||||
let llvm_features = to_llvm_features(sess, rust_feature);
|
let llvm_features = to_llvm_features(sess, rust_feature);
|
||||||
if llvm_features.contains(feature) && !llvm_features.contains(rust_feature)
|
if llvm_features.contains(feature)
|
||||||
|
&& !llvm_features.contains(rust_feature)
|
||||||
{
|
{
|
||||||
Some(rust_feature)
|
Some(rust_feature)
|
||||||
} else {
|
} else {
|
||||||
@ -592,7 +614,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
};
|
};
|
||||||
sess.dcx().emit_warn(unknown_feature);
|
sess.dcx().emit_warn(unknown_feature);
|
||||||
} else if feature_state
|
} else if feature_state
|
||||||
.is_some_and(|(_name, feature_gate)| !feature_gate.is_stable())
|
.is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
|
||||||
{
|
{
|
||||||
// An unstable feature. Warn about using it.
|
// An unstable feature. Warn about using it.
|
||||||
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
||||||
@ -622,21 +644,33 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
let llvm_feature = to_llvm_features(sess, feature);
|
let llvm_feature = to_llvm_features(sess, feature);
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
|
std::iter::once(format!(
|
||||||
.chain(llvm_feature.dependency.into_iter().filter_map(move |feat| {
|
"{}{}",
|
||||||
match (enable_disable, feat) {
|
enable_disable, llvm_feature.llvm_feature_name
|
||||||
|
))
|
||||||
|
.chain(llvm_feature.dependency.into_iter().filter_map(
|
||||||
|
move |feat| match (enable_disable, feat) {
|
||||||
('-' | '+', TargetFeatureFoldStrength::Both(f))
|
('-' | '+', TargetFeatureFoldStrength::Both(f))
|
||||||
| ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
|
| ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
|
||||||
Some(format!("{enable_disable}{f}"))
|
Some(format!("{enable_disable}{f}"))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
},
|
||||||
})),
|
)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.flatten();
|
.flatten();
|
||||||
features.extend(feats);
|
features.extend(feats);
|
||||||
|
|
||||||
|
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
||||||
|
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
|
||||||
|
features: f,
|
||||||
|
span: None,
|
||||||
|
missing_features: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -Zfixed-x18
|
// -Zfixed-x18
|
||||||
if sess.opts.unstable_opts.fixed_x18 {
|
if sess.opts.unstable_opts.fixed_x18 {
|
||||||
if sess.target.arch != "aarch64" {
|
if sess.target.arch != "aarch64" {
|
||||||
@ -646,30 +680,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a workaround for a LLVM bug that doesn't implicitly enable
|
|
||||||
// `simd128` when `relaxed-simd` is.
|
|
||||||
// See <https://github.com/llvm/llvm-project/pull/99803>, which didn't make
|
|
||||||
// it into a released version of LLVM yet.
|
|
||||||
//
|
|
||||||
// This doesn't use the "implicit target feature" system because it is only
|
|
||||||
// used for function attributes in other targets, which fixes this bug as
|
|
||||||
// well on the function attribute level.
|
|
||||||
if sess.target.families.contains(&"wasm".into()) {
|
|
||||||
if features.iter().any(|f| f == "+relaxed-simd")
|
|
||||||
&& !features.iter().any(|f| f == "+simd128")
|
|
||||||
{
|
|
||||||
features.push("+simd128".into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
|
||||||
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
|
|
||||||
features: f,
|
|
||||||
span: None,
|
|
||||||
missing_features: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
features
|
features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use tracing::debug;
|
|||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
use crate::errors::SymbolAlreadyDefined;
|
use crate::errors::SymbolAlreadyDefined;
|
||||||
use crate::type_of::LayoutLlvmExt;
|
use crate::type_of::LayoutLlvmExt;
|
||||||
use crate::{attributes, base, llvm};
|
use crate::{base, llvm};
|
||||||
|
|
||||||
impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
||||||
fn predefine_static(
|
fn predefine_static(
|
||||||
@ -87,8 +87,6 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||||||
|
|
||||||
debug!("predefine_fn: instance = {:?}", instance);
|
debug!("predefine_fn: instance = {:?}", instance);
|
||||||
|
|
||||||
attributes::from_fn_attrs(self, lldecl, instance);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.should_assume_dso_local(lldecl, false) {
|
if self.should_assume_dso_local(lldecl, false) {
|
||||||
llvm::LLVMRustSetDSOLocal(lldecl, true);
|
llvm::LLVMRustSetDSOLocal(lldecl, true);
|
||||||
|
@ -208,6 +208,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
|
|||||||
"powerpc64" => (Architecture::PowerPc64, None),
|
"powerpc64" => (Architecture::PowerPc64, None),
|
||||||
"riscv32" => (Architecture::Riscv32, None),
|
"riscv32" => (Architecture::Riscv32, None),
|
||||||
"riscv64" => (Architecture::Riscv64, None),
|
"riscv64" => (Architecture::Riscv64, None),
|
||||||
|
"sparc" => (Architecture::Sparc32Plus, None),
|
||||||
"sparc64" => (Architecture::Sparc64, None),
|
"sparc64" => (Architecture::Sparc64, None),
|
||||||
"avr" => (Architecture::Avr, None),
|
"avr" => (Architecture::Avr, None),
|
||||||
"msp430" => (Architecture::Msp430, None),
|
"msp430" => (Architecture::Msp430, None),
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_attr::InstructionSetAttr;
|
use rustc_attr::InstructionSetAttr;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
|
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
@ -18,7 +19,7 @@ pub fn from_target_feature(
|
|||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
attr: &ast::Attribute,
|
attr: &ast::Attribute,
|
||||||
supported_target_features: &UnordMap<String, Option<Symbol>>,
|
supported_target_features: &UnordMap<String, Option<Symbol>>,
|
||||||
target_features: &mut Vec<Symbol>,
|
target_features: &mut Vec<TargetFeature>,
|
||||||
) {
|
) {
|
||||||
let Some(list) = attr.meta_item_list() else { return };
|
let Some(list) = attr.meta_item_list() else { return };
|
||||||
let bad_item = |span| {
|
let bad_item = |span| {
|
||||||
@ -30,6 +31,7 @@ pub fn from_target_feature(
|
|||||||
.emit();
|
.emit();
|
||||||
};
|
};
|
||||||
let rust_features = tcx.features();
|
let rust_features = tcx.features();
|
||||||
|
let mut added_target_features = Vec::new();
|
||||||
for item in list {
|
for item in list {
|
||||||
// Only `enable = ...` is accepted in the meta-item list.
|
// Only `enable = ...` is accepted in the meta-item list.
|
||||||
if !item.has_name(sym::enable) {
|
if !item.has_name(sym::enable) {
|
||||||
@ -44,7 +46,7 @@ pub fn from_target_feature(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// We allow comma separation to enable multiple features.
|
// We allow comma separation to enable multiple features.
|
||||||
target_features.extend(value.as_str().split(',').filter_map(|feature| {
|
added_target_features.extend(value.as_str().split(',').filter_map(|feature| {
|
||||||
let Some(feature_gate) = supported_target_features.get(feature) else {
|
let Some(feature_gate) = supported_target_features.get(feature) else {
|
||||||
let msg = format!("the feature named `{feature}` is not valid for this target");
|
let msg = format!("the feature named `{feature}` is not valid for this target");
|
||||||
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
|
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
|
||||||
@ -98,13 +100,26 @@ pub fn from_target_feature(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (feature, requires) in tcx.sess.target.implicit_target_features() {
|
// Add explicit features
|
||||||
if target_features.iter().any(|f| f.as_str() == *feature)
|
target_features.extend(
|
||||||
&& !target_features.iter().any(|f| f.as_str() == *requires)
|
added_target_features.iter().copied().map(|name| TargetFeature { name, implied: false }),
|
||||||
{
|
);
|
||||||
target_features.push(Symbol::intern(requires));
|
|
||||||
|
// Add implied features
|
||||||
|
let mut implied_target_features = UnordSet::new();
|
||||||
|
for feature in added_target_features.iter() {
|
||||||
|
implied_target_features.extend(tcx.implied_target_features(*feature).clone());
|
||||||
}
|
}
|
||||||
|
for feature in added_target_features.iter() {
|
||||||
|
implied_target_features.remove(feature);
|
||||||
}
|
}
|
||||||
|
target_features.extend(
|
||||||
|
implied_target_features
|
||||||
|
.into_sorted_stable_ord()
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(|name| TargetFeature { name, implied: true }),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the set of target features used in a function for the purposes of
|
/// Computes the set of target features used in a function for the purposes of
|
||||||
@ -113,7 +128,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
|
|||||||
let mut target_features = tcx.sess.unstable_target_features.clone();
|
let mut target_features = tcx.sess.unstable_target_features.clone();
|
||||||
if tcx.def_kind(did).has_codegen_attrs() {
|
if tcx.def_kind(did).has_codegen_attrs() {
|
||||||
let attrs = tcx.codegen_fn_attrs(did);
|
let attrs = tcx.codegen_fn_attrs(did);
|
||||||
target_features.extend(&attrs.target_features);
|
target_features.extend(attrs.target_features.iter().map(|feature| feature.name));
|
||||||
match attrs.instruction_set {
|
match attrs.instruction_set {
|
||||||
None => {}
|
None => {}
|
||||||
Some(InstructionSetAttr::ArmA32) => {
|
Some(InstructionSetAttr::ArmA32) => {
|
||||||
@ -158,10 +173,14 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||||||
.target
|
.target
|
||||||
.supported_target_features()
|
.supported_target_features()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(a, b)| (a.to_string(), b.as_feature_name()))
|
.map(|&(a, b, _)| (a.to_string(), b.as_feature_name()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
implied_target_features: |tcx, feature| {
|
||||||
|
UnordSet::from(tcx.sess.target.implied_target_features(std::iter::once(feature)))
|
||||||
|
.into_sorted_stable_ord()
|
||||||
|
},
|
||||||
asm_target_features,
|
asm_target_features,
|
||||||
..*providers
|
..*providers
|
||||||
}
|
}
|
||||||
|
@ -317,19 +317,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
&& attrs
|
&& attrs
|
||||||
.target_features
|
.target_features
|
||||||
.iter()
|
.iter()
|
||||||
.any(|feature| !self.tcx.sess.target_features.contains(feature))
|
.any(|feature| !self.tcx.sess.target_features.contains(&feature.name))
|
||||||
{
|
{
|
||||||
throw_ub_custom!(
|
throw_ub_custom!(
|
||||||
fluent::const_eval_unavailable_target_features_for_fn,
|
fluent::const_eval_unavailable_target_features_for_fn,
|
||||||
unavailable_feats = attrs
|
unavailable_feats = attrs
|
||||||
.target_features
|
.target_features
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&feature| !self.tcx.sess.target_features.contains(feature))
|
.filter(|&feature| !feature.implied
|
||||||
|
&& !self.tcx.sess.target_features.contains(&feature.name))
|
||||||
.fold(String::new(), |mut s, feature| {
|
.fold(String::new(), |mut s, feature| {
|
||||||
if !s.is_empty() {
|
if !s.is_empty() {
|
||||||
s.push_str(", ");
|
s.push_str(", ");
|
||||||
}
|
}
|
||||||
s.push_str(feature.as_str());
|
s.push_str(feature.name.as_str());
|
||||||
s
|
s
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -675,6 +675,13 @@ trait UnusedDelimLint {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not lint against parentheses around `&raw [const|mut] expr`.
|
||||||
|
// These parentheses will have to be added e.g. when calling a method on the result of this
|
||||||
|
// expression, and we want to avoid churn wrt adding and removing parentheses.
|
||||||
|
if matches!(inner.kind, ast::ExprKind::AddrOf(ast::BorrowKind::Raw, ..)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if LHS needs parens to prevent false-positives in cases like
|
// Check if LHS needs parens to prevent false-positives in cases like
|
||||||
// `fn x() -> u8 { ({ 0 } + 1) }`.
|
// `fn x() -> u8 { ({ 0 } + 1) }`.
|
||||||
//
|
//
|
||||||
|
@ -28,7 +28,7 @@ pub struct CodegenFnAttrs {
|
|||||||
pub link_ordinal: Option<u16>,
|
pub link_ordinal: Option<u16>,
|
||||||
/// The `#[target_feature(enable = "...")]` attribute and the enabled
|
/// The `#[target_feature(enable = "...")]` attribute and the enabled
|
||||||
/// features (only enabled features are supported right now).
|
/// features (only enabled features are supported right now).
|
||||||
pub target_features: Vec<Symbol>,
|
pub target_features: Vec<TargetFeature>,
|
||||||
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
|
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
|
||||||
pub linkage: Option<Linkage>,
|
pub linkage: Option<Linkage>,
|
||||||
/// The `#[linkage = "..."]` attribute on foreign items and the value we found.
|
/// The `#[linkage = "..."]` attribute on foreign items and the value we found.
|
||||||
@ -51,6 +51,15 @@ pub struct CodegenFnAttrs {
|
|||||||
pub patchable_function_entry: Option<PatchableFunctionEntry>,
|
pub patchable_function_entry: Option<PatchableFunctionEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||||
|
pub struct TargetFeature {
|
||||||
|
/// The name of the target feature (e.g. "avx")
|
||||||
|
pub name: Symbol,
|
||||||
|
/// The feature is implied by another feature, rather than explicitly added by the
|
||||||
|
/// `#[target_feature]` attribute
|
||||||
|
pub implied: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||||
pub struct PatchableFunctionEntry {
|
pub struct PatchableFunctionEntry {
|
||||||
/// Nops to prepend to the function
|
/// Nops to prepend to the function
|
||||||
|
@ -2183,6 +2183,12 @@ rustc_queries! {
|
|||||||
desc { "looking up supported target features" }
|
desc { "looking up supported target features" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query implied_target_features(feature: Symbol) -> &'tcx Vec<Symbol> {
|
||||||
|
arena_cache
|
||||||
|
eval_always
|
||||||
|
desc { "looking up implied target features" }
|
||||||
|
}
|
||||||
|
|
||||||
query features_query(_: ()) -> &'tcx rustc_feature::Features {
|
query features_query(_: ()) -> &'tcx rustc_feature::Features {
|
||||||
feedable
|
feedable
|
||||||
desc { "looking up enabled feature gates" }
|
desc { "looking up enabled feature gates" }
|
||||||
|
@ -5,6 +5,7 @@ use std::ops::Bound;
|
|||||||
use rustc_errors::DiagArgValue;
|
use rustc_errors::DiagArgValue;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
|
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
|
||||||
|
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
|
||||||
use rustc_middle::mir::BorrowKind;
|
use rustc_middle::mir::BorrowKind;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::thir::visit::Visitor;
|
use rustc_middle::thir::visit::Visitor;
|
||||||
@ -31,7 +32,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
|
|||||||
safety_context: SafetyContext,
|
safety_context: SafetyContext,
|
||||||
/// The `#[target_feature]` attributes of the body. Used for checking
|
/// The `#[target_feature]` attributes of the body. Used for checking
|
||||||
/// calls to functions with `#[target_feature]` (RFC 2396).
|
/// calls to functions with `#[target_feature]` (RFC 2396).
|
||||||
body_target_features: &'tcx [Symbol],
|
body_target_features: &'tcx [TargetFeature],
|
||||||
/// When inside the LHS of an assignment to a field, this is the type
|
/// When inside the LHS of an assignment to a field, this is the type
|
||||||
/// of the LHS and the span of the assignment expression.
|
/// of the LHS and the span of the assignment expression.
|
||||||
assignment_info: Option<Ty<'tcx>>,
|
assignment_info: Option<Ty<'tcx>>,
|
||||||
@ -442,14 +443,21 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||||||
// is_like_wasm check in hir_analysis/src/collect.rs
|
// is_like_wasm check in hir_analysis/src/collect.rs
|
||||||
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
|
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
|
||||||
if !self.tcx.sess.target.options.is_like_wasm
|
if !self.tcx.sess.target.options.is_like_wasm
|
||||||
&& !callee_features
|
&& !callee_features.iter().all(|feature| {
|
||||||
.iter()
|
self.body_target_features.iter().any(|f| f.name == feature.name)
|
||||||
.all(|feature| self.body_target_features.contains(feature))
|
})
|
||||||
{
|
{
|
||||||
let missing: Vec<_> = callee_features
|
let missing: Vec<_> = callee_features
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.filter(|feature| !self.body_target_features.contains(feature))
|
.filter(|feature| {
|
||||||
|
!feature.implied
|
||||||
|
&& !self
|
||||||
|
.body_target_features
|
||||||
|
.iter()
|
||||||
|
.any(|body_feature| body_feature.name == feature.name)
|
||||||
|
})
|
||||||
|
.map(|feature| feature.name)
|
||||||
.collect();
|
.collect();
|
||||||
let build_enabled = self
|
let build_enabled = self
|
||||||
.tcx
|
.tcx
|
||||||
|
@ -479,7 +479,9 @@ impl<'tcx> Inliner<'tcx> {
|
|||||||
return Err("incompatible instruction set");
|
return Err("incompatible instruction set");
|
||||||
}
|
}
|
||||||
|
|
||||||
if callee_attrs.target_features != self.codegen_fn_attrs.target_features {
|
let callee_feature_names = callee_attrs.target_features.iter().map(|f| f.name);
|
||||||
|
let this_feature_names = self.codegen_fn_attrs.target_features.iter().map(|f| f.name);
|
||||||
|
if callee_feature_names.ne(this_feature_names) {
|
||||||
// In general it is not correct to inline a callee with target features that are a
|
// In general it is not correct to inline a callee with target features that are a
|
||||||
// subset of the caller. This is because the callee might contain calls, and the ABI of
|
// subset of the caller. This is because the callee might contain calls, and the ABI of
|
||||||
// those calls depends on the target features of the surrounding function. By moving a
|
// those calls depends on the target features of the surrounding function. By moving a
|
||||||
|
@ -283,6 +283,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
finalize.then(|| Finalize::new(id, path.span)),
|
finalize.then(|| Finalize::new(id, path.span)),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
|
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
|
||||||
let res = module.res().expect("visibility resolved to unnamed block");
|
let res = module.res().expect("visibility resolved to unnamed block");
|
||||||
@ -372,7 +373,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||||||
has_attributes: !item.attrs.is_empty(),
|
has_attributes: !item.attrs.is_empty(),
|
||||||
root_span,
|
root_span,
|
||||||
root_id,
|
root_id,
|
||||||
vis: Cell::new(Some(vis)),
|
vis,
|
||||||
used: Default::default(),
|
used: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -888,7 +889,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||||||
root_span: item.span,
|
root_span: item.span,
|
||||||
span: item.span,
|
span: item.span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis: Cell::new(Some(vis)),
|
vis,
|
||||||
used: Cell::new(used.then_some(Used::Other)),
|
used: Cell::new(used.then_some(Used::Other)),
|
||||||
});
|
});
|
||||||
self.r.potentially_unused_imports.push(import);
|
self.r.potentially_unused_imports.push(import);
|
||||||
@ -1089,7 +1090,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||||||
root_span: span,
|
root_span: span,
|
||||||
span,
|
span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis: Cell::new(Some(ty::Visibility::Restricted(CRATE_DEF_ID))),
|
vis: ty::Visibility::Restricted(CRATE_DEF_ID),
|
||||||
used: Default::default(),
|
used: Default::default(),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -1125,6 +1126,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||||||
ident,
|
ident,
|
||||||
MacroNS,
|
MacroNS,
|
||||||
&self.parent_scope,
|
&self.parent_scope,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
if let Ok(binding) = result {
|
if let Ok(binding) = result {
|
||||||
let import = macro_use_import(self, ident.span, false);
|
let import = macro_use_import(self, ident.span, false);
|
||||||
@ -1253,7 +1255,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||||||
root_span: span,
|
root_span: span,
|
||||||
span,
|
span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis: Cell::new(Some(vis)),
|
vis,
|
||||||
used: Cell::new(Some(Used::Other)),
|
used: Cell::new(Some(Used::Other)),
|
||||||
});
|
});
|
||||||
let import_binding = self.r.import(binding, import);
|
let import_binding = self.r.import(binding, import);
|
||||||
|
@ -382,7 +382,7 @@ impl Resolver<'_, '_> {
|
|||||||
for import in self.potentially_unused_imports.iter() {
|
for import in self.potentially_unused_imports.iter() {
|
||||||
match import.kind {
|
match import.kind {
|
||||||
_ if import.used.get().is_some()
|
_ if import.used.get().is_some()
|
||||||
|| import.expect_vis().is_public()
|
|| import.vis.is_public()
|
||||||
|| import.span.is_dummy() =>
|
|| import.span.is_dummy() =>
|
||||||
{
|
{
|
||||||
if let ImportKind::MacroUse { .. } = import.kind {
|
if let ImportKind::MacroUse { .. } = import.kind {
|
||||||
|
@ -1052,6 +1052,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
suggestions.extend(
|
suggestions.extend(
|
||||||
ext.helper_attrs
|
ext.helper_attrs
|
||||||
@ -1506,6 +1507,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
let desc = match binding.res() {
|
let desc = match binding.res() {
|
||||||
Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
|
Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
|
||||||
@ -1983,6 +1985,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
module: Option<ModuleOrUniformRoot<'a>>,
|
module: Option<ModuleOrUniformRoot<'a>>,
|
||||||
failed_segment_idx: usize,
|
failed_segment_idx: usize,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
@ -2066,11 +2069,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
None,
|
None,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
} else if let Some(ribs) = ribs
|
} else if let Some(ribs) = ribs
|
||||||
&& let Some(TypeNS | ValueNS) = opt_ns
|
&& let Some(TypeNS | ValueNS) = opt_ns
|
||||||
{
|
{
|
||||||
|
assert!(ignore_import.is_none());
|
||||||
match self.resolve_ident_in_lexical_scope(
|
match self.resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ns_to_try,
|
ns_to_try,
|
||||||
@ -2091,6 +2096,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
};
|
};
|
||||||
@ -2132,6 +2138,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
} else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
|
} else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
|
||||||
// Check whether the name refers to an item in the value namespace.
|
// Check whether the name refers to an item in the value namespace.
|
||||||
let binding = if let Some(ribs) = ribs {
|
let binding = if let Some(ribs) = ribs {
|
||||||
|
assert!(ignore_import.is_none());
|
||||||
self.resolve_ident_in_lexical_scope(
|
self.resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ValueNS,
|
ValueNS,
|
||||||
@ -2206,6 +2213,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
) {
|
) {
|
||||||
let descr = binding.res().descr();
|
let descr = binding.res().descr();
|
||||||
(format!("{descr} `{ident}` is not a crate or module"), suggestion)
|
(format!("{descr} `{ident}` is not a crate or module"), suggestion)
|
||||||
@ -2259,7 +2267,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
) -> Option<(Vec<Segment>, Option<String>)> {
|
) -> Option<(Vec<Segment>, Option<String>)> {
|
||||||
// Replace first ident with `self` and check if that is valid.
|
// Replace first ident with `self` and check if that is valid.
|
||||||
path[0].ident.name = kw::SelfLower;
|
path[0].ident.name = kw::SelfLower;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope);
|
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
|
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
|
||||||
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
||||||
}
|
}
|
||||||
@ -2278,7 +2286,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
) -> Option<(Vec<Segment>, Option<String>)> {
|
) -> Option<(Vec<Segment>, Option<String>)> {
|
||||||
// Replace first ident with `crate` and check if that is valid.
|
// Replace first ident with `crate` and check if that is valid.
|
||||||
path[0].ident.name = kw::Crate;
|
path[0].ident.name = kw::Crate;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope);
|
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
|
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
|
||||||
if let PathResult::Module(..) = result {
|
if let PathResult::Module(..) = result {
|
||||||
Some((
|
Some((
|
||||||
@ -2309,7 +2317,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
) -> Option<(Vec<Segment>, Option<String>)> {
|
) -> Option<(Vec<Segment>, Option<String>)> {
|
||||||
// Replace first ident with `crate` and check if that is valid.
|
// Replace first ident with `crate` and check if that is valid.
|
||||||
path[0].ident.name = kw::Super;
|
path[0].ident.name = kw::Super;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope);
|
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
|
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
|
||||||
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
||||||
}
|
}
|
||||||
@ -2343,7 +2351,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
for name in extern_crate_names.into_iter() {
|
for name in extern_crate_names.into_iter() {
|
||||||
// Replace first ident with a crate name and check if that is valid.
|
// Replace first ident with a crate name and check if that is valid.
|
||||||
path[0].ident.name = name;
|
path[0].ident.name = name;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope);
|
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!(
|
debug!(
|
||||||
"make_external_crate_suggestion: name={:?} path={:?} result={:?}",
|
"make_external_crate_suggestion: name={:?} path={:?} result={:?}",
|
||||||
name, path, result
|
name, path, result
|
||||||
@ -2509,12 +2517,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Finds a cfg-ed out item inside `module` with the matching name.
|
/// Finds a cfg-ed out item inside `module` with the matching name.
|
||||||
pub(crate) fn find_cfg_stripped(
|
pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
|
||||||
&mut self,
|
|
||||||
err: &mut Diag<'_>,
|
|
||||||
segment: &Symbol,
|
|
||||||
module: DefId,
|
|
||||||
) {
|
|
||||||
let local_items;
|
let local_items;
|
||||||
let symbols = if module.is_local() {
|
let symbols = if module.is_local() {
|
||||||
local_items = self
|
local_items = self
|
||||||
|
@ -14,6 +14,7 @@ use Determinacy::*;
|
|||||||
use Namespace::*;
|
use Namespace::*;
|
||||||
|
|
||||||
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
|
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
|
||||||
|
use crate::imports::Import;
|
||||||
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
|
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
|
||||||
use crate::macros::{sub_namespace_match, MacroRulesScope};
|
use crate::macros::{sub_namespace_match, MacroRulesScope};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -351,6 +352,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
if let Ok(binding) = item {
|
if let Ok(binding) = item {
|
||||||
// The ident resolves to an item.
|
// The ident resolves to an item.
|
||||||
@ -364,6 +366,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
finalize,
|
finalize,
|
||||||
finalize.is_some(),
|
finalize.is_some(),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
.map(LexicalScopeBinding::Item)
|
.map(LexicalScopeBinding::Item)
|
||||||
@ -383,6 +386,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
force: bool,
|
force: bool,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<NameBinding<'a>, Determinacy> {
|
) -> Result<NameBinding<'a>, Determinacy> {
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -455,6 +459,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
true,
|
true,
|
||||||
force,
|
force,
|
||||||
|
ignore_import,
|
||||||
) {
|
) {
|
||||||
Ok((Some(ext), _)) => {
|
Ok((Some(ext), _)) => {
|
||||||
if ext.helper_attrs.contains(&ident.name) {
|
if ext.helper_attrs.contains(&ident.name) {
|
||||||
@ -496,6 +501,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
finalize,
|
finalize,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
);
|
);
|
||||||
match binding {
|
match binding {
|
||||||
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
|
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
|
||||||
@ -518,6 +524,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
!matches!(scope_set, ScopeSet::Late(..)),
|
!matches!(scope_set, ScopeSet::Late(..)),
|
||||||
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
);
|
);
|
||||||
match binding {
|
match binding {
|
||||||
Ok(binding) => {
|
Ok(binding) => {
|
||||||
@ -585,6 +592,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
None,
|
None,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
) {
|
) {
|
||||||
if matches!(use_prelude, UsePrelude::Yes)
|
if matches!(use_prelude, UsePrelude::Yes)
|
||||||
|| this.is_builtin_macro(binding.res())
|
|| this.is_builtin_macro(binding.res())
|
||||||
@ -738,8 +746,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
ident: Ident,
|
ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<NameBinding<'a>, Determinacy> {
|
) -> Result<NameBinding<'a>, Determinacy> {
|
||||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None)
|
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import)
|
||||||
.map_err(|(determinacy, _)| determinacy)
|
.map_err(|(determinacy, _)| determinacy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,8 +761,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<NameBinding<'a>, Determinacy> {
|
) -> Result<NameBinding<'a>, Determinacy> {
|
||||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding)
|
self.resolve_ident_in_module_ext(
|
||||||
|
module,
|
||||||
|
ident,
|
||||||
|
ns,
|
||||||
|
parent_scope,
|
||||||
|
finalize,
|
||||||
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
|
)
|
||||||
.map_err(|(determinacy, _)| determinacy)
|
.map_err(|(determinacy, _)| determinacy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,6 +784,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
|
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
|
||||||
let tmp_parent_scope;
|
let tmp_parent_scope;
|
||||||
let mut adjusted_parent_scope = parent_scope;
|
let mut adjusted_parent_scope = parent_scope;
|
||||||
@ -792,6 +811,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
false,
|
false,
|
||||||
finalize,
|
finalize,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,6 +824,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<NameBinding<'a>, Determinacy> {
|
) -> Result<NameBinding<'a>, Determinacy> {
|
||||||
self.resolve_ident_in_module_unadjusted_ext(
|
self.resolve_ident_in_module_unadjusted_ext(
|
||||||
module,
|
module,
|
||||||
@ -813,6 +834,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
false,
|
false,
|
||||||
finalize,
|
finalize,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
)
|
)
|
||||||
.map_err(|(determinacy, _)| determinacy)
|
.map_err(|(determinacy, _)| determinacy)
|
||||||
}
|
}
|
||||||
@ -831,6 +853,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
// This binding should be ignored during in-module resolution, so that we don't get
|
// This binding should be ignored during in-module resolution, so that we don't get
|
||||||
// "self-confirming" import resolutions during import validation and checking.
|
// "self-confirming" import resolutions during import validation and checking.
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
|
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
|
||||||
let module = match module {
|
let module = match module {
|
||||||
ModuleOrUniformRoot::Module(module) => module,
|
ModuleOrUniformRoot::Module(module) => module,
|
||||||
@ -843,6 +866,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
finalize,
|
finalize,
|
||||||
finalize.is_some(),
|
finalize.is_some(),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
);
|
);
|
||||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||||
}
|
}
|
||||||
@ -879,6 +903,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
finalize,
|
finalize,
|
||||||
finalize.is_some(),
|
finalize.is_some(),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
);
|
);
|
||||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||||
}
|
}
|
||||||
@ -962,25 +987,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
// Check if one of single imports can still define the name,
|
// Check if one of single imports can still define the name,
|
||||||
// if it can then our result is not determined and can be invalidated.
|
// if it can then our result is not determined and can be invalidated.
|
||||||
for single_import in &resolution.single_imports {
|
for single_import in &resolution.single_imports {
|
||||||
let Some(import_vis) = single_import.vis.get() else {
|
if ignore_import == Some(*single_import) {
|
||||||
// This branch handles a cycle in single imports, which occurs
|
// This branch handles a cycle in single imports.
|
||||||
// when we've previously **steal** the `vis` value during an import
|
|
||||||
// process.
|
|
||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
// ```
|
// ```
|
||||||
// use a::b;
|
// use a::b;
|
||||||
// use b as a;
|
// use b as a;
|
||||||
// ```
|
// ```
|
||||||
// 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the
|
// 1. Record `use a::b` as the `ignore_import` and attempt to locate `a` in the
|
||||||
// current module.
|
// current module.
|
||||||
// 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
|
// 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
|
||||||
// and try to find `b` in the current module.
|
// and try to find `b` in the current module.
|
||||||
// 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
|
// 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
|
||||||
// This leads to entering this branch.
|
// This leads to entering this branch.
|
||||||
continue;
|
continue;
|
||||||
};
|
}
|
||||||
if !self.is_accessible_from(import_vis, parent_scope.module) {
|
if !self.is_accessible_from(single_import.vis, parent_scope.module) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(ignored) = ignore_binding
|
if let Some(ignored) = ignore_binding
|
||||||
@ -1022,6 +1045,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&single_import.parent_scope,
|
&single_import.parent_scope,
|
||||||
None,
|
None,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
) {
|
) {
|
||||||
Err(Determined) => continue,
|
Err(Determined) => continue,
|
||||||
Ok(binding)
|
Ok(binding)
|
||||||
@ -1070,10 +1094,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
// Check if one of glob imports can still define the name,
|
// Check if one of glob imports can still define the name,
|
||||||
// if it can then our "no resolution" result is not determined and can be invalidated.
|
// if it can then our "no resolution" result is not determined and can be invalidated.
|
||||||
for glob_import in module.globs.borrow().iter() {
|
for glob_import in module.globs.borrow().iter() {
|
||||||
let Some(import_vis) = glob_import.vis.get() else {
|
if ignore_import == Some(*glob_import) {
|
||||||
continue;
|
continue;
|
||||||
};
|
}
|
||||||
if !self.is_accessible_from(import_vis, parent_scope.module) {
|
if !self.is_accessible_from(glob_import.vis, parent_scope.module) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let module = match glob_import.imported_module.get() {
|
let module = match glob_import.imported_module.get() {
|
||||||
@ -1100,6 +1124,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
adjusted_parent_scope,
|
adjusted_parent_scope,
|
||||||
None,
|
None,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
);
|
);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
@ -1412,8 +1437,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
path: &[Segment],
|
path: &[Segment],
|
||||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> PathResult<'a> {
|
) -> PathResult<'a> {
|
||||||
self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None)
|
self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
@ -1424,8 +1450,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> PathResult<'a> {
|
) -> PathResult<'a> {
|
||||||
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding)
|
self.resolve_path_with_ribs(
|
||||||
|
path,
|
||||||
|
opt_ns,
|
||||||
|
parent_scope,
|
||||||
|
finalize,
|
||||||
|
None,
|
||||||
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_path_with_ribs(
|
pub(crate) fn resolve_path_with_ribs(
|
||||||
@ -1436,6 +1471,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
||||||
ignore_binding: Option<NameBinding<'a>>,
|
ignore_binding: Option<NameBinding<'a>>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> PathResult<'a> {
|
) -> PathResult<'a> {
|
||||||
let mut module = None;
|
let mut module = None;
|
||||||
let mut allow_super = true;
|
let mut allow_super = true;
|
||||||
@ -1538,10 +1574,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
finalize,
|
finalize,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
)
|
)
|
||||||
} else if let Some(ribs) = ribs
|
} else if let Some(ribs) = ribs
|
||||||
&& let Some(TypeNS | ValueNS) = opt_ns
|
&& let Some(TypeNS | ValueNS) = opt_ns
|
||||||
{
|
{
|
||||||
|
assert!(ignore_import.is_none());
|
||||||
match self.resolve_ident_in_lexical_scope(
|
match self.resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@ -1570,6 +1608,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
finalize,
|
finalize,
|
||||||
finalize.is_some(),
|
finalize.is_some(),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1644,6 +1683,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope,
|
parent_scope,
|
||||||
ribs,
|
ribs,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
module,
|
module,
|
||||||
segment_idx,
|
segment_idx,
|
||||||
ident,
|
ident,
|
||||||
|
@ -175,7 +175,7 @@ pub(crate) struct ImportData<'a> {
|
|||||||
pub module_path: Vec<Segment>,
|
pub module_path: Vec<Segment>,
|
||||||
/// The resolution of `module_path`.
|
/// The resolution of `module_path`.
|
||||||
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
|
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
|
||||||
pub vis: Cell<Option<ty::Visibility>>,
|
pub vis: ty::Visibility,
|
||||||
pub used: Cell<Option<Used>>,
|
pub used: Cell<Option<Used>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,10 +195,6 @@ impl<'a> ImportData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn expect_vis(&self) -> ty::Visibility {
|
|
||||||
self.vis.get().expect("encountered cleared import visibility")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn id(&self) -> Option<NodeId> {
|
pub(crate) fn id(&self) -> Option<NodeId> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ImportKind::Single { id, .. }
|
ImportKind::Single { id, .. }
|
||||||
@ -267,7 +263,7 @@ fn pub_use_of_private_extern_crate_hack(
|
|||||||
match (&import.kind, &binding.kind) {
|
match (&import.kind, &binding.kind) {
|
||||||
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
|
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
|
||||||
if let ImportKind::ExternCrate { id, .. } = binding_import.kind
|
if let ImportKind::ExternCrate { id, .. } = binding_import.kind
|
||||||
&& import.expect_vis().is_public() =>
|
&& import.vis.is_public() =>
|
||||||
{
|
{
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
@ -279,7 +275,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
/// Given a binding and an import that resolves to it,
|
/// Given a binding and an import that resolves to it,
|
||||||
/// return the corresponding binding defined by the import.
|
/// return the corresponding binding defined by the import.
|
||||||
pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
|
pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
|
||||||
let import_vis = import.expect_vis().to_def_id();
|
let import_vis = import.vis.to_def_id();
|
||||||
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|
||||||
|| pub_use_of_private_extern_crate_hack(import, binding).is_some()
|
|| pub_use_of_private_extern_crate_hack(import, binding).is_some()
|
||||||
{
|
{
|
||||||
@ -773,11 +769,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
let module = if let Some(module) = import.imported_module.get() {
|
let module = if let Some(module) = import.imported_module.get() {
|
||||||
module
|
module
|
||||||
} else {
|
} else {
|
||||||
// For better failure detection, pretend that the import will
|
let path_res = self.maybe_resolve_path(
|
||||||
// not define any names while resolving its module path.
|
&import.module_path,
|
||||||
let orig_vis = import.vis.take();
|
None,
|
||||||
let path_res = self.maybe_resolve_path(&import.module_path, None, &import.parent_scope);
|
&import.parent_scope,
|
||||||
import.vis.set(orig_vis);
|
Some(import),
|
||||||
|
);
|
||||||
|
|
||||||
match path_res {
|
match path_res {
|
||||||
PathResult::Module(module) => module,
|
PathResult::Module(module) => module,
|
||||||
@ -807,16 +804,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if !type_ns_only || ns == TypeNS {
|
if !type_ns_only || ns == TypeNS {
|
||||||
if let Err(Undetermined) = source_bindings[ns].get() {
|
if let Err(Undetermined) = source_bindings[ns].get() {
|
||||||
// For better failure detection, pretend that the import will
|
|
||||||
// not define any names while resolving its module path.
|
|
||||||
let orig_vis = import.vis.take();
|
|
||||||
let binding = this.maybe_resolve_ident_in_module(
|
let binding = this.maybe_resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
source,
|
source,
|
||||||
ns,
|
ns,
|
||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
|
Some(import),
|
||||||
);
|
);
|
||||||
import.vis.set(orig_vis);
|
|
||||||
source_bindings[ns].set(binding);
|
source_bindings[ns].set(binding);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@ -855,7 +849,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
/// Optionally returns an unresolved import error. This error is buffered and used to
|
/// Optionally returns an unresolved import error. This error is buffered and used to
|
||||||
/// consolidate multiple unresolved import errors into a single diagnostic.
|
/// consolidate multiple unresolved import errors into a single diagnostic.
|
||||||
fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
|
fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
|
||||||
let orig_vis = import.vis.take();
|
|
||||||
let ignore_binding = match &import.kind {
|
let ignore_binding = match &import.kind {
|
||||||
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
|
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -874,11 +867,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
Some(finalize),
|
Some(finalize),
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
|
Some(import),
|
||||||
);
|
);
|
||||||
|
|
||||||
let no_ambiguity =
|
let no_ambiguity =
|
||||||
ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
|
ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
|
||||||
import.vis.set(orig_vis);
|
|
||||||
let module = match path_res {
|
let module = match path_res {
|
||||||
PathResult::Module(module) => {
|
PathResult::Module(module) => {
|
||||||
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
||||||
@ -1013,8 +1007,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
if !is_prelude
|
if !is_prelude
|
||||||
&& let Some(max_vis) = max_vis.get()
|
&& let Some(max_vis) = max_vis.get()
|
||||||
&& let import_vis = import.expect_vis()
|
&& !max_vis.is_at_least(import.vis, self.tcx)
|
||||||
&& !max_vis.is_at_least(import_vis, self.tcx)
|
|
||||||
{
|
{
|
||||||
let def_id = self.local_def_id(id);
|
let def_id = self.local_def_id(id);
|
||||||
self.lint_buffer.buffer_lint(
|
self.lint_buffer.buffer_lint(
|
||||||
@ -1023,7 +1016,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
import.span,
|
import.span,
|
||||||
BuiltinLintDiag::RedundantImportVisibility {
|
BuiltinLintDiag::RedundantImportVisibility {
|
||||||
max_vis: max_vis.to_string(def_id, self.tcx),
|
max_vis: max_vis.to_string(def_id, self.tcx),
|
||||||
import_vis: import_vis.to_string(def_id, self.tcx),
|
import_vis: import.vis.to_string(def_id, self.tcx),
|
||||||
span: import.span,
|
span: import.span,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -1038,9 +1031,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
// importing it if available.
|
// importing it if available.
|
||||||
let mut path = import.module_path.clone();
|
let mut path = import.module_path.clone();
|
||||||
path.push(Segment::from_ident(ident));
|
path.push(Segment::from_ident(ident));
|
||||||
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
|
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(
|
||||||
self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding)
|
&path,
|
||||||
{
|
None,
|
||||||
|
&import.parent_scope,
|
||||||
|
Some(finalize),
|
||||||
|
ignore_binding,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
let res = module.res().map(|r| (r, ident));
|
let res = module.res().map(|r| (r, ident));
|
||||||
for error in &mut self.privacy_errors[privacy_errors_len..] {
|
for error in &mut self.privacy_errors[privacy_errors_len..] {
|
||||||
error.outermost_res = res;
|
error.outermost_res = res;
|
||||||
@ -1051,7 +1049,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
let mut all_ns_err = true;
|
let mut all_ns_err = true;
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if !type_ns_only || ns == TypeNS {
|
if !type_ns_only || ns == TypeNS {
|
||||||
let orig_vis = import.vis.take();
|
|
||||||
let binding = this.resolve_ident_in_module(
|
let binding = this.resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
ident,
|
ident,
|
||||||
@ -1059,8 +1056,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
Some(Finalize { report_private: false, ..finalize }),
|
Some(Finalize { report_private: false, ..finalize }),
|
||||||
target_bindings[ns].get(),
|
target_bindings[ns].get(),
|
||||||
|
Some(import),
|
||||||
);
|
);
|
||||||
import.vis.set(orig_vis);
|
|
||||||
|
|
||||||
match binding {
|
match binding {
|
||||||
Ok(binding) => {
|
Ok(binding) => {
|
||||||
@ -1123,6 +1120,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
Some(finalize),
|
Some(finalize),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
if binding.is_ok() {
|
if binding.is_ok() {
|
||||||
all_ns_failed = false;
|
all_ns_failed = false;
|
||||||
@ -1233,7 +1231,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
let mut crate_private_reexport = false;
|
let mut crate_private_reexport = false;
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if let Ok(binding) = source_bindings[ns].get() {
|
if let Ok(binding) = source_bindings[ns].get() {
|
||||||
if !binding.vis.is_at_least(import.expect_vis(), this.tcx) {
|
if !binding.vis.is_at_least(import.vis, this.tcx) {
|
||||||
reexport_error = Some((ns, binding));
|
reexport_error = Some((ns, binding));
|
||||||
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
|
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
|
||||||
if binding_def_id.is_top_level_module() {
|
if binding_def_id.is_top_level_module() {
|
||||||
@ -1370,6 +1368,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
target_bindings[ns].get(),
|
target_bindings[ns].get(),
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
Ok(other_binding) => {
|
Ok(other_binding) => {
|
||||||
is_redundant = binding.res() == other_binding.res()
|
is_redundant = binding.res() == other_binding.res()
|
||||||
|
@ -1388,6 +1388,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||||||
finalize,
|
finalize,
|
||||||
Some(&self.ribs),
|
Some(&self.ribs),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4186,7 +4187,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||||||
let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
|
let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
|
||||||
let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
|
let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
|
||||||
if let Ok((_, res)) =
|
if let Ok((_, res)) =
|
||||||
self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false)
|
self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None)
|
||||||
{
|
{
|
||||||
return Ok(Some(PartialRes::new(res)));
|
return Ok(Some(PartialRes::new(res)));
|
||||||
}
|
}
|
||||||
|
@ -2058,6 +2058,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
&self.parent_scope,
|
&self.parent_scope,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
let res = binding.res();
|
let res = binding.res();
|
||||||
if filter_fn(res) {
|
if filter_fn(res) {
|
||||||
|
@ -2120,7 +2120,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) {
|
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope, None) {
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
|
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
|
||||||
PathResult::NonModule(path_res) => path_res.full_res(),
|
PathResult::NonModule(path_res) => path_res.full_res(),
|
||||||
PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
|
PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
|
||||||
@ -2204,6 +2204,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
ident,
|
ident,
|
||||||
ValueNS,
|
ValueNS,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
|
None,
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -39,6 +39,7 @@ use crate::errors::{
|
|||||||
self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
|
self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
|
||||||
MacroExpectedFound, RemoveSurroundingDerive,
|
MacroExpectedFound, RemoveSurroundingDerive,
|
||||||
};
|
};
|
||||||
|
use crate::imports::Import;
|
||||||
use crate::Namespace::*;
|
use crate::Namespace::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, MacroData, ModuleKind,
|
BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, MacroData, ModuleKind,
|
||||||
@ -399,6 +400,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
|
|||||||
&parent_scope,
|
&parent_scope,
|
||||||
true,
|
true,
|
||||||
force,
|
force,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
Ok((Some(ext), _)) => {
|
Ok((Some(ext), _)) => {
|
||||||
if !ext.helper_attrs.is_empty() {
|
if !ext.helper_attrs.is_empty() {
|
||||||
@ -551,6 +553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
force,
|
force,
|
||||||
deleg_impl,
|
deleg_impl,
|
||||||
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
|
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
Ok((Some(ext), res)) => (ext, res),
|
Ok((Some(ext), res)) => (ext, res),
|
||||||
Ok((None, res)) => (self.dummy_ext(kind), res),
|
Ok((None, res)) => (self.dummy_ext(kind), res),
|
||||||
@ -704,8 +707,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
trace: bool,
|
trace: bool,
|
||||||
force: bool,
|
force: bool,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
|
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
|
||||||
self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None, None)
|
self.resolve_macro_or_delegation_path(
|
||||||
|
path,
|
||||||
|
kind,
|
||||||
|
parent_scope,
|
||||||
|
trace,
|
||||||
|
force,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
ignore_import,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_macro_or_delegation_path(
|
fn resolve_macro_or_delegation_path(
|
||||||
@ -717,6 +730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
force: bool,
|
force: bool,
|
||||||
deleg_impl: Option<LocalDefId>,
|
deleg_impl: Option<LocalDefId>,
|
||||||
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
|
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
|
||||||
|
ignore_import: Option<Import<'a>>,
|
||||||
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
|
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
|
||||||
let path_span = ast_path.span;
|
let path_span = ast_path.span;
|
||||||
let mut path = Segment::from_path(ast_path);
|
let mut path = Segment::from_path(ast_path);
|
||||||
@ -733,7 +747,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
|
|
||||||
let res = if deleg_impl.is_some() || path.len() > 1 {
|
let res = if deleg_impl.is_some() || path.len() > 1 {
|
||||||
let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
|
let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
|
||||||
let res = match self.maybe_resolve_path(&path, Some(ns), parent_scope) {
|
let res = match self.maybe_resolve_path(&path, Some(ns), parent_scope, ignore_import) {
|
||||||
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
|
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
|
||||||
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
||||||
PathResult::NonModule(..)
|
PathResult::NonModule(..)
|
||||||
@ -768,6 +782,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
force,
|
force,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
if let Err(Determinacy::Undetermined) = binding {
|
if let Err(Determinacy::Undetermined) = binding {
|
||||||
return Err(Determinacy::Undetermined);
|
return Err(Determinacy::Undetermined);
|
||||||
@ -852,6 +867,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&parent_scope,
|
&parent_scope,
|
||||||
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
|
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
|
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
|
||||||
check_consistency(self, &path, path_span, kind, initial_res, res)
|
check_consistency(self, &path, path_span, kind, initial_res, res)
|
||||||
@ -871,7 +887,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
if let PathResult::Failed { span, label, module, .. } = path_res {
|
if let PathResult::Failed { span, label, module, .. } = path_res {
|
||||||
// try to suggest if it's not a macro, maybe a function
|
// try to suggest if it's not a macro, maybe a function
|
||||||
if let PathResult::NonModule(partial_res) =
|
if let PathResult::NonModule(partial_res) =
|
||||||
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
|
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
|
||||||
&& partial_res.unresolved_segments() == 0
|
&& partial_res.unresolved_segments() == 0
|
||||||
{
|
{
|
||||||
let sm = self.tcx.sess.source_map();
|
let sm = self.tcx.sess.source_map();
|
||||||
@ -921,6 +937,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
) {
|
) {
|
||||||
Ok(binding) => {
|
Ok(binding) => {
|
||||||
let initial_res = initial_binding.map(|initial_binding| {
|
let initial_res = initial_binding.map(|initial_binding| {
|
||||||
@ -966,6 +983,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1070,6 +1088,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
|
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
|
||||||
self.tcx.sess.psess.buffer_lint(
|
self.tcx.sess.psess.buffer_lint(
|
||||||
@ -1143,7 +1162,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
|
|
||||||
let mut indeterminate = false;
|
let mut indeterminate = false;
|
||||||
for ns in namespaces {
|
for ns in namespaces {
|
||||||
match self.maybe_resolve_path(path, Some(*ns), &parent_scope) {
|
match self.maybe_resolve_path(path, Some(*ns), &parent_scope, None) {
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
|
PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
|
||||||
PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
|
PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
/// Features that control behaviour of rustc, rather than the codegen.
|
/// Features that control behaviour of rustc, rather than the codegen.
|
||||||
@ -53,136 +54,154 @@ impl Stability {
|
|||||||
//
|
//
|
||||||
// Stabilizing a target feature requires t-lang approval.
|
// Stabilizing a target feature requires t-lang approval.
|
||||||
|
|
||||||
const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
type ImpliedFeatures = &'static [&'static str];
|
||||||
|
|
||||||
|
const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("aclass", Unstable(sym::arm_target_feature)),
|
("aclass", Unstable(sym::arm_target_feature), &[]),
|
||||||
("aes", Unstable(sym::arm_target_feature)),
|
("aes", Unstable(sym::arm_target_feature), &["neon"]),
|
||||||
("crc", Unstable(sym::arm_target_feature)),
|
("crc", Unstable(sym::arm_target_feature), &[]),
|
||||||
("d32", Unstable(sym::arm_target_feature)),
|
("d32", Unstable(sym::arm_target_feature), &[]),
|
||||||
("dotprod", Unstable(sym::arm_target_feature)),
|
("dotprod", Unstable(sym::arm_target_feature), &["neon"]),
|
||||||
("dsp", Unstable(sym::arm_target_feature)),
|
("dsp", Unstable(sym::arm_target_feature), &[]),
|
||||||
("fp-armv8", Unstable(sym::arm_target_feature)),
|
("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]),
|
||||||
("i8mm", Unstable(sym::arm_target_feature)),
|
("i8mm", Unstable(sym::arm_target_feature), &["neon"]),
|
||||||
("mclass", Unstable(sym::arm_target_feature)),
|
("mclass", Unstable(sym::arm_target_feature), &[]),
|
||||||
("neon", Unstable(sym::arm_target_feature)),
|
("neon", Unstable(sym::arm_target_feature), &["vfp3"]),
|
||||||
("rclass", Unstable(sym::arm_target_feature)),
|
("rclass", Unstable(sym::arm_target_feature), &[]),
|
||||||
("sha2", Unstable(sym::arm_target_feature)),
|
("sha2", Unstable(sym::arm_target_feature), &["neon"]),
|
||||||
// This is needed for inline assembly, but shouldn't be stabilized as-is
|
// This is needed for inline assembly, but shouldn't be stabilized as-is
|
||||||
// since it should be enabled per-function using #[instruction_set], not
|
// since it should be enabled per-function using #[instruction_set], not
|
||||||
// #[target_feature].
|
// #[target_feature].
|
||||||
("thumb-mode", Unstable(sym::arm_target_feature)),
|
("thumb-mode", Unstable(sym::arm_target_feature), &[]),
|
||||||
("thumb2", Unstable(sym::arm_target_feature)),
|
("thumb2", Unstable(sym::arm_target_feature), &[]),
|
||||||
("trustzone", Unstable(sym::arm_target_feature)),
|
("trustzone", Unstable(sym::arm_target_feature), &[]),
|
||||||
("v5te", Unstable(sym::arm_target_feature)),
|
("v5te", Unstable(sym::arm_target_feature), &[]),
|
||||||
("v6", Unstable(sym::arm_target_feature)),
|
("v6", Unstable(sym::arm_target_feature), &["v5te"]),
|
||||||
("v6k", Unstable(sym::arm_target_feature)),
|
("v6k", Unstable(sym::arm_target_feature), &["v6"]),
|
||||||
("v6t2", Unstable(sym::arm_target_feature)),
|
("v6t2", Unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
|
||||||
("v7", Unstable(sym::arm_target_feature)),
|
("v7", Unstable(sym::arm_target_feature), &["v6t2"]),
|
||||||
("v8", Unstable(sym::arm_target_feature)),
|
("v8", Unstable(sym::arm_target_feature), &["v7"]),
|
||||||
("vfp2", Unstable(sym::arm_target_feature)),
|
("vfp2", Unstable(sym::arm_target_feature), &[]),
|
||||||
("vfp3", Unstable(sym::arm_target_feature)),
|
("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]),
|
||||||
("vfp4", Unstable(sym::arm_target_feature)),
|
("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
|
||||||
("virtualization", Unstable(sym::arm_target_feature)),
|
("virtualization", Unstable(sym::arm_target_feature), &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
// FEAT_AES & FEAT_PMULL
|
// FEAT_AES & FEAT_PMULL
|
||||||
("aes", Stable),
|
("aes", Stable, &["neon"]),
|
||||||
// FEAT_BF16
|
// FEAT_BF16
|
||||||
("bf16", Stable),
|
("bf16", Stable, &[]),
|
||||||
// FEAT_BTI
|
// FEAT_BTI
|
||||||
("bti", Stable),
|
("bti", Stable, &[]),
|
||||||
// FEAT_CRC
|
// FEAT_CRC
|
||||||
("crc", Stable),
|
("crc", Stable, &[]),
|
||||||
// FEAT_DIT
|
// FEAT_DIT
|
||||||
("dit", Stable),
|
("dit", Stable, &[]),
|
||||||
// FEAT_DotProd
|
// FEAT_DotProd
|
||||||
("dotprod", Stable),
|
("dotprod", Stable, &["neon"]),
|
||||||
// FEAT_DPB
|
// FEAT_DPB
|
||||||
("dpb", Stable),
|
("dpb", Stable, &[]),
|
||||||
// FEAT_DPB2
|
// FEAT_DPB2
|
||||||
("dpb2", Stable),
|
("dpb2", Stable, &["dpb"]),
|
||||||
// FEAT_F32MM
|
// FEAT_F32MM
|
||||||
("f32mm", Stable),
|
("f32mm", Stable, &["sve"]),
|
||||||
// FEAT_F64MM
|
// FEAT_F64MM
|
||||||
("f64mm", Stable),
|
("f64mm", Stable, &["sve"]),
|
||||||
// FEAT_FCMA
|
// FEAT_FCMA
|
||||||
("fcma", Stable),
|
("fcma", Stable, &["neon"]),
|
||||||
// FEAT_FHM
|
// FEAT_FHM
|
||||||
("fhm", Stable),
|
("fhm", Stable, &["fp16"]),
|
||||||
// FEAT_FLAGM
|
// FEAT_FLAGM
|
||||||
("flagm", Stable),
|
("flagm", Stable, &[]),
|
||||||
// FEAT_FP16
|
// FEAT_FP16
|
||||||
("fp16", Stable),
|
// Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
|
||||||
|
("fp16", Stable, &["neon"]),
|
||||||
// FEAT_FRINTTS
|
// FEAT_FRINTTS
|
||||||
("frintts", Stable),
|
("frintts", Stable, &[]),
|
||||||
// FEAT_I8MM
|
// FEAT_I8MM
|
||||||
("i8mm", Stable),
|
("i8mm", Stable, &[]),
|
||||||
// FEAT_JSCVT
|
// FEAT_JSCVT
|
||||||
("jsconv", Stable),
|
// Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
|
||||||
|
("jsconv", Stable, &["neon"]),
|
||||||
// FEAT_LOR
|
// FEAT_LOR
|
||||||
("lor", Stable),
|
("lor", Stable, &[]),
|
||||||
// FEAT_LSE
|
// FEAT_LSE
|
||||||
("lse", Stable),
|
("lse", Stable, &[]),
|
||||||
// FEAT_MTE & FEAT_MTE2
|
// FEAT_MTE & FEAT_MTE2
|
||||||
("mte", Stable),
|
("mte", Stable, &[]),
|
||||||
// FEAT_AdvSimd & FEAT_FP
|
// FEAT_AdvSimd & FEAT_FP
|
||||||
("neon", Stable),
|
("neon", Stable, &[]),
|
||||||
// FEAT_PAUTH (address authentication)
|
// FEAT_PAUTH (address authentication)
|
||||||
("paca", Stable),
|
("paca", Stable, &[]),
|
||||||
// FEAT_PAUTH (generic authentication)
|
// FEAT_PAUTH (generic authentication)
|
||||||
("pacg", Stable),
|
("pacg", Stable, &[]),
|
||||||
// FEAT_PAN
|
// FEAT_PAN
|
||||||
("pan", Stable),
|
("pan", Stable, &[]),
|
||||||
// FEAT_PMUv3
|
// FEAT_PMUv3
|
||||||
("pmuv3", Stable),
|
("pmuv3", Stable, &[]),
|
||||||
// FEAT_RAND
|
// FEAT_RAND
|
||||||
("rand", Stable),
|
("rand", Stable, &[]),
|
||||||
// FEAT_RAS & FEAT_RASv1p1
|
// FEAT_RAS & FEAT_RASv1p1
|
||||||
("ras", Stable),
|
("ras", Stable, &[]),
|
||||||
// FEAT_RCPC
|
// FEAT_RCPC
|
||||||
("rcpc", Stable),
|
("rcpc", Stable, &[]),
|
||||||
// FEAT_RCPC2
|
// FEAT_RCPC2
|
||||||
("rcpc2", Stable),
|
("rcpc2", Stable, &["rcpc"]),
|
||||||
// FEAT_RDM
|
// FEAT_RDM
|
||||||
("rdm", Stable),
|
("rdm", Stable, &["neon"]),
|
||||||
// FEAT_SB
|
// FEAT_SB
|
||||||
("sb", Stable),
|
("sb", Stable, &[]),
|
||||||
// FEAT_SHA1 & FEAT_SHA256
|
// FEAT_SHA1 & FEAT_SHA256
|
||||||
("sha2", Stable),
|
("sha2", Stable, &["neon"]),
|
||||||
// FEAT_SHA512 & FEAT_SHA3
|
// FEAT_SHA512 & FEAT_SHA3
|
||||||
("sha3", Stable),
|
("sha3", Stable, &["sha2"]),
|
||||||
// FEAT_SM3 & FEAT_SM4
|
// FEAT_SM3 & FEAT_SM4
|
||||||
("sm4", Stable),
|
("sm4", Stable, &["neon"]),
|
||||||
// FEAT_SPE
|
// FEAT_SPE
|
||||||
("spe", Stable),
|
("spe", Stable, &[]),
|
||||||
// FEAT_SSBS & FEAT_SSBS2
|
// FEAT_SSBS & FEAT_SSBS2
|
||||||
("ssbs", Stable),
|
("ssbs", Stable, &[]),
|
||||||
// FEAT_SVE
|
// FEAT_SVE
|
||||||
("sve", Stable),
|
// It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608
|
||||||
|
//
|
||||||
|
// LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always
|
||||||
|
// exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2
|
||||||
|
//
|
||||||
|
// "For backwards compatibility, Neon and VFP are required in the latest architectures."
|
||||||
|
("sve", Stable, &["neon"]),
|
||||||
// FEAT_SVE2
|
// FEAT_SVE2
|
||||||
("sve2", Stable),
|
("sve2", Stable, &["sve"]),
|
||||||
// FEAT_SVE2_AES
|
// FEAT_SVE2_AES
|
||||||
("sve2-aes", Stable),
|
("sve2-aes", Stable, &["sve2", "aes"]),
|
||||||
// FEAT_SVE2_BitPerm
|
// FEAT_SVE2_BitPerm
|
||||||
("sve2-bitperm", Stable),
|
("sve2-bitperm", Stable, &["sve2"]),
|
||||||
// FEAT_SVE2_SHA3
|
// FEAT_SVE2_SHA3
|
||||||
("sve2-sha3", Stable),
|
("sve2-sha3", Stable, &["sve2", "sha3"]),
|
||||||
// FEAT_SVE2_SM4
|
// FEAT_SVE2_SM4
|
||||||
("sve2-sm4", Stable),
|
("sve2-sm4", Stable, &["sve2", "sm4"]),
|
||||||
// FEAT_TME
|
// FEAT_TME
|
||||||
("tme", Stable),
|
("tme", Stable, &[]),
|
||||||
("v8.1a", Unstable(sym::aarch64_ver_target_feature)),
|
(
|
||||||
("v8.2a", Unstable(sym::aarch64_ver_target_feature)),
|
"v8.1a",
|
||||||
("v8.3a", Unstable(sym::aarch64_ver_target_feature)),
|
Unstable(sym::aarch64_ver_target_feature),
|
||||||
("v8.4a", Unstable(sym::aarch64_ver_target_feature)),
|
&["crc", "lse", "rdm", "pan", "lor", "vh"],
|
||||||
("v8.5a", Unstable(sym::aarch64_ver_target_feature)),
|
),
|
||||||
("v8.6a", Unstable(sym::aarch64_ver_target_feature)),
|
("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
|
||||||
("v8.7a", Unstable(sym::aarch64_ver_target_feature)),
|
(
|
||||||
|
"v8.3a",
|
||||||
|
Unstable(sym::aarch64_ver_target_feature),
|
||||||
|
&["v8.2a", "rcpc", "paca", "pacg", "jsconv"],
|
||||||
|
),
|
||||||
|
("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
|
||||||
|
("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
|
||||||
|
("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
|
||||||
|
("v8.7a", Unstable(sym::aarch64_ver_target_feature), &[]),
|
||||||
// FEAT_VHE
|
// FEAT_VHE
|
||||||
("vh", Stable),
|
("vh", Stable, &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -190,224 +209,223 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
|
|||||||
&["paca", "pacg"], // Together these represent `pauth` in LLVM
|
&["paca", "pacg"], // Together these represent `pauth` in LLVM
|
||||||
];
|
];
|
||||||
|
|
||||||
const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("adx", Stable),
|
("adx", Stable, &[]),
|
||||||
("aes", Stable),
|
("aes", Stable, &["sse2"]),
|
||||||
("amx-bf16", Unstable(sym::x86_amx_intrinsics)),
|
("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
|
||||||
("amx-complex", Unstable(sym::x86_amx_intrinsics)),
|
("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
|
||||||
("amx-fp16", Unstable(sym::x86_amx_intrinsics)),
|
("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
|
||||||
("amx-int8", Unstable(sym::x86_amx_intrinsics)),
|
("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
|
||||||
("amx-tile", Unstable(sym::x86_amx_intrinsics)),
|
("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
|
||||||
("avx", Stable),
|
("avx", Stable, &["sse4.2"]),
|
||||||
("avx2", Stable),
|
("avx2", Stable, &["avx"]),
|
||||||
("avx512bf16", Unstable(sym::avx512_target_feature)),
|
("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
|
||||||
("avx512bitalg", Unstable(sym::avx512_target_feature)),
|
("avx512bitalg", Unstable(sym::avx512_target_feature), &["avx512bw"]),
|
||||||
("avx512bw", Unstable(sym::avx512_target_feature)),
|
("avx512bw", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512cd", Unstable(sym::avx512_target_feature)),
|
("avx512cd", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512dq", Unstable(sym::avx512_target_feature)),
|
("avx512dq", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512f", Unstable(sym::avx512_target_feature)),
|
("avx512f", Unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]),
|
||||||
("avx512fp16", Unstable(sym::avx512_target_feature)),
|
("avx512fp16", Unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]),
|
||||||
("avx512ifma", Unstable(sym::avx512_target_feature)),
|
("avx512ifma", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512vbmi", Unstable(sym::avx512_target_feature)),
|
("avx512vbmi", Unstable(sym::avx512_target_feature), &["avx512bw"]),
|
||||||
("avx512vbmi2", Unstable(sym::avx512_target_feature)),
|
("avx512vbmi2", Unstable(sym::avx512_target_feature), &["avx512bw"]),
|
||||||
("avx512vl", Unstable(sym::avx512_target_feature)),
|
("avx512vl", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512vnni", Unstable(sym::avx512_target_feature)),
|
("avx512vnni", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512vp2intersect", Unstable(sym::avx512_target_feature)),
|
("avx512vp2intersect", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avx512vpopcntdq", Unstable(sym::avx512_target_feature)),
|
("avx512vpopcntdq", Unstable(sym::avx512_target_feature), &["avx512f"]),
|
||||||
("avxifma", Unstable(sym::avx512_target_feature)),
|
("avxifma", Unstable(sym::avx512_target_feature), &["avx2"]),
|
||||||
("avxneconvert", Unstable(sym::avx512_target_feature)),
|
("avxneconvert", Unstable(sym::avx512_target_feature), &["avx2"]),
|
||||||
("avxvnni", Unstable(sym::avx512_target_feature)),
|
("avxvnni", Unstable(sym::avx512_target_feature), &["avx2"]),
|
||||||
("avxvnniint16", Unstable(sym::avx512_target_feature)),
|
("avxvnniint16", Unstable(sym::avx512_target_feature), &["avx2"]),
|
||||||
("avxvnniint8", Unstable(sym::avx512_target_feature)),
|
("avxvnniint8", Unstable(sym::avx512_target_feature), &["avx2"]),
|
||||||
("bmi1", Stable),
|
("bmi1", Stable, &[]),
|
||||||
("bmi2", Stable),
|
("bmi2", Stable, &[]),
|
||||||
("cmpxchg16b", Stable),
|
("cmpxchg16b", Stable, &[]),
|
||||||
("ermsb", Unstable(sym::ermsb_target_feature)),
|
("ermsb", Unstable(sym::ermsb_target_feature), &[]),
|
||||||
("f16c", Stable),
|
("f16c", Stable, &["avx"]),
|
||||||
("fma", Stable),
|
("fma", Stable, &["avx"]),
|
||||||
("fxsr", Stable),
|
("fxsr", Stable, &[]),
|
||||||
("gfni", Unstable(sym::avx512_target_feature)),
|
("gfni", Unstable(sym::avx512_target_feature), &["sse2"]),
|
||||||
("lahfsahf", Unstable(sym::lahfsahf_target_feature)),
|
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
|
||||||
("lzcnt", Stable),
|
("lzcnt", Stable, &[]),
|
||||||
("movbe", Stable),
|
("movbe", Stable, &[]),
|
||||||
("pclmulqdq", Stable),
|
("pclmulqdq", Stable, &[]),
|
||||||
("popcnt", Stable),
|
("popcnt", Stable, &[]),
|
||||||
("prfchw", Unstable(sym::prfchw_target_feature)),
|
("prfchw", Unstable(sym::prfchw_target_feature), &[]),
|
||||||
("rdrand", Stable),
|
("rdrand", Stable, &[]),
|
||||||
("rdseed", Stable),
|
("rdseed", Stable, &[]),
|
||||||
("rtm", Unstable(sym::rtm_target_feature)),
|
("rtm", Unstable(sym::rtm_target_feature), &[]),
|
||||||
("sha", Stable),
|
("sha", Stable, &["sse2"]),
|
||||||
("sha512", Unstable(sym::sha512_sm_x86)),
|
("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
|
||||||
("sm3", Unstable(sym::sha512_sm_x86)),
|
("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
|
||||||
("sm4", Unstable(sym::sha512_sm_x86)),
|
("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
|
||||||
("sse", Stable),
|
("sse", Stable, &[]),
|
||||||
("sse2", Stable),
|
("sse2", Stable, &["sse"]),
|
||||||
("sse3", Stable),
|
("sse3", Stable, &["sse2"]),
|
||||||
("sse4.1", Stable),
|
("sse4.1", Stable, &["ssse3"]),
|
||||||
("sse4.2", Stable),
|
("sse4.2", Stable, &["sse4.1"]),
|
||||||
("sse4a", Unstable(sym::sse4a_target_feature)),
|
("sse4a", Unstable(sym::sse4a_target_feature), &["sse3"]),
|
||||||
("ssse3", Stable),
|
("ssse3", Stable, &["sse3"]),
|
||||||
("tbm", Unstable(sym::tbm_target_feature)),
|
("tbm", Unstable(sym::tbm_target_feature), &[]),
|
||||||
("vaes", Unstable(sym::avx512_target_feature)),
|
("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]),
|
||||||
("vpclmulqdq", Unstable(sym::avx512_target_feature)),
|
("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
|
||||||
("xop", Unstable(sym::xop_target_feature)),
|
("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
|
||||||
("xsave", Stable),
|
("xsave", Stable, &[]),
|
||||||
("xsavec", Stable),
|
("xsavec", Stable, &["xsave"]),
|
||||||
("xsaveopt", Stable),
|
("xsaveopt", Stable, &["xsave"]),
|
||||||
("xsaves", Stable),
|
("xsaves", Stable, &["xsave"]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("hvx", Unstable(sym::hexagon_target_feature)),
|
("hvx", Unstable(sym::hexagon_target_feature), &[]),
|
||||||
("hvx-length128b", Unstable(sym::hexagon_target_feature)),
|
("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const POWERPC_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("altivec", Unstable(sym::powerpc_target_feature)),
|
("altivec", Unstable(sym::powerpc_target_feature), &[]),
|
||||||
("power10-vector", Unstable(sym::powerpc_target_feature)),
|
("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
|
||||||
("power8-altivec", Unstable(sym::powerpc_target_feature)),
|
("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
|
||||||
("power8-vector", Unstable(sym::powerpc_target_feature)),
|
("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
|
||||||
("power9-altivec", Unstable(sym::powerpc_target_feature)),
|
("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
|
||||||
("power9-vector", Unstable(sym::powerpc_target_feature)),
|
("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
|
||||||
("vsx", Unstable(sym::powerpc_target_feature)),
|
("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const MIPS_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("fp64", Unstable(sym::mips_target_feature)),
|
("fp64", Unstable(sym::mips_target_feature), &[]),
|
||||||
("msa", Unstable(sym::mips_target_feature)),
|
("msa", Unstable(sym::mips_target_feature), &[]),
|
||||||
("virt", Unstable(sym::mips_target_feature)),
|
("virt", Unstable(sym::mips_target_feature), &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("a", Stable),
|
("a", Stable, &[]),
|
||||||
("c", Stable),
|
("c", Stable, &[]),
|
||||||
("d", Unstable(sym::riscv_target_feature)),
|
("d", Unstable(sym::riscv_target_feature), &["f"]),
|
||||||
("e", Unstable(sym::riscv_target_feature)),
|
("e", Unstable(sym::riscv_target_feature), &[]),
|
||||||
("f", Unstable(sym::riscv_target_feature)),
|
("f", Unstable(sym::riscv_target_feature), &[]),
|
||||||
("m", Stable),
|
("m", Stable, &[]),
|
||||||
("relax", Unstable(sym::riscv_target_feature)),
|
("relax", Unstable(sym::riscv_target_feature), &[]),
|
||||||
("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)),
|
("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
|
||||||
("v", Unstable(sym::riscv_target_feature)),
|
("v", Unstable(sym::riscv_target_feature), &[]),
|
||||||
("zba", Stable),
|
("zba", Stable, &[]),
|
||||||
("zbb", Stable),
|
("zbb", Stable, &[]),
|
||||||
("zbc", Stable),
|
("zbc", Stable, &[]),
|
||||||
("zbkb", Stable),
|
("zbkb", Stable, &[]),
|
||||||
("zbkc", Stable),
|
("zbkc", Stable, &[]),
|
||||||
("zbkx", Stable),
|
("zbkx", Stable, &[]),
|
||||||
("zbs", Stable),
|
("zbs", Stable, &[]),
|
||||||
("zdinx", Unstable(sym::riscv_target_feature)),
|
("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
|
||||||
("zfh", Unstable(sym::riscv_target_feature)),
|
("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
|
||||||
("zfhmin", Unstable(sym::riscv_target_feature)),
|
("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
|
||||||
("zfinx", Unstable(sym::riscv_target_feature)),
|
("zfinx", Unstable(sym::riscv_target_feature), &[]),
|
||||||
("zhinx", Unstable(sym::riscv_target_feature)),
|
("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
|
||||||
("zhinxmin", Unstable(sym::riscv_target_feature)),
|
("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
|
||||||
("zk", Stable),
|
("zk", Stable, &["zkn", "zkr", "zkt"]),
|
||||||
("zkn", Stable),
|
("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
|
||||||
("zknd", Stable),
|
("zknd", Stable, &[]),
|
||||||
("zkne", Stable),
|
("zkne", Stable, &[]),
|
||||||
("zknh", Stable),
|
("zknh", Stable, &[]),
|
||||||
("zkr", Stable),
|
("zkr", Stable, &[]),
|
||||||
("zks", Stable),
|
("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
|
||||||
("zksed", Stable),
|
("zksed", Stable, &[]),
|
||||||
("zksh", Stable),
|
("zksh", Stable, &[]),
|
||||||
("zkt", Stable),
|
("zkt", Stable, &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("atomics", Unstable(sym::wasm_target_feature)),
|
("atomics", Unstable(sym::wasm_target_feature), &[]),
|
||||||
("bulk-memory", Stable),
|
("bulk-memory", Stable, &[]),
|
||||||
("exception-handling", Unstable(sym::wasm_target_feature)),
|
("exception-handling", Unstable(sym::wasm_target_feature), &[]),
|
||||||
("extended-const", Stable),
|
("extended-const", Stable, &[]),
|
||||||
("multivalue", Unstable(sym::wasm_target_feature)),
|
("multivalue", Unstable(sym::wasm_target_feature), &[]),
|
||||||
("mutable-globals", Stable),
|
("mutable-globals", Stable, &[]),
|
||||||
("nontrapping-fptoint", Stable),
|
("nontrapping-fptoint", Stable, &[]),
|
||||||
("reference-types", Unstable(sym::wasm_target_feature)),
|
("reference-types", Unstable(sym::wasm_target_feature), &[]),
|
||||||
("relaxed-simd", Stable),
|
("relaxed-simd", Stable, &["simd128"]),
|
||||||
("sign-ext", Stable),
|
("sign-ext", Stable, &[]),
|
||||||
("simd128", Stable),
|
("simd128", Stable, &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const WASM_IMPLICIT_FEATURES: &[(&str, &str)] = &[("relaxed-simd", "simd128")];
|
const BPF_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
|
||||||
|
&[("alu32", Unstable(sym::bpf_target_feature), &[])];
|
||||||
|
|
||||||
const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))];
|
const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
|
|
||||||
const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("10e60", Unstable(sym::csky_target_feature)),
|
("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
|
||||||
("2e3", Unstable(sym::csky_target_feature)),
|
("2e3", Unstable(sym::csky_target_feature), &["e2"]),
|
||||||
("3e3r1", Unstable(sym::csky_target_feature)),
|
("3e3r1", Unstable(sym::csky_target_feature), &[]),
|
||||||
("3e3r2", Unstable(sym::csky_target_feature)),
|
("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
|
||||||
("3e3r3", Unstable(sym::csky_target_feature)),
|
("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]),
|
||||||
("3e7", Unstable(sym::csky_target_feature)),
|
("3e7", Unstable(sym::csky_target_feature), &["2e3"]),
|
||||||
("7e10", Unstable(sym::csky_target_feature)),
|
("7e10", Unstable(sym::csky_target_feature), &["3e7"]),
|
||||||
("cache", Unstable(sym::csky_target_feature)),
|
("cache", Unstable(sym::csky_target_feature), &[]),
|
||||||
("doloop", Unstable(sym::csky_target_feature)),
|
("doloop", Unstable(sym::csky_target_feature), &[]),
|
||||||
("dsp1e2", Unstable(sym::csky_target_feature)),
|
("dsp1e2", Unstable(sym::csky_target_feature), &[]),
|
||||||
("dspe60", Unstable(sym::csky_target_feature)),
|
("dspe60", Unstable(sym::csky_target_feature), &[]),
|
||||||
("e1", Unstable(sym::csky_target_feature)),
|
("e1", Unstable(sym::csky_target_feature), &["elrw"]),
|
||||||
("e2", Unstable(sym::csky_target_feature)),
|
("e2", Unstable(sym::csky_target_feature), &["e2"]),
|
||||||
("edsp", Unstable(sym::csky_target_feature)),
|
("edsp", Unstable(sym::csky_target_feature), &[]),
|
||||||
("elrw", Unstable(sym::csky_target_feature)),
|
("elrw", Unstable(sym::csky_target_feature), &[]),
|
||||||
("float1e2", Unstable(sym::csky_target_feature)),
|
("float1e2", Unstable(sym::csky_target_feature), &[]),
|
||||||
("float1e3", Unstable(sym::csky_target_feature)),
|
("float1e3", Unstable(sym::csky_target_feature), &[]),
|
||||||
("float3e4", Unstable(sym::csky_target_feature)),
|
("float3e4", Unstable(sym::csky_target_feature), &[]),
|
||||||
("float7e60", Unstable(sym::csky_target_feature)),
|
("float7e60", Unstable(sym::csky_target_feature), &[]),
|
||||||
("floate1", Unstable(sym::csky_target_feature)),
|
("floate1", Unstable(sym::csky_target_feature), &[]),
|
||||||
("hard-tp", Unstable(sym::csky_target_feature)),
|
("hard-tp", Unstable(sym::csky_target_feature), &[]),
|
||||||
("high-registers", Unstable(sym::csky_target_feature)),
|
("high-registers", Unstable(sym::csky_target_feature), &[]),
|
||||||
("hwdiv", Unstable(sym::csky_target_feature)),
|
("hwdiv", Unstable(sym::csky_target_feature), &[]),
|
||||||
("mp", Unstable(sym::csky_target_feature)),
|
("mp", Unstable(sym::csky_target_feature), &["2e3"]),
|
||||||
("mp1e2", Unstable(sym::csky_target_feature)),
|
("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]),
|
||||||
("nvic", Unstable(sym::csky_target_feature)),
|
("nvic", Unstable(sym::csky_target_feature), &[]),
|
||||||
("trust", Unstable(sym::csky_target_feature)),
|
("trust", Unstable(sym::csky_target_feature), &[]),
|
||||||
("vdsp2e60f", Unstable(sym::csky_target_feature)),
|
("vdsp2e60f", Unstable(sym::csky_target_feature), &[]),
|
||||||
("vdspv1", Unstable(sym::csky_target_feature)),
|
("vdspv1", Unstable(sym::csky_target_feature), &[]),
|
||||||
("vdspv2", Unstable(sym::csky_target_feature)),
|
("vdspv2", Unstable(sym::csky_target_feature), &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
//fpu
|
//fpu
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("fdivdu", Unstable(sym::csky_target_feature)),
|
("fdivdu", Unstable(sym::csky_target_feature), &[]),
|
||||||
("fpuv2_df", Unstable(sym::csky_target_feature)),
|
("fpuv2_df", Unstable(sym::csky_target_feature), &[]),
|
||||||
("fpuv2_sf", Unstable(sym::csky_target_feature)),
|
("fpuv2_sf", Unstable(sym::csky_target_feature), &[]),
|
||||||
("fpuv3_df", Unstable(sym::csky_target_feature)),
|
("fpuv3_df", Unstable(sym::csky_target_feature), &[]),
|
||||||
("fpuv3_hf", Unstable(sym::csky_target_feature)),
|
("fpuv3_hf", Unstable(sym::csky_target_feature), &[]),
|
||||||
("fpuv3_hi", Unstable(sym::csky_target_feature)),
|
("fpuv3_hi", Unstable(sym::csky_target_feature), &[]),
|
||||||
("fpuv3_sf", Unstable(sym::csky_target_feature)),
|
("fpuv3_sf", Unstable(sym::csky_target_feature), &[]),
|
||||||
("hard-float", Unstable(sym::csky_target_feature)),
|
("hard-float", Unstable(sym::csky_target_feature), &[]),
|
||||||
("hard-float-abi", Unstable(sym::csky_target_feature)),
|
("hard-float-abi", Unstable(sym::csky_target_feature), &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("d", Unstable(sym::loongarch_target_feature)),
|
("d", Unstable(sym::loongarch_target_feature), &["f"]),
|
||||||
("f", Unstable(sym::loongarch_target_feature)),
|
("f", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("frecipe", Unstable(sym::loongarch_target_feature)),
|
("frecipe", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("lasx", Unstable(sym::loongarch_target_feature)),
|
("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]),
|
||||||
("lbt", Unstable(sym::loongarch_target_feature)),
|
("lbt", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("lsx", Unstable(sym::loongarch_target_feature)),
|
("lsx", Unstable(sym::loongarch_target_feature), &["d"]),
|
||||||
("lvz", Unstable(sym::loongarch_target_feature)),
|
("lvz", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("relax", Unstable(sym::loongarch_target_feature)),
|
("relax", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("ual", Unstable(sym::loongarch_target_feature)),
|
("ual", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
const IBMZ_ALLOWED_FEATURES: &[(&str, Stability)] = &[
|
const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
("backchain", Unstable(sym::s390x_target_feature)),
|
("backchain", Unstable(sym::s390x_target_feature), &[]),
|
||||||
("vector", Unstable(sym::s390x_target_feature)),
|
("vector", Unstable(sym::s390x_target_feature), &[]),
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -430,10 +448,13 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
|
|||||||
.chain(LOONGARCH_ALLOWED_FEATURES)
|
.chain(LOONGARCH_ALLOWED_FEATURES)
|
||||||
.chain(IBMZ_ALLOWED_FEATURES)
|
.chain(IBMZ_ALLOWED_FEATURES)
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|(f, s, _)| (f, s))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::spec::Target {
|
impl super::spec::Target {
|
||||||
pub fn supported_target_features(&self) -> &'static [(&'static str, Stability)] {
|
pub fn supported_target_features(
|
||||||
|
&self,
|
||||||
|
) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
|
||||||
match &*self.arch {
|
match &*self.arch {
|
||||||
"arm" => ARM_ALLOWED_FEATURES,
|
"arm" => ARM_ALLOWED_FEATURES,
|
||||||
"aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES,
|
"aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES,
|
||||||
@ -458,12 +479,27 @@ impl super::spec::Target {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of target features. Each items first target feature
|
pub fn implied_target_features(
|
||||||
/// implicitly enables the second one.
|
&self,
|
||||||
pub fn implicit_target_features(&self) -> &'static [(&'static str, &'static str)] {
|
base_features: impl Iterator<Item = Symbol>,
|
||||||
match &*self.arch {
|
) -> FxHashSet<Symbol> {
|
||||||
"wasm32" | "wasm64" => WASM_IMPLICIT_FEATURES,
|
let implied_features = self
|
||||||
_ => &[],
|
.supported_target_features()
|
||||||
|
.iter()
|
||||||
|
.map(|(f, _, i)| (Symbol::intern(f), i))
|
||||||
|
.collect::<FxHashMap<_, _>>();
|
||||||
|
|
||||||
|
// implied target features have their own implied target features, so we traverse the
|
||||||
|
// map until there are no more features to add
|
||||||
|
let mut features = FxHashSet::default();
|
||||||
|
let mut new_features = base_features.collect::<Vec<Symbol>>();
|
||||||
|
while let Some(new_feature) = new_features.pop() {
|
||||||
|
if features.insert(new_feature) {
|
||||||
|
if let Some(implied_features) = implied_features.get(&new_feature) {
|
||||||
|
new_features.extend(implied_features.iter().copied().map(Symbol::intern))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
features
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1433,6 +1433,20 @@ pub struct Iter<'a, T: 'a> {
|
|||||||
iter: slice::Iter<'a, T>,
|
iter: slice::Iter<'a, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
impl<T> Default for Iter<'_, T> {
|
||||||
|
/// Creates an empty `binary_heap::Iter`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::binary_heap;
|
||||||
|
/// let iter: binary_heap::Iter<'_, u8> = Default::default();
|
||||||
|
/// assert_eq!(iter.len(), 0);
|
||||||
|
/// ```
|
||||||
|
fn default() -> Self {
|
||||||
|
Iter { iter: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||||
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
@ -2016,6 +2016,20 @@ impl<K, V> Default for Range<'_, K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
impl<K, V> Default for RangeMut<'_, K, V> {
|
||||||
|
/// Creates an empty `btree_map::RangeMut`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::btree_map;
|
||||||
|
/// let iter: btree_map::RangeMut<'_, u8, u8> = Default::default();
|
||||||
|
/// assert_eq!(iter.count(), 0);
|
||||||
|
/// ```
|
||||||
|
fn default() -> Self {
|
||||||
|
RangeMut { inner: Default::default(), _marker: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
||||||
impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
|
impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
|
||||||
type Item = &'a mut V;
|
type Item = &'a mut V;
|
||||||
@ -2050,6 +2064,20 @@ impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
|
|||||||
#[stable(feature = "fused", since = "1.26.0")]
|
#[stable(feature = "fused", since = "1.26.0")]
|
||||||
impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
|
impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
|
||||||
|
|
||||||
|
#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
impl<K, V> Default for ValuesMut<'_, K, V> {
|
||||||
|
/// Creates an empty `btree_map::ValuesMut`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::btree_map;
|
||||||
|
/// let iter: btree_map::ValuesMut<'_, u8, u8> = Default::default();
|
||||||
|
/// assert_eq!(iter.count(), 0);
|
||||||
|
/// ```
|
||||||
|
fn default() -> Self {
|
||||||
|
ValuesMut { inner: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "map_into_keys_values", since = "1.54.0")]
|
#[stable(feature = "map_into_keys_values", since = "1.54.0")]
|
||||||
impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> {
|
impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> {
|
||||||
type Item = K;
|
type Item = K;
|
||||||
|
@ -28,6 +28,20 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
impl<T> Default for Iter<'_, T> {
|
||||||
|
/// Creates an empty `vec_deque::Iter`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::vec_deque;
|
||||||
|
/// let iter: vec_deque::Iter<'_, u8> = Default::default();
|
||||||
|
/// assert_eq!(iter.len(), 0);
|
||||||
|
/// ```
|
||||||
|
fn default() -> Self {
|
||||||
|
Iter { i1: Default::default(), i2: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
|
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Clone for Iter<'_, T> {
|
impl<T> Clone for Iter<'_, T> {
|
||||||
|
@ -28,6 +28,20 @@ impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
impl<T> Default for IterMut<'_, T> {
|
||||||
|
/// Creates an empty `vec_deque::IterMut`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::collections::vec_deque;
|
||||||
|
/// let iter: vec_deque::IterMut<'_, u8> = Default::default();
|
||||||
|
/// assert_eq!(iter.len(), 0);
|
||||||
|
/// ```
|
||||||
|
fn default() -> Self {
|
||||||
|
IterMut { i1: Default::default(), i2: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T> Iterator for IterMut<'a, T> {
|
impl<'a, T> Iterator for IterMut<'a, T> {
|
||||||
type Item = &'a mut T;
|
type Item = &'a mut T;
|
||||||
|
@ -212,11 +212,13 @@ impl Step for GenerateCopyright {
|
|||||||
let license_metadata = builder.ensure(CollectLicenseMetadata);
|
let license_metadata = builder.ensure(CollectLicenseMetadata);
|
||||||
|
|
||||||
// Temporary location, it will be moved to the proper one once it's accurate.
|
// Temporary location, it will be moved to the proper one once it's accurate.
|
||||||
let dest = builder.out.join("COPYRIGHT.md");
|
let dest = builder.out.join("COPYRIGHT.html");
|
||||||
|
|
||||||
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
|
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
|
||||||
cmd.env("LICENSE_METADATA", &license_metadata);
|
cmd.env("LICENSE_METADATA", &license_metadata);
|
||||||
cmd.env("DEST", &dest);
|
cmd.env("DEST", &dest);
|
||||||
|
cmd.env("OUT_DIR", &builder.out);
|
||||||
|
cmd.env("CARGO", &builder.initial_cargo);
|
||||||
cmd.run(builder);
|
cmd.run(builder);
|
||||||
|
|
||||||
dest
|
dest
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
name = "collect-license-metadata"
|
name = "collect-license-metadata"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
description = "Runs the reuse tool and caches the output, so rust toolchain devs don't need to have reuse installed"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.65"
|
anyhow = "1.0.65"
|
||||||
|
@ -8,6 +8,11 @@ use anyhow::Error;
|
|||||||
|
|
||||||
use crate::licenses::LicensesInterner;
|
use crate::licenses::LicensesInterner;
|
||||||
|
|
||||||
|
/// The entry point to the binary.
|
||||||
|
///
|
||||||
|
/// You should probably let `bootstrap` execute this program instead of running it directly.
|
||||||
|
///
|
||||||
|
/// Run `x.py run collect-license-metadata`
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
|
let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
|
||||||
let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
|
let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
name = "generate-copyright"
|
name = "generate-copyright"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
description = "Produces a manifest of all the copyrighted materials in the Rust Toolchain"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.65"
|
anyhow = "1.0.65"
|
||||||
|
cargo_metadata = "0.18.1"
|
||||||
|
rinja = "0.3.0"
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
|
thiserror = "1"
|
||||||
|
191
src/tools/generate-copyright/src/cargo_metadata.rs
Normal file
191
src/tools/generate-copyright/src/cargo_metadata.rs
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
//! Gets metadata about a workspace from Cargo
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
/// Describes how this module can fail
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("I/O Error: {0:?}")]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[error("Failed get output from cargo-metadata: {0:?}")]
|
||||||
|
GettingMetadata(#[from] cargo_metadata::Error),
|
||||||
|
#[error("Failed to run cargo vendor: {0:?}")]
|
||||||
|
LaunchingVendor(std::io::Error),
|
||||||
|
#[error("Failed to complete cargo vendor")]
|
||||||
|
RunningVendor,
|
||||||
|
#[error("Bad path {0:?} whilst scraping files")]
|
||||||
|
Scraping(PathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Uniquely describes a package on crates.io
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Package {
|
||||||
|
/// The name of the package
|
||||||
|
pub name: String,
|
||||||
|
/// The version number
|
||||||
|
pub version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extra data about a package
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct PackageMetadata {
|
||||||
|
/// The license it is under
|
||||||
|
pub license: String,
|
||||||
|
/// The list of authors from the package metadata
|
||||||
|
pub authors: Vec<String>,
|
||||||
|
/// A list of important files from the package, with their contents.
|
||||||
|
///
|
||||||
|
/// This includes *COPYRIGHT*, *NOTICE*, *AUTHOR*, *LICENSE*, and *LICENCE* files, case-insensitive.
|
||||||
|
pub notices: BTreeMap<String, String>,
|
||||||
|
/// If this is true, this dep is in the Rust Standard Library
|
||||||
|
pub is_in_libstd: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data.
|
||||||
|
///
|
||||||
|
/// This will involve running `cargo vendor` into `${BUILD}/vendor` so we can
|
||||||
|
/// grab the license files.
|
||||||
|
///
|
||||||
|
/// Any dependency with a path beginning with `root_path` is ignored, as we
|
||||||
|
/// assume `reuse` has covered it already.
|
||||||
|
pub fn get_metadata_and_notices(
|
||||||
|
cargo: &Path,
|
||||||
|
dest: &Path,
|
||||||
|
root_path: &Path,
|
||||||
|
manifest_paths: &[&Path],
|
||||||
|
) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
|
||||||
|
let mut output = get_metadata(cargo, root_path, manifest_paths)?;
|
||||||
|
|
||||||
|
// Now do a cargo-vendor and grab everything
|
||||||
|
let vendor_path = dest.join("vendor");
|
||||||
|
println!("Vendoring deps into {}...", vendor_path.display());
|
||||||
|
run_cargo_vendor(cargo, &vendor_path, manifest_paths)?;
|
||||||
|
|
||||||
|
// Now for each dependency we found, go and grab any important looking files
|
||||||
|
for (package, metadata) in output.iter_mut() {
|
||||||
|
load_important_files(package, metadata, &vendor_path)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use `cargo metadata` to get a list of dependencies and their license data.
|
||||||
|
///
|
||||||
|
/// Any dependency with a path beginning with `root_path` is ignored, as we
|
||||||
|
/// assume `reuse` has covered it already.
|
||||||
|
pub fn get_metadata(
|
||||||
|
cargo: &Path,
|
||||||
|
root_path: &Path,
|
||||||
|
manifest_paths: &[&Path],
|
||||||
|
) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
|
||||||
|
let mut output = BTreeMap::new();
|
||||||
|
// Look at the metadata for each manifest
|
||||||
|
for manifest_path in manifest_paths {
|
||||||
|
if manifest_path.file_name() != Some(OsStr::new("Cargo.toml")) {
|
||||||
|
panic!("cargo_manifest::get requires a path to a Cargo.toml file");
|
||||||
|
}
|
||||||
|
let metadata = cargo_metadata::MetadataCommand::new()
|
||||||
|
.cargo_path(cargo)
|
||||||
|
.env("RUSTC_BOOTSTRAP", "1")
|
||||||
|
.manifest_path(manifest_path)
|
||||||
|
.exec()?;
|
||||||
|
for package in metadata.packages {
|
||||||
|
let manifest_path = package.manifest_path.as_path();
|
||||||
|
if manifest_path.starts_with(root_path) {
|
||||||
|
// it's an in-tree dependency and reuse covers it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// otherwise it's an out-of-tree dependency
|
||||||
|
let package_id = Package { name: package.name, version: package.version.to_string() };
|
||||||
|
output.insert(
|
||||||
|
package_id,
|
||||||
|
PackageMetadata {
|
||||||
|
license: package.license.unwrap_or_else(|| String::from("Unspecified")),
|
||||||
|
authors: package.authors,
|
||||||
|
notices: BTreeMap::new(),
|
||||||
|
is_in_libstd: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run cargo-vendor, fetching into the given dir
|
||||||
|
fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> {
|
||||||
|
let mut vendor_command = std::process::Command::new(cargo);
|
||||||
|
vendor_command.env("RUSTC_BOOTSTRAP", "1");
|
||||||
|
vendor_command.arg("vendor");
|
||||||
|
vendor_command.arg("--quiet");
|
||||||
|
vendor_command.arg("--versioned-dirs");
|
||||||
|
for manifest_path in manifest_paths {
|
||||||
|
vendor_command.arg("-s");
|
||||||
|
vendor_command.arg(manifest_path);
|
||||||
|
}
|
||||||
|
vendor_command.arg(dest);
|
||||||
|
|
||||||
|
let vendor_status = vendor_command.status().map_err(Error::LaunchingVendor)?;
|
||||||
|
|
||||||
|
if !vendor_status.success() {
|
||||||
|
return Err(Error::RunningVendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add important files off disk into this dependency.
|
||||||
|
///
|
||||||
|
/// Maybe one-day Cargo.toml will contain enough information that we don't need
|
||||||
|
/// to do this manual scraping.
|
||||||
|
fn load_important_files(
|
||||||
|
package: &Package,
|
||||||
|
dep: &mut PackageMetadata,
|
||||||
|
vendor_root: &Path,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let name_version = format!("{}-{}", package.name, package.version);
|
||||||
|
println!("Scraping notices for {}...", name_version);
|
||||||
|
let dep_vendor_path = vendor_root.join(name_version);
|
||||||
|
for entry in std::fs::read_dir(dep_vendor_path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let metadata = entry.metadata()?;
|
||||||
|
let path = entry.path();
|
||||||
|
let Some(filename) = path.file_name() else {
|
||||||
|
return Err(Error::Scraping(path));
|
||||||
|
};
|
||||||
|
let lc_filename = filename.to_ascii_lowercase();
|
||||||
|
let lc_filename_str = lc_filename.to_string_lossy();
|
||||||
|
let mut keep = false;
|
||||||
|
for m in ["copyright", "licence", "license", "author", "notice"] {
|
||||||
|
if lc_filename_str.contains(m) {
|
||||||
|
keep = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if keep {
|
||||||
|
if metadata.is_dir() {
|
||||||
|
for inner_entry in std::fs::read_dir(entry.path())? {
|
||||||
|
let inner_entry = inner_entry?;
|
||||||
|
if inner_entry.metadata()?.is_file() {
|
||||||
|
let inner_filename = inner_entry.file_name();
|
||||||
|
let inner_filename_str = inner_filename.to_string_lossy();
|
||||||
|
let qualified_filename =
|
||||||
|
format!("{}/{}", lc_filename_str, inner_filename_str);
|
||||||
|
println!("Scraping {}", qualified_filename);
|
||||||
|
dep.notices.insert(
|
||||||
|
qualified_filename.to_string(),
|
||||||
|
std::fs::read_to_string(inner_entry.path())?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if metadata.is_file() {
|
||||||
|
let filename = filename.to_string_lossy();
|
||||||
|
println!("Scraping {}", filename);
|
||||||
|
dep.notices.insert(filename.to_string(), std::fs::read_to_string(path)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,79 +1,70 @@
|
|||||||
use std::io::Write;
|
use std::collections::BTreeMap;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use rinja::Template;
|
||||||
|
|
||||||
|
mod cargo_metadata;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "COPYRIGHT.html")]
|
||||||
|
struct CopyrightTemplate {
|
||||||
|
in_tree: Node,
|
||||||
|
dependencies: BTreeMap<cargo_metadata::Package, cargo_metadata::PackageMetadata>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The entry point to the binary.
|
||||||
|
///
|
||||||
|
/// You should probably let `bootstrap` execute this program instead of running it directly.
|
||||||
|
///
|
||||||
|
/// Run `x.py run generate-copyright`
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
let dest = env_path("DEST")?;
|
let dest_file = env_path("DEST")?;
|
||||||
|
let out_dir = env_path("OUT_DIR")?;
|
||||||
|
let cargo = env_path("CARGO")?;
|
||||||
let license_metadata = env_path("LICENSE_METADATA")?;
|
let license_metadata = env_path("LICENSE_METADATA")?;
|
||||||
|
|
||||||
let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
|
let collected_tree_metadata: Metadata =
|
||||||
|
serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
|
||||||
|
|
||||||
let mut buffer = Vec::new();
|
let root_path = std::path::absolute(".")?;
|
||||||
render_recursive(&metadata.files, &mut buffer, 0)?;
|
let workspace_paths = [
|
||||||
|
Path::new("./Cargo.toml"),
|
||||||
|
Path::new("./src/tools/cargo/Cargo.toml"),
|
||||||
|
Path::new("./library/Cargo.toml"),
|
||||||
|
];
|
||||||
|
let mut collected_cargo_metadata =
|
||||||
|
cargo_metadata::get_metadata_and_notices(&cargo, &out_dir, &root_path, &workspace_paths)?;
|
||||||
|
|
||||||
std::fs::write(&dest, &buffer)?;
|
let stdlib_set =
|
||||||
|
cargo_metadata::get_metadata(&cargo, &root_path, &[Path::new("./library/std/Cargo.toml")])?;
|
||||||
Ok(())
|
|
||||||
}
|
for (key, value) in collected_cargo_metadata.iter_mut() {
|
||||||
|
value.is_in_libstd = Some(stdlib_set.contains_key(key));
|
||||||
fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(), Error> {
|
}
|
||||||
let prefix = std::iter::repeat("> ").take(depth + 1).collect::<String>();
|
|
||||||
|
let template = CopyrightTemplate {
|
||||||
match node {
|
in_tree: collected_tree_metadata.files,
|
||||||
Node::Root { children } => {
|
dependencies: collected_cargo_metadata,
|
||||||
for child in children {
|
};
|
||||||
render_recursive(child, buffer, depth)?;
|
|
||||||
}
|
let output = template.render()?;
|
||||||
}
|
|
||||||
Node::Directory { name, children, license } => {
|
std::fs::write(&dest_file, output)?;
|
||||||
render_license(&prefix, std::iter::once(name), license.as_ref(), buffer)?;
|
|
||||||
if !children.is_empty() {
|
|
||||||
writeln!(buffer, "{prefix}")?;
|
|
||||||
writeln!(buffer, "{prefix}*Exceptions:*")?;
|
|
||||||
for child in children {
|
|
||||||
writeln!(buffer, "{prefix}")?;
|
|
||||||
render_recursive(child, buffer, depth + 1)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Node::Group { files, directories, license } => {
|
|
||||||
render_license(&prefix, directories.iter().chain(files.iter()), Some(license), buffer)?;
|
|
||||||
}
|
|
||||||
Node::File { name, license } => {
|
|
||||||
render_license(&prefix, std::iter::once(name), Some(license), buffer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_license<'a>(
|
|
||||||
prefix: &str,
|
|
||||||
names: impl Iterator<Item = &'a String>,
|
|
||||||
license: Option<&License>,
|
|
||||||
buffer: &mut Vec<u8>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
for name in names {
|
|
||||||
writeln!(buffer, "{prefix}**`{name}`** ")?;
|
|
||||||
}
|
|
||||||
if let Some(license) = license {
|
|
||||||
writeln!(buffer, "{prefix}License: `{}`", license.spdx)?;
|
|
||||||
for copyright in license.copyright.iter() {
|
|
||||||
writeln!(buffer, "{prefix}Copyright: {copyright}")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes a tree of metadata for our filesystem tree
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
struct Metadata {
|
struct Metadata {
|
||||||
files: Node,
|
files: Node,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
/// Describes one node in our metadata tree
|
||||||
|
#[derive(serde::Deserialize, rinja::Template)]
|
||||||
#[serde(rename_all = "kebab-case", tag = "type")]
|
#[serde(rename_all = "kebab-case", tag = "type")]
|
||||||
|
#[template(path = "Node.html")]
|
||||||
pub(crate) enum Node {
|
pub(crate) enum Node {
|
||||||
Root { children: Vec<Node> },
|
Root { children: Vec<Node> },
|
||||||
Directory { name: String, children: Vec<Node>, license: Option<License> },
|
Directory { name: String, children: Vec<Node>, license: Option<License> },
|
||||||
@ -81,12 +72,14 @@ pub(crate) enum Node {
|
|||||||
Group { files: Vec<String>, directories: Vec<String>, license: License },
|
Group { files: Vec<String>, directories: Vec<String>, license: License },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A License has an SPDX license name and a list of copyright holders.
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
struct License {
|
struct License {
|
||||||
spdx: String,
|
spdx: String,
|
||||||
copyright: Vec<String>,
|
copyright: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Grab an environment variable as a PathBuf, or fail nicely.
|
||||||
fn env_path(var: &str) -> Result<PathBuf, Error> {
|
fn env_path(var: &str) -> Result<PathBuf, Error> {
|
||||||
if let Some(var) = std::env::var_os(var) {
|
if let Some(var) = std::env::var_os(var) {
|
||||||
Ok(var.into())
|
Ok(var.into())
|
||||||
|
54
src/tools/generate-copyright/templates/COPYRIGHT.html
Normal file
54
src/tools/generate-copyright/templates/COPYRIGHT.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Copyright notices for The Rust Toolchain</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>Copyright notices for The Rust Toolchain</h1>
|
||||||
|
|
||||||
|
<p>This file describes the copyright and licensing information for the source
|
||||||
|
code within The Rust Project git tree, and the third-party dependencies used
|
||||||
|
when building the Rust toolchain (including the Rust Standard Library).</p>
|
||||||
|
|
||||||
|
<h2>Table of Contents</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#in-tree-files">In-tree files</a></li>
|
||||||
|
<li><a href="#out-of-tree-dependencies">Out-of-tree dependencies</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="in-tree-files">In-tree files</h2>
|
||||||
|
|
||||||
|
<p>The following licenses cover the in-tree source files that were used in this
|
||||||
|
release:</p>
|
||||||
|
|
||||||
|
{{ in_tree|safe }}
|
||||||
|
|
||||||
|
<h2 id="out-of-tree-dependencies">Out-of-tree dependencies</h2>
|
||||||
|
|
||||||
|
<p>The following licenses cover the out-of-tree crates that were used in this
|
||||||
|
release:</p>
|
||||||
|
|
||||||
|
{% for (key, value) in dependencies %}
|
||||||
|
<h3>📦 {{key.name}}-{{key.version}}</h3>
|
||||||
|
<p><b>URL:</b> <a href="https://crates.io/crates/{{ key.name }}/{{ key.version }}">https://crates.io/crates/{{ key.name }}/{{ key.version }}</a></p>
|
||||||
|
<p><b>In libstd:</b> {% if value.is_in_libstd.unwrap() %} Yes {% else %} No {% endif %}</p>
|
||||||
|
<p><b>Authors:</b> {{ value.authors|join(", ") }}</p>
|
||||||
|
<p><b>License:</b> {{ value.license }}</p>
|
||||||
|
{% let len = value.notices.len() %}
|
||||||
|
{% if len > 0 %}
|
||||||
|
<p><b>Notices:</b>
|
||||||
|
{% for (notice_name, notice_text) in value.notices %}
|
||||||
|
<details>
|
||||||
|
<summary><code>{{ notice_name }}</code></summary>
|
||||||
|
<pre>
|
||||||
|
{{ notice_text }}
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
71
src/tools/generate-copyright/templates/Node.html
Normal file
71
src/tools/generate-copyright/templates/Node.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{% match self %}
|
||||||
|
|
||||||
|
{% when Node::Root { children } %}
|
||||||
|
|
||||||
|
{% for child in children %}
|
||||||
|
{{ child|safe }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% when Node::Directory { name, children, license } %}
|
||||||
|
|
||||||
|
<div style="border:1px solid black; padding: 5px;">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>File/Directory:</b> <code>{{ name }}</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% if let Some(license) = license %}
|
||||||
|
|
||||||
|
<p><b>License:</b> {{ license.spdx }}</p>
|
||||||
|
{% for copyright in license.copyright.iter() %}
|
||||||
|
<p><b>Copyright:</b> {{ copyright }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if !children.is_empty() %}
|
||||||
|
|
||||||
|
<p><b>Exceptions:</b></p>
|
||||||
|
{% for child in children %}
|
||||||
|
{{ child|safe }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% when Node::File { name, license } %}
|
||||||
|
|
||||||
|
<div style="border:1px solid black; padding: 5px;">
|
||||||
|
<p>
|
||||||
|
<b>File/Directory:</b> <code>{{ name }}</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><b>License:</b> {{ license.spdx }}</p>
|
||||||
|
{% for copyright in license.copyright.iter() %}
|
||||||
|
<p><b>Copyright:</b> {{ copyright }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% when Node::Group { files, directories, license } %}
|
||||||
|
|
||||||
|
<div style="border:1px solid black; padding: 5px;">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>File/Directory:</b>
|
||||||
|
{% for name in files %}
|
||||||
|
<code>{{ name }}</code>
|
||||||
|
{% endfor %}
|
||||||
|
{% for name in directories %}
|
||||||
|
<code>{{ name }}</code>
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><b>License:</b> {{ license.spdx }}</p>
|
||||||
|
{% for copyright in license.copyright.iter() %}
|
||||||
|
<p><b>Copyright:</b> {{ copyright }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endmatch %}
|
@ -12,4 +12,4 @@ pub unsafe fn crc32sse(v: u8) -> u32 {
|
|||||||
_mm_crc32_u8(out, v)
|
_mm_crc32_u8(out, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: attributes #0 {{.*"target-features"=".*\+sse4.2,\+crc32"}}
|
// CHECK: attributes #0 {{.*"target-features"=".*\+sse4.2,\+crc32.*"}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//@ revisions: COMPAT INCOMPAT
|
//@ revisions: COMPAT INCOMPAT
|
||||||
//@ needs-llvm-components: x86
|
//@ needs-llvm-components: x86
|
||||||
//@ compile-flags: --target=x86_64-unknown-linux-gnu -Copt-level=3
|
//@ compile-flags: --target=x86_64-unknown-linux-gnu -Copt-level=3
|
||||||
//@ [COMPAT] compile-flags: -Ctarget-feature=+avx2,+avx
|
//@ [COMPAT] compile-flags: -Ctarget-feature=+avx2
|
||||||
//@ [INCOMPAT] compile-flags: -Ctarget-feature=-avx2,-avx
|
//@ [INCOMPAT] compile-flags: -Ctarget-feature=-avx2,-avx
|
||||||
|
|
||||||
// See also tests/assembly/target-feature-multiple.rs
|
// See also tests/assembly/target-feature-multiple.rs
|
||||||
@ -39,8 +39,8 @@ pub unsafe fn banana() -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: attributes [[APPLEATTRS]]
|
// CHECK: attributes [[APPLEATTRS]]
|
||||||
// COMPAT-SAME: "target-features"="+avx2,+avx,+avx"
|
// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}"
|
||||||
// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx"
|
// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx,{{.*}}"
|
||||||
// CHECK: attributes [[BANANAATTRS]]
|
// CHECK: attributes [[BANANAATTRS]]
|
||||||
// COMPAT-SAME: "target-features"="+avx2,+avx"
|
// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}"
|
||||||
// INCOMPAT-SAME: "target-features"="-avx2,-avx"
|
// INCOMPAT-SAME: "target-features"="-avx2,-avx"
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// is LLVM-14 we can remove the optional regex matching for this feature.
|
// is LLVM-14 we can remove the optional regex matching for this feature.
|
||||||
|
|
||||||
//@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0
|
//@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0
|
||||||
// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
|
// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" }
|
||||||
|
|
||||||
//@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0
|
//@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0
|
||||||
// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
|
// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
|
||||||
|
2
tests/rustdoc-ui/intra-doc/.gitattributes
vendored
2
tests/rustdoc-ui/intra-doc/.gitattributes
vendored
@ -1 +1 @@
|
|||||||
warning-crlf.rs eol=crlf
|
warning-crlf.rs -text
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
|
|
||||||
#![deny(unused_parens)]
|
#![deny(unused_parens)]
|
||||||
|
#![feature(raw_ref_op)]
|
||||||
#![allow(while_true)] // for rustfix
|
#![allow(while_true)] // for rustfix
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
@ -125,4 +126,11 @@ fn main() {
|
|||||||
// FIXME: false positive. This parenthesis is required.
|
// FIXME: false positive. This parenthesis is required.
|
||||||
unit! {} - One //~ ERROR unnecessary parentheses around block return value
|
unit! {} - One //~ ERROR unnecessary parentheses around block return value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Do *not* lint around `&raw` (but do lint when `&` creates a reference).
|
||||||
|
let mut x = 0;
|
||||||
|
let _r = &x; //~ ERROR unnecessary parentheses
|
||||||
|
let _r = &mut x; //~ ERROR unnecessary parentheses
|
||||||
|
let _r = (&raw const x);
|
||||||
|
let _r = (&raw mut x);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
|
|
||||||
#![deny(unused_parens)]
|
#![deny(unused_parens)]
|
||||||
|
#![feature(raw_ref_op)]
|
||||||
#![allow(while_true)] // for rustfix
|
#![allow(while_true)] // for rustfix
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
@ -125,4 +126,11 @@ fn main() {
|
|||||||
// FIXME: false positive. This parenthesis is required.
|
// FIXME: false positive. This parenthesis is required.
|
||||||
(unit! {} - One) //~ ERROR unnecessary parentheses around block return value
|
(unit! {} - One) //~ ERROR unnecessary parentheses around block return value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Do *not* lint around `&raw` (but do lint when `&` creates a reference).
|
||||||
|
let mut x = 0;
|
||||||
|
let _r = (&x); //~ ERROR unnecessary parentheses
|
||||||
|
let _r = (&mut x); //~ ERROR unnecessary parentheses
|
||||||
|
let _r = (&raw const x);
|
||||||
|
let _r = (&raw mut x);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: unnecessary parentheses around `return` value
|
error: unnecessary parentheses around `return` value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:13:12
|
--> $DIR/lint-unnecessary-parens.rs:14:12
|
||||||
|
|
|
|
||||||
LL | return (1);
|
LL | return (1);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -16,7 +16,7 @@ LL + return 1;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `return` value
|
error: unnecessary parentheses around `return` value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:16:12
|
--> $DIR/lint-unnecessary-parens.rs:17:12
|
||||||
|
|
|
|
||||||
LL | return (X { y });
|
LL | return (X { y });
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -28,7 +28,7 @@ LL + return X { y };
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around type
|
error: unnecessary parentheses around type
|
||||||
--> $DIR/lint-unnecessary-parens.rs:19:46
|
--> $DIR/lint-unnecessary-parens.rs:20:46
|
||||||
|
|
|
|
||||||
LL | pub fn unused_parens_around_return_type() -> (u32) {
|
LL | pub fn unused_parens_around_return_type() -> (u32) {
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -40,7 +40,7 @@ LL + pub fn unused_parens_around_return_type() -> u32 {
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around block return value
|
error: unnecessary parentheses around block return value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:25:9
|
--> $DIR/lint-unnecessary-parens.rs:26:9
|
||||||
|
|
|
|
||||||
LL | (5)
|
LL | (5)
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -52,7 +52,7 @@ LL + 5
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around block return value
|
error: unnecessary parentheses around block return value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:27:5
|
--> $DIR/lint-unnecessary-parens.rs:28:5
|
||||||
|
|
|
|
||||||
LL | (5)
|
LL | (5)
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -64,7 +64,7 @@ LL + 5
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `if` condition
|
error: unnecessary parentheses around `if` condition
|
||||||
--> $DIR/lint-unnecessary-parens.rs:39:7
|
--> $DIR/lint-unnecessary-parens.rs:40:7
|
||||||
|
|
|
|
||||||
LL | if(true) {}
|
LL | if(true) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -76,7 +76,7 @@ LL + if true {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `while` condition
|
error: unnecessary parentheses around `while` condition
|
||||||
--> $DIR/lint-unnecessary-parens.rs:40:10
|
--> $DIR/lint-unnecessary-parens.rs:41:10
|
||||||
|
|
|
|
||||||
LL | while(true) {}
|
LL | while(true) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -88,7 +88,7 @@ LL + while true {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `for` iterator expression
|
error: unnecessary parentheses around `for` iterator expression
|
||||||
--> $DIR/lint-unnecessary-parens.rs:41:13
|
--> $DIR/lint-unnecessary-parens.rs:42:13
|
||||||
|
|
|
|
||||||
LL | for _ in(e) {}
|
LL | for _ in(e) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -100,7 +100,7 @@ LL + for _ in e {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `match` scrutinee expression
|
error: unnecessary parentheses around `match` scrutinee expression
|
||||||
--> $DIR/lint-unnecessary-parens.rs:42:10
|
--> $DIR/lint-unnecessary-parens.rs:43:10
|
||||||
|
|
|
|
||||||
LL | match(1) { _ => ()}
|
LL | match(1) { _ => ()}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -112,7 +112,7 @@ LL + match 1 { _ => ()}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `return` value
|
error: unnecessary parentheses around `return` value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:43:11
|
--> $DIR/lint-unnecessary-parens.rs:44:11
|
||||||
|
|
|
|
||||||
LL | return(1);
|
LL | return(1);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -124,7 +124,7 @@ LL + return 1;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around assigned value
|
error: unnecessary parentheses around assigned value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:74:31
|
--> $DIR/lint-unnecessary-parens.rs:75:31
|
||||||
|
|
|
|
||||||
LL | pub const CONST_ITEM: usize = (10);
|
LL | pub const CONST_ITEM: usize = (10);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -136,7 +136,7 @@ LL + pub const CONST_ITEM: usize = 10;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around assigned value
|
error: unnecessary parentheses around assigned value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:75:33
|
--> $DIR/lint-unnecessary-parens.rs:76:33
|
||||||
|
|
|
|
||||||
LL | pub static STATIC_ITEM: usize = (10);
|
LL | pub static STATIC_ITEM: usize = (10);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -148,7 +148,7 @@ LL + pub static STATIC_ITEM: usize = 10;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around function argument
|
error: unnecessary parentheses around function argument
|
||||||
--> $DIR/lint-unnecessary-parens.rs:79:9
|
--> $DIR/lint-unnecessary-parens.rs:80:9
|
||||||
|
|
|
|
||||||
LL | bar((true));
|
LL | bar((true));
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -160,7 +160,7 @@ LL + bar(true);
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `if` condition
|
error: unnecessary parentheses around `if` condition
|
||||||
--> $DIR/lint-unnecessary-parens.rs:81:8
|
--> $DIR/lint-unnecessary-parens.rs:82:8
|
||||||
|
|
|
|
||||||
LL | if (true) {}
|
LL | if (true) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -172,7 +172,7 @@ LL + if true {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `while` condition
|
error: unnecessary parentheses around `while` condition
|
||||||
--> $DIR/lint-unnecessary-parens.rs:82:11
|
--> $DIR/lint-unnecessary-parens.rs:83:11
|
||||||
|
|
|
|
||||||
LL | while (true) {}
|
LL | while (true) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -184,7 +184,7 @@ LL + while true {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `match` scrutinee expression
|
error: unnecessary parentheses around `match` scrutinee expression
|
||||||
--> $DIR/lint-unnecessary-parens.rs:83:11
|
--> $DIR/lint-unnecessary-parens.rs:84:11
|
||||||
|
|
|
|
||||||
LL | match (true) {
|
LL | match (true) {
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -196,7 +196,7 @@ LL + match true {
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `let` scrutinee expression
|
error: unnecessary parentheses around `let` scrutinee expression
|
||||||
--> $DIR/lint-unnecessary-parens.rs:86:16
|
--> $DIR/lint-unnecessary-parens.rs:87:16
|
||||||
|
|
|
|
||||||
LL | if let 1 = (1) {}
|
LL | if let 1 = (1) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -208,7 +208,7 @@ LL + if let 1 = 1 {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around `let` scrutinee expression
|
error: unnecessary parentheses around `let` scrutinee expression
|
||||||
--> $DIR/lint-unnecessary-parens.rs:87:19
|
--> $DIR/lint-unnecessary-parens.rs:88:19
|
||||||
|
|
|
|
||||||
LL | while let 1 = (2) {}
|
LL | while let 1 = (2) {}
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -220,7 +220,7 @@ LL + while let 1 = 2 {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around method argument
|
error: unnecessary parentheses around method argument
|
||||||
--> $DIR/lint-unnecessary-parens.rs:103:24
|
--> $DIR/lint-unnecessary-parens.rs:104:24
|
||||||
|
|
|
|
||||||
LL | X { y: false }.foo((true));
|
LL | X { y: false }.foo((true));
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -232,7 +232,7 @@ LL + X { y: false }.foo(true);
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around assigned value
|
error: unnecessary parentheses around assigned value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:105:18
|
--> $DIR/lint-unnecessary-parens.rs:106:18
|
||||||
|
|
|
|
||||||
LL | let mut _a = (0);
|
LL | let mut _a = (0);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -244,7 +244,7 @@ LL + let mut _a = 0;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around assigned value
|
error: unnecessary parentheses around assigned value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:106:10
|
--> $DIR/lint-unnecessary-parens.rs:107:10
|
||||||
|
|
|
|
||||||
LL | _a = (0);
|
LL | _a = (0);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -256,7 +256,7 @@ LL + _a = 0;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around assigned value
|
error: unnecessary parentheses around assigned value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:107:11
|
--> $DIR/lint-unnecessary-parens.rs:108:11
|
||||||
|
|
|
|
||||||
LL | _a += (1);
|
LL | _a += (1);
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -268,7 +268,7 @@ LL + _a += 1;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around pattern
|
error: unnecessary parentheses around pattern
|
||||||
--> $DIR/lint-unnecessary-parens.rs:109:8
|
--> $DIR/lint-unnecessary-parens.rs:110:8
|
||||||
|
|
|
|
||||||
LL | let(mut _a) = 3;
|
LL | let(mut _a) = 3;
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -280,7 +280,7 @@ LL + let mut _a = 3;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around pattern
|
error: unnecessary parentheses around pattern
|
||||||
--> $DIR/lint-unnecessary-parens.rs:110:9
|
--> $DIR/lint-unnecessary-parens.rs:111:9
|
||||||
|
|
|
|
||||||
LL | let (mut _a) = 3;
|
LL | let (mut _a) = 3;
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -292,7 +292,7 @@ LL + let mut _a = 3;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around pattern
|
error: unnecessary parentheses around pattern
|
||||||
--> $DIR/lint-unnecessary-parens.rs:111:8
|
--> $DIR/lint-unnecessary-parens.rs:112:8
|
||||||
|
|
|
|
||||||
LL | let( mut _a) = 3;
|
LL | let( mut _a) = 3;
|
||||||
| ^^ ^
|
| ^^ ^
|
||||||
@ -304,7 +304,7 @@ LL + let mut _a = 3;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around pattern
|
error: unnecessary parentheses around pattern
|
||||||
--> $DIR/lint-unnecessary-parens.rs:113:8
|
--> $DIR/lint-unnecessary-parens.rs:114:8
|
||||||
|
|
|
|
||||||
LL | let(_a) = 3;
|
LL | let(_a) = 3;
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -316,7 +316,7 @@ LL + let _a = 3;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around pattern
|
error: unnecessary parentheses around pattern
|
||||||
--> $DIR/lint-unnecessary-parens.rs:114:9
|
--> $DIR/lint-unnecessary-parens.rs:115:9
|
||||||
|
|
|
|
||||||
LL | let (_a) = 3;
|
LL | let (_a) = 3;
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -328,7 +328,7 @@ LL + let _a = 3;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around pattern
|
error: unnecessary parentheses around pattern
|
||||||
--> $DIR/lint-unnecessary-parens.rs:115:8
|
--> $DIR/lint-unnecessary-parens.rs:116:8
|
||||||
|
|
|
|
||||||
LL | let( _a) = 3;
|
LL | let( _a) = 3;
|
||||||
| ^^ ^
|
| ^^ ^
|
||||||
@ -340,7 +340,7 @@ LL + let _a = 3;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around block return value
|
error: unnecessary parentheses around block return value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:121:9
|
--> $DIR/lint-unnecessary-parens.rs:122:9
|
||||||
|
|
|
|
||||||
LL | (unit!() - One)
|
LL | (unit!() - One)
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -352,7 +352,7 @@ LL + unit!() - One
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around block return value
|
error: unnecessary parentheses around block return value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:123:9
|
--> $DIR/lint-unnecessary-parens.rs:124:9
|
||||||
|
|
|
|
||||||
LL | (unit![] - One)
|
LL | (unit![] - One)
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -364,7 +364,7 @@ LL + unit![] - One
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unnecessary parentheses around block return value
|
error: unnecessary parentheses around block return value
|
||||||
--> $DIR/lint-unnecessary-parens.rs:126:9
|
--> $DIR/lint-unnecessary-parens.rs:127:9
|
||||||
|
|
|
|
||||||
LL | (unit! {} - One)
|
LL | (unit! {} - One)
|
||||||
| ^ ^
|
| ^ ^
|
||||||
@ -375,5 +375,29 @@ LL - (unit! {} - One)
|
|||||||
LL + unit! {} - One
|
LL + unit! {} - One
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 31 previous errors
|
error: unnecessary parentheses around assigned value
|
||||||
|
--> $DIR/lint-unnecessary-parens.rs:132:14
|
||||||
|
|
|
||||||
|
LL | let _r = (&x);
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: remove these parentheses
|
||||||
|
|
|
||||||
|
LL - let _r = (&x);
|
||||||
|
LL + let _r = &x;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: unnecessary parentheses around assigned value
|
||||||
|
--> $DIR/lint-unnecessary-parens.rs:133:14
|
||||||
|
|
|
||||||
|
LL | let _r = (&mut x);
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: remove these parentheses
|
||||||
|
|
|
||||||
|
LL - let _r = (&mut x);
|
||||||
|
LL + let _r = &mut x;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 33 previous errors
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ fn foo() {
|
|||||||
|
|
||||||
#[target_feature(enable = "sse2")]
|
#[target_feature(enable = "sse2")]
|
||||||
fn bar() {
|
fn bar() {
|
||||||
|
sse2();
|
||||||
avx_bmi2();
|
avx_bmi2();
|
||||||
//~^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
|
//~^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
|
||||||
Quux.avx_bmi2();
|
Quux.avx_bmi2();
|
||||||
@ -43,7 +44,6 @@ fn bar() {
|
|||||||
#[target_feature(enable = "avx")]
|
#[target_feature(enable = "avx")]
|
||||||
fn baz() {
|
fn baz() {
|
||||||
sse2();
|
sse2();
|
||||||
//~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
|
|
||||||
avx_bmi2();
|
avx_bmi2();
|
||||||
//~^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
|
//~^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
|
||||||
Quux.avx_bmi2();
|
Quux.avx_bmi2();
|
||||||
@ -54,7 +54,8 @@ fn baz() {
|
|||||||
#[target_feature(enable = "bmi2")]
|
#[target_feature(enable = "bmi2")]
|
||||||
fn qux() {
|
fn qux() {
|
||||||
sse2();
|
sse2();
|
||||||
//~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
|
avx_bmi2();
|
||||||
|
Quux.avx_bmi2();
|
||||||
}
|
}
|
||||||
|
|
||||||
const _: () = sse2();
|
const _: () = sse2();
|
||||||
@ -64,8 +65,6 @@ const _: () = sse2_and_fxsr();
|
|||||||
//~^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe
|
//~^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe
|
||||||
|
|
||||||
#[deny(unsafe_op_in_unsafe_fn)]
|
#[deny(unsafe_op_in_unsafe_fn)]
|
||||||
#[target_feature(enable = "avx")]
|
|
||||||
#[target_feature(enable = "bmi2")]
|
|
||||||
unsafe fn needs_unsafe_block() {
|
unsafe fn needs_unsafe_block() {
|
||||||
sse2();
|
sse2();
|
||||||
//~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
|
//~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
|
||||||
|
@ -24,7 +24,7 @@ LL | Quux.avx_bmi2();
|
|||||||
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
|
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
|
||||||
|
|
||||||
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:37:5
|
--> $DIR/safe-calls.rs:38:5
|
||||||
|
|
|
|
||||||
LL | avx_bmi2();
|
LL | avx_bmi2();
|
||||||
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
@ -32,22 +32,13 @@ LL | avx_bmi2();
|
|||||||
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
|
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
|
||||||
|
|
||||||
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:39:5
|
--> $DIR/safe-calls.rs:40:5
|
||||||
|
|
|
|
||||||
LL | Quux.avx_bmi2();
|
LL | Quux.avx_bmi2();
|
||||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
|
||||||
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
|
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
|
||||||
|
|
||||||
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:45:5
|
|
||||||
|
|
|
||||||
LL | sse2();
|
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= help: in order for the call to be safe, the context requires the following additional target feature: sse2
|
|
||||||
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
|
|
||||||
|
|
||||||
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:47:5
|
--> $DIR/safe-calls.rs:47:5
|
||||||
|
|
|
|
||||||
@ -65,16 +56,7 @@ LL | Quux.avx_bmi2();
|
|||||||
= help: in order for the call to be safe, the context requires the following additional target feature: bmi2
|
= help: in order for the call to be safe, the context requires the following additional target feature: bmi2
|
||||||
|
|
||||||
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:56:5
|
--> $DIR/safe-calls.rs:61:15
|
||||||
|
|
|
||||||
LL | sse2();
|
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= help: in order for the call to be safe, the context requires the following additional target feature: sse2
|
|
||||||
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
|
|
||||||
|
|
||||||
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:60:15
|
|
||||||
|
|
|
|
||||||
LL | const _: () = sse2();
|
LL | const _: () = sse2();
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
@ -83,7 +65,7 @@ LL | const _: () = sse2();
|
|||||||
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
|
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
|
||||||
|
|
||||||
error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:63:15
|
--> $DIR/safe-calls.rs:64:15
|
||||||
|
|
|
|
||||||
LL | const _: () = sse2_and_fxsr();
|
LL | const _: () = sse2_and_fxsr();
|
||||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
@ -92,7 +74,7 @@ LL | const _: () = sse2_and_fxsr();
|
|||||||
= note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
|
= note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
|
||||||
|
|
||||||
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block
|
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block
|
||||||
--> $DIR/safe-calls.rs:70:5
|
--> $DIR/safe-calls.rs:69:5
|
||||||
|
|
|
|
||||||
LL | sse2();
|
LL | sse2();
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
@ -101,16 +83,16 @@ LL | sse2();
|
|||||||
= help: in order for the call to be safe, the context requires the following additional target feature: sse2
|
= help: in order for the call to be safe, the context requires the following additional target feature: sse2
|
||||||
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
|
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
|
||||||
note: an unsafe function restricts its caller, but its body is safe by default
|
note: an unsafe function restricts its caller, but its body is safe by default
|
||||||
--> $DIR/safe-calls.rs:69:1
|
--> $DIR/safe-calls.rs:68:1
|
||||||
|
|
|
|
||||||
LL | unsafe fn needs_unsafe_block() {
|
LL | unsafe fn needs_unsafe_block() {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/safe-calls.rs:66:8
|
--> $DIR/safe-calls.rs:67:8
|
||||||
|
|
|
|
||||||
LL | #[deny(unsafe_op_in_unsafe_fn)]
|
LL | #[deny(unsafe_op_in_unsafe_fn)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0133`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
10
tests/ui/target-feature/asm-implied-features-issue-128125.rs
Normal file
10
tests/ui/target-feature/asm-implied-features-issue-128125.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//@ only-x86_64
|
||||||
|
//@ build-pass
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
#[target_feature(enable = "avx2")]
|
||||||
|
unsafe fn demo(v: std::arch::x86_64::__m256i) {
|
||||||
|
std::arch::asm!("/* {v} */", v = in(ymm_reg) v);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
24
tests/ui/target-feature/implied-features.rs
Normal file
24
tests/ui/target-feature/implied-features.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//@ only-x86_64
|
||||||
|
//@ build-pass
|
||||||
|
#![feature(target_feature_11)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
#[target_feature(enable = "ssse3")]
|
||||||
|
fn call_ssse3() {}
|
||||||
|
|
||||||
|
#[target_feature(enable = "avx")]
|
||||||
|
fn call_avx() {}
|
||||||
|
|
||||||
|
#[target_feature(enable = "avx2")]
|
||||||
|
fn test_avx2() {
|
||||||
|
call_ssse3();
|
||||||
|
call_avx();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[target_feature(enable = "fma")]
|
||||||
|
fn test_fma() {
|
||||||
|
call_ssse3();
|
||||||
|
call_avx();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user