Auto merge of #113391 - fee1-dead-contrib:rollup-9bqlw9z, r=fee1-dead
Rollup of 9 pull requests Successful merges: - #111119 (style-guide: Add chapter about formatting for nightly-only syntax) - #112791 (llvm ffi: Expose `CallInst->setTailCallKind`) - #113145 (style-guide: Document newline rules for assignment operators) - #113163 (Add a regression test for #112895) - #113332 (resolve: Use `Interned` for some interned structures) - #113334 (Revert the lexing of `c"…"` string literals) - #113350 (Fix the issue of wrong diagnosis for extern pub fn) - #113371 (Fix submodule handling when the current branch is named after a tag) - #113384 (style-guide: Clarify grammar for small patterns (not a semantic change)) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0d50ab7739
11
Cargo.lock
11
Cargo.lock
@ -766,6 +766,16 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cstr"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c11a39d776a3b35896711da8a04dc1835169dcd36f710878187637314e47941b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.0"
|
||||
@ -3016,6 +3026,7 @@ name = "rustc_codegen_llvm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cstr",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object",
|
||||
|
@ -8,6 +8,7 @@ test = false
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
cstr = "0.2"
|
||||
libc = "0.2"
|
||||
measureme = "10.0.0"
|
||||
object = { version = "0.31.1", default-features = false, features = [
|
||||
|
@ -77,7 +77,7 @@ pub(crate) unsafe fn codegen(
|
||||
llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
|
||||
llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast());
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
|
||||
|
||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
||||
@ -129,7 +129,7 @@ pub(crate) unsafe fn codegen(
|
||||
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
|
||||
llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast());
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
|
||||
|
||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
||||
|
@ -601,7 +601,7 @@ pub(crate) fn run_pass_manager(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
module.module_llvm.llmod(),
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"LTOPostLink".as_ptr().cast(),
|
||||
"LTOPostLink\0".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
@ -931,16 +931,16 @@ unsafe fn embed_bitcode(
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.module".as_ptr().cast(),
|
||||
"rustc.embedded.module\0".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
|
||||
let section = if is_apple {
|
||||
c"__LLVM,__bitcode"
|
||||
"__LLVM,__bitcode\0"
|
||||
} else if is_aix {
|
||||
c".ipa"
|
||||
".ipa\0"
|
||||
} else {
|
||||
c".llvmbc"
|
||||
".llvmbc\0"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
@ -950,15 +950,15 @@ unsafe fn embed_bitcode(
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.cmdline".as_ptr().cast(),
|
||||
"rustc.embedded.cmdline\0".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if is_apple {
|
||||
c"__LLVM,__cmdline"
|
||||
"__LLVM,__cmdline\0"
|
||||
} else if is_aix {
|
||||
c".info"
|
||||
".info\0"
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
".llvmcmd\0"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
|
@ -19,6 +19,8 @@ use crate::context::CodegenCx;
|
||||
use crate::llvm;
|
||||
use crate::value::Value;
|
||||
|
||||
use cstr::cstr;
|
||||
|
||||
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
||||
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
@ -108,11 +110,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
|
||||
|
||||
// Create the llvm.used and llvm.compiler.used variables.
|
||||
if !cx.used_statics.borrow().is_empty() {
|
||||
cx.create_used_variable_impl(c"llvm.used", &*cx.used_statics.borrow());
|
||||
cx.create_used_variable_impl(cstr!("llvm.used"), &*cx.used_statics.borrow());
|
||||
}
|
||||
if !cx.compiler_used_statics.borrow().is_empty() {
|
||||
cx.create_used_variable_impl(
|
||||
c"llvm.compiler.used",
|
||||
cstr!("llvm.compiler.used"),
|
||||
&*cx.compiler_used_statics.borrow(),
|
||||
);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True}
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
use cstr::cstr;
|
||||
use libc::{c_char, c_uint};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
|
||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
@ -25,6 +26,7 @@ use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
|
||||
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
@ -44,10 +46,13 @@ impl Drop for Builder<'_, '_, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) use a checked constructor when they become `const fn`.
|
||||
const EMPTY_C_STR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") };
|
||||
|
||||
/// Empty string, to be used where LLVM expects an instruction name, indicating
|
||||
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
|
||||
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
|
||||
const UNNAMED: *const c_char = c"".as_ptr();
|
||||
const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr();
|
||||
|
||||
impl<'ll, 'tcx> BackendTypes for Builder<'_, 'll, 'tcx> {
|
||||
type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
|
||||
@ -1002,13 +1007,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
}
|
||||
|
||||
fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> {
|
||||
let name = cstr!("cleanuppad");
|
||||
let ret = unsafe {
|
||||
llvm::LLVMBuildCleanupPad(
|
||||
self.llbuilder,
|
||||
parent,
|
||||
args.as_ptr(),
|
||||
args.len() as c_uint,
|
||||
c"cleanuppad".as_ptr(),
|
||||
name.as_ptr(),
|
||||
)
|
||||
};
|
||||
Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
|
||||
@ -1022,13 +1028,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
}
|
||||
|
||||
fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> {
|
||||
let name = cstr!("catchpad");
|
||||
let ret = unsafe {
|
||||
llvm::LLVMBuildCatchPad(
|
||||
self.llbuilder,
|
||||
parent,
|
||||
args.as_ptr(),
|
||||
args.len() as c_uint,
|
||||
c"catchpad".as_ptr(),
|
||||
name.as_ptr(),
|
||||
)
|
||||
};
|
||||
Funclet::new(ret.expect("LLVM does not have support for catchpad"))
|
||||
@ -1040,13 +1047,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
unwind: Option<&'ll BasicBlock>,
|
||||
handlers: &[&'ll BasicBlock],
|
||||
) -> &'ll Value {
|
||||
let name = cstr!("catchswitch");
|
||||
let ret = unsafe {
|
||||
llvm::LLVMBuildCatchSwitch(
|
||||
self.llbuilder,
|
||||
parent,
|
||||
unwind,
|
||||
handlers.len() as c_uint,
|
||||
c"catchswitch".as_ptr(),
|
||||
name.as_ptr(),
|
||||
)
|
||||
};
|
||||
let ret = ret.expect("LLVM does not have support for catchswitch");
|
||||
|
@ -8,6 +8,7 @@ use crate::llvm::{self, True};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
use cstr::cstr;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
@ -481,9 +482,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||
.all(|&byte| byte == 0);
|
||||
|
||||
let sect_name = if all_bytes_are_zero {
|
||||
c"__DATA,__thread_bss"
|
||||
cstr!("__DATA,__thread_bss")
|
||||
} else {
|
||||
c"__DATA,__thread_data"
|
||||
cstr!("__DATA,__thread_data")
|
||||
};
|
||||
llvm::LLVMSetSection(g, sect_name.as_ptr());
|
||||
}
|
||||
@ -512,7 +513,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||
let val = llvm::LLVMMetadataAsValue(self.llcx, meta);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
self.llmod,
|
||||
c"wasm.custom_sections".as_ptr().cast(),
|
||||
"wasm.custom_sections\0".as_ptr().cast(),
|
||||
val,
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
|
||||
use cstr::cstr;
|
||||
use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::base_n;
|
||||
@ -223,42 +224,36 @@ pub unsafe fn create_module<'ll>(
|
||||
// If skipping the PLT is enabled, we need to add some module metadata
|
||||
// to ensure intrinsic calls don't use it.
|
||||
if !sess.needs_plt() {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"RtLibUseGOT".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
let avoid_plt = "RtLibUseGOT\0".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
}
|
||||
|
||||
// Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
|
||||
if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
|
||||
let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"CFI Canonical Jump Tables".as_ptr().cast(),
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
|
||||
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
||||
let enable_split_lto_unit = "EnableSplitLTOUnit\0".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"EnableSplitLTOUnit".as_ptr().cast(),
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
|
||||
if sess.is_sanitizer_kcfi_enabled() {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"kcfi".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
let kcfi = "kcfi\0".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||
@ -270,7 +265,7 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
"cfguard\0".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
@ -279,7 +274,7 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
"cfguard\0".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
}
|
||||
@ -297,26 +292,26 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
behavior,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
"branch-target-enforcement\0".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
behavior,
|
||||
c"sign-return-address".as_ptr().cast(),
|
||||
"sign-return-address\0".as_ptr().cast(),
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
behavior,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
"sign-return-address-all\0".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
behavior,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
"sign-return-address-with-bkey\0".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
} else {
|
||||
@ -332,7 +327,7 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
"cf-protection-branch\0".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
}
|
||||
@ -340,7 +335,7 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
"cf-protection-return\0".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
}
|
||||
@ -349,7 +344,7 @@ pub unsafe fn create_module<'ll>(
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
"Virtual Function Elim\0".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
@ -481,13 +476,14 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
}
|
||||
|
||||
pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
|
||||
let section = cstr!("llvm.metadata");
|
||||
let array = self.const_array(self.type_ptr_to(self.type_i8()), values);
|
||||
|
||||
unsafe {
|
||||
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
|
||||
llvm::LLVMSetInitializer(g, array);
|
||||
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
|
||||
llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr());
|
||||
llvm::LLVMSetSection(g, section.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
|
||||
unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) };
|
||||
|
||||
section_var.unwrap_or_else(|| {
|
||||
let section_name = b".debug_gdb_scripts\0";
|
||||
let mut section_contents = Vec::new();
|
||||
|
||||
// Add the pretty printers for the standard library first.
|
||||
@ -70,7 +71,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
|
||||
let section_var = cx
|
||||
.define_global(section_var_name, llvm_type)
|
||||
.unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
|
||||
llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr().cast());
|
||||
llvm::LLVMSetSection(section_var, section_name.as_ptr().cast());
|
||||
llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
|
||||
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
||||
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
|
||||
|
@ -20,6 +20,7 @@ use crate::llvm::debuginfo::{
|
||||
};
|
||||
use crate::value::Value;
|
||||
|
||||
use cstr::cstr;
|
||||
use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
|
||||
use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
@ -811,6 +812,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
|
||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||
let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped);
|
||||
let flags = "\0";
|
||||
let output_filenames = tcx.output_filenames(());
|
||||
let split_name = if tcx.sess.target_can_use_split_dwarf() {
|
||||
output_filenames
|
||||
@ -847,7 +849,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
producer.as_ptr().cast(),
|
||||
producer.len(),
|
||||
tcx.sess.opts.optimize != config::OptLevel::No,
|
||||
c"".as_ptr().cast(),
|
||||
flags.as_ptr().cast(),
|
||||
0,
|
||||
// NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
|
||||
// put the path supplied to `MCSplitDwarfFile` into the debug info of the final
|
||||
@ -876,7 +878,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
);
|
||||
let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata);
|
||||
|
||||
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, c"llvm.gcov".as_ptr(), val);
|
||||
let llvm_gcov_ident = cstr!("llvm.gcov");
|
||||
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val);
|
||||
}
|
||||
|
||||
// Insert `llvm.ident` metadata on the wasm targets since that will
|
||||
@ -889,7 +892,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
debug_context.llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
cstr!("llvm.ident").as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1),
|
||||
);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"Dwarf Version".as_ptr().cast(),
|
||||
"Dwarf Version\0".as_ptr().cast(),
|
||||
dwarf_version,
|
||||
);
|
||||
} else {
|
||||
@ -121,16 +121,17 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"CodeView".as_ptr().cast(),
|
||||
"CodeView\0".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
// Prevent bitcode readers from deleting the debug info.
|
||||
let ptr = "Debug Info Version\0".as_ptr();
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
self.llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"Debug Info Version".as_ptr().cast(),
|
||||
ptr.cast(),
|
||||
llvm::LLVMRustDebugMetadataVersion(),
|
||||
);
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(c_str_literals)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
@ -585,6 +585,16 @@ pub enum ThreadLocalMode {
|
||||
LocalExec,
|
||||
}
|
||||
|
||||
/// LLVMRustTailCallKind
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum TailCallKind {
|
||||
None,
|
||||
Tail,
|
||||
MustTail,
|
||||
NoTail,
|
||||
}
|
||||
|
||||
/// LLVMRustChecksumKind
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
@ -1196,6 +1206,7 @@ extern "C" {
|
||||
NameLen: size_t,
|
||||
) -> Option<&Value>;
|
||||
pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
|
||||
pub fn LLVMRustSetTailCallKind(CallInst: &Value, TKC: TailCallKind);
|
||||
|
||||
// Operations on attributes
|
||||
pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute;
|
||||
|
@ -367,13 +367,6 @@ impl Cursor<'_> {
|
||||
Some(|terminated| Byte { terminated }),
|
||||
),
|
||||
|
||||
// c-string literal, raw c-string literal or identifier.
|
||||
'c' => self.c_or_byte_string(
|
||||
|terminated| CStr { terminated },
|
||||
|n_hashes| RawCStr { n_hashes },
|
||||
None,
|
||||
),
|
||||
|
||||
// Identifier (this should be checked after other variant that can
|
||||
// start as identifier).
|
||||
c if is_id_start(c) => self.ident_or_unknown_prefix(),
|
||||
|
@ -121,6 +121,32 @@ extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
|
||||
return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
|
||||
}
|
||||
|
||||
enum class LLVMRustTailCallKind {
|
||||
None,
|
||||
Tail,
|
||||
MustTail,
|
||||
NoTail,
|
||||
};
|
||||
|
||||
static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) {
|
||||
switch (Kind) {
|
||||
case LLVMRustTailCallKind::None:
|
||||
return CallInst::TailCallKind::TCK_None;
|
||||
case LLVMRustTailCallKind::Tail:
|
||||
return CallInst::TailCallKind::TCK_Tail;
|
||||
case LLVMRustTailCallKind::MustTail:
|
||||
return CallInst::TailCallKind::TCK_MustTail;
|
||||
case LLVMRustTailCallKind::NoTail:
|
||||
return CallInst::TailCallKind::TCK_NoTail;
|
||||
default:
|
||||
report_fatal_error("bad CallInst::TailCallKind.");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, LLVMRustTailCallKind TCK) {
|
||||
unwrap<CallInst>(Call)->setTailCallKind(fromRust(TCK));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
|
||||
const char *Name,
|
||||
size_t NameLen,
|
||||
|
@ -2182,7 +2182,11 @@ impl<'a> Parser<'a> {
|
||||
// `extern ABI fn`
|
||||
|| self.check_keyword_case(kw::Extern, case)
|
||||
&& self.look_ahead(1, |t| t.can_begin_literal_maybe_minus())
|
||||
&& self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case))
|
||||
&& (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) ||
|
||||
// this branch is only for better diagnostic in later, `pub` is not allowed here
|
||||
(self.may_recover()
|
||||
&& self.look_ahead(2, |t| t.is_keyword(kw::Pub))
|
||||
&& self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case))))
|
||||
}
|
||||
|
||||
/// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
|
||||
|
@ -6,10 +6,10 @@
|
||||
//! Imports are also considered items and placed into modules here, but not resolved yet.
|
||||
|
||||
use crate::def_collector::collect_definitions;
|
||||
use crate::imports::{Import, ImportKind};
|
||||
use crate::imports::{ImportData, ImportKind};
|
||||
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
|
||||
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
|
||||
use crate::{errors, BindingKey, MacroData};
|
||||
use crate::{errors, BindingKey, MacroData, NameBindingData};
|
||||
use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
|
||||
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
|
||||
use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
|
||||
@ -31,15 +31,14 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
|
||||
type Res = def::Res<NodeId>;
|
||||
|
||||
impl<'a, Id: Into<DefId>> ToNameBinding<'a>
|
||||
for (Module<'a>, ty::Visibility<Id>, Span, LocalExpnId)
|
||||
{
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBinding {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBindingData {
|
||||
kind: NameBindingKind::Module(self.0),
|
||||
ambiguity: None,
|
||||
vis: self.1.to_def_id(),
|
||||
@ -50,8 +49,8 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a>
|
||||
}
|
||||
|
||||
impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span, LocalExpnId) {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBinding {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBindingData {
|
||||
kind: NameBindingKind::Res(self.0),
|
||||
ambiguity: None,
|
||||
vis: self.1.to_def_id(),
|
||||
@ -71,7 +70,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
let binding = def.to_name_binding(self.arenas);
|
||||
let key = self.new_disambiguated_key(ident, ns);
|
||||
if let Err(old_binding) = self.try_define(parent, key, binding) {
|
||||
self.report_conflict(parent, ident, ns, old_binding, &binding);
|
||||
self.report_conflict(parent, ident, ns, old_binding, binding);
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,8 +141,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
Some(def_id) => self.macro_def_scope(def_id),
|
||||
None => expn_id
|
||||
.as_local()
|
||||
.and_then(|expn_id| self.ast_transform_scopes.get(&expn_id))
|
||||
.unwrap_or(&self.graph_root),
|
||||
.and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied())
|
||||
.unwrap_or(self.graph_root),
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +353,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
vis: ty::Visibility,
|
||||
) {
|
||||
let current_module = self.parent_scope.module;
|
||||
let import = self.r.arenas.alloc_import(Import {
|
||||
let import = self.r.arenas.alloc_import(ImportData {
|
||||
kind,
|
||||
parent_scope: self.parent_scope,
|
||||
module_path,
|
||||
@ -378,7 +377,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
if !type_ns_only || ns == TypeNS {
|
||||
let key = BindingKey::new(target, ns);
|
||||
let mut resolution = this.resolution(current_module, key).borrow_mut();
|
||||
resolution.add_single_import(import);
|
||||
resolution.single_imports.insert(import);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -848,7 +847,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
(used, Some(ModuleOrUniformRoot::Module(module)), binding)
|
||||
})
|
||||
.unwrap_or((true, None, self.r.dummy_binding));
|
||||
let import = self.r.arenas.alloc_import(Import {
|
||||
let import = self.r.arenas.alloc_import(ImportData {
|
||||
kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id },
|
||||
root_id: item.id,
|
||||
parent_scope: self.parent_scope,
|
||||
@ -864,7 +863,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
});
|
||||
self.r.potentially_unused_imports.push(import);
|
||||
let imported_binding = self.r.import(binding, import);
|
||||
if ptr::eq(parent, self.r.graph_root) {
|
||||
if parent == self.r.graph_root {
|
||||
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
|
||||
if expansion != LocalExpnId::ROOT
|
||||
&& orig_name.is_some()
|
||||
@ -996,7 +995,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
fn add_macro_use_binding(
|
||||
&mut self,
|
||||
name: Symbol,
|
||||
binding: &'a NameBinding<'a>,
|
||||
binding: NameBinding<'a>,
|
||||
span: Span,
|
||||
allow_shadowing: bool,
|
||||
) {
|
||||
@ -1058,7 +1057,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
let macro_use_import = |this: &Self, span| {
|
||||
this.r.arenas.alloc_import(Import {
|
||||
this.r.arenas.alloc_import(ImportData {
|
||||
kind: ImportKind::MacroUse,
|
||||
root_id: item.id,
|
||||
parent_scope: this.parent_scope,
|
||||
@ -1228,7 +1227,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
self.r.set_binding_parent_module(binding, parent_scope.module);
|
||||
self.r.all_macro_rules.insert(ident.name, res);
|
||||
if is_macro_export {
|
||||
let import = self.r.arenas.alloc_import(Import {
|
||||
let import = self.r.arenas.alloc_import(ImportData {
|
||||
kind: ImportKind::MacroExport,
|
||||
root_id: item.id,
|
||||
parent_scope: self.parent_scope,
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::ptr;
|
||||
|
||||
use rustc_ast::expand::StrippedCfgItem;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
@ -182,13 +180,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn report_conflict<'b>(
|
||||
pub(crate) fn report_conflict(
|
||||
&mut self,
|
||||
parent: Module<'_>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
new_binding: &NameBinding<'b>,
|
||||
old_binding: &NameBinding<'b>,
|
||||
new_binding: NameBinding<'a>,
|
||||
old_binding: NameBinding<'a>,
|
||||
) {
|
||||
// Error on the second of two conflicting names
|
||||
if old_binding.span.lo() > new_binding.span.lo() {
|
||||
@ -262,7 +260,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/32354
|
||||
use NameBindingKind::Import;
|
||||
let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| {
|
||||
let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| {
|
||||
!binding.span.is_dummy()
|
||||
&& !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
|
||||
};
|
||||
@ -272,22 +270,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
(Import { import: new, .. }, Import { import: old, .. })
|
||||
if {
|
||||
(new.has_attributes || old.has_attributes)
|
||||
&& can_suggest(old_binding, old)
|
||||
&& can_suggest(new_binding, new)
|
||||
&& can_suggest(old_binding, *old)
|
||||
&& can_suggest(new_binding, *new)
|
||||
} =>
|
||||
{
|
||||
if old.has_attributes {
|
||||
Some((new, new_binding.span, true))
|
||||
Some((*new, new_binding.span, true))
|
||||
} else {
|
||||
Some((old, old_binding.span, true))
|
||||
Some((*old, old_binding.span, true))
|
||||
}
|
||||
}
|
||||
// Otherwise prioritize the new binding.
|
||||
(Import { import, .. }, other) if can_suggest(new_binding, import) => {
|
||||
Some((import, new_binding.span, other.is_import()))
|
||||
(Import { import, .. }, other) if can_suggest(new_binding, *import) => {
|
||||
Some((*import, new_binding.span, other.is_import()))
|
||||
}
|
||||
(other, Import { import, .. }) if can_suggest(old_binding, import) => {
|
||||
Some((import, old_binding.span, other.is_import()))
|
||||
(other, Import { import, .. }) if can_suggest(old_binding, *import) => {
|
||||
Some((*import, old_binding.span, other.is_import()))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
@ -341,7 +339,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
name: Symbol,
|
||||
import: &Import<'_>,
|
||||
import: Import<'_>,
|
||||
binding_span: Span,
|
||||
) {
|
||||
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
|
||||
@ -413,7 +411,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
fn add_suggestion_for_duplicate_nested_use(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
import: &Import<'_>,
|
||||
import: Import<'_>,
|
||||
binding_span: Span,
|
||||
) {
|
||||
assert!(import.is_nested());
|
||||
@ -455,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
&mut self,
|
||||
finalize: Option<Finalize>,
|
||||
path: &[Segment],
|
||||
second_binding: Option<&NameBinding<'_>>,
|
||||
second_binding: Option<NameBinding<'_>>,
|
||||
) {
|
||||
let Some(Finalize { node_id, root_span, .. }) = finalize else {
|
||||
return;
|
||||
@ -1198,7 +1196,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// avoid suggesting anything with a hygienic name
|
||||
if ident.name == lookup_ident.name
|
||||
&& ns == namespace
|
||||
&& !ptr::eq(in_module, parent_scope.module)
|
||||
&& in_module != parent_scope.module
|
||||
&& !ident.span.normalize_to_macros_2_0().from_expansion()
|
||||
{
|
||||
let res = name_binding.res();
|
||||
@ -1515,7 +1513,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
true
|
||||
}
|
||||
|
||||
fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
|
||||
fn binding_description(&self, b: NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
|
||||
let res = b.res();
|
||||
if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
|
||||
// These already contain the "built-in" prefix or look bad with it.
|
||||
@ -1555,7 +1553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
err.span_label(ident.span, "ambiguous name");
|
||||
err.note(format!("ambiguous because of {}", kind.descr()));
|
||||
|
||||
let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
|
||||
let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
|
||||
let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
|
||||
let note_msg = format!("`{ident}` could{also} refer to {what}");
|
||||
|
||||
@ -1595,7 +1593,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
/// If the binding refers to a tuple struct constructor with fields,
|
||||
/// returns the span of its fields.
|
||||
fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
|
||||
fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
|
||||
if let NameBindingKind::Res(Res::Def(
|
||||
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
|
||||
ctor_def_id,
|
||||
@ -1622,7 +1620,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
|
||||
let import_descr = nonimport_descr.clone() + " import";
|
||||
let get_descr =
|
||||
|b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
|
||||
|b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
|
||||
|
||||
// Print the primary message.
|
||||
let descr = get_descr(binding);
|
||||
@ -1702,7 +1700,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let first = ptr::eq(binding, first_binding);
|
||||
let first = binding == first_binding;
|
||||
let msg = format!(
|
||||
"{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
|
||||
and_refers_to = if first { "" } else { "...and refers to " },
|
||||
@ -1732,7 +1730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
pub(crate) fn find_similarly_named_module_or_crate(
|
||||
&mut self,
|
||||
ident: Symbol,
|
||||
current_module: &Module<'a>,
|
||||
current_module: Module<'a>,
|
||||
) -> Option<Symbol> {
|
||||
let mut candidates = self
|
||||
.extern_prelude
|
||||
@ -1742,7 +1740,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.module_map
|
||||
.iter()
|
||||
.filter(|(_, module)| {
|
||||
current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module)
|
||||
current_module.is_ancestor_of(**module) && current_module != **module
|
||||
})
|
||||
.flat_map(|(_, module)| module.kind.name()),
|
||||
)
|
||||
@ -1762,7 +1760,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||
parent_scope: &ParentScope<'a>,
|
||||
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
failed_segment_idx: usize,
|
||||
ident: Ident,
|
||||
@ -1945,7 +1943,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
|
||||
suggestion = suggestion.or_else(|| {
|
||||
self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map(
|
||||
self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
|
||||
|sugg| {
|
||||
(
|
||||
vec![(ident.span, sugg.to_string())],
|
||||
@ -2114,7 +2112,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
/// ```
|
||||
pub(crate) fn check_for_module_export_macro(
|
||||
&mut self,
|
||||
import: &'a Import<'a>,
|
||||
import: Import<'a>,
|
||||
module: ModuleOrUniformRoot<'a>,
|
||||
ident: Ident,
|
||||
) -> Option<(Option<Suggestion>, Option<String>)> {
|
||||
@ -2126,9 +2124,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
crate_module = parent;
|
||||
}
|
||||
|
||||
if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) {
|
||||
// Don't make a suggestion if the import was already from the root of the
|
||||
// crate.
|
||||
if module == ModuleOrUniformRoot::Module(crate_module) {
|
||||
// Don't make a suggestion if the import was already from the root of the crate.
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::Crate;
|
||||
use rustc_ast::EnumDef;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_middle::middle::privacy::Level;
|
||||
@ -13,12 +12,10 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
|
||||
use rustc_middle::ty::Visibility;
|
||||
use std::mem;
|
||||
|
||||
type ImportId<'a> = Interned<'a, NameBinding<'a>>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum ParentId<'a> {
|
||||
Def(LocalDefId),
|
||||
Import(ImportId<'a>),
|
||||
Import(NameBinding<'a>),
|
||||
}
|
||||
|
||||
impl ParentId<'_> {
|
||||
@ -36,7 +33,7 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
|
||||
/// While walking import chains we need to track effective visibilities per-binding, and def id
|
||||
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
|
||||
/// bindings can correspond to a single def id in imports. So we keep a separate table.
|
||||
import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>,
|
||||
import_effective_visibilities: EffectiveVisibilities<NameBinding<'a>>,
|
||||
// It's possible to recalculate this at any point, but it's relatively expensive.
|
||||
current_private_vis: Visibility,
|
||||
changed: bool,
|
||||
@ -47,7 +44,7 @@ impl Resolver<'_, '_> {
|
||||
self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
|
||||
}
|
||||
|
||||
fn private_vis_import(&mut self, binding: ImportId<'_>) -> Visibility {
|
||||
fn private_vis_import(&mut self, binding: NameBinding<'_>) -> Visibility {
|
||||
let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
|
||||
Visibility::Restricted(
|
||||
import
|
||||
@ -75,7 +72,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
|
||||
pub(crate) fn compute_effective_visibilities<'c>(
|
||||
r: &'r mut Resolver<'a, 'tcx>,
|
||||
krate: &'c Crate,
|
||||
) -> FxHashSet<Interned<'a, NameBinding<'a>>> {
|
||||
) -> FxHashSet<NameBinding<'a>> {
|
||||
let mut visitor = EffectiveVisibilitiesVisitor {
|
||||
r,
|
||||
def_effective_visibilities: Default::default(),
|
||||
@ -133,8 +130,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
|
||||
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
|
||||
let mut parent_id = ParentId::Def(module_id);
|
||||
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
|
||||
let binding_id = ImportId::new_unchecked(binding);
|
||||
self.update_import(binding_id, parent_id);
|
||||
self.update_import(binding, parent_id);
|
||||
|
||||
if binding.ambiguity.is_some() {
|
||||
// Stop at the root ambiguity, further bindings in the chain should not
|
||||
@ -143,7 +139,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
|
||||
break;
|
||||
}
|
||||
|
||||
parent_id = ParentId::Import(binding_id);
|
||||
parent_id = ParentId::Import(binding);
|
||||
binding = nested_binding;
|
||||
}
|
||||
|
||||
@ -192,7 +188,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
|
||||
fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) {
|
||||
let nominal_vis = binding.vis.expect_local();
|
||||
let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return };
|
||||
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
|
||||
|
@ -11,8 +11,6 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use std::ptr;
|
||||
|
||||
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
|
||||
use crate::late::{
|
||||
ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
|
||||
@ -20,7 +18,7 @@ use crate::late::{
|
||||
use crate::macros::{sub_namespace_match, MacroRulesScope};
|
||||
use crate::BindingKey;
|
||||
use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
|
||||
use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
|
||||
use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
|
||||
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
|
||||
use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak};
|
||||
|
||||
@ -284,7 +282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
ribs: &[Rib<'a>],
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Option<LexicalScopeBinding<'a>> {
|
||||
assert!(ns == TypeNS || ns == ValueNS);
|
||||
let orig_ident = ident;
|
||||
@ -378,8 +376,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
force: bool,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Result<NameBinding<'a>, Determinacy> {
|
||||
bitflags::bitflags! {
|
||||
struct Flags: u8 {
|
||||
const MACRO_RULES = 1 << 0;
|
||||
@ -415,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// }
|
||||
// So we have to save the innermost solution and continue searching in outer scopes
|
||||
// to detect potential ambiguities.
|
||||
let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None;
|
||||
let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
|
||||
let mut determinacy = Determinacy::Determined;
|
||||
|
||||
// Go through all the scopes and try to resolve the name.
|
||||
@ -538,7 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
),
|
||||
);
|
||||
}
|
||||
let misc_flags = if ptr::eq(module, this.graph_root) {
|
||||
let misc_flags = if module == this.graph_root {
|
||||
Flags::MISC_SUGGEST_CRATE
|
||||
} else if module.is_normal() {
|
||||
Flags::MISC_SUGGEST_SELF
|
||||
@ -717,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
) -> Result<NameBinding<'a>, Determinacy> {
|
||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
@ -730,8 +728,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Result<NameBinding<'a>, Determinacy> {
|
||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
@ -744,8 +742,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
|
||||
let tmp_parent_scope;
|
||||
let mut adjusted_parent_scope = parent_scope;
|
||||
match module {
|
||||
@ -782,8 +780,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Result<NameBinding<'a>, Determinacy> {
|
||||
self.resolve_ident_in_module_unadjusted_ext(
|
||||
module,
|
||||
ident,
|
||||
@ -809,8 +807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
finalize: Option<Finalize>,
|
||||
// This binding should be ignored during in-module resolution, so that we don't get
|
||||
// "self-confirming" import resolutions during import validation and checking.
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
|
||||
let module = match module {
|
||||
ModuleOrUniformRoot::Module(module) => module,
|
||||
ModuleOrUniformRoot::CrateRootAndExternPrelude => {
|
||||
@ -873,13 +871,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// binding if it exists. What we really want here is having two separate scopes in
|
||||
// a module - one for non-globs and one for globs, but until that's done use this
|
||||
// hack to avoid inconsistent resolution ICEs during import validation.
|
||||
let binding =
|
||||
[resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| {
|
||||
match (binding, ignore_binding) {
|
||||
(Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
|
||||
_ => binding,
|
||||
}
|
||||
});
|
||||
let binding = [resolution.binding, resolution.shadowed_glob]
|
||||
.into_iter()
|
||||
.find_map(|binding| if binding == ignore_binding { None } else { binding });
|
||||
|
||||
if let Some(Finalize { path_span, report_private, .. }) = finalize {
|
||||
let Some(binding) = binding else {
|
||||
@ -917,11 +911,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
|
||||
if let NameBindingKind::Import {
|
||||
import: Import { kind: ImportKind::MacroExport, .. },
|
||||
..
|
||||
} = binding.kind
|
||||
{
|
||||
if let NameBindingKind::Import { import, .. } = binding.kind
|
||||
&& matches!(import.kind, ImportKind::MacroExport) {
|
||||
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
||||
}
|
||||
}
|
||||
@ -930,7 +921,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
return Ok(binding);
|
||||
}
|
||||
|
||||
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
|
||||
let check_usable = |this: &mut Self, binding: NameBinding<'a>| {
|
||||
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
|
||||
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
|
||||
};
|
||||
@ -955,7 +946,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
if let Some(ignored) = ignore_binding &&
|
||||
let NameBindingKind::Import { import, .. } = ignored.kind &&
|
||||
ptr::eq(import, &**single_import) {
|
||||
import == *single_import {
|
||||
// Ignore not just the binding itself, but if it has a shadowed_glob,
|
||||
// ignore that, too, because this loop is supposed to only process
|
||||
// named imports.
|
||||
@ -1352,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> PathResult<'a> {
|
||||
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding)
|
||||
}
|
||||
@ -1364,7 +1355,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Finalize>,
|
||||
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> PathResult<'a> {
|
||||
let mut module = None;
|
||||
let mut allow_super = true;
|
||||
|
@ -12,7 +12,7 @@ use crate::{fluent_generated as fluent, Namespace::*};
|
||||
use crate::{module_to_string, names_to_string, ImportSuggestion};
|
||||
use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
|
||||
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
|
||||
use crate::{NameBinding, NameBindingKind, PathResult};
|
||||
use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult};
|
||||
|
||||
use rustc_ast::NodeId;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -35,7 +35,7 @@ use rustc_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::{mem, ptr};
|
||||
use std::mem;
|
||||
|
||||
type Res = def::Res<NodeId>;
|
||||
|
||||
@ -48,9 +48,9 @@ pub(crate) enum ImportKind<'a> {
|
||||
/// `target` in `use prefix::source as target`.
|
||||
target: Ident,
|
||||
/// Bindings to which `source` refers to.
|
||||
source_bindings: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
||||
source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
|
||||
/// Bindings introduced by `target`.
|
||||
target_bindings: PerNS<Cell<Option<&'a NameBinding<'a>>>>,
|
||||
target_bindings: PerNS<Cell<Option<NameBinding<'a>>>>,
|
||||
/// `true` for `...::{self [as target]}` imports, `false` otherwise.
|
||||
type_ns_only: bool,
|
||||
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
|
||||
@ -135,7 +135,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
|
||||
|
||||
/// One import.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Import<'a> {
|
||||
pub(crate) struct ImportData<'a> {
|
||||
pub kind: ImportKind<'a>,
|
||||
|
||||
/// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`
|
||||
@ -172,7 +172,11 @@ pub(crate) struct Import<'a> {
|
||||
pub used: Cell<bool>,
|
||||
}
|
||||
|
||||
impl<'a> Import<'a> {
|
||||
/// All imports are unique and allocated on a same arena,
|
||||
/// so we can use referential equality to compare them.
|
||||
pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>;
|
||||
|
||||
impl<'a> ImportData<'a> {
|
||||
pub(crate) fn is_glob(&self) -> bool {
|
||||
matches!(self.kind, ImportKind::Glob { .. })
|
||||
}
|
||||
@ -214,15 +218,15 @@ impl<'a> Import<'a> {
|
||||
pub(crate) struct NameResolution<'a> {
|
||||
/// Single imports that may define the name in the namespace.
|
||||
/// Imports are arena-allocated, so it's ok to use pointers as keys.
|
||||
pub single_imports: FxHashSet<Interned<'a, Import<'a>>>,
|
||||
pub single_imports: FxHashSet<Import<'a>>,
|
||||
/// The least shadowable known binding for this name, or None if there are no known bindings.
|
||||
pub binding: Option<&'a NameBinding<'a>>,
|
||||
pub shadowed_glob: Option<&'a NameBinding<'a>>,
|
||||
pub binding: Option<NameBinding<'a>>,
|
||||
pub shadowed_glob: Option<NameBinding<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> NameResolution<'a> {
|
||||
/// Returns the binding for the name if it is known or None if it not known.
|
||||
pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
|
||||
pub(crate) fn binding(&self) -> Option<NameBinding<'a>> {
|
||||
self.binding.and_then(|binding| {
|
||||
if !binding.is_glob_import() || self.single_imports.is_empty() {
|
||||
Some(binding)
|
||||
@ -231,10 +235,6 @@ impl<'a> NameResolution<'a> {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn add_single_import(&mut self, import: &'a Import<'a>) {
|
||||
self.single_imports.insert(Interned::new_unchecked(import));
|
||||
}
|
||||
}
|
||||
|
||||
/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
|
||||
@ -250,15 +250,12 @@ struct UnresolvedImportError {
|
||||
|
||||
// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
|
||||
// are permitted for backward-compatibility under a deprecation lint.
|
||||
fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool {
|
||||
fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool {
|
||||
match (&import.kind, &binding.kind) {
|
||||
(
|
||||
ImportKind::Single { .. },
|
||||
NameBindingKind::Import {
|
||||
import: Import { kind: ImportKind::ExternCrate { .. }, .. },
|
||||
..
|
||||
},
|
||||
) => import.expect_vis().is_public(),
|
||||
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => {
|
||||
matches!(binding_import.kind, ImportKind::ExternCrate { .. })
|
||||
&& import.expect_vis().is_public()
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -266,11 +263,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi
|
||||
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
/// Given a binding and an import that resolves to it,
|
||||
/// return the corresponding binding defined by the import.
|
||||
pub(crate) fn import(
|
||||
&self,
|
||||
binding: &'a NameBinding<'a>,
|
||||
import: &'a Import<'a>,
|
||||
) -> &'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 vis = if binding.vis.is_at_least(import_vis, self.tcx)
|
||||
|| pub_use_of_private_extern_crate_hack(import, binding)
|
||||
@ -288,7 +281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.arenas.alloc_name_binding(NameBinding {
|
||||
self.arenas.alloc_name_binding(NameBindingData {
|
||||
kind: NameBindingKind::Import { binding, import, used: Cell::new(false) },
|
||||
ambiguity: None,
|
||||
span: import.span,
|
||||
@ -302,8 +295,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
&mut self,
|
||||
module: Module<'a>,
|
||||
key: BindingKey,
|
||||
binding: &'a NameBinding<'a>,
|
||||
) -> Result<(), &'a NameBinding<'a>> {
|
||||
binding: NameBinding<'a>,
|
||||
) -> Result<(), NameBinding<'a>> {
|
||||
let res = binding.res();
|
||||
self.check_reserved_macro_name(key.ident, res);
|
||||
self.set_binding_parent_module(binding, module);
|
||||
@ -372,12 +365,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
fn ambiguity(
|
||||
&self,
|
||||
kind: AmbiguityKind,
|
||||
primary_binding: &'a NameBinding<'a>,
|
||||
secondary_binding: &'a NameBinding<'a>,
|
||||
) -> &'a NameBinding<'a> {
|
||||
self.arenas.alloc_name_binding(NameBinding {
|
||||
primary_binding: NameBinding<'a>,
|
||||
secondary_binding: NameBinding<'a>,
|
||||
) -> NameBinding<'a> {
|
||||
self.arenas.alloc_name_binding(NameBindingData {
|
||||
ambiguity: Some((secondary_binding, kind)),
|
||||
..primary_binding.clone()
|
||||
..(*primary_binding).clone()
|
||||
})
|
||||
}
|
||||
|
||||
@ -395,13 +388,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
let t = f(self, resolution);
|
||||
|
||||
match resolution.binding() {
|
||||
_ if old_binding.is_some() => return t,
|
||||
None => return t,
|
||||
Some(binding) => match old_binding {
|
||||
Some(old_binding) if ptr::eq(old_binding, binding) => return t,
|
||||
_ => (binding, t),
|
||||
},
|
||||
if old_binding.is_none() && let Some(binding) = resolution.binding() {
|
||||
(binding, t)
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
@ -414,7 +404,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
None => continue,
|
||||
};
|
||||
if self.is_accessible_from(binding.vis, scope) {
|
||||
let imported_binding = self.import(binding, import);
|
||||
let imported_binding = self.import(binding, *import);
|
||||
let key = BindingKey { ident, ..key };
|
||||
let _ = self.try_define(import.parent_scope.module, key, imported_binding);
|
||||
}
|
||||
@ -425,7 +415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
|
||||
// or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
|
||||
fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) {
|
||||
fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) {
|
||||
if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
|
||||
if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
|
||||
{
|
||||
@ -463,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
prev_indeterminate_count = indeterminate_count;
|
||||
indeterminate_count = 0;
|
||||
for import in mem::take(&mut self.indeterminate_imports) {
|
||||
let import_indeterminate_count = self.resolve_import(&import);
|
||||
let import_indeterminate_count = self.resolve_import(import);
|
||||
indeterminate_count += import_indeterminate_count;
|
||||
match import_indeterminate_count {
|
||||
0 => self.determined_imports.push(import),
|
||||
@ -475,7 +465,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
pub(crate) fn finalize_imports(&mut self) {
|
||||
for module in self.arenas.local_modules().iter() {
|
||||
self.finalize_resolutions_in(module);
|
||||
self.finalize_resolutions_in(*module);
|
||||
}
|
||||
|
||||
let mut seen_spans = FxHashSet::default();
|
||||
@ -546,17 +536,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
pub(crate) fn check_hidden_glob_reexports(
|
||||
&mut self,
|
||||
exported_ambiguities: FxHashSet<Interned<'a, NameBinding<'a>>>,
|
||||
exported_ambiguities: FxHashSet<NameBinding<'a>>,
|
||||
) {
|
||||
for module in self.arenas.local_modules().iter() {
|
||||
for (key, resolution) in self.resolutions(module).borrow().iter() {
|
||||
for (key, resolution) in self.resolutions(*module).borrow().iter() {
|
||||
let resolution = resolution.borrow();
|
||||
|
||||
if let Some(binding) = resolution.binding {
|
||||
if let NameBindingKind::Import { import, .. } = binding.kind
|
||||
&& let Some((amb_binding, _)) = binding.ambiguity
|
||||
&& binding.res() != Res::Err
|
||||
&& exported_ambiguities.contains(&Interned::new_unchecked(binding))
|
||||
&& exported_ambiguities.contains(&binding)
|
||||
{
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
AMBIGUOUS_GLOB_REEXPORTS,
|
||||
@ -612,7 +602,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) {
|
||||
fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) {
|
||||
if errors.is_empty() {
|
||||
return;
|
||||
}
|
||||
@ -704,7 +694,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
///
|
||||
/// Meanwhile, if resolve successful, the resolved bindings are written
|
||||
/// into the module.
|
||||
fn resolve_import(&mut self, import: &'a Import<'a>) -> usize {
|
||||
fn resolve_import(&mut self, import: Import<'a>) -> usize {
|
||||
debug!(
|
||||
"(resolving import for module) resolving import `{}::...` in `{}`",
|
||||
Segment::names_to_string(&import.module_path),
|
||||
@ -784,7 +774,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
let key = BindingKey::new(target, ns);
|
||||
this.update_resolution(parent, key, |_, resolution| {
|
||||
resolution.single_imports.remove(&Interned::new_unchecked(import));
|
||||
resolution.single_imports.remove(&import);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -798,7 +788,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
///
|
||||
/// Optionally returns an unresolved import error. This error is buffered and used to
|
||||
/// consolidate multiple unresolved import errors into a single diagnostic.
|
||||
fn finalize_import(&mut self, import: &'a 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 {
|
||||
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
|
||||
@ -824,7 +814,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
PathResult::Module(module) => {
|
||||
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
||||
if let Some(initial_module) = import.imported_module.get() {
|
||||
if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
|
||||
if module != initial_module && no_ambiguity {
|
||||
span_bug!(import.span, "inconsistent resolution for an import");
|
||||
}
|
||||
} else if self.privacy_errors.is_empty() {
|
||||
@ -926,7 +916,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
if ptr::eq(module, import.parent_scope.module) {
|
||||
if module == import.parent_scope.module {
|
||||
// Importing a module into itself is not allowed.
|
||||
return Some(UnresolvedImportError {
|
||||
span: import.span,
|
||||
@ -1242,9 +1232,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
fn check_for_redundant_imports(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
import: &'a Import<'a>,
|
||||
source_bindings: &PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
||||
target_bindings: &PerNS<Cell<Option<&'a NameBinding<'a>>>>,
|
||||
import: Import<'a>,
|
||||
source_bindings: &PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
|
||||
target_bindings: &PerNS<Cell<Option<NameBinding<'a>>>>,
|
||||
target: Ident,
|
||||
) {
|
||||
// This function is only called for single imports.
|
||||
@ -1305,7 +1295,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_glob_import(&mut self, import: &'a Import<'a>) {
|
||||
fn resolve_glob_import(&mut self, import: Import<'a>) {
|
||||
// This function is only called for glob imports.
|
||||
let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() };
|
||||
|
||||
@ -1319,7 +1309,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
if module.is_trait() {
|
||||
self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit();
|
||||
return;
|
||||
} else if ptr::eq(module, import.parent_scope.module) {
|
||||
} else if module == import.parent_scope.module {
|
||||
return;
|
||||
} else if is_prelude {
|
||||
self.prelude = Some(module);
|
||||
|
@ -1284,7 +1284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<NameBinding<'a>>,
|
||||
) -> Option<LexicalScopeBinding<'a>> {
|
||||
self.r.resolve_ident_in_lexical_scope(
|
||||
ident,
|
||||
@ -2972,7 +2972,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||
F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
|
||||
{
|
||||
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
|
||||
let Some((module, _)) = &self.current_trait_ref else { return; };
|
||||
let Some((module, _)) = self.current_trait_ref else { return; };
|
||||
ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
|
||||
let key = BindingKey::new(ident, ns);
|
||||
let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
|
||||
|
@ -1593,7 +1593,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let resolutions = self.r.resolutions(module);
|
||||
let resolutions = self.r.resolutions(*module);
|
||||
let targets = resolutions
|
||||
.borrow()
|
||||
.iter()
|
||||
|
@ -14,6 +14,7 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustdoc::private_intra_doc_links)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
@ -61,10 +62,10 @@ use rustc_span::{Span, DUMMY_SP};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::BTreeSet;
|
||||
use std::{fmt, ptr};
|
||||
use std::fmt;
|
||||
|
||||
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
|
||||
use imports::{Import, ImportKind, NameResolution};
|
||||
use imports::{Import, ImportData, ImportKind, NameResolution};
|
||||
use late::{HasGenericParams, PathSource, PatternSource};
|
||||
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
|
||||
|
||||
@ -352,7 +353,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
|
||||
/// forward.
|
||||
#[derive(Debug)]
|
||||
enum LexicalScopeBinding<'a> {
|
||||
Item(&'a NameBinding<'a>),
|
||||
Item(NameBinding<'a>),
|
||||
Res(Res),
|
||||
}
|
||||
|
||||
@ -365,7 +366,7 @@ impl<'a> LexicalScopeBinding<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
enum ModuleOrUniformRoot<'a> {
|
||||
/// Regular module.
|
||||
Module(Module<'a>),
|
||||
@ -383,23 +384,6 @@ enum ModuleOrUniformRoot<'a> {
|
||||
CurrentScope,
|
||||
}
|
||||
|
||||
impl ModuleOrUniformRoot<'_> {
|
||||
fn same_def(lhs: Self, rhs: Self) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => {
|
||||
ptr::eq(lhs, rhs)
|
||||
}
|
||||
(
|
||||
ModuleOrUniformRoot::CrateRootAndExternPrelude,
|
||||
ModuleOrUniformRoot::CrateRootAndExternPrelude,
|
||||
)
|
||||
| (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude)
|
||||
| (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PathResult<'a> {
|
||||
Module(ModuleOrUniformRoot<'a>),
|
||||
@ -518,11 +502,11 @@ struct ModuleData<'a> {
|
||||
/// Whether `#[no_implicit_prelude]` is active.
|
||||
no_implicit_prelude: bool,
|
||||
|
||||
glob_importers: RefCell<Vec<&'a Import<'a>>>,
|
||||
globs: RefCell<Vec<&'a Import<'a>>>,
|
||||
glob_importers: RefCell<Vec<Import<'a>>>,
|
||||
globs: RefCell<Vec<Import<'a>>>,
|
||||
|
||||
/// Used to memoize the traits in this module for faster searches through all traits in scope.
|
||||
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
|
||||
traits: RefCell<Option<Box<[(Ident, NameBinding<'a>)]>>>,
|
||||
|
||||
/// Span of the module itself. Used for error reporting.
|
||||
span: Span,
|
||||
@ -530,7 +514,11 @@ struct ModuleData<'a> {
|
||||
expansion: ExpnId,
|
||||
}
|
||||
|
||||
type Module<'a> = &'a ModuleData<'a>;
|
||||
/// All modules are unique and allocated on a same arena,
|
||||
/// so we can use referential equality to compare them.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[rustc_pass_by_value]
|
||||
struct Module<'a>(Interned<'a, ModuleData<'a>>);
|
||||
|
||||
impl<'a> ModuleData<'a> {
|
||||
fn new(
|
||||
@ -558,11 +546,13 @@ impl<'a> ModuleData<'a> {
|
||||
expansion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F)
|
||||
impl<'a> Module<'a> {
|
||||
fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F)
|
||||
where
|
||||
R: AsMut<Resolver<'a, 'tcx>>,
|
||||
F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>),
|
||||
F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>),
|
||||
{
|
||||
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
|
||||
if let Some(binding) = name_resolution.borrow().binding {
|
||||
@ -572,7 +562,7 @@ impl<'a> ModuleData<'a> {
|
||||
}
|
||||
|
||||
/// This modifies `self` in place. The traits will be stored in `self.traits`.
|
||||
fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R)
|
||||
fn ensure_traits<'tcx, R>(self, resolver: &mut R)
|
||||
where
|
||||
R: AsMut<Resolver<'a, 'tcx>>,
|
||||
{
|
||||
@ -591,7 +581,7 @@ impl<'a> ModuleData<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn res(&self) -> Option<Res> {
|
||||
fn res(self) -> Option<Res> {
|
||||
match self.kind {
|
||||
ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)),
|
||||
_ => None,
|
||||
@ -599,11 +589,11 @@ impl<'a> ModuleData<'a> {
|
||||
}
|
||||
|
||||
// Public for rustdoc.
|
||||
fn def_id(&self) -> DefId {
|
||||
fn def_id(self) -> DefId {
|
||||
self.opt_def_id().expect("`ModuleData::def_id` is called on a block module")
|
||||
}
|
||||
|
||||
fn opt_def_id(&self) -> Option<DefId> {
|
||||
fn opt_def_id(self) -> Option<DefId> {
|
||||
match self.kind {
|
||||
ModuleKind::Def(_, def_id, _) => Some(def_id),
|
||||
_ => None,
|
||||
@ -611,15 +601,15 @@ impl<'a> ModuleData<'a> {
|
||||
}
|
||||
|
||||
// `self` resolves to the first module ancestor that `is_normal`.
|
||||
fn is_normal(&self) -> bool {
|
||||
fn is_normal(self) -> bool {
|
||||
matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _))
|
||||
}
|
||||
|
||||
fn is_trait(&self) -> bool {
|
||||
fn is_trait(self) -> bool {
|
||||
matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _))
|
||||
}
|
||||
|
||||
fn nearest_item_scope(&'a self) -> Module<'a> {
|
||||
fn nearest_item_scope(self) -> Module<'a> {
|
||||
match self.kind {
|
||||
ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => {
|
||||
self.parent.expect("enum or trait module without a parent")
|
||||
@ -630,15 +620,15 @@ impl<'a> ModuleData<'a> {
|
||||
|
||||
/// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
|
||||
/// This may be the crate root.
|
||||
fn nearest_parent_mod(&self) -> DefId {
|
||||
fn nearest_parent_mod(self) -> DefId {
|
||||
match self.kind {
|
||||
ModuleKind::Def(DefKind::Mod, def_id, _) => def_id,
|
||||
_ => self.parent.expect("non-root module without parent").nearest_parent_mod(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ancestor_of(&self, mut other: &Self) -> bool {
|
||||
while !ptr::eq(self, other) {
|
||||
fn is_ancestor_of(self, mut other: Self) -> bool {
|
||||
while self != other {
|
||||
if let Some(parent) = other.parent {
|
||||
other = parent;
|
||||
} else {
|
||||
@ -649,7 +639,15 @@ impl<'a> ModuleData<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for ModuleData<'a> {
|
||||
impl<'a> std::ops::Deref for Module<'a> {
|
||||
type Target = ModuleData<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for Module<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.res())
|
||||
}
|
||||
@ -657,20 +655,24 @@ impl<'a> fmt::Debug for ModuleData<'a> {
|
||||
|
||||
/// Records a possibly-private value, type, or module definition.
|
||||
#[derive(Clone, Debug)]
|
||||
struct NameBinding<'a> {
|
||||
struct NameBindingData<'a> {
|
||||
kind: NameBindingKind<'a>,
|
||||
ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>,
|
||||
ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>,
|
||||
expansion: LocalExpnId,
|
||||
span: Span,
|
||||
vis: ty::Visibility<DefId>,
|
||||
}
|
||||
|
||||
/// All name bindings are unique and allocated on a same arena,
|
||||
/// so we can use referential equality to compare them.
|
||||
type NameBinding<'a> = Interned<'a, NameBindingData<'a>>;
|
||||
|
||||
trait ToNameBinding<'a> {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>;
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>;
|
||||
}
|
||||
|
||||
impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
|
||||
fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
impl<'a> ToNameBinding<'a> for NameBinding<'a> {
|
||||
fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -679,7 +681,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
|
||||
enum NameBindingKind<'a> {
|
||||
Res(Res),
|
||||
Module(Module<'a>),
|
||||
Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell<bool> },
|
||||
Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell<bool> },
|
||||
}
|
||||
|
||||
impl<'a> NameBindingKind<'a> {
|
||||
@ -692,7 +694,7 @@ impl<'a> NameBindingKind<'a> {
|
||||
#[derive(Debug)]
|
||||
struct PrivacyError<'a> {
|
||||
ident: Ident,
|
||||
binding: &'a NameBinding<'a>,
|
||||
binding: NameBinding<'a>,
|
||||
dedup_span: Span,
|
||||
outermost_res: Option<(Res, Ident)>,
|
||||
parent_scope: ParentScope<'a>,
|
||||
@ -761,13 +763,13 @@ enum AmbiguityErrorMisc {
|
||||
struct AmbiguityError<'a> {
|
||||
kind: AmbiguityKind,
|
||||
ident: Ident,
|
||||
b1: &'a NameBinding<'a>,
|
||||
b2: &'a NameBinding<'a>,
|
||||
b1: NameBinding<'a>,
|
||||
b2: NameBinding<'a>,
|
||||
misc1: AmbiguityErrorMisc,
|
||||
misc2: AmbiguityErrorMisc,
|
||||
}
|
||||
|
||||
impl<'a> NameBinding<'a> {
|
||||
impl<'a> NameBindingData<'a> {
|
||||
fn module(&self) -> Option<Module<'a>> {
|
||||
match self.kind {
|
||||
NameBindingKind::Module(module) => Some(module),
|
||||
@ -805,14 +807,12 @@ impl<'a> NameBinding<'a> {
|
||||
|
||||
fn is_extern_crate(&self) -> bool {
|
||||
match self.kind {
|
||||
NameBindingKind::Import {
|
||||
import: &Import { kind: ImportKind::ExternCrate { .. }, .. },
|
||||
..
|
||||
} => true,
|
||||
NameBindingKind::Module(&ModuleData {
|
||||
kind: ModuleKind::Def(DefKind::Mod, def_id, _),
|
||||
..
|
||||
}) => def_id.is_crate_root(),
|
||||
NameBindingKind::Import { import, .. } => {
|
||||
matches!(import.kind, ImportKind::ExternCrate { .. })
|
||||
}
|
||||
NameBindingKind::Module(module)
|
||||
if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind
|
||||
=> def_id.is_crate_root(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -855,7 +855,7 @@ impl<'a> NameBinding<'a> {
|
||||
fn may_appear_after(
|
||||
&self,
|
||||
invoc_parent_expansion: LocalExpnId,
|
||||
binding: &NameBinding<'_>,
|
||||
binding: NameBinding<'_>,
|
||||
) -> bool {
|
||||
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
|
||||
// Expansions are partially ordered, so "may appear after" is an inversion of
|
||||
@ -872,7 +872,7 @@ impl<'a> NameBinding<'a> {
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct ExternPreludeEntry<'a> {
|
||||
extern_crate_item: Option<&'a NameBinding<'a>>,
|
||||
extern_crate_item: Option<NameBinding<'a>>,
|
||||
introduced_by_item: bool,
|
||||
}
|
||||
|
||||
@ -917,10 +917,10 @@ pub struct Resolver<'a, 'tcx> {
|
||||
field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
|
||||
|
||||
/// All imports known to succeed or fail.
|
||||
determined_imports: Vec<&'a Import<'a>>,
|
||||
determined_imports: Vec<Import<'a>>,
|
||||
|
||||
/// All non-determined imports.
|
||||
indeterminate_imports: Vec<&'a Import<'a>>,
|
||||
indeterminate_imports: Vec<Import<'a>>,
|
||||
|
||||
// Spans for local variables found during pattern resolution.
|
||||
// Used for suggestions during error reporting.
|
||||
@ -962,7 +962,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||
/// language items.
|
||||
empty_module: Module<'a>,
|
||||
module_map: FxHashMap<DefId, Module<'a>>,
|
||||
binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>,
|
||||
binding_parent_modules: FxHashMap<NameBinding<'a>, Module<'a>>,
|
||||
|
||||
underscore_disambiguator: u32,
|
||||
|
||||
@ -984,7 +984,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
|
||||
|
||||
arenas: &'a ResolverArenas<'a>,
|
||||
dummy_binding: &'a NameBinding<'a>,
|
||||
dummy_binding: NameBinding<'a>,
|
||||
|
||||
used_extern_options: FxHashSet<Symbol>,
|
||||
macro_names: FxHashSet<Ident>,
|
||||
@ -993,7 +993,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||
/// the surface (`macro` items in libcore), but are actually attributes or derives.
|
||||
builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
|
||||
registered_tools: &'tcx RegisteredTools,
|
||||
macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>,
|
||||
macro_use_prelude: FxHashMap<Symbol, NameBinding<'a>>,
|
||||
macro_map: FxHashMap<DefId, MacroData>,
|
||||
dummy_ext_bang: Lrc<SyntaxExtension>,
|
||||
dummy_ext_derive: Lrc<SyntaxExtension>,
|
||||
@ -1005,7 +1005,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||
proc_macro_stubs: FxHashSet<LocalDefId>,
|
||||
/// Traces collected during macro resolution and validated when it's complete.
|
||||
single_segment_macro_resolutions:
|
||||
Vec<(Ident, MacroKind, ParentScope<'a>, Option<&'a NameBinding<'a>>)>,
|
||||
Vec<(Ident, MacroKind, ParentScope<'a>, Option<NameBinding<'a>>)>,
|
||||
multi_segment_macro_resolutions:
|
||||
Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, Option<Res>)>,
|
||||
builtin_attrs: Vec<(Ident, ParentScope<'a>)>,
|
||||
@ -1030,7 +1030,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||
/// Avoid duplicated errors for "name already defined".
|
||||
name_already_seen: FxHashMap<Symbol, Span>,
|
||||
|
||||
potentially_unused_imports: Vec<&'a Import<'a>>,
|
||||
potentially_unused_imports: Vec<Import<'a>>,
|
||||
|
||||
/// Table for mapping struct IDs into struct constructor IDs,
|
||||
/// it's not used during normal resolution, only for better error reporting.
|
||||
@ -1085,7 +1085,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||
pub struct ResolverArenas<'a> {
|
||||
modules: TypedArena<ModuleData<'a>>,
|
||||
local_modules: RefCell<Vec<Module<'a>>>,
|
||||
imports: TypedArena<Import<'a>>,
|
||||
imports: TypedArena<ImportData<'a>>,
|
||||
name_resolutions: TypedArena<RefCell<NameResolution<'a>>>,
|
||||
ast_paths: TypedArena<ast::Path>,
|
||||
dropless: DroplessArena,
|
||||
@ -1101,8 +1101,13 @@ impl<'a> ResolverArenas<'a> {
|
||||
no_implicit_prelude: bool,
|
||||
module_map: &mut FxHashMap<DefId, Module<'a>>,
|
||||
) -> Module<'a> {
|
||||
let module =
|
||||
self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude));
|
||||
let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new(
|
||||
parent,
|
||||
kind,
|
||||
expn_id,
|
||||
span,
|
||||
no_implicit_prelude,
|
||||
))));
|
||||
let def_id = module.opt_def_id();
|
||||
if def_id.map_or(true, |def_id| def_id.is_local()) {
|
||||
self.local_modules.borrow_mut().push(module);
|
||||
@ -1115,11 +1120,11 @@ impl<'a> ResolverArenas<'a> {
|
||||
fn local_modules(&'a self) -> std::cell::Ref<'a, Vec<Module<'a>>> {
|
||||
self.local_modules.borrow()
|
||||
}
|
||||
fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
|
||||
self.dropless.alloc(name_binding)
|
||||
fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> {
|
||||
Interned::new_unchecked(self.dropless.alloc(name_binding))
|
||||
}
|
||||
fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> {
|
||||
self.imports.alloc(import)
|
||||
fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> {
|
||||
Interned::new_unchecked(self.imports.alloc(import))
|
||||
}
|
||||
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
|
||||
self.name_resolutions.alloc(Default::default())
|
||||
@ -1314,7 +1319,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
macro_expanded_macro_export_errors: BTreeSet::new(),
|
||||
|
||||
arenas,
|
||||
dummy_binding: arenas.alloc_name_binding(NameBinding {
|
||||
dummy_binding: arenas.alloc_name_binding(NameBindingData {
|
||||
kind: NameBindingKind::Res(Res::Err),
|
||||
ambiguity: None,
|
||||
expansion: LocalExpnId::ROOT,
|
||||
@ -1624,7 +1629,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.maybe_unused_trait_imports.insert(def_id);
|
||||
import_ids.push(def_id);
|
||||
}
|
||||
self.add_to_glob_map(&import, trait_name);
|
||||
self.add_to_glob_map(*import, trait_name);
|
||||
kind = &binding.kind;
|
||||
}
|
||||
import_ids
|
||||
@ -1646,7 +1651,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
module.populate_on_access.set(false);
|
||||
self.build_reduced_graph_external(module);
|
||||
}
|
||||
&module.lazy_resolutions
|
||||
&module.0.0.lazy_resolutions
|
||||
}
|
||||
|
||||
fn resolution(
|
||||
@ -1679,12 +1684,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
false
|
||||
}
|
||||
|
||||
fn record_use(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
used_binding: &'a NameBinding<'a>,
|
||||
is_lexical_scope: bool,
|
||||
) {
|
||||
fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) {
|
||||
if let Some((b2, kind)) = used_binding.ambiguity {
|
||||
let ambiguity_error = AmbiguityError {
|
||||
kind,
|
||||
@ -1704,10 +1704,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// but not introduce it, as used if they are accessed from lexical scope.
|
||||
if is_lexical_scope {
|
||||
if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
|
||||
if let Some(crate_item) = entry.extern_crate_item {
|
||||
if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item {
|
||||
return;
|
||||
}
|
||||
if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1716,13 +1714,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
if let Some(id) = import.id() {
|
||||
self.used_imports.insert(id);
|
||||
}
|
||||
self.add_to_glob_map(&import, ident);
|
||||
self.add_to_glob_map(import, ident);
|
||||
self.record_use(ident, binding, false);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
|
||||
fn add_to_glob_map(&mut self, import: Import<'_>, ident: Ident) {
|
||||
if let ImportKind::Glob { id, .. } = import.kind {
|
||||
let def_id = self.local_def_id(id);
|
||||
self.glob_map.entry(def_id).or_default().insert(ident.name);
|
||||
@ -1831,11 +1829,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
vis.is_accessible_from(module.nearest_parent_mod(), self.tcx)
|
||||
}
|
||||
|
||||
fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) {
|
||||
if let Some(old_module) =
|
||||
self.binding_parent_modules.insert(Interned::new_unchecked(binding), module)
|
||||
{
|
||||
if !ptr::eq(module, old_module) {
|
||||
fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) {
|
||||
if let Some(old_module) = self.binding_parent_modules.insert(binding, module) {
|
||||
if module != old_module {
|
||||
span_bug!(binding.span, "parent module is reset for binding");
|
||||
}
|
||||
}
|
||||
@ -1843,25 +1839,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
fn disambiguate_macro_rules_vs_modularized(
|
||||
&self,
|
||||
macro_rules: &'a NameBinding<'a>,
|
||||
modularized: &'a NameBinding<'a>,
|
||||
macro_rules: NameBinding<'a>,
|
||||
modularized: NameBinding<'a>,
|
||||
) -> bool {
|
||||
// Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules"
|
||||
// is disambiguated to mitigate regressions from macro modularization.
|
||||
// Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
|
||||
match (
|
||||
self.binding_parent_modules.get(&Interned::new_unchecked(macro_rules)),
|
||||
self.binding_parent_modules.get(&Interned::new_unchecked(modularized)),
|
||||
self.binding_parent_modules.get(¯o_rules),
|
||||
self.binding_parent_modules.get(&modularized),
|
||||
) {
|
||||
(Some(macro_rules), Some(modularized)) => {
|
||||
macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod()
|
||||
&& modularized.is_ancestor_of(macro_rules)
|
||||
&& modularized.is_ancestor_of(*macro_rules)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<&'a NameBinding<'a>> {
|
||||
fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBinding<'a>> {
|
||||
if ident.is_path_segment_keyword() {
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
return None;
|
||||
|
@ -42,7 +42,7 @@ type Res = def::Res<NodeId>;
|
||||
/// Not modularized, can shadow previous `macro_rules` bindings, etc.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MacroRulesBinding<'a> {
|
||||
pub(crate) binding: &'a NameBinding<'a>,
|
||||
pub(crate) binding: NameBinding<'a>,
|
||||
/// `macro_rules` scope into which the `macro_rules` item was planted.
|
||||
pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>,
|
||||
pub(crate) ident: Ident,
|
||||
@ -870,7 +870,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
fn prohibit_imported_non_macro_attrs(
|
||||
&self,
|
||||
binding: Option<&'a NameBinding<'a>>,
|
||||
binding: Option<NameBinding<'a>>,
|
||||
res: Option<Res>,
|
||||
span: Span,
|
||||
) {
|
||||
|
@ -241,7 +241,6 @@
|
||||
#![feature(allocator_internals)]
|
||||
#![feature(allow_internal_unsafe)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(c_str_literals)]
|
||||
#![feature(c_unwind)]
|
||||
#![feature(cfg_target_thread_local)]
|
||||
#![feature(concat_idents)]
|
||||
|
@ -242,15 +242,13 @@ mod imp {
|
||||
let mut res = Vec::new();
|
||||
|
||||
unsafe {
|
||||
let process_info_sel =
|
||||
sel_registerName(c"processInfo".as_ptr() as *const libc::c_uchar);
|
||||
let arguments_sel = sel_registerName(c"arguments".as_ptr() as *const libc::c_uchar);
|
||||
let utf8_sel = sel_registerName(c"UTF8String".as_ptr() as *const libc::c_uchar);
|
||||
let count_sel = sel_registerName(c"count".as_ptr() as *const libc::c_uchar);
|
||||
let object_at_sel =
|
||||
sel_registerName(c"objectAtIndex:".as_ptr() as *const libc::c_uchar);
|
||||
let process_info_sel = sel_registerName("processInfo\0".as_ptr());
|
||||
let arguments_sel = sel_registerName("arguments\0".as_ptr());
|
||||
let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
|
||||
let count_sel = sel_registerName("count\0".as_ptr());
|
||||
let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
|
||||
|
||||
let klass = objc_getClass(c"NSProcessInfo".as_ptr() as *const libc::c_uchar);
|
||||
let klass = objc_getClass("NSProcessInfo\0".as_ptr());
|
||||
let info = objc_msgSend(klass, process_info_sel);
|
||||
let args = objc_msgSend(info, arguments_sel);
|
||||
|
||||
|
@ -1097,7 +1097,7 @@ impl File {
|
||||
cfg_has_statx! {
|
||||
if let Some(ret) = unsafe { try_statx(
|
||||
fd,
|
||||
c"".as_ptr() as *const c_char,
|
||||
b"\0" as *const _ as *const c_char,
|
||||
libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
|
||||
libc::STATX_ALL,
|
||||
) } {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![allow(missing_docs, nonstandard_style)]
|
||||
|
||||
use crate::ffi::CStr;
|
||||
use crate::io::ErrorKind;
|
||||
|
||||
pub use self::rand::hashmap_random_keys;
|
||||
@ -74,7 +75,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
||||
// thread-id for the main thread and so renaming the main thread will rename the
|
||||
// process and we only want to enable this on platforms we've tested.
|
||||
if cfg!(target_os = "macos") {
|
||||
thread::Thread::set_name(&c"main");
|
||||
thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0"));
|
||||
}
|
||||
|
||||
unsafe fn sanitize_standard_fds() {
|
||||
@ -121,7 +122,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
||||
if pfd.revents & libc::POLLNVAL == 0 {
|
||||
continue;
|
||||
}
|
||||
if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
|
||||
if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
|
||||
// If the stream is closed but we failed to reopen it, abort the
|
||||
// process. Otherwise we wouldn't preserve the safety of
|
||||
// operations on the corresponding Rust object Stdin, Stdout, or
|
||||
@ -151,7 +152,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
||||
use libc::open64;
|
||||
for fd in 0..3 {
|
||||
if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
|
||||
if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
|
||||
if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
|
||||
// If the stream is closed but we failed to reopen it, abort the
|
||||
// process. Otherwise we wouldn't preserve the safety of
|
||||
// operations on the corresponding Rust object Stdin, Stdout, or
|
||||
|
@ -24,11 +24,11 @@ cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "fuchsia")] {
|
||||
// fuchsia doesn't have /dev/null
|
||||
} else if #[cfg(target_os = "redox")] {
|
||||
const DEV_NULL: &CStr = c"null:";
|
||||
const DEV_NULL: &str = "null:\0";
|
||||
} else if #[cfg(target_os = "vxworks")] {
|
||||
const DEV_NULL: &CStr = c"/null";
|
||||
const DEV_NULL: &str = "/null\0";
|
||||
} else {
|
||||
const DEV_NULL: &CStr = c"/dev/null";
|
||||
const DEV_NULL: &str = "/dev/null\0";
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,7 +474,8 @@ impl Stdio {
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.read(readable);
|
||||
opts.write(!readable);
|
||||
let fd = File::open_c(DEV_NULL, &opts)?;
|
||||
let path = unsafe { CStr::from_ptr(DEV_NULL.as_ptr() as *const _) };
|
||||
let fd = File::open_c(&path, &opts)?;
|
||||
Ok((ChildStdio::Owned(fd.into_inner()), None))
|
||||
}
|
||||
|
||||
|
@ -163,9 +163,10 @@ impl Thread {
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub fn set_name(name: &CStr) {
|
||||
unsafe {
|
||||
let cname = CStr::from_bytes_with_nul_unchecked(b"%s\0".as_slice());
|
||||
let res = libc::pthread_setname_np(
|
||||
libc::pthread_self(),
|
||||
c"%s".as_ptr(),
|
||||
cname.as_ptr(),
|
||||
name.as_ptr() as *mut libc::c_void,
|
||||
);
|
||||
debug_assert_eq!(res, 0);
|
||||
|
@ -321,7 +321,7 @@ pub unsafe fn NtWriteFile(
|
||||
// Functions that aren't available on every version of Windows that we support,
|
||||
// but we still use them and just provide some form of a fallback implementation.
|
||||
compat_fn_with_fallback! {
|
||||
pub static KERNEL32: &CStr = c"kernel32";
|
||||
pub static KERNEL32: &CStr = ansi_str!("kernel32");
|
||||
|
||||
// >= Win10 1607
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
|
||||
@ -354,7 +354,7 @@ compat_fn_optional! {
|
||||
}
|
||||
|
||||
compat_fn_with_fallback! {
|
||||
pub static NTDLL: &CStr = c"ntdll";
|
||||
pub static NTDLL: &CStr = ansi_str!("ntdll");
|
||||
|
||||
pub fn NtCreateKeyedEvent(
|
||||
KeyedEventHandle: LPHANDLE,
|
||||
|
@ -228,9 +228,9 @@ macro_rules! compat_fn_optional {
|
||||
/// Load all needed functions from "api-ms-win-core-synch-l1-2-0".
|
||||
pub(super) fn load_synch_functions() {
|
||||
fn try_load() -> Option<()> {
|
||||
const MODULE_NAME: &CStr = c"api-ms-win-core-synch-l1-2-0";
|
||||
const WAIT_ON_ADDRESS: &CStr = c"WaitOnAddress";
|
||||
const WAKE_BY_ADDRESS_SINGLE: &CStr = c"WakeByAddressSingle";
|
||||
const MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
|
||||
const WAIT_ON_ADDRESS: &CStr = ansi_str!("WaitOnAddress");
|
||||
const WAKE_BY_ADDRESS_SINGLE: &CStr = ansi_str!("WakeByAddressSingle");
|
||||
|
||||
// Try loading the library and all the required functions.
|
||||
// If any step fails, then they all fail.
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(missing_docs, nonstandard_style)]
|
||||
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::io::ErrorKind;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
@ -51,7 +51,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
|
||||
|
||||
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
|
||||
// exists, we have to call it ourselves.
|
||||
thread::Thread::set_name(&c"main");
|
||||
thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0"));
|
||||
}
|
||||
|
||||
// SAFETY: must be called only once during runtime cleanup.
|
||||
|
@ -599,6 +599,9 @@ impl Build {
|
||||
|
||||
let mut git = self.config.git();
|
||||
if let Some(branch) = current_branch {
|
||||
// If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name.
|
||||
// This syntax isn't accepted by `branch.{branch}`. Strip it.
|
||||
let branch = branch.strip_prefix("heads/").unwrap_or(&branch);
|
||||
git.arg("-c").arg(format!("branch.{branch}.remote=origin"));
|
||||
}
|
||||
git.args(&["submodule", "update", "--init", "--recursive", "--depth=1"]);
|
||||
|
@ -9,3 +9,4 @@
|
||||
- [Other style advice](advice.md)
|
||||
- [`Cargo.toml` conventions](cargo.md)
|
||||
- [Guiding principles and rationale](principles.md)
|
||||
- [Nightly-only syntax](nightly.md)
|
||||
|
@ -295,8 +295,9 @@ Use parentheses liberally, do not necessarily elide them due to precedence.
|
||||
Tools should not automatically insert or remove parentheses. Do not use spaces
|
||||
to indicate precedence.
|
||||
|
||||
If line-breaking, put the operator on a new line and block indent. Put each
|
||||
sub-expression on its own line. E.g.,
|
||||
If line-breaking, block-indent each subsequent line. For assignment operators,
|
||||
break after the operator; for all other operators, put the operator on the
|
||||
subsequent line. Put each sub-expression on its own line:
|
||||
|
||||
```rust
|
||||
foo_bar
|
||||
@ -752,9 +753,9 @@ not put the `if` clause on a newline. E.g.,
|
||||
}
|
||||
```
|
||||
|
||||
If every clause in a pattern is *small*, but does not fit on one line, then the
|
||||
pattern may be formatted across multiple lines with as many clauses per line as
|
||||
possible. Again break before a `|`:
|
||||
If every clause in a pattern is *small*, but the whole pattern does not fit on
|
||||
one line, then the pattern may be formatted across multiple lines with as many
|
||||
clauses per line as possible. Again break before a `|`:
|
||||
|
||||
```rust
|
||||
foo | bar | baz
|
||||
@ -763,17 +764,18 @@ possible. Again break before a `|`:
|
||||
}
|
||||
```
|
||||
|
||||
We define a pattern clause to be *small* if it matches the following grammar:
|
||||
We define a pattern clause to be *small* if it fits on a single line and
|
||||
matches "small" in the following grammar:
|
||||
|
||||
```
|
||||
[small, ntp]:
|
||||
- single token
|
||||
- `&[single-line, ntp]`
|
||||
small:
|
||||
- small_no_tuple
|
||||
- unary tuple constructor: `(` small_no_tuple `,` `)`
|
||||
- `&` small
|
||||
|
||||
[small]:
|
||||
- `[small, ntp]`
|
||||
- unary tuple constructor `([small, ntp])`
|
||||
- `&[small]`
|
||||
small_no_tuple:
|
||||
- single token
|
||||
- `&` small_no_tuple
|
||||
```
|
||||
|
||||
E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.
|
||||
|
5
src/doc/style-guide/src/nightly.md
Normal file
5
src/doc/style-guide/src/nightly.md
Normal file
@ -0,0 +1,5 @@
|
||||
This chapter documents style and formatting for nightly-only syntax. The rest of the style guide documents style for stable Rust syntax; nightly syntax only appears in this chapter. Each section here includes the name of the feature gate, so that searches (e.g. `git grep`) for a nightly feature in the Rust repository also turn up the style guide section.
|
||||
|
||||
Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization.
|
||||
|
||||
There is no guarantee of the stability of this chapter in contrast to the rest of the style guide. Refer to the style team policy for nightly formatting procedure regarding breaking changes to this chapter.
|
@ -131,6 +131,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"crypto-common",
|
||||
"cstr",
|
||||
"datafrog",
|
||||
"derive_more",
|
||||
"digest",
|
||||
|
@ -0,0 +1,29 @@
|
||||
// This test checks that we correctly reject the following unsound code.
|
||||
|
||||
trait Lengthen<T> {
|
||||
fn lengthen(self) -> T;
|
||||
}
|
||||
|
||||
impl<'a> Lengthen<&'a str> for &'a str {
|
||||
fn lengthen(self) -> &'a str { self }
|
||||
}
|
||||
|
||||
trait Gat {
|
||||
type Gat<'a>: for<'b> Lengthen<Self::Gat<'b>>;
|
||||
|
||||
fn lengthen(s: Self::Gat<'_>) -> Self::Gat<'static> {
|
||||
s.lengthen()
|
||||
}
|
||||
}
|
||||
|
||||
impl Gat for () {
|
||||
type Gat<'a> = &'a str; //~ ERROR: implementation of `Lengthen` is not general enough
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = "hello, garbage".to_string();
|
||||
let borrow: &'static str = <() as Gat>::lengthen(&s);
|
||||
drop(s);
|
||||
|
||||
println!("{borrow}");
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
error: implementation of `Lengthen` is not general enough
|
||||
--> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20
|
||||
|
|
||||
LL | type Gat<'a> = &'a str;
|
||||
| ^^^^^^^ implementation of `Lengthen` is not general enough
|
||||
|
|
||||
= note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`...
|
||||
= note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
9
tests/ui/parser/issue-113342.rs
Normal file
9
tests/ui/parser/issue-113342.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#[link(name = "my_c_library")]
|
||||
extern "C" {
|
||||
fn my_c_function(x: i32) -> bool;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" pub fn id(x: i32) -> i32 { x } //~ ERROR expected `fn`, found keyword `pub`
|
||||
|
||||
fn main() {}
|
11
tests/ui/parser/issue-113342.stderr
Normal file
11
tests/ui/parser/issue-113342.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: expected `fn`, found keyword `pub`
|
||||
--> $DIR/issue-113342.rs:7:12
|
||||
|
|
||||
LL | extern "C" pub fn id(x: i32) -> i32 { x }
|
||||
| -----------^^^
|
||||
| | |
|
||||
| | expected `fn`
|
||||
| help: visibility `pub` must come before `extern "C"`: `pub extern "C"`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// FIXME(c_str_literals): This should be `run-pass`
|
||||
// known-bug: #113333
|
||||
// edition: 2021
|
||||
|
||||
#![feature(c_str_literals)]
|
||||
|
||||
|
25
tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr
Normal file
25
tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error: prefix `c` is unknown
|
||||
--> $DIR/basic.rs:8:27
|
||||
|
|
||||
LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul());
|
||||
| ^ unknown prefix
|
||||
|
|
||||
= note: prefixed identifiers and literals are reserved since Rust 2021
|
||||
help: consider inserting whitespace here
|
||||
|
|
||||
LL | assert_eq!(b"test\0", c "test".to_bytes_with_nul());
|
||||
| +
|
||||
|
||||
error: no rules expected the token `"test"`
|
||||
--> $DIR/basic.rs:8:28
|
||||
|
|
||||
LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul());
|
||||
| -^^^^^
|
||||
| |
|
||||
| no rules expected this token in macro call
|
||||
| help: missing comma here
|
||||
|
|
||||
= note: while trying to match sequence start
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Regression test for issue #113235.
|
||||
|
||||
// check-pass
|
||||
// revisions: edition2015 edition2018
|
||||
//[edition2015] edition: 2015
|
||||
//[edition2018] edition: 2018
|
||||
|
||||
// Make sure that in pre-2021 editions we continue to parse the snippet
|
||||
// `c"hello"` as an identifier followed by a (normal) string literal and
|
||||
// allow the code below to compile.
|
||||
// Prefixes including `c` as used by C string literals are only reserved
|
||||
// in edition 2021 and onward.
|
||||
//
|
||||
// Consider checking out rust-2021/reserved-prefixes-migration.rs as well.
|
||||
|
||||
macro_rules! parse {
|
||||
(c $e:expr) => {
|
||||
$e
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: &'static str = parse!(c"hello");
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
// gate-test-c_str_literals
|
||||
// known-bug: #113333
|
||||
// edition: 2021
|
||||
|
||||
macro_rules! m {
|
||||
($t:tt) => {}
|
||||
@ -6,8 +8,8 @@ macro_rules! m {
|
||||
|
||||
fn main() {
|
||||
c"foo";
|
||||
//~^ ERROR: `c".."` literals are experimental
|
||||
// FIXME(c_str_literals): This should be ``c".."` literals are experimental`
|
||||
|
||||
m!(c"test");
|
||||
//~^ ERROR: `c".."` literals are experimental
|
||||
// FIXME(c_str_literals): This should be ``c".."` literals are experimental`
|
||||
}
|
||||
|
@ -1,21 +1,32 @@
|
||||
error[E0658]: `c".."` literals are experimental
|
||||
--> $DIR/gate.rs:8:5
|
||||
error: prefix `c` is unknown
|
||||
--> $DIR/gate.rs:10:5
|
||||
|
|
||||
LL | c"foo";
|
||||
| ^^^^^^
|
||||
| ^ unknown prefix
|
||||
|
|
||||
= note: see issue #105723 <https://github.com/rust-lang/rust/issues/105723> for more information
|
||||
= help: add `#![feature(c_str_literals)]` to the crate attributes to enable
|
||||
= note: prefixed identifiers and literals are reserved since Rust 2021
|
||||
help: consider inserting whitespace here
|
||||
|
|
||||
LL | c "foo";
|
||||
| +
|
||||
|
||||
error[E0658]: `c".."` literals are experimental
|
||||
--> $DIR/gate.rs:11:8
|
||||
error: prefix `c` is unknown
|
||||
--> $DIR/gate.rs:13:8
|
||||
|
|
||||
LL | m!(c"test");
|
||||
| ^^^^^^^
|
||||
| ^ unknown prefix
|
||||
|
|
||||
= note: see issue #105723 <https://github.com/rust-lang/rust/issues/105723> for more information
|
||||
= help: add `#![feature(c_str_literals)]` to the crate attributes to enable
|
||||
= note: prefixed identifiers and literals are reserved since Rust 2021
|
||||
help: consider inserting whitespace here
|
||||
|
|
||||
LL | m!(c "test");
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"foo"`
|
||||
--> $DIR/gate.rs:10:6
|
||||
|
|
||||
LL | c"foo";
|
||||
| ^^^^^ expected one of 8 possible tokens
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// FIXME(c_str_literals): This should be `run-pass`
|
||||
// known-bug: #113333
|
||||
// edition: 2021
|
||||
|
||||
#![feature(c_str_literals)]
|
||||
|
||||
|
38
tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr
Normal file
38
tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr
Normal file
@ -0,0 +1,38 @@
|
||||
error: prefix `c` is unknown
|
||||
--> $DIR/non-ascii.rs:9:9
|
||||
|
|
||||
LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
|
||||
| ^ unknown prefix
|
||||
|
|
||||
= note: prefixed identifiers and literals are reserved since Rust 2021
|
||||
help: consider inserting whitespace here
|
||||
|
|
||||
LL | c "\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
|
||||
| +
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/non-ascii.rs:9:11
|
||||
|
|
||||
LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/non-ascii.rs:9:15
|
||||
|
|
||||
LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
||||
error: no rules expected the token `"\xEF\x80🦀\u{1F980}"`
|
||||
--> $DIR/non-ascii.rs:9:10
|
||||
|
|
||||
LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
|
||||
| -^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| no rules expected this token in macro call
|
||||
| help: missing comma here
|
||||
|
|
||||
note: while trying to match `,`
|
||||
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
Loading…
x
Reference in New Issue
Block a user