Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
73e5f54
Move `std::io::copy` to `alloc::io`
bushrat011899 May 12, 2026
a8ef638
Add documentation based on feedback
bushrat011899 Jul 28, 2026
366ebd6
If the first_take is set to true and our first item returned None, re…
asder8215 Jul 27, 2026
8f6a09a
Library lock file maintenance
renovate-bot Aug 1, 2026
2eac8f3
Add regression test for unused_allocation on boxed comparison
chenyukang Aug 1, 2026
9890f66
implement `CmRef` for `CmRefCell`, having 2 different borrow types of…
LorrensP-2158466 Jul 31, 2026
5653258
Check `proc_macro_deps.rs` by reading it, not by including it
Zalathar Aug 1, 2026
bcc5501
Fix(lib/fs/tests): Avoid permission denials when cleaning up TempDirs…
PaulDance Jul 31, 2026
5c2400b
feat: add finalize_check to RustcForceInline attribute parser to chec…
tahadostifam Aug 1, 2026
98cc5dc
test: added testcase ui/attributes/inline/rustc-force-inline-conflict…
tahadostifam Aug 1, 2026
d662e51
Rollup merge of #160262 - renovate-bot:renovate/lock-file-maintenance…
JonathanBrouwer Aug 1, 2026
17acbd8
Rollup merge of #158548 - bushrat011899:alloc_io_copy_internals, r=cl…
JonathanBrouwer Aug 1, 2026
0489fb0
Rollup merge of #158814 - tahadostifam:taha_refactors_rustc_attr_pars…
JonathanBrouwer Aug 1, 2026
2825c03
Rollup merge of #160025 - asder8215:step_by_nth_one, r=clarfonthey
JonathanBrouwer Aug 1, 2026
4f8f88e
Rollup merge of #160271 - LorrensP-2158466:res-cm-refcell, r=petroche…
JonathanBrouwer Aug 1, 2026
68485b5
Rollup merge of #160281 - PaulDance:patches/fix-win7-set_get_permissi…
JonathanBrouwer Aug 1, 2026
661b271
Rollup merge of #160325 - Zalathar:proc-macro-deps, r=clubby789
JonathanBrouwer Aug 1, 2026
a8e864f
Rollup merge of #160334 - chenyukang:yukang-fix-134186-unused-allocat…
JonathanBrouwer Aug 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/inline.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// FIXME(jdonszelmann): merge these two parsers and error when both attributes are present here.
// note: need to model better how duplicate attr errors work when not using
// SingleAttributeParser which is what we have two of here.

use rustc_feature::AttributeStability;
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::find_attr;
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;

use super::prelude::*;
use crate::session_diagnostics::InlineForceInlineConflict;

pub(crate) struct InlineParser;

Expand Down Expand Up @@ -94,4 +92,16 @@ impl SingleAttributeParser for RustcForceInlineParser {
cx.attr_span,
))
}

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
let Some(inline_span) = find_attr!(cx.parsed_attrs, Inline(attr, span) if !matches!(attr, InlineAttr::Force { .. }) => span)
else {
return;
};

cx.emit_err(InlineForceInlineConflict {
inline_span: *inline_span,
force_inline_span: attr_span,
});
}
}
9 changes: 9 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ use rustc_target::spec::TargetTuple;
use crate::AttributeTemplate;
use crate::context::Suggestion;

#[derive(Diagnostic)]
#[diag("`#[rustc_force_inline]` and `#[inline]` cannot be used together")]
pub(crate) struct InlineForceInlineConflict {
#[primary_span]
pub force_inline_span: Span,
#[label("the inline attribute is specified here")]
pub inline_span: Span,
}

#[derive(Diagnostic)]
#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)]
pub(crate) struct BothFfiConstAndPure {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ impl Resolver<'_, '_> {
let unused_imports = visitor.unused_imports;
let mut check_redundant_imports = FxIndexSet::default();
for module in &self.local_modules {
for (_key, resolution) in self.resolutions(module.to_module()).borrow().iter() {
for (_key, resolution) in self.resolutions(module.to_module()).iter() {
if let Some(decl) = resolution.borrow().best_decl()
&& let DeclKind::Import { import, .. } = decl.kind
&& let ImportKind::Single { id, .. } = import.kind
Expand Down
32 changes: 15 additions & 17 deletions compiler/rustc_resolve/src/diagnostics/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1870,24 +1870,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// If so, we have to disambiguate the potential import suggestions by making
// the paths *global* (i.e., by prefixing them with `::`).
let needs_disambiguation =
self.resolutions(parent_scope.module).borrow().iter().any(
|(key, name_resolution)| {
if key.ns == TypeNS
&& key.ident == *ident
&& let Some(decl) = name_resolution.borrow().best_decl()
{
match decl.res() {
// No disambiguation needed if the identically named item we
// found in scope actually refers to the crate in question.
Res::Def(_, def_id) => def_id != crate_def_id,
Res::PrimTy(_) => true,
_ => false,
}
} else {
false
self.resolutions(parent_scope.module).iter().any(|(key, name_resolution)| {
if key.ns == TypeNS
&& key.ident == *ident
&& let Some(decl) = name_resolution.borrow().best_decl()
{
match decl.res() {
// No disambiguation needed if the identically named item we
// found in scope actually refers to the crate in question.
Res::Def(_, def_id) => def_id != crate_def_id,
Res::PrimTy(_) => true,
_ => false,
}
},
);
} else {
false
}
});
let mut crate_path = ThinVec::new();
if needs_disambiguation {
crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/effective_visibilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
/// including their whole reexport chains.
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
let module = self.r.expect_module(module_id.to_def_id());
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
for (_, name_resolution) in self.r.resolutions(module).iter() {
let Some(decl) = name_resolution.borrow().best_decl() else {
continue;
};
Expand Down Expand Up @@ -309,7 +309,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
) {
if self.macro_reachable.insert((module_def_id, defining_mod)) {
let module = self.r.expect_module(module_def_id.to_def_id());
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
for (_, name_resolution) in self.r.resolutions(module).iter() {
let Some(decl) = name_resolution.borrow().best_decl() else {
continue;
};
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra>>) {
for module in &self.local_modules {
for (key, resolution) in self.resolutions(module.to_module()).borrow().iter() {
for (key, resolution) in self.resolutions(module.to_module()).iter() {
let resolution = resolution.borrow();
let Some(binding) = resolution.best_decl() else { continue };

Expand Down Expand Up @@ -1481,7 +1481,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let names = match module {
ModuleOrUniformRoot::Module(module) => {
self.resolutions(module)
.borrow()
.iter()
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
if i.name == ident.name {
Expand Down Expand Up @@ -1799,7 +1798,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let import_bindings = match imported_module {
ModuleOrUniformRoot::Module(module) if module != import.parent_scope.module => self
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
let res = resolution.borrow();
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
assoc_name: Symbol,
) -> Option<DefId> {
let module = self.r.get_module(trait_def_id)?;
self.r.resolutions(module).borrow().iter().find_map(|(key, resolution)| {
self.r.resolutions(module).iter().find_map(|(key, resolution)| {
if key.ident.name != assoc_name {
return None;
}
Expand Down Expand Up @@ -648,7 +648,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
&& self
.r
.resolutions(module)
.borrow()
.iter()
.any(|(key, _r)| key.ident.name == following_seg.ident.name)
} else {
Expand Down Expand Up @@ -1164,7 +1163,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {

fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> {
let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>, item_name: Symbol| {
for resolution in r.resolutions(m).borrow().values() {
for resolution in r.resolutions(m).values() {
let Some(did) =
resolution.borrow().best_decl().and_then(|binding| binding.res().opt_def_id())
else {
Expand Down Expand Up @@ -1904,7 +1903,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let targets: Vec<_> = self
.r
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
let resolution = resolution.borrow();
Expand Down Expand Up @@ -2767,7 +2765,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let targets = self
.r
.resolutions(*module)
.borrow()
.iter()
.filter_map(|(key, res)| res.borrow().best_decl().map(|binding| (key, binding.res())))
.filter(|(_, res)| match (kind, res) {
Expand Down Expand Up @@ -2970,7 +2967,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let module = self.r.expect_module(def_id);
self.r
.resolutions(module)
.borrow()
.iter()
.any(|(key, _)| key.ident.name == following_seg.ident.name)
}
Expand Down
64 changes: 46 additions & 18 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#![recursion_limit = "256"]
// tidy-alphabetical-end

use std::cell::Ref;
use std::cell::{Ref, RefMut};
use std::collections::BTreeSet;
use std::ops::ControlFlow;
use std::sync::{Arc, OnceLock};
Expand Down Expand Up @@ -81,7 +81,7 @@ use crate::diagnostics::impls::{
ImportSuggestion, LabelSuggestion, OnUnknownData, StructCtor, Suggestion,
};
use crate::imports::{ImportResolution, NameResolutionRef};
use crate::ref_mut::{CmCell, CmRefCell};
use crate::ref_mut::{CmCell, CmRef, CmRefCell};

mod build_reduced_graph;
mod check_unused;
Expand Down Expand Up @@ -637,7 +637,7 @@ type ResolutionTable<'ra> = FxIndexMap<BindingKey, NameResolutionRef<'ra>>;

enum Resolutions<'ra> {
Local(CmRefCell<ResolutionTable<'ra>>),
Extern(OnceLock<CmRefCell<ResolutionTable<'ra>>>),
Extern(OnceLock<ResolutionTable<'ra>>),
}

impl<'ra> Resolutions<'ra> {
Expand Down Expand Up @@ -792,7 +792,7 @@ impl<'ra> Module<'ra> {
resolver: &R,
mut f: impl FnMut(&R, IdentKey, Span, Namespace, Decl<'ra>),
) {
for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() {
for (key, name_resolution) in resolver.as_ref().resolutions(self).iter() {
let name_resolution = name_resolution.borrow();
if let Some(decl) = name_resolution.best_decl() {
f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl);
Expand All @@ -805,7 +805,7 @@ impl<'ra> Module<'ra> {
resolver: &mut R,
mut f: impl FnMut(&mut R, IdentKey, Span, Namespace, Decl<'ra>),
) {
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
for (key, name_resolution) in resolver.as_mut().resolutions(self).iter() {
let name_resolution = name_resolution.borrow();
if let Some(decl) = name_resolution.best_decl() {
f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl);
Expand Down Expand Up @@ -2152,7 +2152,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
match (trait_module, assoc_item) {
(Some(trait_module), Some((name, ns))) => self
.resolutions(trait_module)
.borrow()
.iter()
.any(|(key, _name_resolution)| key.ns == ns && key.ident.name == name),
_ => true,
Expand All @@ -2177,14 +2176,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.tcx.hir_arena.alloc_slice(&import_ids)
}

fn resolutions(&self, module: Module<'ra>) -> &'ra CmRefCell<ResolutionTable<'ra>> {
fn resolutions(&self, module: Module<'ra>) -> CmRef<'ra, ResolutionTable<'ra>> {
match &module.0.0.lazy_resolutions {
Resolutions::Local(local_res) => local_res,
Resolutions::Local(local_res) => CmRef::Tracked(local_res.borrow()),
Resolutions::Extern(extern_res) => {
// as long as 1 thread is building this external table, all other threads will wait
extern_res.get_or_init(|| {
CmRefCell::new(self.build_reduced_graph_external(module.expect_extern()))
})
// It is fine to return a `CmRef::Untracked`, we never give out a `&mut`
// to an external table.
CmRef::Untracked(
// As long as 1 thread is building this external table, all other threads will wait.
extern_res
.get_or_init(|| self.build_reduced_graph_external(module.expect_extern())),
)
}
}
}

fn resolutions_mut(&self, module: Module<'ra>) -> RefMut<'ra, ResolutionTable<'ra>> {
match &module.0.0.lazy_resolutions {
Resolutions::Local(local_res) => local_res.borrow_mut(self),
Resolutions::Extern(_) => {
// We do not allow in place mutations of the external resolution table. In fact,
// we never attempt it.
unreachable!("Attempted to mutably borrow an extenral resolution table")
}
}
}
Expand All @@ -2194,7 +2207,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module: Module<'ra>,
key: BindingKey,
) -> Option<Ref<'ra, NameResolution<'ra>>> {
self.resolutions(module).borrow().get(&key).map(|resolution| resolution.0.borrow())
self.resolutions(module).get(&key).map(|resolution| resolution.0.borrow())
}

#[track_caller]
Expand All @@ -2204,7 +2217,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
key: BindingKey,
orig_ident_span: Span,
) -> NameResolutionRef<'ra> {
*self.resolutions(module).borrow_mut(self).entry(key).or_insert_with(|| {
*self.resolutions_mut(module).entry(key).or_insert_with(|| {
self.arenas.alloc_name_resolution(NameResolution::new(orig_ident_span))
})
}
Expand Down Expand Up @@ -2915,6 +2928,24 @@ mod ref_mut {
}
}

pub(crate) enum CmRef<'b, T> {
/// A tracked borrow of a [`CmRefCell`]
Tracked(Ref<'b, T>),
/// An untracked or normal reference (not dynamically borrow-checked by `RefCell`)
Untracked(&'b T),
}

impl<'b, T> Deref for CmRef<'b, T> {
type Target = T;

fn deref(&self) -> &Self::Target {
match self {
CmRef::Tracked(r) => r,
CmRef::Untracked(r) => r,
}
}
}

/// A wrapper around a [`RefCell`] that only allows writes (mutable borrows) based on a condition in the resolver.
#[derive(Default)]
pub(crate) struct CmRefCell<T>(RefCell<T>);
Expand All @@ -2926,10 +2957,7 @@ mod ref_mut {

#[track_caller]
pub(crate) fn borrow_mut<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> RefMut<'_, T> {
if r.assert_speculative {
panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution");
}
self.0.borrow_mut()
self.try_borrow_mut(r).unwrap()
}

#[track_caller]
Expand Down
Loading
Loading