Merge from rustc

This commit is contained in:
The Miri Conjob Bot 2023-07-20 06:38:14 +00:00
commit 7b5b87dee1
229 changed files with 1700 additions and 542 deletions

View file

@ -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"

View file

@ -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>

View file

@ -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 {

View file

@ -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),

View file

@ -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);

View file

@ -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;

View file

@ -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 =

View file

@ -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));
}

View file

@ -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),
})

View file

@ -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>,
}

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -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,

View file

@ -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" }

View file

@ -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}`

View file

@ -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.

View file

@ -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 {

View file

@ -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.

View file

@ -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 {

View file

@ -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) {

View file

@ -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();

View file

@ -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

View file

@ -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) {

View file

@ -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(

View file

@ -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");

View file

@ -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,
}

View file

@ -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 =

View file

@ -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)

View file

@ -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!(

View file

@ -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(

View file

@ -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 {

View file

@ -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.

View file

@ -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) => {

View file

@ -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),

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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()
}

View file

@ -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;
}

View file

@ -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()

View file

@ -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() {

View file

@ -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)

View file

@ -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

View file

@ -67,6 +67,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se
None,
None,
"",
None,
);
(sess, cfg)
}

View file

@ -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);

View file

@ -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
);
}

View file

@ -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| {

View file

@ -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(

View file

@ -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,
},
}

View file

@ -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
}

View file

@ -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(),
}
}
}

View file

@ -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 }
}
}

View file

@ -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

View file

@ -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,

View file

@ -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.
///

View file

@ -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,

View file

@ -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;
}
}

View file

@ -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,
}

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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))]

View file

@ -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)?;

View file

@ -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))

View file

@ -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)
}),

View file

@ -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()
}

View file

@ -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,

View file

@ -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)
}

View file

@ -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.

View file

@ -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())

View file

@ -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))

View file

@ -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)

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -57,6 +57,8 @@ pub struct Cycle {
pub alias: Option<Alias>,
#[subdiagnostic]
pub cycle_usage: Option<CycleUsage>,
#[note]
pub note_span: (),
}
#[derive(Diagnostic)]

View file

@ -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
}

View file

@ -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;
}

View file

@ -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()));

View file

@ -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);

View file

@ -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),
}
)
}

View file

@ -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)]

View file

@ -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>,

View file

@ -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)]

View file

@ -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!(),

View file

@ -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 {

View file

@ -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>),
}

View file

@ -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
}
}

View file

@ -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.

View file

@ -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),

View file

@ -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),

View file

@ -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(),

View file

@ -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(),

View file

@ -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,

View file

@ -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

View file

@ -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)

View file

@ -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));
}
}

View file

@ -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