Merge from rustc
This commit is contained in:
commit
7b5b87dee1
229 changed files with 1700 additions and 542 deletions
28
Cargo.lock
28
Cargo.lock
|
|
@ -3488,6 +3488,7 @@ dependencies = [
|
|||
"rustc_trait_selection",
|
||||
"rustc_ty_utils",
|
||||
"serde_json",
|
||||
"time",
|
||||
"tracing",
|
||||
"windows",
|
||||
]
|
||||
|
|
@ -5142,6 +5143,33 @@ dependencies = [
|
|||
name = "tier-check"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.7.1"
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ Cargo
|
|||
-----
|
||||
- [Allow named debuginfo options in `Cargo.toml`.](https://github.com/rust-lang/cargo/pull/11958/)
|
||||
- [Add `workspace_default_members` to the output of `cargo metadata`.](https://github.com/rust-lang/cargo/pull/11978/)
|
||||
- [`cargo add` now considers `rust-version` when selecting packages.](https://github.com/rust-lang/cargo/pull/12078/)
|
||||
- [Automatically inherit workspace fields when running `cargo new`/`cargo init`.](https://github.com/rust-lang/cargo/pull/12069/)
|
||||
|
||||
<a id="1.71.0-Rustdoc"></a>
|
||||
|
|
|
|||
|
|
@ -1619,13 +1619,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
debug!(?hir_bounds);
|
||||
|
||||
let lifetime_mapping = if in_trait {
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
Some(
|
||||
&*self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
&mut []
|
||||
None
|
||||
};
|
||||
|
||||
let opaque_ty_item = hir::OpaqueTy {
|
||||
|
|
@ -2090,13 +2092,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
|
||||
|
||||
let lifetime_mapping = if in_trait {
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
Some(
|
||||
&*self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
&mut []
|
||||
None
|
||||
};
|
||||
|
||||
let opaque_ty_item = hir::OpaqueTy {
|
||||
|
|
|
|||
|
|
@ -695,7 +695,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
.find_map(find_fn_kind_from_did),
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.arg_iter_copied(tcx, args)
|
||||
.iter_instantiated_copied(tcx, args)
|
||||
.find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
|
||||
ty::Closure(_, args) => match args.as_closure().kind() {
|
||||
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ fn main() {
|
|||
|
||||
#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
|
||||
let nan = f32::NAN;
|
||||
// MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit.
|
||||
// MIPS hardware except MIPS R6 treats f32::NAN as SNAN. Clear the signaling bit.
|
||||
// See https://github.com/rust-lang/rust/issues/52746.
|
||||
#[cfg(any(target_arch = "mips", target_arch = "mips64"))]
|
||||
let nan = f32::from_bits(f32::NAN.to_bits() - 1);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "arm",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "powerpc64"))]
|
||||
const MIN_ALIGN: usize = 8;
|
||||
|
|
@ -17,6 +18,7 @@ const MIN_ALIGN: usize = 8;
|
|||
target_arch = "aarch64",
|
||||
target_arch = "loongarch64",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "s390x",
|
||||
target_arch = "sparc64"))]
|
||||
const MIN_ALIGN: usize = 16;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
|
||||
|
||||
codegen_llvm_dlltool_fail_import_library =
|
||||
Dlltool could not create import library: {$stdout}
|
||||
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
{$stdout}
|
||||
{$stderr}
|
||||
|
||||
codegen_llvm_dynamic_linking_with_lto =
|
||||
|
|
|
|||
|
|
@ -335,6 +335,10 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||
to_add.extend(probestack_attr(cx));
|
||||
to_add.extend(stackprotector_attr(cx));
|
||||
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_BUILTINS) {
|
||||
to_add.push(llvm::CreateAttrString(cx.llcx, "no-builtins"));
|
||||
}
|
||||
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
||||
to_add.push(AttributeKind::Cold.create_attr(cx.llcx));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,25 +198,24 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
"arm" => ("arm", "--32"),
|
||||
_ => panic!("unsupported arch {}", sess.target.arch),
|
||||
};
|
||||
let result = std::process::Command::new(&dlltool)
|
||||
.args([
|
||||
"-d",
|
||||
def_file_path.to_str().unwrap(),
|
||||
"-D",
|
||||
lib_name,
|
||||
"-l",
|
||||
output_path.to_str().unwrap(),
|
||||
"-m",
|
||||
dlltool_target_arch,
|
||||
"-f",
|
||||
dlltool_target_bitness,
|
||||
"--no-leading-underscore",
|
||||
"--temp-prefix",
|
||||
temp_prefix.to_str().unwrap(),
|
||||
])
|
||||
.output();
|
||||
let mut dlltool_cmd = std::process::Command::new(&dlltool);
|
||||
dlltool_cmd.args([
|
||||
"-d",
|
||||
def_file_path.to_str().unwrap(),
|
||||
"-D",
|
||||
lib_name,
|
||||
"-l",
|
||||
output_path.to_str().unwrap(),
|
||||
"-m",
|
||||
dlltool_target_arch,
|
||||
"-f",
|
||||
dlltool_target_bitness,
|
||||
"--no-leading-underscore",
|
||||
"--temp-prefix",
|
||||
temp_prefix.to_str().unwrap(),
|
||||
]);
|
||||
|
||||
match result {
|
||||
match dlltool_cmd.output() {
|
||||
Err(e) => {
|
||||
sess.emit_fatal(ErrorCallingDllTool {
|
||||
dlltool_path: dlltool.to_string_lossy(),
|
||||
|
|
@ -226,6 +225,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
// dlltool returns '0' on failure, so check for error output instead.
|
||||
Ok(output) if !output.stderr.is_empty() => {
|
||||
sess.emit_fatal(DlltoolFailImportLibrary {
|
||||
dlltool_path: dlltool.to_string_lossy(),
|
||||
dlltool_args: dlltool_cmd
|
||||
.get_args()
|
||||
.map(|arg| arg.to_string_lossy())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
stdout: String::from_utf8_lossy(&output.stdout),
|
||||
stderr: String::from_utf8_lossy(&output.stderr),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ pub(crate) struct ErrorCallingDllTool<'a> {
|
|||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dlltool_fail_import_library)]
|
||||
pub(crate) struct DlltoolFailImportLibrary<'a> {
|
||||
pub dlltool_path: Cow<'a, str>,
|
||||
pub dlltool_args: String,
|
||||
pub stdout: Cow<'a, str>,
|
||||
pub stderr: Cow<'a, str>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,8 +193,8 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
|
|||
}
|
||||
"x86" => Architecture::I386,
|
||||
"s390x" => Architecture::S390x,
|
||||
"mips" => Architecture::Mips,
|
||||
"mips64" => Architecture::Mips64,
|
||||
"mips" | "mips32r6" => Architecture::Mips,
|
||||
"mips64" | "mips64r6" => Architecture::Mips64,
|
||||
"x86_64" => {
|
||||
if sess.target.pointer_width == 32 {
|
||||
Architecture::X86_64_X32
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
|||
|
||||
impl<B: WriteBackendMethods> CodegenContext<B> {
|
||||
pub fn create_diag_handler(&self) -> Handler {
|
||||
Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone()))
|
||||
Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone()), None)
|
||||
}
|
||||
|
||||
pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
|
||||
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
|
||||
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -60,6 +60,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||
}
|
||||
|
||||
// When `no_builtins` is applied at the crate level, we should add the
|
||||
// `no-builtins` attribute to each function to ensure it takes effect in LTO.
|
||||
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
|
||||
let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
|
||||
if no_builtins {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
|
||||
}
|
||||
|
||||
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
|
||||
|
||||
let mut inline_span = None;
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
|
|||
"aarch64" => AARCH64_ALLOWED_FEATURES,
|
||||
"x86" | "x86_64" => X86_ALLOWED_FEATURES,
|
||||
"hexagon" => HEXAGON_ALLOWED_FEATURES,
|
||||
"mips" | "mips64" => MIPS_ALLOWED_FEATURES,
|
||||
"mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES,
|
||||
"powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
|
||||
"riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
|
||||
"wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
[lib]
|
||||
|
||||
[dependencies]
|
||||
time = { version = "0.3", default-features = false, features = ["formatting", ] }
|
||||
tracing = { version = "0.1.35" }
|
||||
serde_json = "1.0.59"
|
||||
rustc_log = { path = "../rustc_log" }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
|||
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||
|
||||
driver_impl_ice_flags = compiler flags: {$flags}
|
||||
driver_impl_ice_path = please attach the file at `{$path}` to your bug report
|
||||
driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error}
|
||||
driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}`
|
||||
driver_impl_ice_version = rustc {$version} running on {$triple}
|
||||
|
||||
driver_impl_rlink_empty_version_number = The input does not contain version number
|
||||
|
||||
driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(ice_to_disk)]
|
||||
#![feature(let_chains)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
|
@ -57,8 +59,11 @@ use std::panic::{self, catch_unwind};
|
|||
use std::path::PathBuf;
|
||||
use std::process::{self, Command, Stdio};
|
||||
use std::str;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::OnceLock;
|
||||
use std::time::Instant;
|
||||
use std::time::{Instant, SystemTime};
|
||||
use time::format_description::well_known::Rfc3339;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro do_not_use_print($($t:tt)*) {
|
||||
|
|
@ -294,6 +299,7 @@ fn run_compiler(
|
|||
input: Input::File(PathBuf::new()),
|
||||
output_file: ofile,
|
||||
output_dir: odir,
|
||||
ice_file: ice_path().clone(),
|
||||
file_loader,
|
||||
locale_resources: DEFAULT_LOCALE_RESOURCES,
|
||||
lint_caps: Default::default(),
|
||||
|
|
@ -1292,9 +1298,29 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Stores the default panic hook, from before [`install_ice_hook`] was called.
|
||||
static DEFAULT_HOOK: OnceLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
|
||||
OnceLock::new();
|
||||
pub static ICE_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
|
||||
|
||||
pub fn ice_path() -> &'static Option<PathBuf> {
|
||||
ICE_PATH.get_or_init(|| {
|
||||
if !rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() {
|
||||
return None;
|
||||
}
|
||||
if let Ok("0") = std::env::var("RUST_BACKTRACE").as_deref() {
|
||||
return None;
|
||||
}
|
||||
let mut path = match std::env::var("RUSTC_ICE").as_deref() {
|
||||
// Explicitly opting out of writing ICEs to disk.
|
||||
Ok("0") => return None,
|
||||
Ok(s) => PathBuf::from(s),
|
||||
Err(_) => std::env::current_dir().unwrap_or_default(),
|
||||
};
|
||||
let now: OffsetDateTime = SystemTime::now().into();
|
||||
let file_now = now.format(&Rfc3339).unwrap_or(String::new());
|
||||
let pid = std::process::id();
|
||||
path.push(format!("rustc-ice-{file_now}-{pid}.txt"));
|
||||
Some(path)
|
||||
})
|
||||
}
|
||||
|
||||
/// Installs a panic hook that will print the ICE message on unexpected panics.
|
||||
///
|
||||
|
|
@ -1318,8 +1344,6 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
|
|||
std::env::set_var("RUST_BACKTRACE", "full");
|
||||
}
|
||||
|
||||
let default_hook = DEFAULT_HOOK.get_or_init(panic::take_hook);
|
||||
|
||||
panic::set_hook(Box::new(move |info| {
|
||||
// If the error was caused by a broken pipe then this is not a bug.
|
||||
// Write the error and return immediately. See #98700.
|
||||
|
|
@ -1336,7 +1360,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
|
|||
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
|
||||
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
|
||||
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
|
||||
(*default_hook)(info);
|
||||
std::panic_hook_with_disk_dump(info, ice_path().as_deref());
|
||||
|
||||
// Separate the output with an empty line
|
||||
eprintln!();
|
||||
|
|
@ -1368,7 +1392,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
|
|||
false,
|
||||
TerminalUrl::No,
|
||||
));
|
||||
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
|
||||
let handler = rustc_errors::Handler::with_emitter(true, None, emitter, None);
|
||||
|
||||
// a .span_bug or .bug call has already printed what
|
||||
// it wants to print.
|
||||
|
|
@ -1379,10 +1403,40 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
|
|||
}
|
||||
|
||||
handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
|
||||
handler.emit_note(session_diagnostics::IceVersion {
|
||||
version: util::version_str!().unwrap_or("unknown_version"),
|
||||
triple: config::host_triple(),
|
||||
});
|
||||
|
||||
let version = util::version_str!().unwrap_or("unknown_version");
|
||||
let triple = config::host_triple();
|
||||
|
||||
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
let file = if let Some(path) = ice_path().as_ref() {
|
||||
// Create the ICE dump target file.
|
||||
match crate::fs::File::options().create(true).append(true).open(&path) {
|
||||
Ok(mut file) => {
|
||||
handler
|
||||
.emit_note(session_diagnostics::IcePath { path: path.display().to_string() });
|
||||
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
||||
let _ = write!(file, "\n\nrustc version: {version}\nplatform: {triple}");
|
||||
}
|
||||
Some(file)
|
||||
}
|
||||
Err(err) => {
|
||||
// The path ICE couldn't be written to disk, provide feedback to the user as to why.
|
||||
handler.emit_warning(session_diagnostics::IcePathError {
|
||||
path: path.display().to_string(),
|
||||
error: err.to_string(),
|
||||
env_var: std::env::var("RUSTC_ICE")
|
||||
.ok()
|
||||
.map(|env_var| session_diagnostics::IcePathErrorEnv { env_var }),
|
||||
});
|
||||
handler.emit_note(session_diagnostics::IceVersion { version, triple });
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler.emit_note(session_diagnostics::IceVersion { version, triple });
|
||||
None
|
||||
};
|
||||
|
||||
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
|
||||
handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
|
||||
|
|
@ -1396,7 +1450,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info:
|
|||
|
||||
let num_frames = if backtrace { None } else { Some(2) };
|
||||
|
||||
interface::try_print_query_stack(&handler, num_frames);
|
||||
interface::try_print_query_stack(&handler, num_frames, file);
|
||||
|
||||
// We don't trust this callback not to panic itself, so run it at the end after we're sure we've
|
||||
// printed all the relevant info.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_macros::Diagnostic;
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_unable_to_read)]
|
||||
|
|
@ -56,6 +56,27 @@ pub(crate) struct IceVersion<'a> {
|
|||
pub triple: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_path)]
|
||||
pub(crate) struct IcePath {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_path_error)]
|
||||
pub(crate) struct IcePathError {
|
||||
pub path: String,
|
||||
pub error: String,
|
||||
#[subdiagnostic]
|
||||
pub env_var: Option<IcePathErrorEnv>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(driver_impl_ice_path_error_env)]
|
||||
pub(crate) struct IcePathErrorEnv {
|
||||
pub env_var: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_flags)]
|
||||
pub(crate) struct IceFlags {
|
||||
|
|
|
|||
|
|
@ -14,3 +14,6 @@ trait SecondTrait : FirstTrait {
|
|||
|
||||
The previous example contains a circular dependency between two traits:
|
||||
`FirstTrait` depends on `SecondTrait` which itself depends on `FirstTrait`.
|
||||
|
||||
See https://rustc-dev-guide.rust-lang.org/overview.html#queries and
|
||||
https://rustc-dev-guide.rust-lang.org/query.html for more information.
|
||||
|
|
|
|||
|
|
@ -354,6 +354,13 @@ impl DiagnosticMessage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match self {
|
||||
DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s),
|
||||
DiagnosticMessage::FluentIdentifier(_, _) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for DiagnosticMessage {
|
||||
|
|
|
|||
|
|
@ -1982,7 +1982,7 @@ impl EmitterWriter {
|
|||
// We special case `#[derive(_)]\n` and other attribute suggestions, because those
|
||||
// are the ones where context is most useful.
|
||||
let file_lines = sm
|
||||
.span_to_lines(span.primary_span().unwrap().shrink_to_hi())
|
||||
.span_to_lines(parts[0].span.shrink_to_hi())
|
||||
.expect("span_to_lines failed when emitting suggestion");
|
||||
let line_num = sm.lookup_char_pos(parts[0].span.lo()).line;
|
||||
if let Some(line) = file_lines.file.get_line(line_num - 1) {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
|||
);
|
||||
|
||||
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
|
||||
let handler = Handler::with_emitter(true, None, Box::new(je));
|
||||
let handler = Handler::with_emitter(true, None, Box::new(je), None);
|
||||
handler.span_err(span, "foo");
|
||||
|
||||
let bytes = output.lock().unwrap();
|
||||
|
|
|
|||
|
|
@ -47,9 +47,10 @@ use std::borrow::Cow;
|
|||
use std::error::Report;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::io::Write;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::panic;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use termcolor::{Color, ColorSpec};
|
||||
|
||||
|
|
@ -461,6 +462,10 @@ struct HandlerInner {
|
|||
///
|
||||
/// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
|
||||
fulfilled_expectations: FxHashSet<LintExpectationId>,
|
||||
|
||||
/// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be
|
||||
/// stored along side the main panic backtrace.
|
||||
ice_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// A key denoting where from a diagnostic was stashed.
|
||||
|
|
@ -550,6 +555,7 @@ impl Handler {
|
|||
sm: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
ice_file: Option<PathBuf>,
|
||||
) -> Self {
|
||||
Self::with_tty_emitter_and_flags(
|
||||
color_config,
|
||||
|
|
@ -557,6 +563,7 @@ impl Handler {
|
|||
fluent_bundle,
|
||||
fallback_bundle,
|
||||
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
||||
ice_file,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -566,6 +573,7 @@ impl Handler {
|
|||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
flags: HandlerFlags,
|
||||
ice_file: Option<PathBuf>,
|
||||
) -> Self {
|
||||
let emitter = Box::new(EmitterWriter::stderr(
|
||||
color_config,
|
||||
|
|
@ -579,23 +587,26 @@ impl Handler {
|
|||
flags.track_diagnostics,
|
||||
TerminalUrl::No,
|
||||
));
|
||||
Self::with_emitter_and_flags(emitter, flags)
|
||||
Self::with_emitter_and_flags(emitter, flags, ice_file)
|
||||
}
|
||||
|
||||
pub fn with_emitter(
|
||||
can_emit_warnings: bool,
|
||||
treat_err_as_bug: Option<NonZeroUsize>,
|
||||
emitter: Box<dyn Emitter + sync::Send>,
|
||||
ice_file: Option<PathBuf>,
|
||||
) -> Self {
|
||||
Handler::with_emitter_and_flags(
|
||||
emitter,
|
||||
HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
|
||||
ice_file,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn with_emitter_and_flags(
|
||||
emitter: Box<dyn Emitter + sync::Send>,
|
||||
flags: HandlerFlags,
|
||||
ice_file: Option<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
flags,
|
||||
|
|
@ -618,6 +629,7 @@ impl Handler {
|
|||
check_unstable_expect_diagnostics: false,
|
||||
unstable_expect_diagnostics: Vec::new(),
|
||||
fulfilled_expectations: Default::default(),
|
||||
ice_file,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -991,7 +1003,7 @@ impl Handler {
|
|||
self.emit_diag_at_span(Diagnostic::new_with_code(Warning(None), Some(code), msg), span);
|
||||
}
|
||||
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<String>) -> ! {
|
||||
self.inner.borrow_mut().span_bug(span, msg)
|
||||
}
|
||||
|
||||
|
|
@ -1000,7 +1012,7 @@ impl Handler {
|
|||
pub fn delay_span_bug(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.inner.borrow_mut().delay_span_bug(span, msg)
|
||||
}
|
||||
|
|
@ -1584,8 +1596,8 @@ impl HandlerInner {
|
|||
}
|
||||
|
||||
#[track_caller]
|
||||
fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp);
|
||||
fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<String>) -> ! {
|
||||
self.emit_diag_at_span(Diagnostic::new(Bug, msg.into()), sp);
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
|
||||
|
|
@ -1598,7 +1610,7 @@ impl HandlerInner {
|
|||
fn delay_span_bug(
|
||||
&mut self,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
|
||||
// incrementing `err_count` by one, so we need to +1 the comparing.
|
||||
|
|
@ -1607,9 +1619,9 @@ impl HandlerInner {
|
|||
self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
|
||||
}) {
|
||||
// FIXME: don't abort here if report_delayed_bugs is off
|
||||
self.span_bug(sp, msg);
|
||||
self.span_bug(sp, msg.into());
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg.into());
|
||||
diagnostic.set_span(sp.into());
|
||||
self.emit_diagnostic(&mut diagnostic).unwrap()
|
||||
}
|
||||
|
|
@ -1657,8 +1669,21 @@ impl HandlerInner {
|
|||
explanation: impl Into<DiagnosticMessage> + Copy,
|
||||
) {
|
||||
let mut no_bugs = true;
|
||||
// If backtraces are enabled, also print the query stack
|
||||
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
|
||||
for bug in bugs {
|
||||
let mut bug = bug.decorate();
|
||||
if let Some(file) = self.ice_file.as_ref()
|
||||
&& let Ok(mut out) = std::fs::File::options().append(true).open(file)
|
||||
{
|
||||
let _ = write!(
|
||||
&mut out,
|
||||
"\n\ndelayed span bug: {}\n{}",
|
||||
bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::<String>(),
|
||||
&bug.note
|
||||
);
|
||||
}
|
||||
let mut bug =
|
||||
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
|
||||
|
||||
if no_bugs {
|
||||
// Put the overall explanation before the `DelayedBug`s, to
|
||||
|
|
|
|||
|
|
@ -1147,7 +1147,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
|
||||
self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
|
||||
}
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<String>) -> ! {
|
||||
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
|
||||
}
|
||||
pub fn trace_macros_diag(&mut self) {
|
||||
|
|
|
|||
|
|
@ -1200,7 +1200,7 @@ fn check_matcher_core<'tt>(
|
|||
err.span_label(sp, format!("not allowed after `{}` fragments", kind));
|
||||
|
||||
if kind == NonterminalKind::PatWithOr
|
||||
&& sess.edition.rust_2021()
|
||||
&& sess.edition.at_least_rust_2021()
|
||||
&& next_token.is_token(&BinOp(token::BinOpToken::Or))
|
||||
{
|
||||
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
|||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
||||
let handler = Handler::with_emitter(true, None, Box::new(emitter), None);
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
handler.span_err(msp, "foo");
|
||||
|
||||
|
|
|
|||
|
|
@ -2664,10 +2664,19 @@ pub struct OpaqueTy<'hir> {
|
|||
pub generics: &'hir Generics<'hir>,
|
||||
pub bounds: GenericBounds<'hir>,
|
||||
pub origin: OpaqueTyOrigin,
|
||||
// Opaques have duplicated lifetimes, this mapping connects the original lifetime with the copy
|
||||
// so we can later generate bidirectional outlives predicates to enforce that these lifetimes
|
||||
// stay in sync.
|
||||
pub lifetime_mapping: &'hir [(Lifetime, LocalDefId)],
|
||||
/// Return-position impl traits (and async futures) must "reify" any late-bound
|
||||
/// lifetimes that are captured from the function signature they originate from.
|
||||
///
|
||||
/// This is done by generating a new early-bound lifetime parameter local to the
|
||||
/// opaque which is substituted in the function signature with the late-bound
|
||||
/// lifetime.
|
||||
///
|
||||
/// This mapping associated a captured lifetime (first parameter) with the new
|
||||
/// early-bound lifetime that was generated for the opaque.
|
||||
pub lifetime_mapping: Option<&'hir [(Lifetime, LocalDefId)]>,
|
||||
/// Whether the opaque is a return-position impl trait (or async future)
|
||||
/// originating from a trait method. This makes it so that the opaque is
|
||||
/// lowered as an associated type.
|
||||
pub in_trait: bool,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
));
|
||||
}
|
||||
|
||||
if self_ty.span.edition().rust_2021() {
|
||||
if self_ty.span.edition().at_least_rust_2021() {
|
||||
let msg = "trait objects must include the `dyn` keyword";
|
||||
let label = "add `dyn` keyword before this trait";
|
||||
let mut diag =
|
||||
|
|
|
|||
|
|
@ -867,7 +867,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
|
|||
});
|
||||
self.types.insert(proj.def_id, (infer_ty, proj.args));
|
||||
// Recurse into bounds
|
||||
for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).arg_iter_copied(self.interner(), proj.args) {
|
||||
for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).iter_instantiated_copied(self.interner(), proj.args) {
|
||||
let pred = pred.fold_with(self);
|
||||
let pred = self.ocx.normalize(
|
||||
&ObligationCause::misc(self.span, self.body_id),
|
||||
|
|
@ -2149,7 +2149,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
|
||||
let obligations: Vec<_> = tcx
|
||||
.explicit_item_bounds(trait_ty.def_id)
|
||||
.arg_iter_copied(tcx, rebased_args)
|
||||
.iter_instantiated_copied(tcx, rebased_args)
|
||||
.map(|(concrete_ty_bound, span)| {
|
||||
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
||||
traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ fn fn_sig_suggestion<'tcx>(
|
|||
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
|
||||
output = if let ty::Alias(_, alias_ty) = *output.kind() {
|
||||
tcx.explicit_item_bounds(alias_ty.def_id)
|
||||
.arg_iter_copied(tcx, alias_ty.args)
|
||||
.iter_instantiated_copied(tcx, alias_ty.args)
|
||||
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
|
||||
.unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
|
|
|
|||
|
|
@ -1567,7 +1567,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
|
|||
});
|
||||
for (bound, bound_span) in tcx
|
||||
.explicit_item_bounds(opaque_ty.def_id)
|
||||
.arg_iter_copied(tcx, opaque_ty.args)
|
||||
.iter_instantiated_copied(tcx, opaque_ty.args)
|
||||
{
|
||||
let bound = self.wfcx.normalize(bound_span, None, bound);
|
||||
self.wfcx.register_obligations(traits::wf::predicate_obligations(
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
|
||||
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
|
||||
let Node::Item(&Item {
|
||||
kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }),
|
||||
kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping: Some(lifetime_mapping), .. }),
|
||||
..
|
||||
}) = opaque_ty_node
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
|||
let mut collector =
|
||||
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
|
||||
let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
|
||||
for (pred, _) in tcx.explicit_item_bounds(item_def_id).arg_iter_copied(tcx, id_args) {
|
||||
for (pred, _) in tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx, id_args) {
|
||||
debug!(?pred);
|
||||
|
||||
// We only ignore opaque type args if the opaque type is the outermost type.
|
||||
|
|
|
|||
|
|
@ -551,8 +551,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
for ty in [first_ty, second_ty] {
|
||||
for (clause, _) in
|
||||
self.tcx.explicit_item_bounds(rpit_def_id).arg_iter_copied(self.tcx, args)
|
||||
for (clause, _) in self
|
||||
.tcx
|
||||
.explicit_item_bounds(rpit_def_id)
|
||||
.iter_instantiated_copied(self.tcx, args)
|
||||
{
|
||||
let pred = clause.kind().rebind(match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::Trait(trait_pred) => {
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected_ty,
|
||||
self.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.arg_iter_copied(self.tcx, args)
|
||||
.iter_instantiated_copied(self.tcx, args)
|
||||
.map(|(c, s)| (c.as_predicate(), s)),
|
||||
),
|
||||
ty::Dynamic(ref object_type, ..) => {
|
||||
|
|
@ -720,13 +720,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
|
||||
.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.arg_iter_copied(self.tcx, args)
|
||||
.iter_instantiated_copied(self.tcx, args)
|
||||
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
|
||||
ty::Error(_) => return None,
|
||||
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
|
||||
.tcx
|
||||
.explicit_item_bounds(proj.def_id)
|
||||
.arg_iter_copied(self.tcx, proj.args)
|
||||
.iter_instantiated_copied(self.tcx, proj.args)
|
||||
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
|
||||
_ => span_bug!(
|
||||
self.tcx.def_span(expr_def_id),
|
||||
|
|
|
|||
|
|
@ -860,7 +860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
|
||||
.and_then(|r| {
|
||||
// lint bare trait if the method is found in the trait
|
||||
if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
|
||||
if span.edition().at_least_rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
|
||||
diag.emit();
|
||||
}
|
||||
Ok(r)
|
||||
|
|
@ -890,7 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// emit or cancel the diagnostic for bare traits
|
||||
if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
|
||||
if span.edition().at_least_rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
|
||||
if trait_missing_method {
|
||||
// cancel the diag for bare traits when meeting `MyTrait::missing_method`
|
||||
diag.cancel();
|
||||
|
|
@ -908,7 +908,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
error,
|
||||
None,
|
||||
Expectation::NoExpectation,
|
||||
trait_missing_method && span.edition().rust_2021(), // emits missing method for trait only after edition 2021
|
||||
trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
|
||||
) {
|
||||
e.emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
|
||||
// Rust 2021 and later is already using the new prelude
|
||||
if span.rust_2021() {
|
||||
if span.at_least_rust_2021() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pick: &Pick<'tcx>,
|
||||
) {
|
||||
// Rust 2021 and later is already using the new prelude
|
||||
if span.rust_2021() {
|
||||
if span.at_least_rust_2021() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// this case used to be allowed by the compiler,
|
||||
// so we do a future-compat lint here for the 2015 edition
|
||||
// (see https://github.com/rust-lang/rust/issues/46906)
|
||||
if self.tcx.sess.rust_2018() {
|
||||
if self.tcx.sess.at_least_rust_2018() {
|
||||
self.tcx.sess.emit_err(MethodCallOnUnknownRawPointee { span });
|
||||
} else {
|
||||
self.tcx.struct_span_lint_hir(
|
||||
|
|
@ -1592,7 +1592,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
if let Some(method_name) = self.method_name {
|
||||
// Some trait methods are excluded for arrays before 2021.
|
||||
// (`array.into_iter()` wants a slice iterator for compatibility.)
|
||||
if self_ty.is_array() && !method_name.span.rust_2021() {
|
||||
if self_ty.is_array() && !method_name.span.at_least_rust_2021() {
|
||||
let trait_def = self.tcx.trait_def(trait_ref.def_id);
|
||||
if trait_def.skip_array_during_method_dispatch {
|
||||
return ProbeResult::NoMatch;
|
||||
|
|
|
|||
|
|
@ -2001,7 +2001,7 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
|
|||
tcx: TyCtxt<'_>,
|
||||
closure_id: hir::HirId,
|
||||
) -> bool {
|
||||
if tcx.sess.rust_2021() {
|
||||
if tcx.sess.at_least_rust_2021() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2247,5 +2247,5 @@ fn truncate_capture_for_optimization(
|
|||
fn enable_precise_capture(span: Span) -> bool {
|
||||
// We use span here to ensure that if the closure was generated by a macro with a different
|
||||
// edition.
|
||||
span.rust_2021()
|
||||
span.at_least_rust_2021()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
// substitutions.
|
||||
|
||||
use crate::FnCtxt;
|
||||
use hir::def_id::LocalDefId;
|
||||
use rustc_data_structures::unord::ExtendUnord;
|
||||
use rustc_errors::{ErrorGuaranteed, StashKey};
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -11,13 +10,12 @@ use rustc_hir::intravisit::{self, Visitor};
|
|||
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::mem;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Entry point
|
||||
|
|
@ -565,23 +563,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
|
||||
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
|
||||
|
||||
struct RecursionChecker {
|
||||
def_id: LocalDefId,
|
||||
}
|
||||
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for RecursionChecker {
|
||||
type BreakTy = ();
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
|
||||
if def_id == self.def_id.to_def_id() {
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
if hidden_type
|
||||
.visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id })
|
||||
.is_break()
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
|
||||
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
|
||||
&& alias_ty.args == opaque_type_key.args
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
|
||||
|
||||
self.tcx.explicit_item_bounds(def_id).arg_iter_copied(self.tcx, args).find_map(
|
||||
self.tcx.explicit_item_bounds(def_id).iter_instantiated_copied(self.tcx, args).find_map(
|
||||
|(predicate, _)| {
|
||||
predicate
|
||||
.kind()
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let tcx = self.tcx;
|
||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
||||
|
||||
for (predicate, _) in item_bounds.arg_iter_copied(tcx, args) {
|
||||
for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
|
||||
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| match *ty.kind() {
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
|||
let bounds = tcx.item_bounds(alias_ty.def_id);
|
||||
trace!("{:#?}", bounds.skip_binder());
|
||||
bounds
|
||||
.arg_iter(tcx, alias_ty.args)
|
||||
.iter_instantiated(tcx, alias_ty.args)
|
||||
.filter_map(|p| p.as_type_outlives_clause())
|
||||
.filter_map(|p| p.no_bound_vars())
|
||||
.map(|OutlivesPredicate(_, r)| r)
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ pub struct Config {
|
|||
pub input: Input,
|
||||
pub output_dir: Option<PathBuf>,
|
||||
pub output_file: Option<OutFileName>,
|
||||
pub ice_file: Option<PathBuf>,
|
||||
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
|
||||
pub locale_resources: &'static [&'static str],
|
||||
|
||||
|
|
@ -315,6 +316,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
config.lint_caps,
|
||||
config.make_codegen_backend,
|
||||
registry.clone(),
|
||||
config.ice_file,
|
||||
);
|
||||
|
||||
if let Some(parse_sess_created) = config.parse_sess_created {
|
||||
|
|
@ -346,7 +348,11 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
)
|
||||
}
|
||||
|
||||
pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
|
||||
pub fn try_print_query_stack(
|
||||
handler: &Handler,
|
||||
num_frames: Option<usize>,
|
||||
file: Option<std::fs::File>,
|
||||
) {
|
||||
eprintln!("query stack during panic:");
|
||||
|
||||
// Be careful relying on global state here: this code is called from
|
||||
|
|
@ -358,7 +364,8 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
|
|||
QueryCtxt::new(icx.tcx),
|
||||
icx.query,
|
||||
handler,
|
||||
num_frames
|
||||
num_frames,
|
||||
file,
|
||||
))
|
||||
} else {
|
||||
0
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se
|
|||
None,
|
||||
None,
|
||||
"",
|
||||
None,
|
||||
);
|
||||
(sess, cfg)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ pub fn create_session(
|
|||
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
|
||||
>,
|
||||
descriptions: Registry,
|
||||
ice_file: Option<PathBuf>,
|
||||
) -> (Session, Box<dyn CodegenBackend>) {
|
||||
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
|
||||
make_codegen_backend(&sopts)
|
||||
|
|
@ -111,6 +112,7 @@ pub fn create_session(
|
|||
file_loader,
|
||||
target_override,
|
||||
rustc_version_str().unwrap_or("unknown"),
|
||||
ice_file,
|
||||
);
|
||||
|
||||
codegen_backend.init(&sess);
|
||||
|
|
|
|||
|
|
@ -956,11 +956,11 @@ pub trait LintContext: Sized {
|
|||
db.span_note(glob_reexport_span, format!("the name `{}` in the {} namespace is supposed to be publicly re-exported here", name, namespace));
|
||||
db.span_note(private_item_span, "but the private item here shadows it".to_owned());
|
||||
}
|
||||
BuiltinLintDiagnostics::UnusedQualifications { path_span, unqualified_path } => {
|
||||
BuiltinLintDiagnostics::UnusedQualifications { removal_span } => {
|
||||
db.span_suggestion_verbose(
|
||||
path_span,
|
||||
"replace it with the unqualified path",
|
||||
unqualified_path,
|
||||
removal_span,
|
||||
"remove the unnecessary path segments",
|
||||
"",
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -978,6 +978,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
/// Returns `true` if the lint's feature is enabled.
|
||||
// FIXME only emit this once for each attribute, instead of repeating it 4 times for
|
||||
// pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`.
|
||||
#[track_caller]
|
||||
fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
|
||||
if let Some(feature) = lint_id.lint.feature_gate {
|
||||
if !self.sess.features_untracked().enabled(feature) {
|
||||
|
|
@ -1015,6 +1016,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
///
|
||||
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub(crate) fn struct_lint(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
|
|
@ -1028,6 +1030,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_spanned_lint(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
|
|
@ -1040,6 +1043,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
});
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> DecorateLint<'a, ()>) {
|
||||
let (level, src) = self.lint_level(lint);
|
||||
struct_lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
for (assoc_pred, assoc_pred_span) in cx
|
||||
.tcx
|
||||
.explicit_item_bounds(proj.projection_ty.def_id)
|
||||
.arg_iter_copied(cx.tcx, &proj.projection_ty.args)
|
||||
.iter_instantiated_copied(cx.tcx, &proj.projection_ty.args)
|
||||
{
|
||||
let assoc_pred = assoc_pred.fold_with(proj_replacer);
|
||||
let Ok(assoc_pred) = traits::fully_normalize(
|
||||
|
|
|
|||
|
|
@ -551,10 +551,8 @@ pub enum BuiltinLintDiagnostics {
|
|||
private_item_span: Span,
|
||||
},
|
||||
UnusedQualifications {
|
||||
/// The span of the unnecessarily-qualified path.
|
||||
path_span: Span,
|
||||
/// The replacement unqualified path.
|
||||
unqualified_path: Ident,
|
||||
/// The span of the unnecessarily-qualified path to remove.
|
||||
removal_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,28 @@
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cstore::ForeignModule;
|
||||
|
||||
pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
|
||||
let mut modules = Vec::new();
|
||||
pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> FxIndexMap<DefId, ForeignModule> {
|
||||
let mut modules = FxIndexMap::default();
|
||||
|
||||
// We need to collect all the `ForeignMod`, even if they are empty.
|
||||
for id in tcx.hir().items() {
|
||||
if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let def_id = id.owner_id.to_def_id();
|
||||
let item = tcx.hir().item(id);
|
||||
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
|
||||
|
||||
if let hir::ItemKind::ForeignMod { abi, items } = item.kind {
|
||||
let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect();
|
||||
modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() });
|
||||
modules.insert(def_id, ForeignModule { def_id, abi, foreign_items });
|
||||
}
|
||||
}
|
||||
|
||||
modules
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType};
|
||||
use rustc_session::cstore::{
|
||||
DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
|
||||
};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
|
|
@ -66,10 +68,12 @@ fn find_bundled_library(
|
|||
None
|
||||
}
|
||||
|
||||
pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
|
||||
pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib> {
|
||||
let mut collector = Collector { tcx, libs: Vec::new() };
|
||||
for id in tcx.hir().items() {
|
||||
collector.process_item(id);
|
||||
if tcx.sess.opts.unstable_opts.link_directives {
|
||||
for module in tcx.foreign_modules(LOCAL_CRATE).values() {
|
||||
collector.process_module(module);
|
||||
}
|
||||
}
|
||||
collector.process_command_line();
|
||||
collector.libs
|
||||
|
|
@ -88,29 +92,20 @@ struct Collector<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Collector<'tcx> {
|
||||
fn process_item(&mut self, id: rustc_hir::ItemId) {
|
||||
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
|
||||
return;
|
||||
}
|
||||
fn process_module(&mut self, module: &ForeignModule) {
|
||||
let ForeignModule { def_id, abi, ref foreign_items } = *module;
|
||||
let def_id = def_id.expect_local();
|
||||
|
||||
let it = self.tcx.hir().item(id);
|
||||
let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
|
||||
return;
|
||||
};
|
||||
let sess = self.tcx.sess;
|
||||
|
||||
if matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process all of the #[link(..)]-style arguments
|
||||
let sess = self.tcx.sess;
|
||||
let features = self.tcx.features();
|
||||
|
||||
if !sess.opts.unstable_opts.link_directives {
|
||||
return;
|
||||
}
|
||||
|
||||
for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) {
|
||||
for m in self.tcx.get_attrs(def_id, sym::link) {
|
||||
let Some(items) = m.meta_item_list() else {
|
||||
continue;
|
||||
};
|
||||
|
|
@ -340,9 +335,9 @@ impl<'tcx> Collector<'tcx> {
|
|||
if name.as_str().contains('\0') {
|
||||
sess.emit_err(errors::RawDylibNoNul { span: name_span });
|
||||
}
|
||||
foreign_mod_items
|
||||
foreign_items
|
||||
.iter()
|
||||
.map(|child_item| {
|
||||
.map(|&child_item| {
|
||||
self.build_dll_import(
|
||||
abi,
|
||||
import_name_type.map(|(import_name_type, _)| import_name_type),
|
||||
|
|
@ -352,21 +347,12 @@ impl<'tcx> Collector<'tcx> {
|
|||
.collect()
|
||||
}
|
||||
_ => {
|
||||
for child_item in foreign_mod_items {
|
||||
if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs()
|
||||
&& self
|
||||
.tcx
|
||||
.codegen_fn_attrs(child_item.id.owner_id)
|
||||
.link_ordinal
|
||||
.is_some()
|
||||
for &child_item in foreign_items {
|
||||
if self.tcx.def_kind(child_item).has_codegen_attrs()
|
||||
&& self.tcx.codegen_fn_attrs(child_item).link_ordinal.is_some()
|
||||
{
|
||||
let link_ordinal_attr = self
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(child_item.id.owner_id.into())
|
||||
.iter()
|
||||
.find(|a| a.has_name(sym::link_ordinal))
|
||||
.unwrap();
|
||||
let link_ordinal_attr =
|
||||
self.tcx.get_attr(child_item, sym::link_ordinal).unwrap();
|
||||
sess.emit_err(errors::LinkOrdinalRawDylib {
|
||||
span: link_ordinal_attr.span,
|
||||
});
|
||||
|
|
@ -384,7 +370,7 @@ impl<'tcx> Collector<'tcx> {
|
|||
filename,
|
||||
kind,
|
||||
cfg,
|
||||
foreign_module: Some(it.owner_id.to_def_id()),
|
||||
foreign_module: Some(def_id.to_def_id()),
|
||||
verbatim,
|
||||
dll_imports,
|
||||
});
|
||||
|
|
@ -476,10 +462,10 @@ impl<'tcx> Collector<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
|
||||
fn i686_arg_list_size(&self, item: DefId) -> usize {
|
||||
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
|
||||
self.tcx
|
||||
.type_of(item.id.owner_id)
|
||||
.type_of(item)
|
||||
.instantiate_identity()
|
||||
.fn_sig(self.tcx)
|
||||
.inputs()
|
||||
|
|
@ -505,8 +491,10 @@ impl<'tcx> Collector<'tcx> {
|
|||
&self,
|
||||
abi: Abi,
|
||||
import_name_type: Option<PeImportNameType>,
|
||||
item: &hir::ForeignItemRef,
|
||||
item: DefId,
|
||||
) -> DllImport {
|
||||
let span = self.tcx.def_span(item);
|
||||
|
||||
let calling_convention = if self.tcx.sess.target.arch == "x86" {
|
||||
match abi {
|
||||
Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
|
||||
|
|
@ -520,29 +508,29 @@ impl<'tcx> Collector<'tcx> {
|
|||
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
|
||||
}
|
||||
_ => {
|
||||
self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span });
|
||||
self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match abi {
|
||||
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
|
||||
_ => {
|
||||
self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span });
|
||||
self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id);
|
||||
let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item);
|
||||
let import_name_type = codegen_fn_attrs
|
||||
.link_ordinal
|
||||
.map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord)));
|
||||
|
||||
DllImport {
|
||||
name: codegen_fn_attrs.link_name.unwrap_or(item.ident.name),
|
||||
name: codegen_fn_attrs.link_name.unwrap_or(self.tcx.item_name(item)),
|
||||
import_name_type,
|
||||
calling_convention,
|
||||
span: item.span,
|
||||
is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(),
|
||||
span,
|
||||
is_fn: self.tcx.def_kind(item).is_fn_like(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ use rustc_session::cstore::{
|
|||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::ExpnIndex;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
|
||||
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
|
||||
|
||||
use proc_macro::bridge::client::ProcMacro;
|
||||
use std::iter::TrustedLen;
|
||||
|
|
@ -513,11 +513,26 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
|
|||
|
||||
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
|
||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span {
|
||||
let mode = SpanEncodingMode::decode(decoder);
|
||||
let data = match mode {
|
||||
SpanEncodingMode::Direct => SpanData::decode(decoder),
|
||||
SpanEncodingMode::Shorthand(position) => decoder.with_position(position, |decoder| {
|
||||
let mode = SpanEncodingMode::decode(decoder);
|
||||
debug_assert!(matches!(mode, SpanEncodingMode::Direct));
|
||||
SpanData::decode(decoder)
|
||||
}),
|
||||
};
|
||||
Span::new(data.lo, data.hi, data.ctxt, data.parent)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
|
||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData {
|
||||
let ctxt = SyntaxContext::decode(decoder);
|
||||
let tag = u8::decode(decoder);
|
||||
|
||||
if tag == TAG_PARTIAL_SPAN {
|
||||
return DUMMY_SP.with_ctxt(ctxt);
|
||||
return DUMMY_SP.with_ctxt(ctxt).data();
|
||||
}
|
||||
|
||||
debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
|
||||
|
|
@ -612,7 +627,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
|
|||
let hi = hi + source_file.translated_source_file.start_pos;
|
||||
|
||||
// Do not try to decode parent for foreign spans.
|
||||
Span::new(lo, hi, ctxt, None)
|
||||
SpanData { lo, hi, ctxt, parent: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -403,10 +403,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
|||
.contains(&id)
|
||||
})
|
||||
},
|
||||
native_libraries: |tcx, LocalCrate| native_libs::collect(tcx),
|
||||
foreign_modules: |tcx, LocalCrate| {
|
||||
foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect()
|
||||
},
|
||||
native_libraries: native_libs::collect,
|
||||
foreign_modules: foreign_modules::collect,
|
||||
|
||||
// Returns a map from a sufficiently visible external item (i.e., an
|
||||
// external item that is visible from at least one local module) to a
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ use rustc_session::config::{CrateType, OptLevel};
|
|||
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
|
||||
use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
|
||||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::hash::Hash;
|
||||
|
|
@ -53,6 +53,7 @@ pub(super) struct EncodeContext<'a, 'tcx> {
|
|||
tables: TableBuilders,
|
||||
|
||||
lazy_state: LazyState,
|
||||
span_shorthands: FxHashMap<Span, usize>,
|
||||
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
||||
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
|
||||
|
||||
|
|
@ -177,8 +178,20 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
|
|||
|
||||
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
|
||||
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
||||
let span = self.data();
|
||||
match s.span_shorthands.entry(*self) {
|
||||
Entry::Occupied(o) => SpanEncodingMode::Shorthand(*o.get()).encode(s),
|
||||
Entry::Vacant(v) => {
|
||||
let position = s.opaque.position();
|
||||
v.insert(position);
|
||||
SpanEncodingMode::Direct.encode(s);
|
||||
self.data().encode(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
|
||||
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
|
||||
// Don't serialize any `SyntaxContext`s from a proc-macro crate,
|
||||
// since we don't load proc-macro dependencies during serialization.
|
||||
// This means that any hygiene information from macros used *within*
|
||||
|
|
@ -213,7 +226,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
|
|||
if s.is_proc_macro {
|
||||
SyntaxContext::root().encode(s);
|
||||
} else {
|
||||
span.ctxt.encode(s);
|
||||
self.ctxt.encode(s);
|
||||
}
|
||||
|
||||
if self.is_dummy() {
|
||||
|
|
@ -221,18 +234,18 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
|
|||
}
|
||||
|
||||
// The Span infrastructure should make sure that this invariant holds:
|
||||
debug_assert!(span.lo <= span.hi);
|
||||
debug_assert!(self.lo <= self.hi);
|
||||
|
||||
if !s.source_file_cache.0.contains(span.lo) {
|
||||
if !s.source_file_cache.0.contains(self.lo) {
|
||||
let source_map = s.tcx.sess.source_map();
|
||||
let source_file_index = source_map.lookup_source_file_idx(span.lo);
|
||||
let source_file_index = source_map.lookup_source_file_idx(self.lo);
|
||||
s.source_file_cache =
|
||||
(source_map.files()[source_file_index].clone(), source_file_index);
|
||||
}
|
||||
let (ref source_file, source_file_index) = s.source_file_cache;
|
||||
debug_assert!(source_file.contains(span.lo));
|
||||
debug_assert!(source_file.contains(self.lo));
|
||||
|
||||
if !source_file.contains(span.hi) {
|
||||
if !source_file.contains(self.hi) {
|
||||
// Unfortunately, macro expansion still sometimes generates Spans
|
||||
// that malformed in this way.
|
||||
return TAG_PARTIAL_SPAN.encode(s);
|
||||
|
|
@ -286,11 +299,11 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
|
|||
|
||||
// Encode the start position relative to the file start, so we profit more from the
|
||||
// variable-length integer encoding.
|
||||
let lo = span.lo - source_file.start_pos;
|
||||
let lo = self.lo - source_file.start_pos;
|
||||
|
||||
// Encode length which is usually less than span.hi and profits more
|
||||
// from the variable-length integer encoding that we use.
|
||||
let len = span.hi - span.lo;
|
||||
let len = self.hi - self.lo;
|
||||
|
||||
tag.encode(s);
|
||||
lo.encode(s);
|
||||
|
|
@ -2182,6 +2195,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
|
|||
feat: tcx.features(),
|
||||
tables: Default::default(),
|
||||
lazy_state: LazyState::NoNode,
|
||||
span_shorthands: Default::default(),
|
||||
type_shorthands: Default::default(),
|
||||
predicate_shorthands: Default::default(),
|
||||
source_file_cache,
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ const METADATA_VERSION: u8 = 8;
|
|||
/// unsigned integer, and further followed by the rustc version string.
|
||||
pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
|
||||
|
||||
#[derive(Encodable, Decodable)]
|
||||
enum SpanEncodingMode {
|
||||
Shorthand(usize),
|
||||
Direct,
|
||||
}
|
||||
|
||||
/// A value of type T referred to by its absolute position
|
||||
/// in the metadata, and which can be decoded lazily.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ pub fn explain_lint_level_source(
|
|||
/// // ^^^^^^^^^^^^^^^^^^^^^ returns `&mut DiagnosticBuilder` by default
|
||||
/// )
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn struct_lint_level(
|
||||
sess: &Session,
|
||||
lint: &'static Lint,
|
||||
|
|
@ -291,6 +292,7 @@ pub fn struct_lint_level(
|
|||
) {
|
||||
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
||||
// the "real" work.
|
||||
#[track_caller]
|
||||
fn struct_lint_level_impl(
|
||||
sess: &Session,
|
||||
lint: &'static Lint,
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ bitflags! {
|
|||
const REALLOCATOR = 1 << 18;
|
||||
/// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
|
||||
const ALLOCATOR_ZEROED = 1 << 19;
|
||||
/// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
|
||||
const NO_BUILTINS = 1 << 20;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: if you change how item size estimates work, you might need to
|
||||
// change NON_INCR_MIN_CGU_SIZE as well.
|
||||
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
|
||||
match *self {
|
||||
MonoItem::Fn(instance) => {
|
||||
|
|
@ -248,8 +250,14 @@ pub struct CodegenUnit<'tcx> {
|
|||
/// Auxiliary info about a `MonoItem`.
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
|
||||
pub struct MonoItemData {
|
||||
/// A cached copy of the result of `MonoItem::instantiation_mode`, where
|
||||
/// `GloballyShared` maps to `false` and `LocalCopy` maps to `true`.
|
||||
pub inlined: bool,
|
||||
|
||||
pub linkage: Linkage,
|
||||
pub visibility: Visibility,
|
||||
|
||||
/// A cached copy of the result of `MonoItem::size_estimate`.
|
||||
pub size_estimate: usize,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1579,7 +1579,7 @@ rustc_queries! {
|
|||
}
|
||||
|
||||
/// Returns a list of all `extern` blocks of a crate.
|
||||
query foreign_modules(_: CrateNum) -> &'tcx FxHashMap<DefId, ForeignModule> {
|
||||
query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap<DefId, ForeignModule> {
|
||||
arena_cache
|
||||
desc { "looking up the foreign modules of a linked crate" }
|
||||
separate_provide_extern
|
||||
|
|
|
|||
|
|
@ -294,6 +294,14 @@ impl<'tcx> Const<'tcx> {
|
|||
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
|
||||
}
|
||||
|
||||
/// Attempts to convert to a `ValTree`
|
||||
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
|
||||
match self.kind() {
|
||||
ty::ConstKind::Value(valtree) => Some(valtree),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
|
||||
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
|
||||
|
|
|
|||
|
|
@ -1860,6 +1860,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
|
||||
/// typically generated by `#[derive(LintDiagnostic)]`).
|
||||
#[track_caller]
|
||||
pub fn emit_spanned_lint(
|
||||
self,
|
||||
lint: &'static Lint,
|
||||
|
|
@ -1880,6 +1881,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
///
|
||||
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_lint_hir(
|
||||
self,
|
||||
lint: &'static Lint,
|
||||
|
|
@ -1896,6 +1898,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
||||
/// generated by `#[derive(LintDiagnostic)]`).
|
||||
#[track_caller]
|
||||
pub fn emit_lint(
|
||||
self,
|
||||
lint: &'static Lint,
|
||||
|
|
@ -1911,6 +1914,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
///
|
||||
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_lint_node(
|
||||
self,
|
||||
lint: &'static Lint,
|
||||
|
|
|
|||
|
|
@ -610,8 +610,12 @@ impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
|
|||
where
|
||||
I::Item: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
pub fn arg_iter(self, tcx: TyCtxt<'tcx>, args: &'s [GenericArg<'tcx>]) -> ArgIter<'s, 'tcx, I> {
|
||||
ArgIter { it: self.value.into_iter(), tcx, args }
|
||||
pub fn iter_instantiated(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'s [GenericArg<'tcx>],
|
||||
) -> IterInstantiated<'s, 'tcx, I> {
|
||||
IterInstantiated { it: self.value.into_iter(), tcx, args }
|
||||
}
|
||||
|
||||
/// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
|
||||
|
|
@ -621,13 +625,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ArgIter<'s, 'tcx, I: IntoIterator> {
|
||||
pub struct IterInstantiated<'s, 'tcx, I: IntoIterator> {
|
||||
it: I::IntoIter,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'s [GenericArg<'tcx>],
|
||||
}
|
||||
|
||||
impl<'tcx, I: IntoIterator> Iterator for ArgIter<'_, 'tcx, I>
|
||||
impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I>
|
||||
where
|
||||
I::Item: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -642,7 +646,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, I: IntoIterator> DoubleEndedIterator for ArgIter<'_, 'tcx, I>
|
||||
impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I>
|
||||
where
|
||||
I::IntoIter: DoubleEndedIterator,
|
||||
I::Item: TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
|
@ -652,7 +656,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, I: IntoIterator> ExactSizeIterator for ArgIter<'_, 'tcx, I>
|
||||
impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiated<'_, 'tcx, I>
|
||||
where
|
||||
I::IntoIter: ExactSizeIterator,
|
||||
I::Item: TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
|
@ -664,12 +668,12 @@ where
|
|||
I::Item: Deref,
|
||||
<I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
pub fn arg_iter_copied(
|
||||
pub fn iter_instantiated_copied(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'s [GenericArg<'tcx>],
|
||||
) -> ArgIterCopied<'s, 'tcx, I> {
|
||||
ArgIterCopied { it: self.value.into_iter(), tcx, args }
|
||||
) -> IterInstantiatedCopied<'s, 'tcx, I> {
|
||||
IterInstantiatedCopied { it: self.value.into_iter(), tcx, args }
|
||||
}
|
||||
|
||||
/// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
|
||||
|
|
@ -681,13 +685,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ArgIterCopied<'a, 'tcx, I: IntoIterator> {
|
||||
pub struct IterInstantiatedCopied<'a, 'tcx, I: IntoIterator> {
|
||||
it: I::IntoIter,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'a [GenericArg<'tcx>],
|
||||
}
|
||||
|
||||
impl<'tcx, I: IntoIterator> Iterator for ArgIterCopied<'_, 'tcx, I>
|
||||
impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I>
|
||||
where
|
||||
I::Item: Deref,
|
||||
<I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
|
@ -703,7 +707,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, I: IntoIterator> DoubleEndedIterator for ArgIterCopied<'_, 'tcx, I>
|
||||
impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, 'tcx, I>
|
||||
where
|
||||
I::IntoIter: DoubleEndedIterator,
|
||||
I::Item: Deref,
|
||||
|
|
@ -716,7 +720,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, I: IntoIterator> ExactSizeIterator for ArgIterCopied<'_, 'tcx, I>
|
||||
impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiatedCopied<'_, 'tcx, I>
|
||||
where
|
||||
I::IntoIter: ExactSizeIterator,
|
||||
I::Item: Deref,
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ impl<'tcx> GenericPredicates<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
|
||||
EarlyBinder::bind(self.predicates).arg_iter_copied(tcx, args)
|
||||
EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, tcx))]
|
||||
|
|
|
|||
|
|
@ -928,7 +928,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
let mut is_sized = false;
|
||||
let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
|
||||
|
||||
for (predicate, _) in bounds.arg_iter_copied(tcx, args) {
|
||||
for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) {
|
||||
let bound_predicate = predicate.kind();
|
||||
|
||||
match bound_predicate.skip_binder() {
|
||||
|
|
@ -1932,7 +1932,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
|
||||
self.empty_path = true;
|
||||
if cnum == LOCAL_CRATE {
|
||||
if self.tcx.sess.rust_2018() {
|
||||
if self.tcx.sess.at_least_rust_2018() {
|
||||
// We add the `crate::` keyword on Rust 2018, only when desired.
|
||||
if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
|
||||
write!(self, "{}", kw::Crate)?;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use hir::def::DefKind;
|
|||
use polonius_engine::Atom;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::DiagnosticMessage;
|
||||
use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -1991,7 +1990,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> Ty<'tcx> {
|
||||
let reported = tcx.sess.delay_span_bug(span, msg);
|
||||
Ty::new(tcx, Error(reported))
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use rustc_index::bit_set::GrowableBitSet;
|
|||
use rustc_macros::HashStable;
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
|
||||
use rustc_target::abi::{Integer, IntegerType, Size};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use smallvec::SmallVec;
|
||||
use std::{fmt, iter};
|
||||
|
|
@ -1085,7 +1085,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
#[inline]
|
||||
pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
// Avoid querying in simple cases.
|
||||
match needs_drop_components(self, &tcx.data_layout) {
|
||||
match needs_drop_components(tcx, self) {
|
||||
Err(AlwaysRequiresDrop) => true,
|
||||
Ok(components) => {
|
||||
let query_ty = match *components {
|
||||
|
|
@ -1118,7 +1118,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
#[inline]
|
||||
pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
// Avoid querying in simple cases.
|
||||
match needs_drop_components(self, &tcx.data_layout) {
|
||||
match needs_drop_components(tcx, self) {
|
||||
Err(AlwaysRequiresDrop) => true,
|
||||
Ok(components) => {
|
||||
let query_ty = match *components {
|
||||
|
|
@ -1278,10 +1278,10 @@ impl<'tcx> ExplicitSelf<'tcx> {
|
|||
/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
|
||||
/// this type always needs drop.
|
||||
pub fn needs_drop_components<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
target_layout: &TargetDataLayout,
|
||||
) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> {
|
||||
match ty.kind() {
|
||||
match *ty.kind() {
|
||||
ty::Infer(ty::FreshIntTy(_))
|
||||
| ty::Infer(ty::FreshFloatTy(_))
|
||||
| ty::Bool
|
||||
|
|
@ -1303,11 +1303,11 @@ pub fn needs_drop_components<'tcx>(
|
|||
|
||||
ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
|
||||
|
||||
ty::Slice(ty) => needs_drop_components(*ty, target_layout),
|
||||
ty::Slice(ty) => needs_drop_components(tcx, ty),
|
||||
ty::Array(elem_ty, size) => {
|
||||
match needs_drop_components(*elem_ty, target_layout) {
|
||||
match needs_drop_components(tcx, elem_ty) {
|
||||
Ok(v) if v.is_empty() => Ok(v),
|
||||
res => match size.try_to_bits(target_layout.pointer_size) {
|
||||
res => match size.try_to_target_usize(tcx) {
|
||||
// Arrays of size zero don't need drop, even if their element
|
||||
// type does.
|
||||
Some(0) => Ok(SmallVec::new()),
|
||||
|
|
@ -1321,7 +1321,7 @@ pub fn needs_drop_components<'tcx>(
|
|||
}
|
||||
// If any field needs drop, then the whole tuple does.
|
||||
ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| {
|
||||
acc.extend(needs_drop_components(elem, target_layout)?);
|
||||
acc.extend(needs_drop_components(tcx, elem)?);
|
||||
Ok(acc)
|
||||
}),
|
||||
|
||||
|
|
|
|||
|
|
@ -730,5 +730,5 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
/// Precise capture is enabled if user is using Rust Edition 2021 or higher.
|
||||
fn enable_precise_capture(closure_span: Span) -> bool {
|
||||
closure_span.rust_2021()
|
||||
closure_span.at_least_rust_2021()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,7 +248,8 @@ where
|
|||
}
|
||||
let size_estimate = mono_item.size_estimate(cx.tcx);
|
||||
|
||||
cgu.items_mut().insert(mono_item, MonoItemData { linkage, visibility, size_estimate });
|
||||
cgu.items_mut()
|
||||
.insert(mono_item, MonoItemData { inlined: false, linkage, visibility, size_estimate });
|
||||
|
||||
// Get all inlined items that are reachable from `mono_item` without
|
||||
// going via another root item. This includes drop-glue, functions from
|
||||
|
|
@ -263,6 +264,7 @@ where
|
|||
for inlined_item in reachable_inlined_items {
|
||||
// This is a CGU-private copy.
|
||||
cgu.items_mut().entry(inlined_item).or_insert_with(|| MonoItemData {
|
||||
inlined: true,
|
||||
linkage: Linkage::Internal,
|
||||
visibility: Visibility::Default,
|
||||
size_estimate: inlined_item.size_estimate(cx.tcx),
|
||||
|
|
@ -316,6 +318,60 @@ fn merge_codegen_units<'tcx>(
|
|||
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
|
||||
codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
|
||||
|
||||
// If N is the maximum number of CGUs, and the CGUs are sorted from largest
|
||||
// to smallest, we repeatedly find which CGU in codegen_units[N..] has the
|
||||
// greatest overlap of inlined items with codegen_units[N-1], merge that
|
||||
// CGU into codegen_units[N-1], then re-sort by size and repeat.
|
||||
//
|
||||
// We use inlined item overlap to guide this merging because it minimizes
|
||||
// duplication of inlined items, which makes LLVM be faster and generate
|
||||
// better and smaller machine code.
|
||||
//
|
||||
// Why merge into codegen_units[N-1]? We want CGUs to have similar sizes,
|
||||
// which means we don't want codegen_units[0..N] (the already big ones)
|
||||
// getting any bigger, if we can avoid it. When we have more than N CGUs
|
||||
// then at least one of the biggest N will have to grow. codegen_units[N-1]
|
||||
// is the smallest of those, and so has the most room to grow.
|
||||
let max_codegen_units = cx.tcx.sess.codegen_units().as_usize();
|
||||
while codegen_units.len() > max_codegen_units {
|
||||
// Sort small CGUs to the back.
|
||||
codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
|
||||
|
||||
let cgu_dst = &codegen_units[max_codegen_units - 1];
|
||||
|
||||
// Find the CGU that overlaps the most with `cgu_dst`. In the case of a
|
||||
// tie, favour the earlier (bigger) CGU.
|
||||
let mut max_overlap = 0;
|
||||
let mut max_overlap_i = max_codegen_units;
|
||||
for (i, cgu_src) in codegen_units.iter().enumerate().skip(max_codegen_units) {
|
||||
if cgu_src.size_estimate() <= max_overlap {
|
||||
// None of the remaining overlaps can exceed `max_overlap`, so
|
||||
// stop looking.
|
||||
break;
|
||||
}
|
||||
|
||||
let overlap = compute_inlined_overlap(cgu_dst, cgu_src);
|
||||
if overlap > max_overlap {
|
||||
max_overlap = overlap;
|
||||
max_overlap_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
let mut cgu_src = codegen_units.swap_remove(max_overlap_i);
|
||||
let cgu_dst = &mut codegen_units[max_codegen_units - 1];
|
||||
|
||||
// Move the items from `cgu_src` to `cgu_dst`. Some of them may be
|
||||
// duplicate inlined items, in which case the destination CGU is
|
||||
// unaffected. Recalculate size estimates afterwards.
|
||||
cgu_dst.items_mut().extend(cgu_src.items_mut().drain());
|
||||
cgu_dst.compute_size_estimate();
|
||||
|
||||
// Record that `cgu_dst` now contains all the stuff that was in
|
||||
// `cgu_src` before.
|
||||
let mut consumed_cgu_names = cgu_contents.remove(&cgu_src.name()).unwrap();
|
||||
cgu_contents.get_mut(&cgu_dst.name()).unwrap().append(&mut consumed_cgu_names);
|
||||
}
|
||||
|
||||
// Having multiple CGUs can drastically speed up compilation. But for
|
||||
// non-incremental builds, tiny CGUs slow down compilation *and* result in
|
||||
// worse generated code. So we don't allow CGUs smaller than this (unless
|
||||
|
|
@ -323,24 +379,22 @@ fn merge_codegen_units<'tcx>(
|
|||
// common in larger programs, so this isn't all that large.
|
||||
const NON_INCR_MIN_CGU_SIZE: usize = 1800;
|
||||
|
||||
// Repeatedly merge the two smallest codegen units as long as:
|
||||
// - we have more CGUs than the upper limit, or
|
||||
// - (Non-incremental builds only) the user didn't specify a CGU count, and
|
||||
// there are multiple CGUs, and some are below the minimum size.
|
||||
// Repeatedly merge the two smallest codegen units as long as: it's a
|
||||
// non-incremental build, and the user didn't specify a CGU count, and
|
||||
// there are multiple CGUs, and some are below the minimum size.
|
||||
//
|
||||
// The "didn't specify a CGU count" condition is because when an explicit
|
||||
// count is requested we observe it as closely as possible. For example,
|
||||
// the `compiler_builtins` crate sets `codegen-units = 10000` and it's
|
||||
// critical they aren't merged. Also, some tests use explicit small values
|
||||
// and likewise won't work if small CGUs are merged.
|
||||
while codegen_units.len() > cx.tcx.sess.codegen_units().as_usize()
|
||||
|| (cx.tcx.sess.opts.incremental.is_none()
|
||||
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
|
||||
&& codegen_units.len() > 1
|
||||
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE))
|
||||
while cx.tcx.sess.opts.incremental.is_none()
|
||||
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
|
||||
&& codegen_units.len() > 1
|
||||
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE)
|
||||
{
|
||||
// Sort small cgus to the back.
|
||||
codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
|
||||
codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
|
||||
|
||||
let mut smallest = codegen_units.pop().unwrap();
|
||||
let second_smallest = codegen_units.last_mut().unwrap();
|
||||
|
|
@ -351,16 +405,7 @@ fn merge_codegen_units<'tcx>(
|
|||
second_smallest.items_mut().extend(smallest.items_mut().drain());
|
||||
second_smallest.compute_size_estimate();
|
||||
|
||||
// Record that `second_smallest` now contains all the stuff that was
|
||||
// in `smallest` before.
|
||||
let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
|
||||
cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
|
||||
|
||||
debug!(
|
||||
"CodegenUnit {} merged into CodegenUnit {}",
|
||||
smallest.name(),
|
||||
second_smallest.name()
|
||||
);
|
||||
// Don't update `cgu_contents`, that's only for incremental builds.
|
||||
}
|
||||
|
||||
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
|
||||
|
|
@ -439,6 +484,25 @@ fn merge_codegen_units<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Compute the combined size of all inlined items that appear in both `cgu1`
|
||||
/// and `cgu2`.
|
||||
fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'tcx>) -> usize {
|
||||
// Either order works. We pick the one that involves iterating over fewer
|
||||
// items.
|
||||
let (src_cgu, dst_cgu) =
|
||||
if cgu1.items().len() <= cgu2.items().len() { (cgu1, cgu2) } else { (cgu2, cgu1) };
|
||||
|
||||
let mut overlap = 0;
|
||||
for (item, data) in src_cgu.items().iter() {
|
||||
if data.inlined {
|
||||
if dst_cgu.items().contains_key(item) {
|
||||
overlap += data.size_estimate;
|
||||
}
|
||||
}
|
||||
}
|
||||
overlap
|
||||
}
|
||||
|
||||
fn internalize_symbols<'tcx>(
|
||||
cx: &PartitioningCx<'_, 'tcx>,
|
||||
codegen_units: &mut [CodegenUnit<'tcx>],
|
||||
|
|
@ -870,19 +934,16 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
|
|||
all_cgu_sizes.push(cgu.size_estimate());
|
||||
|
||||
for (item, data) in cgu.items() {
|
||||
match item.instantiation_mode(tcx) {
|
||||
InstantiationMode::GloballyShared { .. } => {
|
||||
root_items += 1;
|
||||
root_size += data.size_estimate;
|
||||
}
|
||||
InstantiationMode::LocalCopy => {
|
||||
if inlined_items.insert(item) {
|
||||
unique_inlined_items += 1;
|
||||
unique_inlined_size += data.size_estimate;
|
||||
}
|
||||
placed_inlined_items += 1;
|
||||
placed_inlined_size += data.size_estimate;
|
||||
if !data.inlined {
|
||||
root_items += 1;
|
||||
root_size += data.size_estimate;
|
||||
} else {
|
||||
if inlined_items.insert(item) {
|
||||
unique_inlined_items += 1;
|
||||
unique_inlined_size += data.size_estimate;
|
||||
}
|
||||
placed_inlined_items += 1;
|
||||
placed_inlined_size += data.size_estimate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -937,10 +998,7 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
|
|||
let symbol_name = item.symbol_name(tcx).name;
|
||||
let symbol_hash_start = symbol_name.rfind('h');
|
||||
let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
|
||||
let kind = match item.instantiation_mode(tcx) {
|
||||
InstantiationMode::GloballyShared { .. } => "root",
|
||||
InstantiationMode::LocalCopy => "inlined",
|
||||
};
|
||||
let kind = if !data.inlined { "root" } else { "inlined" };
|
||||
let size = data.size_estimate;
|
||||
let _ = with_no_trimmed_paths!(writeln!(
|
||||
s,
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
|
|||
self.sess.span_diagnostic.struct_span_err(sp, m)
|
||||
}
|
||||
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<DiagnosticMessage>) -> ! {
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<String>) -> ! {
|
||||
self.sess.span_diagnostic.span_bug(sp, m)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1309,7 +1309,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Assuming we have just parsed `.`, continue parsing into an expression.
|
||||
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) {
|
||||
if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await) {
|
||||
return Ok(self.mk_await_expr(self_arg, lo));
|
||||
}
|
||||
|
||||
|
|
@ -1442,8 +1442,8 @@ impl<'a> Parser<'a> {
|
|||
self.parse_expr_let()
|
||||
} else if self.eat_keyword(kw::Underscore) {
|
||||
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
|
||||
} else if self.token.uninterpolated_span().rust_2018() {
|
||||
// `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||
} else if self.token.uninterpolated_span().at_least_rust_2018() {
|
||||
// `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||
if self.check_keyword(kw::Async) {
|
||||
if self.is_async_block() {
|
||||
// Check for `async {` and `async move {`.
|
||||
|
|
@ -2230,7 +2230,7 @@ impl<'a> Parser<'a> {
|
|||
let movability =
|
||||
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
|
||||
|
||||
let asyncness = if self.token.uninterpolated_span().rust_2018() {
|
||||
let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() {
|
||||
self.parse_asyncness(Case::Sensitive)
|
||||
} else {
|
||||
Async::No
|
||||
|
|
@ -3014,7 +3014,7 @@ impl<'a> Parser<'a> {
|
|||
fn is_try_block(&self) -> bool {
|
||||
self.token.is_keyword(kw::Try)
|
||||
&& self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace))
|
||||
&& self.token.uninterpolated_span().rust_2018()
|
||||
&& self.token.uninterpolated_span().at_least_rust_2018()
|
||||
}
|
||||
|
||||
/// Parses an `async move? {...}` expression.
|
||||
|
|
|
|||
|
|
@ -1210,7 +1210,8 @@ impl<'a> Parser<'a> {
|
|||
fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
|
||||
// Avoid const blocks and const closures to be parsed as const items
|
||||
if (self.check_const_closure() == is_closure)
|
||||
&& self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
|
||||
&& !self
|
||||
.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
|
||||
&& self.eat_keyword_case(kw::Const, case)
|
||||
{
|
||||
Const::Yes(self.prev_token.uninterpolated_span())
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use crate::errors::{
|
|||
TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
||||
UnexpectedVertVertInPattern,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
|
||||
use rustc_ast::ptr::P;
|
||||
|
|
@ -214,41 +213,25 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if let PatKind::Or(pats) = &pat.kind {
|
||||
let span = pat.span;
|
||||
|
||||
if trailing_vert {
|
||||
// We already emitted an error and suggestion to remove the trailing vert. Don't
|
||||
// emit again.
|
||||
|
||||
// FIXME(#100717): pass `TopLevelOrPatternNotAllowed::* { sub: None }` to
|
||||
// `delay_span_bug()` instead of fluent message
|
||||
self.sess.span_diagnostic.delay_span_bug(
|
||||
span,
|
||||
match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
fluent::parse_or_pattern_not_allowed_in_let_binding
|
||||
}
|
||||
PatternLocation::FunctionParameter => {
|
||||
fluent::parse_or_pattern_not_allowed_in_fn_parameters
|
||||
}
|
||||
},
|
||||
);
|
||||
let pat = pprust::pat_to_string(&pat);
|
||||
let sub = if pats.len() == 1 {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
|
||||
} else {
|
||||
let pat = pprust::pat_to_string(&pat);
|
||||
let sub = if pats.len() == 1 {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
|
||||
} else {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
|
||||
};
|
||||
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
|
||||
};
|
||||
|
||||
self.sess.emit_err(match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
TopLevelOrPatternNotAllowed::LetBinding { span, sub }
|
||||
}
|
||||
PatternLocation::FunctionParameter => {
|
||||
TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
|
||||
}
|
||||
});
|
||||
let mut err = self.sess.create_err(match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
TopLevelOrPatternNotAllowed::LetBinding { span, sub }
|
||||
}
|
||||
PatternLocation::FunctionParameter => {
|
||||
TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
|
||||
}
|
||||
});
|
||||
if trailing_vert {
|
||||
err.delay_as_bug();
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
Ok((pat, colon))
|
||||
|
|
|
|||
|
|
@ -608,7 +608,7 @@ impl<'a> Parser<'a> {
|
|||
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
||||
fn is_explicit_dyn_type(&mut self) -> bool {
|
||||
self.check_keyword(kw::Dyn)
|
||||
&& (self.token.uninterpolated_span().rust_2018()
|
||||
&& (self.token.uninterpolated_span().at_least_rust_2018()
|
||||
|| self.look_ahead(1, |t| {
|
||||
(t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
|
||||
&& !can_continue_type_after_non_fn_ident(t)
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ pub struct Argument<'a> {
|
|||
pub struct FormatSpec<'a> {
|
||||
/// Optionally specified character to fill alignment with.
|
||||
pub fill: Option<char>,
|
||||
/// Span of the optionally specified fill character.
|
||||
pub fill_span: Option<InnerSpan>,
|
||||
/// Optionally specified alignment.
|
||||
pub align: Alignment,
|
||||
/// The `+` or `-` flag.
|
||||
|
|
@ -264,7 +266,7 @@ impl<'a> Iterator for Parser<'a> {
|
|||
Some(String(self.string(pos + 1)))
|
||||
} else {
|
||||
let arg = self.argument(lbrace_end);
|
||||
if let Some(rbrace_pos) = self.must_consume('}') {
|
||||
if let Some(rbrace_pos) = self.consume_closing_brace(&arg) {
|
||||
if self.is_source_literal {
|
||||
let lbrace_byte_pos = self.to_span_index(pos);
|
||||
let rbrace_byte_pos = self.to_span_index(rbrace_pos);
|
||||
|
|
@ -450,69 +452,51 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Forces consumption of the specified character. If the character is not
|
||||
/// found, an error is emitted.
|
||||
fn must_consume(&mut self, c: char) -> Option<usize> {
|
||||
fn consume_closing_brace(&mut self, arg: &Argument<'_>) -> Option<usize> {
|
||||
self.ws();
|
||||
|
||||
if let Some(&(pos, maybe)) = self.cur.peek() {
|
||||
if c == maybe {
|
||||
let pos;
|
||||
let description;
|
||||
|
||||
if let Some(&(peek_pos, maybe)) = self.cur.peek() {
|
||||
if maybe == '}' {
|
||||
self.cur.next();
|
||||
Some(pos)
|
||||
} else {
|
||||
let pos = self.to_span_index(pos);
|
||||
let description = format!("expected `'}}'`, found `{maybe:?}`");
|
||||
let label = "expected `}`".to_owned();
|
||||
let (note, secondary_label) = if c == '}' {
|
||||
(
|
||||
Some(
|
||||
"if you intended to print `{`, you can escape it using `{{`".to_owned(),
|
||||
),
|
||||
self.last_opening_brace
|
||||
.map(|sp| ("because of this opening brace".to_owned(), sp)),
|
||||
)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
self.errors.push(ParseError {
|
||||
description,
|
||||
note,
|
||||
label,
|
||||
span: pos.to(pos),
|
||||
secondary_label,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
None
|
||||
return Some(peek_pos);
|
||||
}
|
||||
|
||||
pos = peek_pos;
|
||||
description = format!("expected `'}}'`, found `{maybe:?}`");
|
||||
} else {
|
||||
let description = format!("expected `{c:?}` but string was terminated");
|
||||
description = "expected `'}'` but string was terminated".to_owned();
|
||||
// point at closing `"`
|
||||
let pos = self.input.len() - if self.append_newline { 1 } else { 0 };
|
||||
let pos = self.to_span_index(pos);
|
||||
if c == '}' {
|
||||
let label = format!("expected `{c:?}`");
|
||||
let (note, secondary_label) = if c == '}' {
|
||||
(
|
||||
Some(
|
||||
"if you intended to print `{`, you can escape it using `{{`".to_owned(),
|
||||
),
|
||||
self.last_opening_brace
|
||||
.map(|sp| ("because of this opening brace".to_owned(), sp)),
|
||||
)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
self.errors.push(ParseError {
|
||||
description,
|
||||
note,
|
||||
label,
|
||||
span: pos.to(pos),
|
||||
secondary_label,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
} else {
|
||||
self.err(description, format!("expected `{c:?}`"), pos.to(pos));
|
||||
}
|
||||
None
|
||||
pos = self.input.len() - if self.append_newline { 1 } else { 0 };
|
||||
}
|
||||
|
||||
let pos = self.to_span_index(pos);
|
||||
|
||||
let label = "expected `'}'`".to_owned();
|
||||
let (note, secondary_label) = if arg.format.fill == Some('}') {
|
||||
(
|
||||
Some("the character `'}'` is interpreted as a fill character because of the `:` that precedes it".to_owned()),
|
||||
arg.format.fill_span.map(|sp| ("this is not interpreted as a formatting closing brace".to_owned(), sp)),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Some("if you intended to print `{`, you can escape it using `{{`".to_owned()),
|
||||
self.last_opening_brace.map(|sp| ("because of this opening brace".to_owned(), sp)),
|
||||
)
|
||||
};
|
||||
|
||||
self.errors.push(ParseError {
|
||||
description,
|
||||
note,
|
||||
label,
|
||||
span: pos.to(pos),
|
||||
secondary_label,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Consumes all whitespace characters until the first non-whitespace character
|
||||
|
|
@ -608,6 +592,7 @@ impl<'a> Parser<'a> {
|
|||
fn format(&mut self) -> FormatSpec<'a> {
|
||||
let mut spec = FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -625,9 +610,10 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
// fill character
|
||||
if let Some(&(_, c)) = self.cur.peek() {
|
||||
if let Some(&(idx, c)) = self.cur.peek() {
|
||||
if let Some((_, '>' | '<' | '^')) = self.cur.clone().nth(1) {
|
||||
spec.fill = Some(c);
|
||||
spec.fill_span = Some(self.span(idx, idx + 1));
|
||||
self.cur.next();
|
||||
}
|
||||
}
|
||||
|
|
@ -722,6 +708,7 @@ impl<'a> Parser<'a> {
|
|||
fn inline_asm(&mut self) -> FormatSpec<'a> {
|
||||
let mut spec = FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ fn same(fmt: &'static str, p: &[Piece<'static>]) {
|
|||
fn fmtdflt() -> FormatSpec<'static> {
|
||||
return FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -128,6 +129,7 @@ fn format_type() {
|
|||
position_span: InnerSpan { start: 2, end: 3 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -152,6 +154,7 @@ fn format_align_fill() {
|
|||
position_span: InnerSpan { start: 2, end: 3 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignRight,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -173,6 +176,7 @@ fn format_align_fill() {
|
|||
position_span: InnerSpan { start: 2, end: 3 },
|
||||
format: FormatSpec {
|
||||
fill: Some('0'),
|
||||
fill_span: Some(InnerSpan::new(4, 5)),
|
||||
align: AlignLeft,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -194,6 +198,7 @@ fn format_align_fill() {
|
|||
position_span: InnerSpan { start: 2, end: 3 },
|
||||
format: FormatSpec {
|
||||
fill: Some('*'),
|
||||
fill_span: Some(InnerSpan::new(4, 5)),
|
||||
align: AlignLeft,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -218,6 +223,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -239,6 +245,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -260,6 +267,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 3 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -281,6 +289,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -302,6 +311,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -323,6 +333,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -344,6 +355,7 @@ fn format_counts() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
@ -368,6 +380,7 @@ fn format_flags() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: Some(Sign::Minus),
|
||||
alternate: false,
|
||||
|
|
@ -389,6 +402,7 @@ fn format_flags() {
|
|||
position_span: InnerSpan { start: 2, end: 2 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: Some(Sign::Plus),
|
||||
alternate: true,
|
||||
|
|
@ -415,6 +429,7 @@ fn format_mixture() {
|
|||
position_span: InnerSpan { start: 7, end: 8 },
|
||||
format: FormatSpec {
|
||||
fill: None,
|
||||
fill_span: None,
|
||||
align: AlignUnknown,
|
||||
sign: None,
|
||||
alternate: false,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
query_system_cycle = cycle detected when {$stack_bottom}
|
||||
.note = see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ pub struct Cycle {
|
|||
pub alias: Option<Alias>,
|
||||
#[subdiagnostic]
|
||||
pub cycle_usage: Option<CycleUsage>,
|
||||
#[note]
|
||||
pub note_span: (),
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use rustc_session::Session;
|
|||
use rustc_span::Span;
|
||||
|
||||
use std::hash::Hash;
|
||||
use std::io::Write;
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
|
|
@ -607,6 +608,7 @@ pub(crate) fn report_cycle<'a, D: DepKind>(
|
|||
alias,
|
||||
cycle_usage: cycle_usage,
|
||||
stack_count,
|
||||
note_span: (),
|
||||
};
|
||||
|
||||
cycle_diag.into_diagnostic(&sess.parse_sess.span_diagnostic)
|
||||
|
|
@ -617,30 +619,50 @@ pub fn print_query_stack<Qcx: QueryContext>(
|
|||
mut current_query: Option<QueryJobId>,
|
||||
handler: &Handler,
|
||||
num_frames: Option<usize>,
|
||||
mut file: Option<std::fs::File>,
|
||||
) -> usize {
|
||||
// Be careful relying on global state here: this code is called from
|
||||
// a panic hook, which means that the global `Handler` may be in a weird
|
||||
// state if it was responsible for triggering the panic.
|
||||
let mut i = 0;
|
||||
let mut count_printed = 0;
|
||||
let mut count_total = 0;
|
||||
let query_map = qcx.try_collect_active_jobs();
|
||||
|
||||
if let Some(ref mut file) = file {
|
||||
let _ = writeln!(file, "\n\nquery stack during panic:");
|
||||
}
|
||||
while let Some(query) = current_query {
|
||||
if Some(i) == num_frames {
|
||||
break;
|
||||
}
|
||||
let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else {
|
||||
break;
|
||||
};
|
||||
let mut diag = Diagnostic::new(
|
||||
Level::FailureNote,
|
||||
format!("#{} [{:?}] {}", i, query_info.query.dep_kind, query_info.query.description),
|
||||
);
|
||||
diag.span = query_info.job.span.into();
|
||||
handler.force_print_diagnostic(diag);
|
||||
if Some(count_printed) < num_frames || num_frames.is_none() {
|
||||
// Only print to stderr as many stack frames as `num_frames` when present.
|
||||
let mut diag = Diagnostic::new(
|
||||
Level::FailureNote,
|
||||
format!(
|
||||
"#{} [{:?}] {}",
|
||||
count_printed, query_info.query.dep_kind, query_info.query.description
|
||||
),
|
||||
);
|
||||
diag.span = query_info.job.span.into();
|
||||
handler.force_print_diagnostic(diag);
|
||||
count_printed += 1;
|
||||
}
|
||||
|
||||
if let Some(ref mut file) = file {
|
||||
let _ = writeln!(
|
||||
file,
|
||||
"#{} [{:?}] {}",
|
||||
count_total, query_info.query.dep_kind, query_info.query.description
|
||||
);
|
||||
}
|
||||
|
||||
current_query = query_info.job.parent;
|
||||
i += 1;
|
||||
count_total += 1;
|
||||
}
|
||||
|
||||
i
|
||||
if let Some(ref mut file) = file {
|
||||
let _ = writeln!(file, "end of query stack");
|
||||
}
|
||||
count_printed
|
||||
}
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ impl Resolver<'_, '_> {
|
|||
|
||||
// If we are not in Rust 2018 edition, then we don't make any further
|
||||
// suggestions.
|
||||
if !tcx.sess.rust_2018() {
|
||||
if !tcx.sess.at_least_rust_2018() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1203,7 +1203,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if filter_fn(res) {
|
||||
// create the path
|
||||
let mut segms = path_segments.clone();
|
||||
if lookup_ident.span.rust_2018() {
|
||||
if lookup_ident.span.at_least_rust_2018() {
|
||||
// crate-local absolute paths start with `crate::` in edition 2018
|
||||
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
|
||||
segms.insert(0, ast::PathSegment::from_ident(crate_name));
|
||||
|
|
@ -1268,7 +1268,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
path_segments.push(ast::PathSegment::from_ident(ident));
|
||||
|
||||
let is_extern_crate_that_also_appears_in_prelude =
|
||||
name_binding.is_extern_crate() && lookup_ident.span.rust_2018();
|
||||
name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
|
||||
|
||||
if !is_extern_crate_that_also_appears_in_prelude {
|
||||
// add the module to the lookup
|
||||
|
|
@ -1315,7 +1315,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
&filter_fn,
|
||||
);
|
||||
|
||||
if lookup_ident.span.rust_2018() {
|
||||
if lookup_ident.span.at_least_rust_2018() {
|
||||
let extern_prelude_names = self.extern_prelude.clone();
|
||||
for (ident, _) in extern_prelude_names.into_iter() {
|
||||
if ident.span.from_expansion() {
|
||||
|
|
@ -1568,7 +1568,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
"consider adding an explicit import of `{ident}` to disambiguate"
|
||||
))
|
||||
}
|
||||
if b.is_extern_crate() && ident.span.rust_2018() {
|
||||
if b.is_extern_crate() && ident.span.at_least_rust_2018() {
|
||||
help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
|
||||
}
|
||||
match misc {
|
||||
|
|
@ -1973,7 +1973,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {}
|
||||
// `ident::...` on 2018.
|
||||
(Some(fst), _)
|
||||
if fst.ident.span.rust_2018() && !fst.ident.is_path_segment_keyword() =>
|
||||
if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() =>
|
||||
{
|
||||
// Insert a placeholder that's later replaced by `self`/`super`/etc.
|
||||
path.insert(0, Segment::from_ident(Ident::empty()));
|
||||
|
|
|
|||
|
|
@ -1417,13 +1417,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
));
|
||||
continue;
|
||||
}
|
||||
if name == kw::PathRoot && ident.span.rust_2018() {
|
||||
if name == kw::PathRoot && ident.span.at_least_rust_2018() {
|
||||
module = Some(ModuleOrUniformRoot::ExternPrelude);
|
||||
continue;
|
||||
}
|
||||
if name == kw::PathRoot
|
||||
&& ident.span.is_rust_2015()
|
||||
&& self.tcx.sess.rust_2018()
|
||||
&& self.tcx.sess.at_least_rust_2018()
|
||||
{
|
||||
// `::a::b` from 2015 macro on 2018 global edition
|
||||
module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
|
||||
|
|
|
|||
|
|
@ -3911,8 +3911,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
&& path[0].ident.name != kw::PathRoot
|
||||
&& path[0].ident.name != kw::DollarCrate
|
||||
{
|
||||
let last_segment = *path.last().unwrap();
|
||||
let unqualified_result = {
|
||||
match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
|
||||
match self.resolve_path(&[last_segment], Some(ns), None) {
|
||||
PathResult::NonModule(path_res) => path_res.expect_full_res(),
|
||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
|
||||
module.res().unwrap()
|
||||
|
|
@ -3928,8 +3929,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
finalize.path_span,
|
||||
"unnecessary qualification",
|
||||
lint::BuiltinLintDiagnostics::UnusedQualifications {
|
||||
path_span: finalize.path_span,
|
||||
unqualified_path: path.last().unwrap().ident
|
||||
removal_span: finalize.path_span.until(last_segment.ident.span),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
|
|||
use rustc_span::hygiene::{ExpnHash, ExpnId};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_target::spec::Target;
|
||||
|
||||
use std::any::Any;
|
||||
|
|
@ -147,6 +148,7 @@ pub enum DllCallingConvention {
|
|||
pub struct ForeignModule {
|
||||
pub foreign_items: Vec<DefId>,
|
||||
pub def_id: DefId,
|
||||
pub abi: Abi,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ pub fn feature_err_issue(
|
|||
/// Construct a future incompatibility diagnostic for a feature gate.
|
||||
///
|
||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
||||
#[track_caller]
|
||||
pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
|
||||
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
|
||||
}
|
||||
|
|
@ -129,6 +130,7 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st
|
|||
/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[track_caller]
|
||||
pub fn feature_warn_issue(
|
||||
sess: &ParseSess,
|
||||
feature: Symbol,
|
||||
|
|
@ -229,6 +231,7 @@ impl ParseSess {
|
|||
Some(sm.clone()),
|
||||
None,
|
||||
fallback_bundle,
|
||||
None,
|
||||
);
|
||||
ParseSess::with_span_handler(handler, sm)
|
||||
}
|
||||
|
|
@ -259,12 +262,20 @@ impl ParseSess {
|
|||
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
|
||||
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
|
||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let fatal_handler =
|
||||
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
|
||||
let fatal_handler = Handler::with_tty_emitter(
|
||||
ColorConfig::Auto,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
fallback_bundle,
|
||||
None,
|
||||
);
|
||||
let handler = Handler::with_emitter(
|
||||
false,
|
||||
None,
|
||||
Box::new(SilentEmitter { fatal_handler, fatal_note }),
|
||||
None,
|
||||
);
|
||||
ParseSess::with_span_handler(handler, sm)
|
||||
}
|
||||
|
|
@ -351,6 +362,7 @@ impl ParseSess {
|
|||
self.create_warning(warning).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_note<'a>(
|
||||
&'a self,
|
||||
note: impl IntoDiagnostic<'a, Noted>,
|
||||
|
|
@ -358,10 +370,12 @@ impl ParseSess {
|
|||
note.into_diagnostic(&self.span_diagnostic)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
|
||||
self.create_note(note).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_fatal<'a>(
|
||||
&'a self,
|
||||
fatal: impl IntoDiagnostic<'a, !>,
|
||||
|
|
@ -369,6 +383,7 @@ impl ParseSess {
|
|||
fatal.into_diagnostic(&self.span_diagnostic)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
|
||||
self.create_fatal(fatal).emit()
|
||||
}
|
||||
|
|
@ -383,16 +398,19 @@ impl ParseSess {
|
|||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
self.span_diagnostic.struct_warn(msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
|
||||
self.span_diagnostic.struct_fatal(msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_diagnostic<G: EmissionGuarantee>(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
|
|
|
|||
|
|
@ -677,7 +677,7 @@ impl Session {
|
|||
pub fn delay_span_bug<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.diagnostic().delay_span_bug(sp, msg)
|
||||
}
|
||||
|
|
@ -995,18 +995,18 @@ impl Session {
|
|||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 edition?
|
||||
pub fn rust_2018(&self) -> bool {
|
||||
self.edition().rust_2018()
|
||||
pub fn at_least_rust_2018(&self) -> bool {
|
||||
self.edition().at_least_rust_2018()
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2021 edition?
|
||||
pub fn rust_2021(&self) -> bool {
|
||||
self.edition().rust_2021()
|
||||
pub fn at_least_rust_2021(&self) -> bool {
|
||||
self.edition().at_least_rust_2021()
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2024 edition?
|
||||
pub fn rust_2024(&self) -> bool {
|
||||
self.edition().rust_2024()
|
||||
pub fn at_least_rust_2024(&self) -> bool {
|
||||
self.edition().at_least_rust_2024()
|
||||
}
|
||||
|
||||
/// Returns `true` if we should use the PLT for shared library calls.
|
||||
|
|
@ -1392,6 +1392,7 @@ pub fn build_session(
|
|||
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
|
||||
target_override: Option<Target>,
|
||||
cfg_version: &'static str,
|
||||
ice_file: Option<PathBuf>,
|
||||
) -> Session {
|
||||
// FIXME: This is not general enough to make the warning lint completely override
|
||||
// normal diagnostic warnings, since the warning lint can also be denied and changed
|
||||
|
|
@ -1440,6 +1441,7 @@ pub fn build_session(
|
|||
let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
|
||||
emitter,
|
||||
sopts.unstable_opts.diagnostic_handler_flags(can_emit_warnings),
|
||||
ice_file,
|
||||
);
|
||||
|
||||
let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile
|
||||
|
|
@ -1731,7 +1733,7 @@ pub struct EarlyErrorHandler {
|
|||
impl EarlyErrorHandler {
|
||||
pub fn new(output: ErrorOutputType) -> Self {
|
||||
let emitter = mk_emitter(output);
|
||||
Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter) }
|
||||
Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter, None) }
|
||||
}
|
||||
|
||||
pub fn abort_if_errors(&self) {
|
||||
|
|
@ -1745,7 +1747,7 @@ impl EarlyErrorHandler {
|
|||
self.handler.abort_if_errors();
|
||||
|
||||
let emitter = mk_emitter(output);
|
||||
self.handler = Handler::with_emitter(true, None, emitter);
|
||||
self.handler = Handler::with_emitter(true, None, emitter, None);
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
|
|
|
|||
|
|
@ -119,8 +119,12 @@ impl<'tcx> Tables<'tcx> {
|
|||
TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant)))
|
||||
}
|
||||
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(self.intern_ty(*ty))),
|
||||
ty::RawPtr(_) => todo!(),
|
||||
ty::Ref(_, _, _) => todo!(),
|
||||
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
|
||||
TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable()))
|
||||
}
|
||||
ty::Ref(region, ty, mutbl) => {
|
||||
TyKind::RigidTy(RigidTy::Ref(opaque(region), self.intern_ty(*ty), mutbl.stable()))
|
||||
}
|
||||
ty::FnDef(_, _) => todo!(),
|
||||
ty::FnPtr(_) => todo!(),
|
||||
ty::Dynamic(_, _, _) => todo!(),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::rustc_internal::Opaque;
|
||||
use crate::stable_mir::ty::Region;
|
||||
use crate::stable_mir::{self, ty::Ty};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -137,8 +137,6 @@ pub enum Statement {
|
|||
Nop,
|
||||
}
|
||||
|
||||
type Region = Opaque;
|
||||
|
||||
// FIXME this is incomplete
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Rvalue {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::{with, DefId};
|
||||
use super::{mir::Mutability, with, DefId};
|
||||
use crate::rustc_internal::Opaque;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
@ -11,7 +11,7 @@ impl Ty {
|
|||
}
|
||||
|
||||
type Const = Opaque;
|
||||
type Region = Opaque;
|
||||
pub(crate) type Region = Opaque;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TyKind {
|
||||
|
|
@ -29,6 +29,8 @@ pub enum RigidTy {
|
|||
Str,
|
||||
Array(Ty, Const),
|
||||
Slice(Ty),
|
||||
RawPtr(Ty, Mutability),
|
||||
Ref(Region, Ty, Mutability),
|
||||
Tuple(Vec<Ty>),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,17 +82,17 @@ impl Edition {
|
|||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 edition?
|
||||
pub fn rust_2018(self) -> bool {
|
||||
pub fn at_least_rust_2018(self) -> bool {
|
||||
self >= Edition::Edition2018
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2021 edition?
|
||||
pub fn rust_2021(self) -> bool {
|
||||
pub fn at_least_rust_2021(self) -> bool {
|
||||
self >= Edition::Edition2021
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2024 edition?
|
||||
pub fn rust_2024(self) -> bool {
|
||||
pub fn at_least_rust_2024(self) -> bool {
|
||||
self >= Edition::Edition2024
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -707,24 +707,28 @@ impl Span {
|
|||
self.ctxt().edition()
|
||||
}
|
||||
|
||||
/// Is this edition 2015?
|
||||
#[inline]
|
||||
pub fn is_rust_2015(self) -> bool {
|
||||
self.edition().is_rust_2015()
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 edition?
|
||||
#[inline]
|
||||
pub fn rust_2018(self) -> bool {
|
||||
self.edition().rust_2018()
|
||||
pub fn at_least_rust_2018(self) -> bool {
|
||||
self.edition().at_least_rust_2018()
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2021 edition?
|
||||
#[inline]
|
||||
pub fn rust_2021(self) -> bool {
|
||||
self.edition().rust_2021()
|
||||
pub fn at_least_rust_2021(self) -> bool {
|
||||
self.edition().at_least_rust_2021()
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2024 edition?
|
||||
#[inline]
|
||||
pub fn rust_2024(self) -> bool {
|
||||
self.edition().rust_2024()
|
||||
pub fn at_least_rust_2024(self) -> bool {
|
||||
self.edition().at_least_rust_2024()
|
||||
}
|
||||
|
||||
/// Returns the source callee.
|
||||
|
|
|
|||
|
|
@ -693,8 +693,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
|||
"avr" => avr::compute_abi_info(self),
|
||||
"loongarch64" => loongarch::compute_abi_info(cx, self),
|
||||
"m68k" => m68k::compute_abi_info(self),
|
||||
"mips" => mips::compute_abi_info(cx, self),
|
||||
"mips64" => mips64::compute_abi_info(cx, self),
|
||||
"mips" | "mips32r6" => mips::compute_abi_info(cx, self),
|
||||
"mips64" | "mips64r6" => mips64::compute_abi_info(cx, self),
|
||||
"powerpc" => powerpc::compute_abi_info(self),
|
||||
"powerpc64" => powerpc64::compute_abi_info(cx, self),
|
||||
"s390x" => s390x::compute_abi_info(cx, self),
|
||||
|
|
|
|||
|
|
@ -238,8 +238,8 @@ impl FromStr for InlineAsmArch {
|
|||
"powerpc64" => Ok(Self::PowerPC64),
|
||||
"hexagon" => Ok(Self::Hexagon),
|
||||
"loongarch64" => Ok(Self::LoongArch64),
|
||||
"mips" => Ok(Self::Mips),
|
||||
"mips64" => Ok(Self::Mips64),
|
||||
"mips" | "mips32r6" => Ok(Self::Mips),
|
||||
"mips64" | "mips64r6" => Ok(Self::Mips64),
|
||||
"s390x" => Ok(Self::S390x),
|
||||
"spirv" => Ok(Self::SpirV),
|
||||
"wasm32" => Ok(Self::Wasm32),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub fn target() -> Target {
|
|||
llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
|
||||
arch: "mips".into(),
|
||||
arch: "mips32r6".into(),
|
||||
options: TargetOptions {
|
||||
endian: Endian::Big,
|
||||
cpu: "mips32r6".into(),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub fn target() -> Target {
|
|||
llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
|
||||
arch: "mips".into(),
|
||||
arch: "mips32r6".into(),
|
||||
|
||||
options: TargetOptions {
|
||||
cpu: "mips32r6".into(),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub fn target() -> Target {
|
|||
llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
||||
arch: "mips64".into(),
|
||||
arch: "mips64r6".into(),
|
||||
options: TargetOptions {
|
||||
abi: "abi64".into(),
|
||||
endian: Endian::Big,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub fn target() -> Target {
|
|||
llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
|
||||
arch: "mips64".into(),
|
||||
arch: "mips64r6".into(),
|
||||
options: TargetOptions {
|
||||
abi: "abi64".into(),
|
||||
// NOTE(mips64r6) matches C toolchain
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use crate::traits::{self, ObligationCtxt};
|
||||
use crate::traits::{self, DefiningAnchor, ObligationCtxt};
|
||||
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
|
@ -80,7 +80,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||
|
||||
pub trait InferCtxtBuilderExt<'tcx> {
|
||||
fn enter_canonical_trait_query<K, R>(
|
||||
&mut self,
|
||||
self,
|
||||
canonical_key: &Canonical<'tcx, K>,
|
||||
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
|
||||
) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
|
||||
|
|
@ -108,7 +108,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
|
|||
/// have `'tcx` be free on this function so that we can talk about
|
||||
/// `K: TypeFoldable<TyCtxt<'tcx>>`.)
|
||||
fn enter_canonical_trait_query<K, R>(
|
||||
&mut self,
|
||||
self,
|
||||
canonical_key: &Canonical<'tcx, K>,
|
||||
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
|
||||
) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
|
||||
|
|
@ -117,8 +117,9 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
|
|||
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
|
||||
{
|
||||
let (infcx, key, canonical_inference_vars) =
|
||||
self.build_with_canonical(DUMMY_SP, canonical_key);
|
||||
let (infcx, key, canonical_inference_vars) = self
|
||||
.with_opaque_type_inference(DefiningAnchor::Bubble)
|
||||
.build_with_canonical(DUMMY_SP, canonical_key);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let value = operation(&ocx, key)?;
|
||||
ocx.make_canonicalized_query_response(canonical_inference_vars, value)
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
|||
|
||||
ty::Adt(def, args) => {
|
||||
let sized_crit = def.sized_constraint(ecx.tcx());
|
||||
Ok(sized_crit.arg_iter_copied(ecx.tcx(), args).collect())
|
||||
Ok(sized_crit.iter_instantiated_copied(ecx.tcx(), args).collect())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -353,7 +353,8 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
|||
// FIXME(associated_const_equality): Also add associated consts to
|
||||
// the requirements here.
|
||||
if item.kind == ty::AssocKind::Type {
|
||||
requirements.extend(tcx.item_bounds(item.def_id).arg_iter(tcx, trait_ref.args));
|
||||
requirements
|
||||
.extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, trait_ref.args));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2133,7 +2133,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
Where(
|
||||
obligation
|
||||
.predicate
|
||||
.rebind(sized_crit.arg_iter_copied(self.tcx(), args).collect()),
|
||||
.rebind(sized_crit.iter_instantiated_copied(self.tcx(), args).collect()),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue