cargo: Bump rustc to 1.89 (#36818)

Update Rustc to 1.89.

Reviewable by commit.

Leftover work:
- #37330 
- #38777

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
webbeef 2025-08-19 04:07:53 -07:00 committed by GitHub
parent 8587536755
commit 3225d19907
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
126 changed files with 408 additions and 610 deletions

View file

@ -1,5 +1,5 @@
[toolchain]
channel = "1.85.0"
channel = "1.89.0"
components = [
"clippy",

View file

@ -2,19 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use rustc_ast::Mutability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::{ImplItemRef, ItemKind, Node, OwnerId, PrimTy, TraitItemRef};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{EvaluationResult, Obligation, ObligationCause};
use rustc_lint::LateContext;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeVisitableExt, TypingEnv};
use rustc_middle::ty::{self, GenericArg, TraitRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_type_ir::{FloatTy, IntTy, UintTy};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_type_ir::Upcast as _;
/// check if a DefId's path matches the given absolute type path
/// usage e.g. with
@ -65,286 +63,101 @@ macro_rules! symbols {
}
}
pub fn find_first_crate<'tcx>(tcx: &TyCtxt<'tcx>, crate_name: Symbol) -> Option<CrateNum> {
tcx.crates(())
.iter()
.find(|c| tcx.crate_name(**c) == crate_name)
.copied()
}
pub fn trait_in_crate<'tcx>(
tcx: &TyCtxt<'tcx>,
krate: CrateNum,
trait_sym: Symbol,
) -> Option<DefId> {
tcx.traits(krate)
.iter()
.find(|id| tcx.opt_item_name(**id) == Some(trait_sym))
.copied()
}
/*
Stuff copied from clippy:
*/
// This is adapted from
// https://github.com/rust-lang/rust-clippy/blob/546408be416f0355a39601c1457b37727bc74395/clippy_utils/src/lib.rs#L517.
fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
let ty = match name {
"bool" => SimplifiedType::Bool,
"char" => SimplifiedType::Char,
"str" => SimplifiedType::Str,
"array" => SimplifiedType::Array,
"slice" => SimplifiedType::Slice,
// FIXME: rustdoc documents these two using just `pointer`.
//
// Maybe this is something we should do here too.
"const_ptr" => SimplifiedType::Ptr(Mutability::Not),
"mut_ptr" => SimplifiedType::Ptr(Mutability::Mut),
"isize" => SimplifiedType::Int(IntTy::Isize),
"i8" => SimplifiedType::Int(IntTy::I8),
"i16" => SimplifiedType::Int(IntTy::I16),
"i32" => SimplifiedType::Int(IntTy::I32),
"i64" => SimplifiedType::Int(IntTy::I64),
"i128" => SimplifiedType::Int(IntTy::I128),
"usize" => SimplifiedType::Uint(UintTy::Usize),
"u8" => SimplifiedType::Uint(UintTy::U8),
"u16" => SimplifiedType::Uint(UintTy::U16),
"u32" => SimplifiedType::Uint(UintTy::U32),
"u64" => SimplifiedType::Uint(UintTy::U64),
"u128" => SimplifiedType::Uint(UintTy::U128),
"f32" => SimplifiedType::Float(FloatTy::F32),
"f64" => SimplifiedType::Float(FloatTy::F64),
#[allow(trivial_casts)]
_ => {
return [].iter().copied();
},
};
tcx.incoherent_impls(ty).iter().copied()
}
fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
match tcx.def_kind(def_id) {
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
.module_children(def_id)
.iter()
.filter(|item| item.ident.name == name)
.map(|child| child.res.expect_non_local())
.collect(),
DefKind::Impl { .. } => tcx
.associated_item_def_ids(def_id)
.iter()
.copied()
.filter(|assoc_def_id| tcx.item_name(*assoc_def_id) == name)
.map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id))
.collect(),
_ => Vec::new(),
}
}
// This is adapted from clippy:
// https://github.com/rust-lang/rust-clippy/blob/546408be416f0355a39601c1457b37727bc74395/clippy_utils/src/lib.rs#L574.
fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symbol) -> Vec<Res> {
let hir = tcx.hir();
let root_mod;
let item_kind = match tcx.hir_node_by_def_id(local_id) {
Node::Crate(r#mod) => {
root_mod = ItemKind::Mod(r#mod);
&root_mod
},
Node::Item(item) => &item.kind,
_ => return Vec::new(),
};
let res = |ident: Ident, owner_id: OwnerId| {
if ident.name == name {
let def_id = owner_id.to_def_id();
Some(Res::Def(tcx.def_kind(def_id), def_id))
} else {
None
}
};
match item_kind {
ItemKind::Mod(r#mod) => r#mod
.item_ids
.iter()
.filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
.collect(),
ItemKind::Impl(r#impl) => r#impl
.items
.iter()
.filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.owner_id))
.collect(),
ItemKind::Trait(.., trait_item_refs) => trait_item_refs
.iter()
.filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.owner_id))
.collect(),
_ => Vec::new(),
}
}
fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
if let Some(local_id) = def_id.as_local() {
local_item_children_by_name(tcx, local_id, name)
} else {
non_local_item_children_by_name(tcx, def_id, name)
}
}
/// Resolves a def path like `std::vec::Vec`.
///
/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
/// `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0.
///
/// Also returns multiple results when there are multiple paths under the same name e.g. `std::vec`
/// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
///
/// This function is expensive and should be used sparingly.
pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
tcx.crates(())
.iter()
.copied()
.filter(move |&num| tcx.crate_name(num) == name)
.map(CrateNum::as_def_id)
}
let tcx = cx.tcx;
let (base, mut path) = match *path {
[primitive] => {
return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
},
[base, ref path @ ..] => (base, path),
_ => return Vec::new(),
};
let base_sym = Symbol::intern(base);
let local_crate = if tcx.crate_name(LOCAL_CRATE) == base_sym {
Some(LOCAL_CRATE.as_def_id())
} else {
None
};
let starts = find_primitive_impls(tcx, base)
.chain(find_crates(tcx, base_sym))
.chain(local_crate)
.map(|id| Res::Def(tcx.def_kind(id), id));
let mut resolutions: Vec<Res> = starts.collect();
while let [segment, rest @ ..] = path {
path = rest;
let segment = Symbol::intern(segment);
resolutions = resolutions
.into_iter()
.filter_map(|res| res.opt_def_id())
.flat_map(|def_id| {
// When the current def_id is e.g. `struct S`, check the impl items in
// `impl S { ... }`
let inherent_impl_children = tcx
.inherent_impls(def_id)
.into_iter()
.flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
let direct_children = item_children_by_name(tcx, def_id, segment);
inherent_impl_children.chain(direct_children)
})
.collect();
}
resolutions
}
pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
def_path_res(cx, path)
.into_iter()
.find_map(|res| match res {
Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
_ => None,
})
}
// These are special variants made from the above functions.
/// Resolves a def path like `std::vec::Vec`, but searches only local crate
///
/// Also returns multiple results when there are multiple paths under the same name e.g. `std::vec`
/// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
///
/// This function is less expensive than `def_path_res` and should be used sparingly.
pub fn def_local_res(cx: &LateContext<'_>, path: &str) -> Vec<Res> {
let tcx = cx.tcx;
let local_crate = LOCAL_CRATE.as_def_id();
let starts = Res::Def(tcx.def_kind(local_crate), local_crate);
let mut resolutions: Vec<Res> = vec![starts];
let segment = Symbol::intern(path);
resolutions = resolutions
.into_iter()
.filter_map(|res| res.opt_def_id())
.flat_map(|def_id| {
// When the current def_id is e.g. `struct S`, check the impl items in
// `impl S { ... }`
let inherent_impl_children = tcx
.inherent_impls(def_id)
.into_iter()
.flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
let direct_children = item_children_by_name(tcx, def_id, segment);
inherent_impl_children.chain(direct_children)
})
.collect();
resolutions
}
pub fn get_local_trait_def_id(cx: &LateContext<'_>, path: &str) -> Option<DefId> {
def_local_res(cx, path)
.into_iter()
.find_map(|res| match res {
Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
_ => None,
})
}
/// Checks whether a type implements a trait.
/// The function returns false in case the type contains an inference variable.
///
/// See:
/// * [`get_trait_def_id`](super::get_trait_def_id) to get a trait [`DefId`].
/// * [Common tools for writing lints] for an example how to use this function and other options.
/// See [Common tools for writing lints] for an example how to use this function and other options.
///
/// [Common tools for writing lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/common_tools_writing_lints.md#checking-if-a-type-implements-a-specific-trait
pub fn implements_trait<'tcx>(
cx: &LateContext<'tcx>,
ty: Ty<'tcx>,
trait_id: DefId,
ty_params: &[GenericArg<'tcx>],
args: &[GenericArg<'tcx>],
) -> bool {
implements_trait_with_env(
implements_trait_with_env_from_iter(
cx.tcx,
cx.typing_env(),
ty,
trait_id,
ty_params.iter().map(|&arg| Some(arg)),
None,
args.iter().map(|&x| Some(x)),
)
}
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
pub fn implements_trait_with_env<'tcx>(
/// Same as `implements_trait_from_env` but takes the arguments as an iterator.
pub fn implements_trait_with_env_from_iter<'tcx>(
tcx: TyCtxt<'tcx>,
typing_env: TypingEnv<'tcx>,
ty: ty::Ty<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
trait_id: DefId,
ty_params: impl IntoIterator<Item = Option<GenericArg<'tcx>>>,
callee_id: Option<DefId>,
args: impl IntoIterator<Item = impl Into<Option<GenericArg<'tcx>>>>,
) -> bool {
// Clippy shouldn't have infer types
assert!(!ty.has_infer());
// If a `callee_id` is passed, then we assert that it is a body owner
// through calling `body_owner_kind`, which would panic if the callee
// does not have a body.
if let Some(callee_id) = callee_id {
let _ = tcx.hir_body_owner_kind(callee_id);
}
let ty = tcx.erase_regions(ty);
if ty.has_escaping_bound_vars() {
return false;
}
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let ty_params = tcx.mk_args_from_iter(
ty_params
.into_iter()
.map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())),
let args = args
.into_iter()
.map(|arg| {
arg.into()
.unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())
})
.collect::<Vec<_>>();
let trait_ref = TraitRef::new(
tcx,
trait_id,
[GenericArg::from(ty)].into_iter().chain(args),
);
debug_assert!(
matches!(tcx.def_kind(trait_id), DefKind::Trait | DefKind::TraitAlias),
"`DefId` must belong to a trait or trait alias"
);
let obligation = Obligation {
cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: trait_ref.upcast(tcx),
};
infcx
.type_implements_trait(
trait_id,
// for some unknown reason we need to have vec here
// clippy has array
vec![ty.into()].into_iter().chain(ty_params),
param_env,
)
.must_apply_modulo_regions()
.evaluate_obligation(&obligation)
.is_ok_and(EvaluationResult::must_apply_modulo_regions)
}

View file

@ -72,5 +72,5 @@ fn main() {
// Pass cfg(crown) to rustc
args.extend(["--cfg".to_owned(), "crown".to_owned()]);
rustc_driver::RunCompiler::new(&args, &mut MyCallbacks).run()
rustc_driver::run_compiler(&args, &mut MyCallbacks)
}

View file

@ -5,13 +5,14 @@
use rustc_ast::token::TokenKind;
use rustc_ast::tokenstream::TokenTree;
use rustc_error_messages::MultiSpan;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::{self as hir};
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext, LintPass, LintStore};
use rustc_middle::ty;
use rustc_session::declare_tool_lint;
use rustc_span::symbol::Symbol;
use crate::common::{get_local_trait_def_id, get_trait_def_id, implements_trait};
use crate::common::{find_first_crate, implements_trait, trait_in_crate};
use crate::symbols;
declare_tool_lint! {
@ -67,14 +68,11 @@ fn get_must_not_have_traceable(sym: &Symbols, attrs: &[hir::Attribute]) -> Optio
attrs
.iter()
.find(|attr| {
matches!(
&attr.kind,
hir::AttrKind::Normal(normal)
if normal.path.segments.len() == 3 &&
normal.path.segments[0].name == sym.crown &&
normal.path.segments[1].name == sym.trace_in_no_trace_lint &&
normal.path.segments[2].name == sym.must_not_have_traceable
)
attr.path_matches(&[
sym.crown,
sym.trace_in_no_trace_lint,
sym.must_not_have_traceable,
])
})
.map(|x| match &x.get_normal_item().args {
hir::AttrArgs::Empty => 0,
@ -98,13 +96,17 @@ fn get_must_not_have_traceable(sym: &Symbols, attrs: &[hir::Attribute]) -> Optio
})
}
fn is_jstraceable<'tcx>(cx: &LateContext<'tcx>, ty: ty::Ty<'tcx>) -> bool {
// TODO(sagudev): get_trait_def_id is expensive, use lazy and cache it for whole pass
if let Some(trait_id) = get_trait_def_id(cx, &["mozjs", "gc", "Traceable"]) {
return implements_trait(cx, ty, trait_id, &[]);
fn find_jstraceable<'tcx>(cx: &LateContext<'tcx>) -> Option<DefId> {
// mozjs_sys::trace::Traceable
if let Some(mozjs) = find_first_crate(&cx.tcx, Symbol::intern("mozjs_sys")) {
return trait_in_crate(&cx.tcx, mozjs, Symbol::intern("Traceable"));
}
// when running tests
if let Some(trait_id) = get_local_trait_def_id(cx, "JSTraceable") {
trait_in_crate(&cx.tcx, LOCAL_CRATE, Symbol::intern("JSTraceable"))
}
fn is_jstraceable<'tcx>(cx: &LateContext<'tcx>, ty: ty::Ty<'tcx>) -> bool {
if let Some(trait_id) = find_jstraceable(cx) {
return implements_trait(cx, ty, trait_id, &[]);
}
panic!("JSTraceable not found");
@ -119,7 +121,7 @@ fn incorrect_no_trace<'tcx, I: Into<MultiSpan> + Copy>(
) {
let mut walker = ty.walk();
while let Some(generic_arg) = walker.next() {
let t = match generic_arg.unpack() {
let t = match generic_arg.kind() {
rustc_middle::ty::GenericArgKind::Type(t) => t,
_ => {
walker.skip_current_subtree();
@ -168,8 +170,8 @@ impl<'tcx> LateLintPass<'tcx> for NotracePass {
if has_lint_attr(&self.symbols, &attrs, self.symbols.must_root) {
return;
}*/
if let hir::ItemKind::Struct(def, ..) = &item.kind {
for field in def.fields() {
if let hir::ItemKind::Struct(_, _, variant_data) = &item.kind {
for field in variant_data.fields() {
let field_type = cx.tcx.type_of(field.def_id);
incorrect_no_trace(&self.symbols, cx, field_type.skip_binder(), field.span);
}

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use rustc_hir::{self as hir, intravisit as visit, ExprKind};
use rustc_hir::{self as hir, intravisit as visit, AmbigArg, ExprKind};
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext, LintPass, LintStore};
use rustc_middle::ty;
use rustc_session::declare_tool_lint;
@ -61,7 +61,7 @@ fn associated_type_has_attr<'tcx>(
) -> bool {
let mut walker = ty.walk();
while let Some(generic_arg) = walker.next() {
let t = match generic_arg.unpack() {
let t = match generic_arg.kind() {
rustc_middle::ty::GenericArgKind::Type(t) => t,
_ => {
walker.skip_current_subtree();
@ -76,7 +76,7 @@ fn associated_type_has_attr<'tcx>(
);
},
ty::Alias(
ty::AliasTyKind::Projection | ty::AliasTyKind::Inherent | ty::AliasTyKind::Weak,
ty::AliasTyKind::Projection | ty::AliasTyKind::Inherent | ty::AliasTyKind::Free,
ty,
) => {
return cx.tcx.has_attrs_with_path(
@ -100,7 +100,7 @@ fn is_unrooted_ty<'tcx>(
let mut ret = false;
let mut walker = ty.walk();
while let Some(generic_arg) = walker.next() {
let t = match generic_arg.unpack() {
let t = match generic_arg.kind() {
rustc_middle::ty::GenericArgKind::Type(t) => t,
_ => {
walker.skip_current_subtree();
@ -126,7 +126,7 @@ fn is_unrooted_ty<'tcx>(
ty::Alias(
ty::AliasTyKind::Projection |
ty::AliasTyKind::Inherent |
ty::AliasTyKind::Weak,
ty::AliasTyKind::Free,
ty,
) => !has_attr(ty.def_id, sym.allow_unrooted_in_rc),
_ => true,
@ -194,7 +194,7 @@ fn is_unrooted_ty<'tcx>(
ty::Alias(
kind @ ty::AliasTyKind::Projection |
kind @ ty::AliasTyKind::Inherent |
kind @ ty::AliasTyKind::Weak,
kind @ ty::AliasTyKind::Free,
ty,
) => {
if has_attr(ty.def_id, sym.must_root) {
@ -242,8 +242,8 @@ impl<'tcx> LateLintPass<'tcx> for UnrootedPass {
if has_attr(sym.must_root) || has_attr(sym.allow_unrooted_interior) {
return;
}
if let hir::ItemKind::Struct(def, ..) = &item.kind {
for field in def.fields() {
if let hir::ItemKind::Struct(_, _, variant_data) = &item.kind {
for field in variant_data.fields() {
let field_type = cx.tcx.type_of(field.def_id);
if is_unrooted_ty(&self.symbols, cx, field_type.skip_binder(), false) {
cx.lint(UNROOTED_MUST_ROOT, |lint| {
@ -261,8 +261,8 @@ impl<'tcx> LateLintPass<'tcx> for UnrootedPass {
/// All enums containing #[crown::unrooted_must_root_lint::must_root] types
/// must be #[crown::unrooted_must_root_lint::must_root] themselves
fn check_variant(&mut self, cx: &LateContext, var: &hir::Variant) {
let map = &cx.tcx.hir();
let parent_item = map.expect_item(map.get_parent_item(var.hir_id).def_id);
let parent = cx.tcx.hir_get_parent_item(var.hir_id).def_id;
let parent_item = cx.tcx.hir_expect_item(parent);
let sym = &self.symbols;
if !cx.tcx.has_attrs_with_path(
parent_item.hir_id().expect_owner(),
@ -324,7 +324,7 @@ impl<'tcx> LateLintPass<'tcx> for UnrootedPass {
let type_impl = cx
.tcx
.associated_items(impl_def_id)
.find_by_name_and_kind(cx.tcx, trait_item.ident, ty::AssocKind::Type, trait_id)
.find_by_ident_and_kind(cx.tcx, trait_item.ident, ty::AssocTag::Type, trait_id)
.unwrap();
let mir_ty = cx.tcx.type_of(type_impl.def_id).skip_binder();
@ -440,7 +440,14 @@ struct FnDefVisitor<'a, 'tcx: 'a> {
}
impl<'a, 'tcx> visit::Visitor<'tcx> for FnDefVisitor<'a, 'tcx> {
type Map = rustc_middle::hir::map::Map<'tcx>;
// TODO: https://github.com/servo/servo/issues/37330
/*
type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
self.cx.tcx
}
*/
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
let cx = self.cx;
@ -504,11 +511,7 @@ impl<'a, 'tcx> visit::Visitor<'tcx> for FnDefVisitor<'a, 'tcx> {
visit::walk_pat(self, pat);
}
fn visit_ty(&mut self, _: &'tcx hir::Ty) {}
fn nested_visit_map(&mut self) -> Self::Map {
self.cx.tcx.hir()
}
fn visit_ty(&mut self, _: &'tcx rustc_hir::Ty<'tcx, AmbigArg>) {}
}
symbols! {

View file

@ -43,7 +43,7 @@ fn run_mode(mode: &'static str, bless: bool) {
#[test]
fn compile_test() {
let bless = env::var("BLESS").map_or(false, |x| !x.trim().is_empty());
let bless = env::var("BLESS").is_ok_and(|x| !x.trim().is_empty());
run_mode("compile-fail", bless);
run_mode("run-pass", bless);
// UI test fails on windows