diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 553ef676154b..f0e151d25778 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -46,7 +46,7 @@ jobs:
# If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml.
calculate_matrix:
name: Calculate job matrix
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
outputs:
jobs: ${{ steps.jobs.outputs.jobs }}
run_type: ${{ steps.jobs.outputs.run_type }}
@@ -243,7 +243,7 @@ jobs:
# when a workflow is successful listening to webhooks only in our current bors implementation (homu).
outcome:
name: bors build finished
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
needs: [ calculate_matrix, job ]
# !cancelled() executes the job regardless of whether the previous jobs passed or failed
if: ${{ !cancelled() && contains(fromJSON('["auto", "try"]'), needs.calculate_matrix.outputs.run_type) }}
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
index b7b5a03bd41f..98d8c14f7d18 100644
--- a/.github/workflows/dependencies.yml
+++ b/.github/workflows/dependencies.yml
@@ -27,7 +27,7 @@ jobs:
not-waiting-on-bors:
if: github.repository_owner == 'rust-lang'
name: skip if S-waiting-on-bors
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -47,7 +47,7 @@ jobs:
if: github.repository_owner == 'rust-lang'
name: update dependencies
needs: not-waiting-on-bors
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- name: checkout the source code
uses: actions/checkout@v4
@@ -94,7 +94,7 @@ jobs:
if: github.repository_owner == 'rust-lang'
name: amend PR
needs: update
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
permissions:
contents: write
pull-requests: write
diff --git a/Cargo.lock b/Cargo.lock
index 3f05b44ccfa7..1fd288af3a13 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3722,6 +3722,7 @@ dependencies = [
"rustc_fluent_macro",
"rustc_hir",
"rustc_index",
+ "rustc_lexer",
"rustc_lint_defs",
"rustc_macros",
"rustc_serialize",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 69c3e0553d48..cec868e5c8e5 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1322,11 +1322,15 @@ pub fn to_ty(&self) -> Option
> {
}
pub fn precedence(&self) -> ExprPrecedence {
- match self.kind {
- ExprKind::Closure(..) => ExprPrecedence::Closure,
+ match &self.kind {
+ ExprKind::Closure(closure) => {
+ match closure.fn_decl.output {
+ FnRetTy::Default(_) => ExprPrecedence::Jump,
+ FnRetTy::Ty(_) => ExprPrecedence::Unambiguous,
+ }
+ }
ExprKind::Break(..)
- | ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Yield(..)
| ExprKind::Yeet(..)
@@ -1360,6 +1364,7 @@ pub fn precedence(&self) -> ExprPrecedence {
| ExprKind::Block(..)
| ExprKind::Call(..)
| ExprKind::ConstBlock(_)
+ | ExprKind::Continue(..)
| ExprKind::Field(..)
| ExprKind::ForLoop { .. }
| ExprKind::FormatArgs(..)
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 0d8042005a81..1d4b01aa94c9 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -231,8 +231,7 @@ pub fn can_continue_expr_unambiguously(&self) -> bool {
#[derive(Clone, Copy, PartialEq, PartialOrd)]
pub enum ExprPrecedence {
- Closure,
- // return, break, yield
+ // return, break, yield, closures
Jump,
// = += -= *= /= %= &= |= ^= <<= >>=
Assign,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index d39fbf32921a..60f7770d3f79 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -795,7 +795,6 @@ fn apply_member_constraint(
// If the member region lives in a higher universe, we currently choose
// the most conservative option by leaving it unchanged.
-
if !self.constraint_sccs().annotation(scc).min_universe().is_root() {
return;
}
@@ -823,12 +822,14 @@ fn apply_member_constraint(
}
debug!(?choice_regions, "after ub");
- // At this point we can pick any member of `choice_regions`, but to avoid potential
- // non-determinism we will pick the *unique minimum* choice.
+ // At this point we can pick any member of `choice_regions` and would like to choose
+ // it to be a small as possible. To avoid potential non-determinism we will pick the
+ // smallest such choice.
//
// Because universal regions are only partially ordered (i.e, not every two regions are
// comparable), we will ignore any region that doesn't compare to all others when picking
// the minimum choice.
+ //
// For example, consider `choice_regions = ['static, 'a, 'b, 'c, 'd, 'e]`, where
// `'static: 'a, 'static: 'b, 'a: 'c, 'b: 'c, 'c: 'd, 'c: 'e`.
// `['d, 'e]` are ignored because they do not compare - the same goes for `['a, 'b]`.
@@ -853,6 +854,8 @@ fn apply_member_constraint(
return;
};
+ // As we require `'scc: 'min_choice`, we have definitely already computed
+ // its `scc_values` at this point.
let min_choice_scc = self.constraint_sccs.scc(min_choice);
debug!(?min_choice, ?min_choice_scc);
if self.scc_values.add_region(scc, min_choice_scc) {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 4be4291021df..eaab3362c7e8 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -294,7 +294,7 @@ fn dep_symbol_lookup_fn(
// search path.
for &cnum in crate_info.used_crates.iter().rev() {
let src = &crate_info.used_crate_source[&cnum];
- match data[cnum.as_usize() - 1] {
+ match data[cnum] {
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
Linkage::Static => {
let name = crate_info.crate_name[&cnum];
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index d62632d14316..9a2bfd95562f 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -56,25 +56,6 @@ pub enum LLVMRustResult {
Failure,
}
-// Rust version of the C struct with the same name in rustc_llvm/llvm-wrapper/RustWrapper.cpp.
-#[repr(C)]
-pub struct LLVMRustCOFFShortExport {
- pub name: *const c_char,
- pub ordinal_present: bool,
- /// value of `ordinal` only important when `ordinal_present` is true
- pub ordinal: u16,
-}
-
-impl LLVMRustCOFFShortExport {
- pub fn new(name: *const c_char, ordinal: Option) -> LLVMRustCOFFShortExport {
- LLVMRustCOFFShortExport {
- name,
- ordinal_present: ordinal.is_some(),
- ordinal: ordinal.unwrap_or(0),
- }
- }
-}
-
/// Translation of LLVM's MachineTypes enum, defined in llvm\include\llvm\BinaryFormat\COFF.h.
///
/// We include only architectures supported on Windows.
@@ -2347,15 +2328,6 @@ pub fn LLVMRustArchiveMemberNew<'a>(
) -> &'a mut RustArchiveMember<'a>;
pub fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>);
- pub fn LLVMRustWriteImportLibrary(
- ImportName: *const c_char,
- Path: *const c_char,
- Exports: *const LLVMRustCOFFShortExport,
- NumExports: usize,
- Machine: u16,
- MinGW: bool,
- ) -> LLVMRustResult;
-
pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index f4f6161ebbcc..4bc064528f3f 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -15,7 +15,7 @@
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
@@ -234,8 +234,6 @@ pub fn each_linked_rlib(
crate_type: Option,
f: &mut dyn FnMut(CrateNum, &Path),
) -> Result<(), errors::LinkRlibError> {
- let crates = info.used_crates.iter();
-
let fmts = if let Some(crate_type) = crate_type {
let Some(fmts) = info.dependency_formats.get(&crate_type) else {
return Err(errors::LinkRlibError::MissingFormat);
@@ -261,8 +259,9 @@ pub fn each_linked_rlib(
info.dependency_formats.first().unwrap().1
};
- for &cnum in crates {
- match fmts.get(cnum.as_usize() - 1) {
+ let used_dep_crates = info.used_crates.iter();
+ for &cnum in used_dep_crates {
+ match fmts.get(cnum) {
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
Some(_) => {}
None => return Err(errors::LinkRlibError::MissingFormat),
@@ -624,7 +623,7 @@ fn link_staticlib(
let mut all_rust_dylibs = vec![];
for &cnum in crates {
- match fmts.get(cnum.as_usize() - 1) {
+ match fmts.get(cnum) {
Some(&Linkage::Dynamic) => {}
_ => continue,
}
@@ -1039,22 +1038,22 @@ fn is_illegal_instruction(_status: &ExitStatus) -> bool {
Err(e) => {
let linker_not_found = e.kind() == io::ErrorKind::NotFound;
- if linker_not_found {
- sess.dcx().emit_err(errors::LinkerNotFound { linker_path, error: e });
+ let err = if linker_not_found {
+ sess.dcx().emit_err(errors::LinkerNotFound { linker_path, error: e })
} else {
sess.dcx().emit_err(errors::UnableToExeLinker {
linker_path,
error: e,
command_formatted: format!("{cmd:?}"),
- });
- }
+ })
+ };
if sess.target.is_like_msvc && linker_not_found {
sess.dcx().emit_note(errors::MsvcMissingLinker);
sess.dcx().emit_note(errors::CheckInstalledVisualStudio);
sess.dcx().emit_note(errors::InsufficientVSCodeProduct);
}
- FatalError.raise();
+ err.raise_fatal();
}
}
@@ -2361,8 +2360,8 @@ fn linker_with_args(
.crate_info
.native_libraries
.iter()
- .filter_map(|(cnum, libraries)| {
- (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
+ .filter_map(|(&cnum, libraries)| {
+ (dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
})
.flatten()
.collect::>();
@@ -2754,7 +2753,7 @@ fn add_upstream_rust_crates(
// (e.g. `libstd` when `-C prefer-dynamic` is used).
// FIXME: `dependency_formats` can report `profiler_builtins` as `NotLinked` for some
// reason, it shouldn't do that because `profiler_builtins` should indeed be linked.
- let linkage = data[cnum.as_usize() - 1];
+ let linkage = data[cnum];
let link_static_crate = linkage == Linkage::Static
|| (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked)
&& (codegen_results.crate_info.compiler_builtins == Some(cnum)
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 8a2f3d73bc15..3c6513ca26bb 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1744,15 +1744,10 @@ fn for_each_exported_symbols_include_dep<'tcx>(
crate_type: CrateType,
mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
) {
- for &(symbol, info) in tcx.exported_symbols(LOCAL_CRATE).iter() {
- callback(symbol, info, LOCAL_CRATE);
- }
-
let formats = tcx.dependency_formats(());
let deps = &formats[&crate_type];
- for (index, dep_format) in deps.iter().enumerate() {
- let cnum = CrateNum::new(index + 1);
+ for (cnum, dep_format) in deps.iter_enumerated() {
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 5a1a873d4bde..93f3d2ab911f 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -4,7 +4,6 @@
use std::fmt::Write;
use rustc_ast_pretty::pprust as pprust_ast;
-use rustc_errors::FatalError;
use rustc_middle::bug;
use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
use rustc_middle::ty::{self, TyCtxt};
@@ -311,9 +310,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
let tcx = ex.tcx();
let mut out = String::new();
rustc_hir_analysis::check_crate(tcx);
- if tcx.dcx().has_errors().is_some() {
- FatalError.raise();
- }
+ tcx.dcx().abort_if_errors();
debug!("pretty printing THIR tree");
for did in tcx.hir().body_owners() {
let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did));
@@ -324,9 +321,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
let tcx = ex.tcx();
let mut out = String::new();
rustc_hir_analysis::check_crate(tcx);
- if tcx.dcx().has_errors().is_some() {
- FatalError.raise();
- }
+ tcx.dcx().abort_if_errors();
debug!("pretty printing THIR flat");
for did in tcx.hir().body_owners() {
let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did));
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 06bae57638f3..66b9adbead0b 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -16,6 +16,7 @@ rustc_error_messages = { path = "../rustc_error_messages" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
+rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index f63188402fe7..977721a5b8a2 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -19,6 +19,7 @@
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
use rustc_error_messages::{FluentArgs, SpanLabel};
+use rustc_lexer;
use rustc_lint_defs::pluralize;
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::source_map::SourceMap;
@@ -1698,9 +1699,14 @@ fn emit_messages_default_inner(
if let Some(source_string) =
line.line_index.checked_sub(1).and_then(|l| file.get_line(l))
{
+ // Whitespace can only be removed (aka considered leading)
+ // if the lexer considers it whitespace.
+ // non-rustc_lexer::is_whitespace() chars are reported as an
+ // error (ex. no-break-spaces \u{a0}), and thus can't be considered
+ // for removal during error reporting.
let leading_whitespace = source_string
.chars()
- .take_while(|c| c.is_whitespace())
+ .take_while(|c| rustc_lexer::is_whitespace(*c))
.map(|c| {
match c {
// Tabs are displayed as 4 spaces
@@ -1709,7 +1715,7 @@ fn emit_messages_default_inner(
}
})
.sum();
- if source_string.chars().any(|c| !c.is_whitespace()) {
+ if source_string.chars().any(|c| !rustc_lexer::is_whitespace(c)) {
whitespace_margin = min(whitespace_margin, leading_whitespace);
}
}
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 4b9f62fa764c..63e5ebb8688f 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -912,11 +912,20 @@ pub struct BuiltinAttribute {
rustc_attr!(
rustc_deny_explicit_impl,
AttributeType::Normal,
- template!(List: "implement_via_object = (true|false)"),
+ template!(Word),
ErrorFollowing,
EncodeCrossCrate::No,
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
),
+ rustc_attr!(
+ rustc_do_not_implement_via_object,
+ AttributeType::Normal,
+ template!(Word),
+ ErrorFollowing,
+ EncodeCrossCrate::No,
+ "#[rustc_do_not_implement_via_object] opts out of the automatic trait impl for trait objects \
+ (`impl Trait for dyn Trait`)"
+ ),
rustc_attr!(
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
ErrorFollowing, EncodeCrossCrate::Yes,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 398b694ae6bd..8cea269f2982 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1943,11 +1943,15 @@ pub struct Expr<'hir> {
impl Expr<'_> {
pub fn precedence(&self) -> ExprPrecedence {
- match self.kind {
- ExprKind::Closure { .. } => ExprPrecedence::Closure,
+ match &self.kind {
+ ExprKind::Closure(closure) => {
+ match closure.fn_decl.output {
+ FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump,
+ FnRetTy::Return(_) => ExprPrecedence::Unambiguous,
+ }
+ }
ExprKind::Break(..)
- | ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Yield(..)
| ExprKind::Become(..) => ExprPrecedence::Jump,
@@ -1973,6 +1977,7 @@ pub fn precedence(&self) -> ExprPrecedence {
| ExprKind::Block(..)
| ExprKind::Call(..)
| ExprKind::ConstBlock(_)
+ | ExprKind::Continue(..)
| ExprKind::Field(..)
| ExprKind::If(..)
| ExprKind::Index(..)
@@ -1990,7 +1995,7 @@ pub fn precedence(&self) -> ExprPrecedence {
| ExprKind::UnsafeBinderCast(..)
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
- ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
+ ExprKind::DropTemps(expr, ..) => expr.precedence(),
}
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 3aad4bafeb5a..1be4aa2f63ac 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -206,7 +206,9 @@ fn check_object_overlap<'tcx>(
// so this is valid.
} else {
let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id);
- if supertrait_def_ids.any(|d| d == trait_def_id) {
+ if supertrait_def_ids
+ .any(|d| d == trait_def_id && tcx.trait_def(d).implement_via_object)
+ {
let span = tcx.def_span(impl_def_id);
return Err(struct_span_code_err!(
tcx.dcx(),
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 5e662bb96bc4..ada70117b626 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1261,49 +1261,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
no_dups.then_some(list)
});
- let mut deny_explicit_impl = false;
- let mut implement_via_object = true;
- if let Some(attr) = tcx.get_attr(def_id, sym::rustc_deny_explicit_impl) {
- deny_explicit_impl = true;
- let mut seen_attr = false;
- for meta in attr.meta_item_list().iter().flatten() {
- if let Some(meta) = meta.meta_item()
- && meta.name_or_empty() == sym::implement_via_object
- && let Some(lit) = meta.name_value_literal()
- {
- if seen_attr {
- tcx.dcx().span_err(meta.span, "duplicated `implement_via_object` meta item");
- }
- seen_attr = true;
-
- match lit.symbol {
- kw::True => {
- implement_via_object = true;
- }
- kw::False => {
- implement_via_object = false;
- }
- _ => {
- tcx.dcx().span_err(
- meta.span,
- format!(
- "unknown literal passed to `implement_via_object` attribute: {}",
- lit.symbol
- ),
- );
- }
- }
- } else {
- tcx.dcx().span_err(
- meta.span(),
- format!("unknown meta item passed to `rustc_deny_explicit_impl` {meta:?}"),
- );
- }
- }
- if !seen_attr {
- tcx.dcx().span_err(attr.span, "missing `implement_via_object` meta item");
- }
- }
+ let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
+ let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
ty::TraitDef {
def_id: def_id.to_def_id(),
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index fb5995584905..ace114f1ffa0 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1329,6 +1329,15 @@ fn check_for_shadowed_autorefd_method(
mutbl: hir::Mutability,
track_unstable_candidates: bool,
) -> Result<(), MethodError<'tcx>> {
+ // The errors emitted by this function are part of
+ // the arbitrary self types work, and should not impact
+ // other users.
+ if !self.tcx.features().arbitrary_self_types()
+ && !self.tcx.features().arbitrary_self_types_pointers()
+ {
+ return Ok(());
+ }
+
// We don't want to remember any of the diagnostic hints from this
// shadow search, but we do need to provide Some/None for the
// unstable_candidates in order to reflect the behavior of the
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 02905e632ab8..aff66e48fbbe 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -19,7 +19,7 @@
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
-use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
+use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers;
use rustc_parse::{
new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr,
@@ -770,15 +770,14 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>(
// subtyping for GlobalCtxt::enter to be allowed.
let inner: Box<
dyn for<'tcx> FnOnce(
- &'tcx Compiler,
+ &'tcx Session,
+ CurrentGcx,
&'tcx OnceLock>,
&'tcx WorkerLocal>,
&'tcx WorkerLocal>,
F,
) -> T,
- > = Box::new(move |compiler, gcx_cell, arena, hir_arena, f| {
- let sess = &compiler.sess;
-
+ > = Box::new(move |sess, current_gcx, gcx_cell, arena, hir_arena, f| {
TyCtxt::create_global_ctxt(
gcx_cell,
sess,
@@ -796,7 +795,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>(
incremental,
),
providers.hooks,
- compiler.current_gcx.clone(),
+ current_gcx,
|tcx| {
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
assert_eq!(feed.key(), LOCAL_CRATE);
@@ -804,7 +803,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>(
let feed = tcx.feed_unit_query();
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
- sess,
+ tcx.sess,
&pre_configured_attrs,
crate_name,
)));
@@ -819,7 +818,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>(
)
});
- inner(compiler, &gcx_cell, &arena, &hir_arena, f)
+ inner(&compiler.sess, compiler.current_gcx.clone(), &gcx_cell, &arena, &hir_arena, f)
}
/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 0c58c804353f..c0371b1f606d 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -4,7 +4,7 @@
use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagMessage;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
use rustc_middle::ty::{
@@ -444,7 +444,25 @@ fn lint_fn_pointer<'tcx>(
let (l_ty, l_ty_refs) = peel_refs(l_ty);
let (r_ty, r_ty_refs) = peel_refs(r_ty);
- if !l_ty.is_fn() || !r_ty.is_fn() {
+ if l_ty.is_fn() && r_ty.is_fn() {
+ // both operands are function pointers, fallthrough
+ } else if let ty::Adt(l_def, l_args) = l_ty.kind()
+ && let ty::Adt(r_def, r_args) = r_ty.kind()
+ && cx.tcx.is_lang_item(l_def.did(), LangItem::Option)
+ && cx.tcx.is_lang_item(r_def.did(), LangItem::Option)
+ && let Some(l_some_arg) = l_args.get(0)
+ && let Some(r_some_arg) = r_args.get(0)
+ && l_some_arg.expect_ty().is_fn()
+ && r_some_arg.expect_ty().is_fn()
+ {
+ // both operands are `Option<{function ptr}>`
+ return cx.emit_span_lint(
+ UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
+ e.span,
+ UnpredictableFunctionPointerComparisons::Warn,
+ );
+ } else {
+ // types are not function pointers, nothing to do
return;
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index b79205ff946d..36441a95adbf 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1796,56 +1796,6 @@ extern "C" LLVMValueRef LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS,
return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS)));
}
-// This struct contains all necessary info about a symbol exported from a DLL.
-struct LLVMRustCOFFShortExport {
- const char *name;
- bool ordinal_present;
- // The value of `ordinal` is only meaningful if `ordinal_present` is true.
- uint16_t ordinal;
-};
-
-// Machine must be a COFF machine type, as defined in PE specs.
-extern "C" LLVMRustResult
-LLVMRustWriteImportLibrary(const char *ImportName, const char *Path,
- const LLVMRustCOFFShortExport *Exports,
- size_t NumExports, uint16_t Machine, bool MinGW) {
- std::vector ConvertedExports;
- ConvertedExports.reserve(NumExports);
-
- for (size_t i = 0; i < NumExports; ++i) {
- bool ordinal_present = Exports[i].ordinal_present;
- uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
- ConvertedExports.push_back(llvm::object::COFFShortExport{
- Exports[i].name, // Name
- std::string{}, // ExtName
- std::string{}, // SymbolName
- std::string{}, // AliasTarget
-#if LLVM_VERSION_GE(19, 0)
- std::string{}, // ExportAs
-#endif
- ordinal, // Ordinal
- ordinal_present, // Noname
- false, // Data
- false, // Private
- false // Constant
- });
- }
-
- auto Error = llvm::object::writeImportLibrary(
- ImportName, Path, ConvertedExports,
- static_cast(Machine), MinGW);
- if (Error) {
- std::string errorString;
- auto stream = llvm::raw_string_ostream(errorString);
- stream << Error;
- stream.flush();
- LLVMRustSetLastError(errorString.c_str());
- return LLVMRustResult::Failure;
- } else {
- return LLVMRustResult::Success;
- }
-}
-
// Transfers ownership of DiagnosticHandler unique_ptr to the caller.
extern "C" DiagnosticHandler *
LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index e8de0acb7c9f..582c2215d92e 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -52,7 +52,8 @@
//! than finding a number of solutions (there are normally quite a few).
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::CrateNum;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
use rustc_middle::ty::TyCtxt;
@@ -84,7 +85,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
let sess = &tcx.sess;
if !sess.opts.output_types.should_codegen() {
- return Vec::new();
+ return IndexVec::new();
}
let preferred_linkage = match ty {
@@ -131,7 +132,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
match preferred_linkage {
// If the crate is not linked, there are no link-time dependencies.
- Linkage::NotLinked => return Vec::new(),
+ Linkage::NotLinked => return IndexVec::new(),
Linkage::Static => {
// Attempt static linkage first. For dylibs and executables, we may be
// able to retry below with dynamic linkage.
@@ -156,7 +157,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
}
sess.dcx().emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
}
- return Vec::new();
+ return IndexVec::new();
}
}
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
@@ -210,19 +211,32 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
// Collect what we've got so far in the return vector.
let last_crate = tcx.crates(()).len();
- let mut ret = (1..last_crate + 1)
- .map(|cnum| match formats.get(&CrateNum::new(cnum)) {
- Some(&RequireDynamic) => Linkage::Dynamic,
- Some(&RequireStatic) => Linkage::IncludedFromDylib,
- None => Linkage::NotLinked,
- })
- .collect::>();
+ let mut ret = IndexVec::new();
+
+ // We need to fill in something for LOCAL_CRATE as IndexVec is a dense map.
+ // Linkage::Static semantically the most correct thing to use as the local
+ // crate is always statically linked into the linker output, even when
+ // linking a dylib. Using Linkage::Static also allow avoiding special cases
+ // for LOCAL_CRATE in some places.
+ assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE);
+
+ for cnum in 1..last_crate + 1 {
+ let cnum = CrateNum::new(cnum);
+ assert_eq!(
+ ret.push(match formats.get(&cnum) {
+ Some(&RequireDynamic) => Linkage::Dynamic,
+ Some(&RequireStatic) => Linkage::IncludedFromDylib,
+ None => Linkage::NotLinked,
+ }),
+ cnum
+ );
+ }
// Run through the dependency list again, and add any missing libraries as
// static libraries.
//
// If the crate hasn't been included yet and it's not actually required
- // (e.g., it's an allocator) then we skip it here as well.
+ // (e.g., it's a panic runtime) then we skip it here as well.
for &cnum in tcx.crates(()).iter() {
let src = tcx.used_crate_source(cnum);
if src.dylib.is_none()
@@ -232,7 +246,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
assert!(src.rlib.is_some() || src.rmeta.is_some());
info!("adding staticlib: {}", tcx.crate_name(cnum));
add_library(tcx, cnum, RequireStatic, &mut formats, &mut unavailable_as_static);
- ret[cnum.as_usize() - 1] = Linkage::Static;
+ ret[cnum] = Linkage::Static;
}
}
@@ -240,8 +254,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
// artifact which means that we may need to inject dependencies of some
// form.
//
- // Things like allocators and panic runtimes may not have been activated
- // quite yet, so do so here.
+ // Things like panic runtimes may not have been activated quite yet, so do so here.
activate_injected_dep(CStore::from_tcx(tcx).injected_panic_runtime(), &mut ret, &|cnum| {
tcx.is_panic_runtime(cnum)
});
@@ -252,8 +265,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
//
// For situations like this, we perform one last pass over the dependencies,
// making sure that everything is available in the requested format.
- for (cnum, kind) in ret.iter().enumerate() {
- let cnum = CrateNum::new(cnum + 1);
+ for (cnum, kind) in ret.iter_enumerated() {
+ if cnum == LOCAL_CRATE {
+ continue;
+ }
let src = tcx.used_crate_source(cnum);
match *kind {
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
@@ -334,18 +349,21 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option Linkage::Static,
- CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
- })
- .collect::>();
+ let mut ret = IndexVec::new();
+ assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE);
+ for &cnum in tcx.crates(()) {
+ assert_eq!(
+ ret.push(match tcx.dep_kind(cnum) {
+ CrateDepKind::Explicit => Linkage::Static,
+ CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
+ }),
+ cnum
+ );
+ }
- // Our allocator/panic runtime may not have been linked above if it wasn't
- // explicitly linked, which is the case for any injected dependency. Handle
- // that here and activate them.
+ // Our panic runtime may not have been linked above if it wasn't explicitly
+ // linked, which is the case for any injected dependency. Handle that here
+ // and activate it.
activate_injected_dep(CStore::from_tcx(tcx).injected_panic_runtime(), &mut ret, &|cnum| {
tcx.is_panic_runtime(cnum)
});
@@ -367,8 +385,7 @@ fn activate_injected_dep(
list: &mut DependencyList,
replaces_injected: &dyn Fn(CrateNum) -> bool,
) {
- for (i, slot) in list.iter().enumerate() {
- let cnum = CrateNum::new(i + 1);
+ for (cnum, slot) in list.iter_enumerated() {
if !replaces_injected(cnum) {
continue;
}
@@ -377,25 +394,23 @@ fn activate_injected_dep(
}
}
if let Some(injected) = injected {
- let idx = injected.as_usize() - 1;
- assert_eq!(list[idx], Linkage::NotLinked);
- list[idx] = Linkage::Static;
+ assert_eq!(list[injected], Linkage::NotLinked);
+ list[injected] = Linkage::Static;
}
}
-// After the linkage for a crate has been determined we need to verify that
-// there's only going to be one allocator in the output.
-fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
+/// After the linkage for a crate has been determined we need to verify that
+/// there's only going to be one panic runtime in the output.
+fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
let sess = &tcx.sess;
if list.is_empty() {
return;
}
let mut panic_runtime = None;
- for (i, linkage) in list.iter().enumerate() {
+ for (cnum, linkage) in list.iter_enumerated() {
if let Linkage::NotLinked = *linkage {
continue;
}
- let cnum = CrateNum::new(i + 1);
if tcx.is_panic_runtime(cnum) {
if let Some((prev, _)) = panic_runtime {
@@ -431,11 +446,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
// strategy. If the dep isn't linked, we ignore it, and if our strategy
// is abort then it's compatible with everything. Otherwise all crates'
// panic strategy must match our own.
- for (i, linkage) in list.iter().enumerate() {
+ for (cnum, linkage) in list.iter_enumerated() {
if let Linkage::NotLinked = *linkage {
continue;
}
- let cnum = CrateNum::new(i + 1);
if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) {
continue;
}
@@ -450,13 +464,16 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
});
}
- let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
- if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
- sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
- crate_name: tcx.crate_name(cnum),
- found_strategy: found_drop_strategy,
- desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
- });
+ // panic_in_drop_strategy isn't allowed for LOCAL_CRATE
+ if cnum != LOCAL_CRATE {
+ let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
+ if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
+ sess.dcx().emit_err(IncompatiblePanicInDropStrategy {
+ crate_name: tcx.crate_name(cnum),
+ found_strategy: found_drop_strategy,
+ desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
+ });
+ }
}
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 90b1d2952c59..c2b5e318bda7 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1474,7 +1474,7 @@ fn get_dylib_dependency_formats<'tcx>(
) -> &'tcx [(CrateNum, LinkagePreference)] {
tcx.arena.alloc_from_iter(
self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
- let cnum = CrateNum::new(i + 1);
+ let cnum = CrateNum::new(i + 1); // We skipped LOCAL_CRATE when encoding
link.map(|link| (self.cnum_map[cnum], link))
}),
)
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index fff6f3f804fc..c538ab99fb54 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2165,12 +2165,14 @@ fn encode_dylib_dependency_formats(&mut self) -> LazyArray