Skip to content

Rollup of 8 pull requests #141944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
200d742
Clarify &mut-methods' docs on sync::OnceLock
lukaslueg May 6, 2025
f023a69
Async drop - type instead of async drop fn and incorrect drop signatu…
azhogin May 28, 2025
bb063e6
Factor out repeated code into `is_mod_inherent`.
nnethercote May 29, 2025
176c34a
Invert the sense of `is_not_macro_export`.
nnethercote May 29, 2025
c5e758d
Fixed a typo in `ManuallyDrop`'s doc
neeko-cat Jun 1, 2025
d2d0f62
Don't declare variables in ExprKind::Let in invalid positions
compiler-errors Jun 2, 2025
4a803d2
Suppress redundant error
compiler-errors Jun 2, 2025
87054fc
Add missing 2015 edition directives
Veykril Jun 2, 2025
aba70e8
Add missing `dyn` keywords to tests that do not test for them
Veykril Jun 2, 2025
a5f7d44
add test for 141764
jdonszelmann Jun 2, 2025
2e527f0
fix bug where borrowck tries to describe a name from a macro in anoth…
jdonszelmann Jun 2, 2025
8b5b6d0
add fixme to improve error matching
jdonszelmann Jun 2, 2025
8747ccb
Overhaul `UsePath`.
nnethercote May 29, 2025
55f7571
Rollup merge of #140715 - lukaslueg:oncecellsyncdocs, r=tgross35
matthiaskrgr Jun 3, 2025
aed1171
Rollup merge of #141677 - azhogin:azhogin/async-drop-unexpected-type-…
matthiaskrgr Jun 3, 2025
8db6881
Rollup merge of #141741 - nnethercote:overhaul-UsePath, r=petrochenkov
matthiaskrgr Jun 3, 2025
6a5459e
Rollup merge of #141873 - neeko-cat:patch-1, r=tgross35
matthiaskrgr Jun 3, 2025
69ebe39
Rollup merge of #141876 - compiler-errors:missing-let-ty, r=SparrowLii
matthiaskrgr Jun 3, 2025
f616453
Rollup merge of #141886 - ferrocene:lw/2015-edition-directives, r=com…
matthiaskrgr Jun 3, 2025
d7fcb09
Rollup merge of #141889 - ferrocene:lw/missing-dyn-kw, r=petrochenkov
matthiaskrgr Jun 3, 2025
f3622ea
Rollup merge of #141891 - jdonszelmann:fix-141764, r=jieyouxu
matthiaskrgr Jun 3, 2025
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
22 changes: 19 additions & 3 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def::{DefKind, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
Expand Down Expand Up @@ -527,7 +528,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
UseTreeKind::Glob => {
let res = self.expect_full_res(id);
let res = smallvec![self.lower_res(res)];
let res = self.lower_res(res);
// Put the result in the appropriate namespace.
let res = match res {
Res::Def(DefKind::Mod | DefKind::Trait, _) => {
PerNS { type_ns: Some(res), value_ns: None, macro_ns: None }
}
Res::Def(DefKind::Enum, _) => {
PerNS { type_ns: None, value_ns: Some(res), macro_ns: None }
}
Res::Err => {
// Propagate the error to all namespaces, just to be sure.
let err = Some(Res::Err);
PerNS { type_ns: err, value_ns: err, macro_ns: err }
}
_ => span_bug!(path.span, "bad glob res {:?}", res),
};
let path = Path { segments, span: path.span, tokens: None };
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Glob)
Expand Down Expand Up @@ -601,7 +617,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} else {
// For non-empty lists we can just drop all the data, the prefix is already
// present in HIR as a part of nested imports.
self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span })
self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span })
};
hir::ItemKind::Use(path, hir::UseKind::ListStem)
}
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_session::parse::{add_feature_diagnostics, feature_err};
use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, DesugaringKind, Span};
use smallvec::{SmallVec, smallvec};
use smallvec::SmallVec;
use thin_vec::ThinVec;
use tracing::{debug, instrument, trace};

Expand Down Expand Up @@ -705,14 +705,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
}

fn lower_import_res(&mut self, id: NodeId, span: Span) -> SmallVec<[Res; 3]> {
let res = self.resolver.get_import_res(id).present_items();
let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect();
if res.is_empty() {
fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS<Option<Res>> {
let per_ns = self.resolver.get_import_res(id);
let per_ns = per_ns.map(|res| res.map(|res| self.lower_res(res)));
if per_ns.is_empty() {
// Propagate the error to all namespaces, just to be sure.
self.dcx().span_delayed_bug(span, "no resolution for an import");
return smallvec![Res::Err];
let err = Some(Res::Err);
return PerNS { type_ns: err, value_ns: err, macro_ns: err };
}
res
per_ns
}

fn make_lang_item_qpath(
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::sync::Arc;

use rustc_ast::{self as ast, *};
use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::def::{DefKind, PartialRes, PerNS, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, GenericArg};
use rustc_middle::{span_bug, ty};
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
use smallvec::{SmallVec, smallvec};
use smallvec::smallvec;
use tracing::{debug, instrument};

use super::errors::{
Expand Down Expand Up @@ -226,11 +226,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

pub(crate) fn lower_use_path(
&mut self,
res: SmallVec<[Res; 3]>,
res: PerNS<Option<Res>>,
p: &Path,
param_mode: ParamMode,
) -> &'hir hir::UsePath<'hir> {
assert!((1..=3).contains(&res.len()));
assert!(!res.is_empty());
self.arena.alloc(hir::UsePath {
res,
segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
Expand Down
24 changes: 16 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,14 +840,22 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
} else {
bug!("not an upvar")
};
err.span_label(
*span,
format!(
"calling `{}` requires mutable binding due to {}",
self.describe_place(the_place_err).unwrap(),
reason
),
);
// sometimes we deliberately don't store the name of a place when coming from a macro in
// another crate. We generally want to limit those diagnostics a little, to hide
// implementation details (such as those from pin!() or format!()). In that case show a
// slightly different error message, or none at all if something else happened. In other
// cases the message is likely not useful.
if let Some(place_name) = self.describe_place(the_place_err) {
err.span_label(
*span,
format!("calling `{place_name}` requires mutable binding due to {reason}"),
);
} else if span.from_expansion() {
err.span_label(
*span,
format!("a call in this macro requires a mutable binding due to {reason}",),
);
}
}
}

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ macro_rules! arena_types {
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
[] attribute: rustc_hir::Attribute,
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
[] use_path: rustc_hir::UsePath<'tcx>,
[] lit: rustc_hir::Lit,
[] macro_def: rustc_ast::MacroDef,
]);
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ impl<CTX: crate::HashStableContext> ToStableHashKey<CTX> for Namespace {
}

/// Just a helper ‒ separate structure for each namespace.
#[derive(Copy, Clone, Default, Debug)]
#[derive(Copy, Clone, Default, Debug, HashStable_Generic)]
pub struct PerNS<T> {
pub value_ns: T,
pub type_ns: T,
Expand All @@ -596,10 +596,16 @@ impl<T> PerNS<T> {
PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
}

/// Note: Do you really want to use this? Often you know which namespace a
/// name will belong in, and you can consider just that namespace directly,
/// rather than iterating through all of them.
pub fn into_iter(self) -> IntoIter<T, 3> {
[self.value_ns, self.type_ns, self.macro_ns].into_iter()
}

/// Note: Do you really want to use this? Often you know which namespace a
/// name will belong in, and you can consider just that namespace directly,
/// rather than iterating through all of them.
pub fn iter(&self) -> IntoIter<&T, 3> {
[&self.value_ns, &self.type_ns, &self.macro_ns].into_iter()
}
Expand Down Expand Up @@ -634,6 +640,10 @@ impl<T> PerNS<Option<T>> {
}

/// Returns an iterator over the items which are `Some`.
///
/// Note: Do you really want to use this? Often you know which namespace a
/// name will belong in, and you can consider just that namespace directly,
/// rather than iterating through all of them.
pub fn present_items(self) -> impl Iterator<Item = T> {
[self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten()
}
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use thin_vec::ThinVec;
use tracing::debug;

use crate::LangItem;
use crate::def::{CtorKind, DefKind, Res};
use crate::def::{CtorKind, DefKind, PerNS, Res};
use crate::def_id::{DefId, LocalDefIdMap};
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
use crate::intravisit::{FnKind, VisitorExt};
Expand Down Expand Up @@ -347,7 +347,7 @@ pub struct Path<'hir, R = Res> {
}

/// Up to three resolutions for type, value and macro namespaces.
pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
pub type UsePath<'hir> = Path<'hir, PerNS<Option<Res>>>;

impl Path<'_> {
pub fn is_global(&self) -> bool {
Expand Down Expand Up @@ -2370,6 +2370,10 @@ impl Expr<'_> {
// Lang item paths cannot currently be local variables or statics.
ExprKind::Path(QPath::LangItem(..)) => false,

// Suppress errors for bad expressions.
ExprKind::Err(_guar)
| ExprKind::Let(&LetExpr { recovered: ast::Recovered::Yes(_guar), .. }) => true,

// Partially qualified paths in expressions can only legally
// refer to associated items which are always rvalues.
ExprKind::Path(QPath::TypeRelative(..))
Expand Down Expand Up @@ -2401,8 +2405,7 @@ impl Expr<'_> {
| ExprKind::Binary(..)
| ExprKind::Yield(..)
| ExprKind::Cast(..)
| ExprKind::DropTemps(..)
| ExprKind::Err(_) => false,
| ExprKind::DropTemps(..) => false,
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,7 @@ pub fn walk_use<'v, V: Visitor<'v>>(
hir_id: HirId,
) -> V::Result {
let UsePath { segments, ref res, span } = *path;
for &res in res {
for res in res.present_items() {
try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id));
}
V::Result::output()
Expand Down
20 changes: 11 additions & 9 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,16 +328,19 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };

let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
let is_mod_inherent = |res: Res| {
res.opt_def_id()
.is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id))
};

// Path segments except for the final.
if let Some(seg) =
path.segments.iter().find(|seg| seg.res.opt_def_id().is_some_and(is_mod_inherent))
{
if let Some(seg) = path.segments.iter().find(|seg| is_mod_inherent(seg.res)) {
cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage);
}
// Final path resolutions, like `use rustc_type_ir::inherent`
else if path.res.iter().any(|res| res.opt_def_id().is_some_and(is_mod_inherent)) {
else if let Some(type_ns) = path.res.type_ns
&& is_mod_inherent(type_ns)
{
cx.emit_span_lint(
USAGE_OF_TYPE_IR_INHERENT,
path.segments.last().unwrap().ident.span,
Expand All @@ -346,13 +349,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
}

let (lo, hi, snippet) = match path.segments {
[.., penultimate, segment]
if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) =>
{
[.., penultimate, segment] if is_mod_inherent(penultimate.res) => {
(segment.ident.span, item.kind.ident().unwrap().span, "*")
}
[.., segment]
if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent)
if let Some(type_ns) = path.res.type_ns
&& is_mod_inherent(type_ns)
&& let rustc_hir::UseKind::Single(ident) = kind =>
{
let (lo, snippet) =
Expand Down
21 changes: 9 additions & 12 deletions compiler/rustc_lint/src/unqualified_local_imports.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{self as hir};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::kw;
Expand Down Expand Up @@ -47,17 +46,15 @@ declare_lint_pass!(UnqualifiedLocalImports => [UNQUALIFIED_LOCAL_IMPORTS]);
impl<'tcx> LateLintPass<'tcx> for UnqualifiedLocalImports {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let hir::ItemKind::Use(path, _kind) = item.kind else { return };
// `path` has three resolutions for the type, module, value namespaces.
// Check if any of them qualifies: local crate, and not a macro.
// (Macros can't be imported any other way so we don't complain about them.)
let is_local_import = |res: &Res| {
matches!(
res,
hir::def::Res::Def(def_kind, def_id)
if def_id.is_local() && !matches!(def_kind, DefKind::Macro(_)),
)
};
if !path.res.iter().any(is_local_import) {
// Check the type and value namespace resolutions for a local crate.
let is_local_import = matches!(
path.res.type_ns,
Some(hir::def::Res::Def(_, def_id)) if def_id.is_local()
) || matches!(
path.res.value_ns,
Some(hir::def::Res::Def(_, def_id)) if def_id.is_local()
);
if !is_local_import {
return;
}
// So this does refer to something local. Let's check whether it starts with `self`,
Expand Down
35 changes: 15 additions & 20 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,26 +1047,21 @@ fn find_fallback_pattern_typo<'tcx>(
let hir::ItemKind::Use(path, _) = item.kind else {
continue;
};
for res in &path.res {
if let Res::Def(DefKind::Const, id) = res
&& infcx.can_eq(param_env, ty, cx.tcx.type_of(id).instantiate_identity())
{
if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
// The original const is accessible, suggest using it directly.
let item_name = cx.tcx.item_name(*id);
accessible.push(item_name);
accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
} else if cx
.tcx
.visibility(item.owner_id)
.is_accessible_from(parent, cx.tcx)
{
// The const is accessible only through the re-export, point at
// the `use`.
let ident = item.kind.ident().unwrap();
imported.push(ident.name);
imported_spans.push(ident.span);
}
if let Some(value_ns) = path.res.value_ns
&& let Res::Def(DefKind::Const, id) = value_ns
&& infcx.can_eq(param_env, ty, cx.tcx.type_of(id).instantiate_identity())
{
if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
// The original const is accessible, suggest using it directly.
let item_name = cx.tcx.item_name(id);
accessible.push(item_name);
accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
} else if cx.tcx.visibility(item.owner_id).is_accessible_from(parent, cx.tcx) {
// The const is accessible only through the re-export, point at
// the `use`.
let ident = item.kind.ident().unwrap();
imported.push(ident.name);
imported_spans.push(ident.span);
}
}
}
Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_mir_transform/src/elaborate_drop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{fmt, iter, mem};

use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
use rustc_hir::def::DefKind;
use rustc_hir::lang_items::LangItem;
use rustc_index::Idx;
use rustc_middle::mir::*;
Expand Down Expand Up @@ -254,8 +255,19 @@ where
// impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...'
// (#140974).
// Such code will report error, so just generate sync drop here and return
let Some(drop_fn_def_id) =
tcx.associated_item_def_ids(drop_trait).into_iter().nth(0).copied()
let Some(drop_fn_def_id) = tcx
.associated_item_def_ids(drop_trait)
.first()
.and_then(|def_id| {
if tcx.def_kind(def_id) == DefKind::AssocFn
&& tcx.check_args_compatible(*def_id, trait_args)
{
Some(def_id)
} else {
None
}
})
.copied()
else {
tcx.dcx().span_delayed_bug(
self.elaborator.body().span,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/check_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<'tcx> Visitor<'tcx> for ExportableItemCollector<'tcx> {
self.add_exportable(def_id);
}
hir::ItemKind::Use(path, _) => {
for res in &path.res {
for res in path.res.present_items() {
// Only local items are exportable.
if let Some(res_id) = res.opt_def_id()
&& let Some(res_id) = res_id.as_local()
Expand Down
Loading
Loading