diff --git a/compiler/rustc_ast_lowering/src/contract.rs b/compiler/rustc_ast_lowering/src/contract.rs index 2f1c3d66d4e70..ed32ac5c287d4 100644 --- a/compiler/rustc_ast_lowering/src/contract.rs +++ b/compiler/rustc_ast_lowering/src/contract.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use thin_vec::thin_vec; use crate::LoweringContext; @@ -118,7 +120,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let req_span = self.mark_span_with_reason( rustc_span::DesugaringKind::Contract, lowered_req.span, - None, + Some(Arc::clone(&self.allow_contracts)), ); let precond = self.expr_call_lang_item_fn_mut( req_span, @@ -133,8 +135,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ens: &Box, ) -> &'hir rustc_hir::Expr<'hir> { let ens_span = self.lower_span(ens.span); - let ens_span = - self.mark_span_with_reason(rustc_span::DesugaringKind::Contract, ens_span, None); + let ens_span = self.mark_span_with_reason( + rustc_span::DesugaringKind::Contract, + ens_span, + Some(Arc::clone(&self.allow_contracts)), + ); let lowered_ens = self.lower_expr_mut(&ens); self.expr_call_lang_item_fn( ens_span, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9467f86a22527..d8322909d160a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -865,6 +865,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let features = match await_kind { + FutureKind::Future if is_async_gen => Some(Arc::clone(&self.allow_async_gen)), FutureKind::Future => None, FutureKind::AsyncIterator => Some(Arc::clone(&self.allow_for_await)), }; @@ -1484,7 +1485,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); let e2 = self.lower_expr_mut(e2); - let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span); + let fn_path = self.make_lang_item_qpath(hir::LangItem::RangeInclusiveNew, span, None); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path))); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1570,7 +1571,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ExprKind::Struct( - self.arena.alloc(hir::QPath::LangItem(lang_item, span)), + self.arena.alloc(self.make_lang_item_qpath(lang_item, span, None)), fields, hir::StructTailExpr::None, ) @@ -1720,8 +1721,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`. // This ensures that we store our resumed `ResumeContext` correctly, and also that // the apparent value of the `yield` expression is `()`. - let wrapped_yielded = self.expr_call_lang_item_fn( + let desugar_span = self.mark_span_with_reason( + DesugaringKind::Async, span, + Some(Arc::clone(&self.allow_async_gen)), + ); + let wrapped_yielded = self.expr_call_lang_item_fn( + desugar_span, hir::LangItem::AsyncGenReady, std::slice::from_ref(yielded), ); @@ -1733,7 +1739,7 @@ impl<'hir> LoweringContext<'_, 'hir> { unreachable!("use of `await` outside of an async context."); }; let task_context_ident = Ident::with_dummy_span(sym::_task_context); - let lhs = self.expr_ident(span, task_context_ident, task_context_hid); + let lhs = self.expr_ident(desugar_span, task_context_ident, task_context_hid); hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)) } else { @@ -2166,7 +2172,7 @@ impl<'hir> LoweringContext<'_, 'hir> { lang_item: hir::LangItem, fields: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir> { - let path = self.arena.alloc(self.lang_item_path(span, lang_item)); + let path = self.arena.alloc(self.make_lang_item_qpath(lang_item, span, None)); self.expr_enum_variant(span, path, fields) } @@ -2203,16 +2209,8 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, ) -> hir::Expr<'hir> { - let path = self.lang_item_path(span, lang_item); - self.expr(span, hir::ExprKind::Path(path)) - } - - pub(super) fn lang_item_path( - &mut self, - span: Span, - lang_item: hir::LangItem, - ) -> hir::QPath<'hir> { - hir::QPath::LangItem(lang_item, self.lower_span(span)) + let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span), None); + self.expr(span, hir::ExprKind::Path(qpath)) } /// `::name` diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 2871430030c45..c5bbc2b811887 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -391,7 +391,8 @@ fn make_format_spec<'hir>( let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp); let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp); let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp); - let placeholder = ctx.arena.alloc(hir::QPath::LangItem(hir::LangItem::FormatPlaceholder, sp)); + let placeholder = + ctx.arena.alloc(ctx.make_lang_item_qpath(hir::LangItem::FormatPlaceholder, sp, None)); let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]); ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None)) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index be9db9257356c..dd458ab1ea70f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -138,9 +138,11 @@ struct LoweringContext<'a, 'hir> { #[cfg(debug_assertions)] node_id_to_local_id: NodeMap, + allow_contracts: Arc<[Symbol]>, allow_try_trait: Arc<[Symbol]>, allow_gen_future: Arc<[Symbol]>, allow_pattern_type: Arc<[Symbol]>, + allow_async_gen: Arc<[Symbol]>, allow_async_iterator: Arc<[Symbol]>, allow_for_await: Arc<[Symbol]>, allow_async_fn_traits: Arc<[Symbol]>, @@ -183,6 +185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { current_item: None, impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), + allow_contracts: [sym::contracts_internals].into(), allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(), allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(), allow_gen_future: if tcx.features().async_fn_track_caller() { @@ -190,8 +193,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { [sym::gen_future].into() }, - allow_for_await: [sym::async_iterator].into(), + allow_for_await: [sym::async_gen_internals, sym::async_iterator].into(), allow_async_fn_traits: [sym::async_fn_traits].into(), + allow_async_gen: [sym::async_gen_internals].into(), // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller` // interact with `gen`/`async gen` blocks allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), @@ -2531,8 +2535,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lang_item: hir::LangItem, fields: &'hir [hir::PatField<'hir>], ) -> &'hir hir::Pat<'hir> { - let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); - self.pat(span, hir::PatKind::Struct(qpath, fields, None)) + let path = self.make_lang_item_qpath(lang_item, self.lower_span(span), None); + self.pat(span, hir::PatKind::Struct(path, fields, None)) } fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 47a1ad0d9489a..f84ed64e036e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -503,8 +503,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } if let hir::Node::Expr(parent_expr) = parent && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind - && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) = - call_expr.kind + && let hir::ExprKind::Path(qpath) = call_expr.kind + && tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter) { // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans @@ -2312,6 +2312,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let typeck_results = tcx.typeck(self.mir_def_id()); struct ExprFinder<'hir> { + tcx: TyCtxt<'hir>, issue_span: Span, expr_span: Span, body_expr: Option<&'hir hir::Expr<'hir>>, @@ -2336,9 +2337,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // }; // corresponding to the desugaring of a for loop `for in { }`. if let hir::ExprKind::Call(path, [arg]) = ex.kind - && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) = - path.kind + && let hir::ExprKind::Path(qpath) = path.kind + && self.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter) && arg.span.contains(self.issue_span) + && ex.span.desugaring_kind() == Some(DesugaringKind::ForLoop) { // Find `IntoIterator::into_iter()` self.head = Some(arg); @@ -2355,10 +2357,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .. }) = stmt.kind && let hir::ExprKind::Call(path, _args) = call.kind - && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _)) = - path.kind - && let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind - && let hir::QPath::LangItem(LangItem::OptionSome, pat_span) = path + && let hir::ExprKind::Path(qpath) = path.kind + && self.tcx.qpath_is_lang_item(qpath, LangItem::IteratorNext) + && let hir::PatKind::Struct(qpath, [field, ..], _) = bind.pat.kind + && self.tcx.qpath_is_lang_item(qpath, LangItem::OptionSome) && call.span.contains(self.issue_span) { // Find `` and the span for the whole `for` loop. @@ -2370,7 +2372,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.loop_bind = Some(ident); } self.head_span = Some(*head_span); - self.pat_span = Some(pat_span); + self.pat_span = Some(bind.pat.span); self.loop_span = Some(stmt.span); } @@ -2385,6 +2387,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } let mut finder = ExprFinder { + tcx, expr_span: span, issue_span, loop_bind: None, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 38cb12cf24bcb..d6fd5e6a23bd2 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -23,13 +23,14 @@ use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Spanned; -use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; +use rustc_span::{ + BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, Span, Symbol, kw, sym, +}; use rustc_target::asm::InlineAsmRegOrRegClass; use smallvec::SmallVec; use thin_vec::ThinVec; use tracing::debug; -use crate::LangItem; use crate::attrs::AttributeKind; use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; use crate::def_id::{DefId, LocalDefIdMap}; @@ -2418,9 +2419,6 @@ impl Expr<'_> { allow_projections_from(base) || base.is_place_expr(allow_projections_from) } - // 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, @@ -2590,112 +2588,27 @@ impl Expr<'_> { pub fn equivalent_for_indexing(&self, other: &Expr<'_>) -> bool { match (self.kind, other.kind) { (ExprKind::Lit(lit1), ExprKind::Lit(lit2)) => lit1.node == lit2.node, - ( - ExprKind::Path(QPath::LangItem(item1, _)), - ExprKind::Path(QPath::LangItem(item2, _)), - ) => item1 == item2, ( ExprKind::Path(QPath::Resolved(None, path1)), ExprKind::Path(QPath::Resolved(None, path2)), ) => path1.res == path2.res, ( ExprKind::Struct( - QPath::LangItem(LangItem::RangeTo, _), - [val1], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::RangeTo, _), - [val2], - StructTailExpr::None, - ), - ) - | ( - ExprKind::Struct( - QPath::LangItem(LangItem::RangeToInclusive, _), - [val1], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::RangeToInclusive, _), - [val2], - StructTailExpr::None, - ), - ) - | ( - ExprKind::Struct( - QPath::LangItem(LangItem::RangeToInclusiveCopy, _), - [val1], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::RangeToInclusiveCopy, _), - [val2], - StructTailExpr::None, - ), - ) - | ( - ExprKind::Struct( - QPath::LangItem(LangItem::RangeFrom, _), - [val1], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::RangeFrom, _), - [val2], - StructTailExpr::None, - ), - ) - | ( - ExprKind::Struct( - QPath::LangItem(LangItem::RangeFromCopy, _), - [val1], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::RangeFromCopy, _), - [val2], - StructTailExpr::None, - ), - ) => val1.expr.equivalent_for_indexing(val2.expr), - ( - ExprKind::Struct( - QPath::LangItem(LangItem::Range, _), - [val1, val3], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::Range, _), - [val2, val4], - StructTailExpr::None, - ), - ) - | ( - ExprKind::Struct( - QPath::LangItem(LangItem::RangeCopy, _), - [val1, val3], + &QPath::Resolved(None, &Path { res: Res::Def(_, path1_def_id), .. }), + args1, StructTailExpr::None, ), ExprKind::Struct( - QPath::LangItem(LangItem::RangeCopy, _), - [val2, val4], - StructTailExpr::None, - ), - ) - | ( - ExprKind::Struct( - QPath::LangItem(LangItem::RangeInclusiveCopy, _), - [val1, val3], - StructTailExpr::None, - ), - ExprKind::Struct( - QPath::LangItem(LangItem::RangeInclusiveCopy, _), - [val2, val4], + &QPath::Resolved(None, &Path { res: Res::Def(_, path2_def_id), .. }), + args2, StructTailExpr::None, ), ) => { - val1.expr.equivalent_for_indexing(val2.expr) - && val3.expr.equivalent_for_indexing(val4.expr) + path2_def_id == path1_def_id + && is_range_literal(self) + && is_range_literal(other) + && std::iter::zip(args1, args2) + .all(|(a, b)| a.expr.equivalent_for_indexing(b.expr)) } _ => false, } @@ -2713,30 +2626,29 @@ impl Expr<'_> { /// Checks if the specified expression is a built-in range literal. /// (See: `LoweringContext::lower_expr()`). pub fn is_range_literal(expr: &Expr<'_>) -> bool { - match expr.kind { - // All built-in range literals but `..=` and `..` desugar to `Struct`s. - ExprKind::Struct(ref qpath, _, _) => matches!( - **qpath, - QPath::LangItem( - LangItem::Range - | LangItem::RangeTo - | LangItem::RangeFrom - | LangItem::RangeFull - | LangItem::RangeToInclusive - | LangItem::RangeCopy - | LangItem::RangeFromCopy - | LangItem::RangeInclusiveCopy - | LangItem::RangeToInclusiveCopy, - .. - ) - ), - - // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. - ExprKind::Call(ref func, _) => { - matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..))) - } - - _ => false, + if let ExprKind::Struct(QPath::Resolved(None, path), _, StructTailExpr::None) = expr.kind + && let [.., segment] = path.segments + && let sym::RangeFrom + | sym::RangeFull + | sym::Range + | sym::RangeToInclusive + | sym::RangeTo + | sym::RangeFromCopy + | sym::RangeCopy + | sym::RangeInclusiveCopy + | sym::RangeToInclusiveCopy = segment.ident.name + && expr.span.is_desugaring(DesugaringKind::RangeExpr) + { + true + } else if let ExprKind::Call(func, _) = &expr.kind + && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind + && let [.., segment] = path.segments + && let sym::range_inclusive_new = segment.ident.name + && expr.span.is_desugaring(DesugaringKind::RangeExpr) + { + true + } else { + false } } @@ -2930,9 +2842,6 @@ pub enum QPath<'hir> { /// `::new`, and `T::X::Y::method` into `<<::X>::Y>::method`, /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>), - - /// Reference to a `#[lang = "foo"]` item. - LangItem(LangItem, Span), } impl<'hir> QPath<'hir> { @@ -2941,7 +2850,6 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span), - QPath::LangItem(_, span) => span, } } @@ -2951,7 +2859,6 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, _) => qself.span, - QPath::LangItem(_, span) => span, } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index dde71e499c47a..48b5200019b37 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1416,7 +1416,6 @@ pub fn walk_qpath<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ty_unambig(qself)); visitor.visit_path_segment(segment) } - QPath::LangItem(..) => V::Result::output(), } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 82a931dcca2a0..c1eb277b1380b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2240,13 +2240,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) .unwrap_or_else(|guar| Const::new_error(tcx, guar)) } - hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => { - ty::Const::new_error_with_message( - tcx, - qpath.span(), - format!("Const::lower_const_arg: invalid qpath {qpath:?}"), - ) - } hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon), hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span), } @@ -2561,17 +2554,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|(ty, _, _)| ty) .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } - &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { - let def_id = tcx.require_lang_item(lang_item, span); - let (args, _) = self.lower_generic_args_of_path( - span, - def_id, - &[], - &hir::PathSegment::invalid(), - None, - ); - tcx.at(span).type_of(def_id).instantiate(tcx, args) - } hir::TyKind::Array(ty, length) => { let length = self.lower_const_arg(length, FeedConstTy::No); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ed5f61b3c69ab..f7bbc2e51f4cf 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1774,11 +1774,6 @@ impl<'a> State<'a> { self.print_ident(item_segment.ident); self.print_generic_args(item_segment.args(), colons_before_params) } - hir::QPath::LangItem(lang_item, span) => { - self.word("#[lang = \""); - self.print_ident(Ident::new(lang_item.name(), span)); - self.word("\"]"); - } } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 880b0ca2fb1fe..f1e74028f4ce7 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1196,6 +1196,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr.hir_id) else { return; }; + if parent_expr.span.desugaring_kind().is_some() { + return; + } enum CallableKind { Function, Method, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 0b1c725ba4082..e720958746f7a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -19,7 +19,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, HirId, QPath, find_attr}; +use rustc_hir::{ExprKind, HirId, QPath, find_attr, is_range_literal}; use rustc_hir_analysis::NoVariantNamed; use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, RegionVariableOrigin}; @@ -545,9 +545,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::AddrOf(kind, mutbl, oprnd) => { self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) } - ExprKind::Path(QPath::LangItem(lang_item, _)) => { - self.check_lang_item_path(lang_item, expr) - } ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None), ExprKind::InlineAsm(asm) => { // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars). @@ -748,14 +745,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_lang_item_path( - &self, - lang_item: hir::LangItem, - expr: &'tcx hir::Expr<'tcx>, - ) -> Ty<'tcx> { - self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 - } - pub(crate) fn check_expr_path( &self, qpath: &'tcx hir::QPath<'tcx>, @@ -763,6 +752,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr_and_args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, ) -> Ty<'tcx> { let tcx = self.tcx; + + if let Some((_, [arg])) = call_expr_and_args + && let QPath::Resolved(_, path) = qpath + && let Res::Def(_, def_id) = path.res + && let Some(lang_item) = tcx.lang_items().from_def_id(def_id) + { + let code = match lang_item { + LangItem::IntoFutureIntoFuture + if expr.span.is_desugaring(DesugaringKind::Await) => + { + Some(ObligationCauseCode::AwaitableExpr(arg.hir_id)) + } + LangItem::IntoIterIntoIter | LangItem::IteratorNext + if expr.span.is_desugaring(DesugaringKind::ForLoop) => + { + Some(ObligationCauseCode::ForLoopIterator) + } + LangItem::TryTraitFromOutput + if expr.span.is_desugaring(DesugaringKind::TryBlock) => + { + // FIXME it's a try block, not a question mark + Some(ObligationCauseCode::QuestionMark) + } + LangItem::TryTraitBranch | LangItem::TryTraitFromResidual + if expr.span.is_desugaring(DesugaringKind::QuestionMark) => + { + Some(ObligationCauseCode::QuestionMark) + } + _ => None, + }; + if let Some(code) = code { + let args = self.fresh_args_for_item(expr.span, def_id); + self.add_required_obligations_with_code(expr.span, def_id, args, |_, _| { + code.clone() + }); + return tcx.type_of(def_id).instantiate(tcx, args); + } + } + let (res, opt_ty, segs) = self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); let ty = match res { @@ -2483,9 +2511,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args: GenericArgsRef<'tcx>, mut err: Diag<'_>, ) { - // I don't use 'is_range_literal' because only double-sided, half-open ranges count. - if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [range_start, range_end], _) = - last_expr_field.expr.kind + if is_range_literal(last_expr_field.expr) + && let ExprKind::Struct(&qpath, [range_start, range_end], _) = last_expr_field.expr.kind + && self.tcx.qpath_is_lang_item(qpath, LangItem::Range) && let variant_field = variant.fields.iter().find(|field| field.ident(self.tcx) == last_expr_field.ident) && let range_def_id = self.tcx.lang_items().range_struct() diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index be1c173ffbf6f..15e502a600561 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -671,9 +671,6 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { path.segments.last().expect("paths should have a segment") } hir::QPath::TypeRelative(_, segment) => segment, - hir::QPath::LangItem(..) => { - return hir::intravisit::walk_qpath(self, qpath, id); - } }; // Alternatively, try to turbofish `::<_, (), _>`. if let Some(def_id) = self.fcx.typeck_results.borrow().qpath_res(qpath, id).opt_def_id() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index dde6b8ce9b8b2..f4e65b42cd423 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -691,53 +691,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { vec![ty_error; len] } - pub(crate) fn resolve_lang_item_path( - &self, - lang_item: hir::LangItem, - span: Span, - hir_id: HirId, - ) -> (Res, Ty<'tcx>) { - let def_id = self.tcx.require_lang_item(lang_item, span); - let def_kind = self.tcx.def_kind(def_id); - - let item_ty = if let DefKind::Variant = def_kind { - self.tcx.type_of(self.tcx.parent(def_id)) - } else { - self.tcx.type_of(def_id) - }; - let args = self.fresh_args_for_item(span, def_id); - let ty = item_ty.instantiate(self.tcx, args); - - self.write_args(hir_id, args); - self.write_resolution(hir_id, Ok((def_kind, def_id))); - - let code = match lang_item { - hir::LangItem::IntoFutureIntoFuture => { - if let hir::Node::Expr(into_future_call) = self.tcx.parent_hir_node(hir_id) - && let hir::ExprKind::Call(_, [arg0]) = &into_future_call.kind - { - Some(ObligationCauseCode::AwaitableExpr(arg0.hir_id)) - } else { - None - } - } - hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { - Some(ObligationCauseCode::ForLoopIterator) - } - hir::LangItem::TryTraitFromOutput - | hir::LangItem::TryTraitFromResidual - | hir::LangItem::TryTraitBranch => Some(ObligationCauseCode::QuestionMark), - _ => None, - }; - if let Some(code) = code { - self.add_required_obligations_with_code(span, def_id, args, move |_, _| code.clone()); - } else { - self.add_required_obligations_for_hir(span, def_id, args, hir_id); - } - - (Res::Def(def_kind, def_id), ty) - } - /// Resolves an associated value path into a base type and associated constant, or method /// resolution. The newly resolved definition is written into `type_dependent_defs`. #[instrument(level = "trace", skip(self), ret)] @@ -768,9 +721,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.lowerer().lower_ty(qself); (LoweredTy::from_raw(self, span, ty), qself, segment) } - QPath::LangItem(..) => { - bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") - } }; self.register_wf_obligation( @@ -1035,8 +985,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // inherent impl, we need to record the // `T` for posterity (see `UserSelfTy` for // details). - let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw; - user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty }); + // Generated desugaring code may have a path without a self. + user_self_ty = self_ty.map(|self_ty| UserSelfTy { + impl_def_id: container_id, + self_ty: self_ty.raw, + }); } } } @@ -1374,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[instrument(level = "debug", skip(self, code, span, args))] - fn add_required_obligations_with_code( + pub(crate) fn add_required_obligations_with_code( &self, span: Span, def_id: DefId, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index f478cab740e4b..837328e379ca3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -419,7 +419,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - _ => {} } false diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 4d1c7be391977..41dba9edf5ea8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, lis use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath}; +use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath, is_range_literal}; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants}; use rustc_index::IndexVec; @@ -1291,10 +1291,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) } - QPath::LangItem(lang_item, span) => { - let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id); - (res, LoweredTy::from_raw(self, path_span, ty)) - } } } @@ -2052,8 +2048,9 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> { fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) { if let ty::Adt(adt, _) = ty.kind() && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull) - && let hir::ExprKind::Struct(hir::QPath::LangItem(hir::LangItem::RangeFull, _), [], _) = - expr.kind + && is_range_literal(expr) + && let hir::ExprKind::Struct(&path, [], _) = expr.kind + && self.tcx().qpath_is_lang_item(path, hir::LangItem::RangeFull) { // We have `Foo(a, .., c)`, where the user might be trying to use the "rest" syntax // from default field values, which is not supported on tuples. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index d097f8ab84850..28bd3e7e8d5bb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -11,7 +11,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{ self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind, - WherePredicateKind, expr_needs_parens, + WherePredicateKind, expr_needs_parens, is_range_literal, }; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_hir_analysis::suggest_impl_trait; @@ -1664,7 +1664,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } match expr.kind { - ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [start, end], _) => { + ExprKind::Struct(&qpath, [start, end], _) + if is_range_literal(expr) + && self.tcx.qpath_is_lang_item(qpath, LangItem::Range) => + { err.span_suggestion_verbose( start.expr.span.shrink_to_hi().with_hi(end.expr.span.lo()), "remove the unnecessary `.` operator for a floating point literal", @@ -1673,24 +1676,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); true } - ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, ..), [start], _) => { - let range_span = expr.span.parent_callsite().unwrap(); - err.span_suggestion_verbose( - range_span.with_lo(start.expr.span.hi()), - "remove the unnecessary `.` operator for a floating point literal", - '.', - Applicability::MaybeIncorrect, - ); - true - } - ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, ..), [end], _) => { + ExprKind::Struct(&qpath, [arg], _) + if is_range_literal(expr) + && let Some(qpath @ (LangItem::RangeFrom | LangItem::RangeTo)) = + self.tcx.qpath_lang_item(qpath) => + { let range_span = expr.span.parent_callsite().unwrap(); - err.span_suggestion_verbose( - range_span.until(end.expr.span), - "remove the unnecessary `.` operator and add an integer part for a floating point literal", - "0.", - Applicability::MaybeIncorrect, - ); + match qpath { + LangItem::RangeFrom => { + err.span_suggestion_verbose( + range_span.with_lo(arg.expr.span.hi()), + "remove the unnecessary `.` operator for a floating point literal", + '.', + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestion_verbose( + range_span.until(arg.expr.span), + "remove the unnecessary `.` operator and add an integer part for a floating point literal", + "0.", + Applicability::MaybeIncorrect, + ); + } + } true } ExprKind::Lit(Spanned { @@ -3497,11 +3506,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !hir::is_range_literal(expr) { return; } - let hir::ExprKind::Struct(hir::QPath::LangItem(LangItem::Range, ..), [start, end], _) = - expr.kind - else { + let hir::ExprKind::Struct(&qpath, [start, end], _) = expr.kind else { return; }; + if !self.tcx.qpath_is_lang_item(qpath, LangItem::Range) { + return; + } if let hir::Node::ExprField(_) = self.tcx.parent_hir_node(expr.hir_id) { // Ignore `Foo { field: a..Default::default() }` return; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8f2e06dd71272..11ed1657d879b 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -19,7 +19,9 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr}; +use rustc_hir::{ + self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr, is_range_literal, +}; use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin}; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; @@ -2412,22 +2414,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::MethodCall(expr) = source { for (_, parent) in tcx.hir_parent_iter(expr.hir_id).take(5) { if let Node::Expr(parent_expr) = parent { + if !is_range_literal(parent_expr) { + continue; + } let lang_item = match parent_expr.kind { - ExprKind::Struct(qpath, _, _) => match *qpath { - QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range), - QPath::LangItem(LangItem::RangeCopy, ..) => Some(LangItem::RangeCopy), - QPath::LangItem(LangItem::RangeInclusiveCopy, ..) => { - Some(LangItem::RangeInclusiveCopy) - } - QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo), - QPath::LangItem(LangItem::RangeToInclusive, ..) => { - Some(LangItem::RangeToInclusive) - } + ExprKind::Struct(qpath, _, _) => match tcx.qpath_lang_item(*qpath) { + Some( + lang_item @ (LangItem::Range + | LangItem::RangeCopy + | LangItem::RangeInclusiveCopy + | LangItem::RangeTo + | LangItem::RangeToInclusive), + ) => Some(lang_item), _ => None, }, ExprKind::Call(func, _) => match func.kind { // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. - ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => { + ExprKind::Path(qpath) + if tcx.qpath_is_lang_item(qpath, LangItem::RangeInclusiveNew) => + { Some(LangItem::RangeInclusiveStruct) } _ => None, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 0669da1a025b1..a3dd3c53ece7c 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -718,7 +718,7 @@ impl<'tcx> LateContext<'tcx> { pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { match *qpath { hir::QPath::Resolved(_, path) => path.res, - hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self + hir::QPath::TypeRelative(..) => self .maybe_typeck_results() .filter(|typeck_results| typeck_results.hir_owner == id.owner) .or_else(|| { diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index d296ae46f43e7..45c32bfd1d5c5 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -132,8 +132,8 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter { && let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) = &parent_expr.kind && let hir::ExprKind::Call(path, [_]) = &arg.kind - && let hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoIterIntoIter, ..)) = - &path.kind + && let hir::ExprKind::Path(qpath) = path.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter) { Some(ShadowedIntoIterDiagSub::RemoveIntoIter { span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index e13ef7e70f447..e4cb56bc8eea5 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2586,8 +2586,6 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: Loc // FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty // contains const arguments. Is there a *concise* way to check for this? hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple, - // FIXME: Can they contain const arguments and thus leak private struct fields? - hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple, _ => Complex, } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 9e3162785f4b5..42150dd6a1907 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -10,7 +10,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in}; -use rustc_hir::def::DefKind; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lints::DelayedLint; use rustc_hir::*; @@ -203,6 +203,20 @@ impl<'tcx> TyCtxt<'tcx> { } }) } + + pub fn qpath_is_lang_item(self, qpath: QPath<'_>, lang_item: LangItem) -> bool { + self.qpath_lang_item(qpath) == Some(lang_item) + } + + /// This does not use typeck results since this is intended to be used with generated code. + pub fn qpath_lang_item(self, qpath: QPath<'_>) -> Option { + if let QPath::Resolved(_, path) = qpath + && let Res::Def(_, def_id) = path.res + { + return self.lang_items().from_def_id(def_id); + } + None + } } /// Hashes computed by [`TyCtxt::hash_owner_nodes`] if necessary. diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index d1fb700913d91..20657ba8c726c 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -266,7 +266,7 @@ impl<'tcx> TypeckResults<'tcx> { pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res { match *qpath { hir::QPath::Resolved(_, path) => path.res, - hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self + hir::QPath::TypeRelative(..) => self .type_dependent_def(id) .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 0b9bc018a09b3..8ce0b73e47e36 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -425,7 +425,6 @@ impl<'tcx> ThirBuildCx<'tcx> { None } } - _ => None, } } else { None diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index e87bac6114dd6..bfa0f01d1192e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1268,7 +1268,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { Res::Def(kind, def_id) => Some((kind, def_id)), _ => None, }, - hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { + hir::QPath::TypeRelative(..) => { match self.maybe_typeck_results { Some(typeck_results) => typeck_results.type_dependent_def(id), // FIXME: Check type-relative associated types in signatures. @@ -1287,9 +1287,6 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { if let DefKind::Static { .. } = kind { def_id.is_local() } else { false }; if !self.item_is_accessible(def_id) && !is_local_static { let name = match *qpath { - hir::QPath::LangItem(it, ..) => { - self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did)) - } hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())), hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()), }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 223d818a2949b..c1c9fa57f85b2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -517,6 +517,7 @@ symbols! { async_fn_track_caller, async_fn_traits, async_for_loop, + async_gen_internals, async_iterator, async_iterator_poll_next, async_trait_bounds, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 75283dc4ffaa6..0a2442b71e78f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1147,7 +1147,6 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { Box::new(segment.into_iter()) } - hir::QPath::LangItem(_, _) => Box::new(iter::empty()), } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4a95f21a3a5bd..75291e9cd7207 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1703,7 +1703,6 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type trait_, })) } - hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index bfb7962213972..23aaa6cf98604 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -253,7 +253,6 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String { let segments = match *p { hir::QPath::Resolved(_, path) => &path.segments, hir::QPath::TypeRelative(_, segment) => return segment.ident.to_string(), - hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(), }; join_path_idents(segments.iter().map(|seg| seg.ident)) diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 257f5da877b56..47cda92066282 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -300,7 +300,6 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { intravisit::walk_path(self, path); } } - _ => {} } } diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index b8bf8b25b3233..454026e80ab30 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -550,7 +550,6 @@ fn get_item_name(item: &Item<'_>) -> Option { // This case doesn't exist in the clippy tests codebase. None }, - QPath::LangItem(_, _) => None, } } else { // Impls for anything that isn't a named type can be skipped. diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index 89988be587588..bfe7a6355c00d 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -4,7 +4,7 @@ use clippy_utils::msrvs::Msrv; use clippy_utils::{is_in_const_context, is_in_test}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; -use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, QPath, RustcVersion, StabilityLevel, StableSince}; +use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, RustcVersion, StabilityLevel, StableSince}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; @@ -193,10 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { self.emit_lint_if_under_msrv(cx, method_did, expr.hir_id, span); } }, - // Desugaring into function calls by the compiler will use `QPath::LangItem` variants. Those should - // not be linted as they will not be generated in older compilers if the function is not available, - // and the compiler is allowed to call unstable functions. - ExprKind::Path(qpath @ (QPath::Resolved(..) | QPath::TypeRelative(..))) => { + ExprKind::Path(qpath) => { if let Some(path_def_id) = cx.qpath_res(&qpath, expr.hir_id).opt_def_id() { self.emit_lint_if_under_msrv(cx, path_def_id, expr.hir_id, expr.span); } @@ -206,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { } fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) { - if let hir::TyKind::Path(qpath @ (QPath::Resolved(..) | QPath::TypeRelative(..))) = hir_ty.kind + if let hir::TyKind::Path(qpath) = hir_ty.kind && let Some(ty_def_id) = cx.qpath_res(&qpath, hir_ty.hir_id).opt_def_id() // `CStr` and `CString` have been moved around but have been available since Rust 1.0.0 && !matches!(cx.tcx.get_diagnostic_name(ty_def_id), Some(sym::cstr_type | sym::cstring_type)) diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 99a393b4d53af..a2fcdb4a54b43 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { let note = "the suggestion might not be applicable in constant blocks"; let ty = cx.typeck_results().expr_ty(array).peel_refs(); let allowed_in_tests = self.allow_indexing_slicing_in_tests && is_in_test(cx.tcx, expr.hir_id); - if let Some(range) = higher::Range::hir(index) { + if let Some(range) = higher::Range::hir(cx, index) { // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.kind() { let size: u128 = if let Some(size) = s.try_to_target_usize(cx.tcx) { diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index f193f065e68d5..8f6de9fc60bdd 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -178,7 +178,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { Finite } }, - ExprKind::Struct(..) => higher::Range::hir(expr).is_some_and(|r| r.end.is_none()).into(), + ExprKind::Struct(..) => higher::Range::hir(cx, expr).is_some_and(|r| r.end.is_none()).into(), _ => Finite, } } diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index fd7965d564d59..b11e89a9b566c 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; use rustc_abi::Size; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; +use rustc_hir::{Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -58,7 +58,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let ExprKind::Match(scrutinee, _, MatchSource::AwaitDesugar) = expr.kind && let ExprKind::Call(func, [arg]) = scrutinee.kind - && let ExprKind::Path(QPath::LangItem(LangItem::IntoFutureIntoFuture, ..)) = func.kind + && let ExprKind::Path(qpath) = func.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoFutureIntoFuture) && !expr.span.from_expansion() && let ty = cx.typeck_results().expr_ty(arg) && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() diff --git a/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs b/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs index 7acf2a5462220..4aae602ea0516 100644 --- a/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs +++ b/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs @@ -131,7 +131,7 @@ fn check_index_usage<'tcx>( fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) { match node { - Node::Expr(expr) if higher::Range::hir(expr).is_some() => {}, + Node::Expr(expr) if higher::Range::hir(cx, expr).is_some() => {}, Node::ExprField(_) => {}, Node::Expr(expr) => return Some(expr), _ => break, diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index 7e48fe28011a8..e5c37377e857b 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -29,7 +29,7 @@ pub(super) fn check<'tcx>( end: Some(end), limits, span: _, - }) = higher::Range::hir(arg) + }) = higher::Range::hir(cx, arg) // the var must be a single name && let PatKind::Binding(_, canonical_id, _, _) = pat.kind { diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs b/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs index 94cddb4a15069..a2ff60a3d8ac8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs @@ -32,7 +32,7 @@ pub(super) fn check<'tcx>( end: Some(end), limits: RangeLimits::HalfOpen, span: _, - }) = higher::Range::hir(arg) + }) = higher::Range::hir(cx, arg) && let ExprKind::Lit(Spanned { node: LitKind::Int(Pu128(0), _), .. diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index daeda227f670c..6ab7bb628eca5 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { start: Some(start), end: Some(end), .. - }) = higher::Range::hir(arg) + }) = higher::Range::hir(cx, arg) && let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end)) && (mut_id_start.is_some() || mut_id_end.is_some()) { diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 7d890621d47c0..c974d9cca7d23 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>( ref end, limits, span, - }) = higher::Range::hir(arg) + }) = higher::Range::hir(cx, arg) // the var must be a single name && let PatKind::Binding(_, canonical_id, ident, _) = pat.kind { diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index d66771a8b5bec..edbf6e63e659f 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -90,7 +90,7 @@ pub(super) fn check<'tcx>( arg_snip = format!("({arg_snip})").into(); } - if clippy_utils::higher::Range::hir(arg_expression).is_some() { + if clippy_utils::higher::Range::hir(cx, arg_expression).is_some() { let range_expr = snippet(cx, arg_expression.span, "?").to_string(); let sugg = snippet(cx, arg_expression.span, ".."); diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index 456b488080907..a0f946d22fa61 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { end: Some(end), limits: RangeLimits::Closed, span: _, - }) = higher::Range::hir(receiver) + }) = higher::Range::hir(cx, receiver) && !matches!(cx.typeck_results().expr_ty(arg).peel_refs().kind(), ty::Param(_)) { let arg = peel_ref_operators(cx, arg); diff --git a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs index 63f6d89f2ad74..86f0eff9cd869 100644 --- a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs +++ b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs @@ -207,7 +207,7 @@ fn is_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { ExprKind::Index(arr, range, _) => match arr.kind { ExprKind::Array([]) => is_range_literal(range), ExprKind::Array(_) => { - let Some(range) = clippy_utils::higher::Range::hir(range) else { + let Some(range) = clippy_utils::higher::Range::hir(cx, range) else { return false; }; range.end.is_some_and(|e| clippy_utils::is_integer_const(cx, e, 0)) diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index f5d15310879a3..b668f391d67a2 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -237,7 +237,7 @@ fn find_stripping<'tcx>( if is_ref_str(self.cx, ex) && let unref = peel_ref(ex) && let ExprKind::Index(indexed, index, _) = &unref.kind - && let Some(higher::Range { start, end, .. }) = higher::Range::hir(index) + && let Some(higher::Range { start, end, .. }) = higher::Range::hir(self.cx, index) && let ExprKind::Path(path) = &indexed.kind && self.cx.qpath_res(path, ex.hir_id) == self.target { diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs index 7358628f0f7e6..401b8468135bc 100644 --- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs @@ -5,7 +5,7 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::option_arg_ty; use rustc_errors::Applicability; use rustc_hir::LangItem::ResultErr; -use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; +use rustc_hir::{Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::{hygiene, sym}; @@ -23,8 +23,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine // val, // }; if let ExprKind::Call(match_fun, [try_arg]) = scrutinee.kind - && let ExprKind::Path(ref match_fun_path) = match_fun.kind - && matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..)) + && let ExprKind::Path(match_fun_path) = match_fun.kind + && cx.tcx.qpath_is_lang_item(match_fun_path, LangItem::TryTraitBranch) && let ExprKind::Call(err_fun, [err_arg]) = try_arg.kind && err_fun.res(cx).ctor_parent(cx).is_lang_item(cx, ResultErr) && let Some(return_ty) = find_return_type(cx, &expr.kind) diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index 2a0ae14a4b088..8980a22ad6131 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_copy; use rustc_errors::Applicability; -use rustc_hir::{BindingMode, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; +use rustc_hir::{BindingMode, ByRef, Expr, ExprKind, MatchSource, Node, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; @@ -47,7 +47,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) // ? is a Call, makes sure not to rec *x?, but rather (*x)? ExprKind::Call(hir_callee, [_]) => matches!( hir_callee.kind, - ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, ..)) + ExprKind::Path(qpath) + if cx.tcx.qpath_is_lang_item(qpath, rustc_hir::LangItem::TryTraitBranch) ), ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true, ExprKind::Match(_, _, MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar) diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs index f37b15371c259..8c8c8c1dd8557 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs @@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal end: None, limits: ast::RangeLimits::HalfOpen, span: _, - }) = higher::Range::hir(index_expr) + }) = higher::Range::hir(cx, index_expr) && let hir::ExprKind::Lit(start_lit) = &start_expr.kind && let ast::LitKind::Int(start_idx, _) = start_lit.node { diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs index 38ca15cb1334c..f60387fe86f71 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -66,7 +66,7 @@ pub(super) fn check( method_name_span: Span, ) { let mut applicability = Applicability::MaybeIncorrect; - if let Some(range) = higher::Range::hir(receiver) + if let Some(range) = higher::Range::hir(cx, receiver) && let ExprKind::Closure(Closure { body, .. }) = arg.kind && let body_hir = cx.tcx.hir_body(*body) && let Body { diff --git a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs index de4207c2abf45..7ece83ba7ca39 100644 --- a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs @@ -11,7 +11,7 @@ use super::RANGE_ZIP_WITH_LEN; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, zip_arg: &'tcx Expr<'_>) { if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator) // range expression in `.zip()` call: `0..x.len()` - && let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg) + && let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(cx, zip_arg) && is_integer_const(cx, start, 0) // `.len()` call && let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index eee7fb0c5a813..fff203296bce9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -9,7 +9,7 @@ use clippy_utils::{paths, sym}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{ - BindingMode, Expr, ExprKind, HirId, LangItem, LetStmt, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind, + BindingMode, Expr, ExprKind, HirId, LangItem, LetStmt, MatchSource, Node, Pat, PatKind, Stmt, StmtKind, }; use rustc_lint::LateContext; use rustc_middle::ty; @@ -332,12 +332,12 @@ fn parse_iter_usage<'tcx>( let (unwrap_kind, span) = if let Some((_, Node::Expr(e))) = iter.next() { match e.kind { ExprKind::Call( - Expr { - kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)), + &Expr { + kind: ExprKind::Path(qpath), .. }, [_], - ) => { + ) if cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitBranch) => { let parent_span = e.span.parent_callsite().unwrap(); if parent_span.ctxt() == ctxt { (Some(UnwrapKind::QuestionMark), parent_span) diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs index 0ec2d8b4fc312..23546cad0af70 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs @@ -181,7 +181,6 @@ pub(super) fn check_function(cx: &LateContext<'_>, expr: &Expr<'_>, callee: &Exp QPath::TypeRelative(_, seg) => Some(SpansKind::Fn { fn_span: seg.ident.span, }), - QPath::LangItem(_, _) => unreachable!("`TryFrom` and `TryInto` are not lang items"), }; check( diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index cf0c85990b150..35d06780bcb82 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -220,14 +220,14 @@ impl<'hir> IndexEntry<'hir> { /// /// E.g. for `5` this returns `Some(5)`, for `..5` this returns `Some(4)`, /// for `..=5` this returns `Some(5)` -fn upper_index_expr(expr: &Expr<'_>) -> Option { +fn upper_index_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = &expr.kind && let LitKind::Int(Pu128(index), _) = lit.node { Some(index as usize) } else if let Some(higher::Range { end: Some(end), limits, .. - }) = higher::Range::hir(expr) + }) = higher::Range::hir(cx, expr) && let ExprKind::Lit(lit) = &end.kind && let LitKind::Int(Pu128(index @ 1..), _) = lit.node { @@ -244,7 +244,7 @@ fn upper_index_expr(expr: &Expr<'_>) -> Option { fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnindexMap>>) { if let ExprKind::Index(slice, index_lit, _) = expr.kind && cx.typeck_results().expr_ty_adjusted(slice).peel_refs().is_slice() - && let Some(index) = upper_index_expr(index_lit) + && let Some(index) = upper_index_expr(cx, index_lit) { let hash = hash_expr(cx, slice); diff --git a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs index 021a11593f3a7..f270ba7277cb6 100644 --- a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs +++ b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs @@ -74,7 +74,7 @@ fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) { impl<'tcx> LateLintPass<'tcx> for NeedlessParensOnRangeLiterals { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::Range { start, end, .. }) = higher::Range::hir(expr) { + if let Some(higher::Range { start, end, .. }) = higher::Range::hir(cx, expr) { if let Some(start) = start { check_for_parens(cx, start, true); } diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 986a827c59c55..29c45168b61e5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::MaybeQPath; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Block, Body, Expr, ExprKind, LangItem, MatchSource, QPath}; +use rustc_hir::{Block, Body, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -105,7 +105,8 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { } && let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind && let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind - && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind + && let ExprKind::Path(qpath) = called.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitBranch) && expr.span.eq_ctxt(inner_expr.span) && let expr_ty = cx.typeck_results().expr_ty(expr) && let inner_ty = cx.typeck_results().expr_ty(inner_expr) diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index e67ea1f5e370d..1a6165d0af835 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -530,11 +530,13 @@ impl QuestionMark { } } -fn is_try_block(bl: &Block<'_>) -> bool { +fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool { if let Some(expr) = bl.expr && let ExprKind::Call(callee, [_]) = expr.kind + && let ExprKind::Path(qpath) = callee.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitFromOutput) { - callee.opt_lang_path() == Some(LangItem::TryTraitFromOutput) + true } else { false } @@ -590,8 +592,8 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { } } - fn check_block(&mut self, _: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { - if is_try_block(block) { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { + if is_try_block(cx, block) { *self .try_block_depth_stack .last_mut() @@ -607,8 +609,8 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { self.try_block_depth_stack.pop(); } - fn check_block_post(&mut self, _: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { - if is_try_block(block) { + fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { + if is_try_block(cx, block) { *self .try_block_depth_stack .last_mut() diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index ac2cc11d30206..ca0d41fca5248 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::res::{MaybeQPath, MaybeResPath}; +use clippy_utils::res::MaybeResPath; use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; @@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_middle::ty::{self, ClauseKind, GenericArgKind, PredicatePolarity, Ty}; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; -use rustc_span::{Span, sym}; +use rustc_span::{DesugaringKind, Span, sym}; use std::cmp::Ordering; declare_clippy_lint! { @@ -368,7 +368,9 @@ fn can_switch_ranges<'tcx>( // Check if `expr` is the argument of a compiler-generated `IntoIter::into_iter(expr)` if let ExprKind::Call(func, [arg]) = parent_expr.kind && arg.hir_id == use_ctxt.child_id - && func.opt_lang_path() == Some(LangItem::IntoIterIntoIter) + && let ExprKind::Path(qpath) = func.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter) + && parent_expr.span.is_desugaring(DesugaringKind::ForLoop) { return true; } @@ -501,7 +503,7 @@ fn check_range_switch<'tcx>( msg: &'static str, operator: &str, ) { - if let Some(range) = higher::Range::hir(expr) + if let Some(range) = higher::Range::hir(cx, expr) && let higher::Range { start, end: Some(end), @@ -569,7 +571,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) { end: Some(end), limits, span, - }) = higher::Range::hir(expr) + }) = higher::Range::hir(cx, expr) && let ty = cx.typeck_results().expr_ty(start) && let ty::Int(_) | ty::Uint(_) = ty.kind() && let ecx = ConstEvalCtxt::new(cx) diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index 7bd4d6e993b47..e298fa55a2b69 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -97,7 +97,6 @@ fn extract_fn_ty<'tcx>( // let a: String = String::new(); // let a: String = String::get_string(); hir::QPath::TypeRelative(..) => func_hir_id_to_func_ty(cx, call.hir_id), - hir::QPath::LangItem(..) => None, } } diff --git a/src/tools/clippy/clippy_lints/src/returns/needless_return.rs b/src/tools/clippy/clippy_lints/src/returns/needless_return.rs index 04739fc1b22ad..7d836b610e5f8 100644 --- a/src/tools/clippy/clippy_lints/src/returns/needless_return.rs +++ b/src/tools/clippy/clippy_lints/src/returns/needless_return.rs @@ -7,7 +7,7 @@ use clippy_utils::{ use rustc_ast::MetaItemInner; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, Expr, ExprKind, HirId, LangItem, MatchSource, QPath, StmtKind}; +use rustc_hir::{Body, Expr, ExprKind, HirId, LangItem, MatchSource, StmtKind}; use rustc_lint::{LateContext, Level, LintContext}; use rustc_middle::ty::{self, Ty}; use rustc_span::{BytePos, Pos, Span}; @@ -134,7 +134,8 @@ fn check_final_expr<'tcx>( let replacement = if let Some(inner_expr) = inner { // if desugar of `do yeet`, don't lint if let ExprKind::Call(path_expr, [_]) = inner_expr.kind - && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, ..)) = path_expr.kind + && let ExprKind::Path(qpath) = path_expr.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::TryTraitFromYeet) { return; } diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs index dda2f8cc1d00b..960edc6b02803 100644 --- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs @@ -6,7 +6,7 @@ use clippy_utils::ty::implements_trait; use clippy_utils::{is_no_std_crate, sym}; use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr}; +use rustc_hir::{Expr, ExprKind, LangItem, StructTailExpr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use std::fmt::{self, Display, Formatter}; @@ -86,12 +86,12 @@ impl LateLintPass<'_> for SingleRangeInVecInit { return; }; - let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], StructTailExpr::None) = inner_expr.kind + let ExprKind::Struct(&qpath, [start, end], StructTailExpr::None) = inner_expr.kind else { return; }; - if matches!(lang_item, LangItem::Range) + if cx.tcx.qpath_is_lang_item(qpath, LangItem::Range) && let ty = cx.typeck_results().expr_ty(start.expr) && let Some(snippet) = span.get_source_text(cx) // `is_from_proc_macro` will skip any `vec![]`. Let's not! diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 47306949a6990..1d0efa46a14c1 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -6,7 +6,7 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath}; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::declare_lint_pass; @@ -266,7 +266,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { && expressions[0].1.is_empty() // Check for slicer - && let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind + && let ExprKind::Struct(&qpath, _, _) = right.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::Range) { let mut applicability = Applicability::MachineApplicable; let string_expression = &expressions[0].0; diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index ccb027f77bf5f..7018146f184b2 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -655,7 +655,6 @@ impl Types { } } }, - QPath::LangItem(..) => {}, } }, TyKind::Path(ref qpath) => { diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index e6663182fec53..48f1cda9ee7b9 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -106,7 +106,6 @@ fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Op _ => None, } }, - QPath::LangItem(..) => None, } } @@ -291,7 +290,6 @@ fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>, } get_hir_ty_def_id(tcx, *ty) == Some(implemented_ty_id) }, - QPath::LangItem(..) => false, } } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs index 94b1a34455ff0..af9f291f5deb7 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs @@ -60,7 +60,6 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor { } }, hir::QPath::TypeRelative(_, path) => path.ident.name, - hir::QPath::LangItem(..) => return, }; match constructor_symbol { sym::Some | sym::Ok if path.ident.name == sym::map => (), diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 2884bbd9280d2..ffce03cb5dbea 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -192,9 +192,9 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option { inner = unpack_match(inner); - inner = unpack_try(inner); + inner = unpack_try(cx, inner); inner = unpack_call_chain(inner); - inner = unpack_await(inner); + inner = unpack_await(cx, inner); // we type-check it to get whether it's a read/write or their vectorized forms // and keep only the ones that are produce io amount check_io_mode(cx, inner) @@ -256,12 +256,10 @@ fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { expr } -fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { +fn unpack_try<'a>(cx: &LateContext<'_>, mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { while let ExprKind::Call(func, [arg_0]) = expr.kind - && matches!( - func.kind, - ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) - ) + && let ExprKind::Path(qpath) = func.kind + && cx.tcx.qpath_is_lang_item(qpath, hir::LangItem::TryTraitBranch) { expr = arg_0; } @@ -277,13 +275,11 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { /// If `expr` is an (e).await, return the inner expression "e" that's being /// waited on. Otherwise return None. -fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { +fn unpack_await<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind && let ExprKind::Call(func, [arg_0]) = expr.kind - && matches!( - func.kind, - ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) - ) + && let ExprKind::Path(qpath) = func.kind + && cx.tcx.qpath_is_lang_item(qpath, hir::LangItem::IntoFutureIntoFuture) { return arg_0; } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 68e51dace2db2..222427cd3075f 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -270,9 +270,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } fn qpath(&self, qpath: &Binding<&QPath<'_>>, hir_id_binding: &str, hir_id: HirId) { - if let QPath::LangItem(lang_item, ..) = *qpath.value { - chain!(self, "matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _))"); - } else if let Some(def_id) = self.cx.qpath_res(qpath.value, hir_id).opt_def_id() + if let Some(def_id) = self.cx.qpath_res(qpath.value, hir_id).opt_def_id() && !def_id.is_local() { bind!(self, def_id); diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index ff3e7b94f03bf..544218e09930a 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -121,7 +121,6 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) { (start, end) }, QPath::TypeRelative(_, name) => (Pat::Str(""), Pat::Sym(name.ident.name)), - QPath::LangItem(..) => (Pat::Str(""), Pat::Str("")), } } diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index eb3f442ac754b..6f0e57bd3ab1c 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -167,7 +167,6 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS QPath::TypeRelative(_, name) => { self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, !args.is_empty()); }, - QPath::LangItem(..) => self.eagerness = Lazy, }, _ => self.eagerness = Lazy, }, diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 9d895c9aa649a..3904818cc9b6f 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -215,14 +215,12 @@ pub struct Range<'a> { impl<'a> Range<'a> { /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. #[expect(clippy::similar_names)] - pub fn hir(expr: &'a Expr<'_>) -> Option> { + pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option> { let span = expr.range_span()?; match expr.kind { ExprKind::Call(path, [arg1, arg2]) - if matches!( - path.kind, - ExprKind::Path(QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..)) - ) => + if let ExprKind::Path(qpath) = path.kind + && cx.tcx.qpath_is_lang_item(qpath, hir::LangItem::RangeInclusiveNew) => { Some(Range { start: Some(arg1), @@ -231,14 +229,14 @@ impl<'a> Range<'a> { span, }) }, - ExprKind::Struct(path, fields, StructTailExpr::None) => match (path, fields) { - (QPath::LangItem(hir::LangItem::RangeFull, ..), []) => Some(Range { + ExprKind::Struct(&qpath, fields, StructTailExpr::None) => match (cx.tcx.qpath_lang_item(qpath)?, fields) { + (hir::LangItem::RangeFull, []) => Some(Range { start: None, end: None, limits: ast::RangeLimits::HalfOpen, span, }), - (QPath::LangItem(hir::LangItem::RangeFrom, ..), [field]) if field.ident.name == sym::start => { + (hir::LangItem::RangeFrom, [field]) if field.ident.name == sym::start => { Some(Range { start: Some(field.expr), end: None, @@ -246,7 +244,7 @@ impl<'a> Range<'a> { span, }) }, - (QPath::LangItem(hir::LangItem::Range, ..), [field1, field2]) => { + (hir::LangItem::Range, [field1, field2]) => { let (start, end) = match (field1.ident.name, field2.ident.name) { (sym::start, sym::end) => (field1.expr, field2.expr), (sym::end, sym::start) => (field2.expr, field1.expr), @@ -259,7 +257,7 @@ impl<'a> Range<'a> { span, }) }, - (QPath::LangItem(hir::LangItem::RangeToInclusive, ..), [field]) if field.ident.name == sym::end => { + (hir::LangItem::RangeToInclusive, [field]) if field.ident.name == sym::end => { Some(Range { start: None, end: Some(field.expr), @@ -267,7 +265,7 @@ impl<'a> Range<'a> { span, }) }, - (QPath::LangItem(hir::LangItem::RangeTo, ..), [field]) if field.ident.name == sym::end => Some(Range { + (hir::LangItem::RangeTo, [field]) if field.ident.name == sym::end => Some(Range { start: None, end: Some(field.expr), limits: ast::RangeLimits::HalfOpen, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 974596a81a409..710b88e92154e 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -555,7 +555,6 @@ impl HirEqInterExpr<'_, '_, '_> { (QPath::TypeRelative(lty, lseg), QPath::TypeRelative(rty, rseg)) => { self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg) }, - (QPath::LangItem(llang_item, ..), QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item, _ => false, } } @@ -1092,9 +1091,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { QPath::TypeRelative(_, path) => { self.hash_name(path.ident.name); }, - QPath::LangItem(lang_item, ..) => { - std::mem::discriminant(lang_item).hash(&mut self.s); - }, } // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 6ee991eae137f..11220a8c4c017 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -361,7 +361,6 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> { match *path { QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"), QPath::TypeRelative(_, seg) => seg, - QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"), } } @@ -1282,7 +1281,7 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { /// If the given `Expr` is not some kind of range, the function returns `false`. pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool { let ty = cx.typeck_results().expr_ty(expr); - if let Some(Range { start, end, limits, .. }) = Range::hir(expr) { + if let Some(Range { start, end, limits, .. }) = Range::hir(cx, expr) { let start_is_none_or_min = start.is_none_or(|start| { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) diff --git a/src/tools/clippy/clippy_utils/src/res.rs b/src/tools/clippy/clippy_utils/src/res.rs index 90b9529278964..d1f6ebf35ce24 100644 --- a/src/tools/clippy/clippy_utils/src/res.rs +++ b/src/tools/clippy/clippy_utils/src/res.rs @@ -99,15 +99,6 @@ pub trait MaybeQPath<'a>: Copy { /// use for type dependant lookup. fn opt_qpath(self) -> Option>; - /// If this node is a `QPath::LangItem` gets the item it resolves to. - #[inline] - fn opt_lang_path(self) -> Option { - match self.opt_qpath() { - Some((&QPath::LangItem(item, _), _)) => Some(item), - _ => None, - } - } - /// If this is a path gets its resolution. Returns `Res::Err` otherwise. #[inline] #[cfg_attr(debug_assertions, track_caller)] @@ -116,10 +107,10 @@ pub trait MaybeQPath<'a>: Copy { fn f(qpath: &QPath<'_>, id: HirId, typeck: &TypeckResults<'_>) -> Res { match *qpath { QPath::Resolved(_, p) => p.res, - QPath::TypeRelative(..) | QPath::LangItem(..) if let Some((kind, id)) = typeck.ty_based_def(id) => { + QPath::TypeRelative(..) if let Some((kind, id)) = typeck.ty_based_def(id) => { Res::Def(kind, id) }, - QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err, + QPath::TypeRelative(..) => Res::Err, } } match self.opt_qpath() { @@ -148,7 +139,7 @@ pub trait MaybeQPath<'a>: Copy { { Res::Def(kind, id) }, - QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err, + QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err, } } match self.opt_qpath() { @@ -168,7 +159,7 @@ pub trait MaybeQPath<'a>: Copy { QPath::TypeRelative(_, seg) if let Some((kind, id)) = typeck.ty_based_def(id) => { (Res::Def(kind, id), Some(seg)) }, - QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => (Res::Err, None), + QPath::Resolved(..) | QPath::TypeRelative(..) => (Res::Err, None), } } match self.opt_qpath() { @@ -202,7 +193,7 @@ pub trait MaybeQPath<'a>: Copy { }, _, ) if let Some((kind, id)) = typeck.ty_based_def(id) => Res::Def(kind, id), - QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err, + QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err, } } match self.opt_qpath() { @@ -244,7 +235,7 @@ pub trait MaybeQPath<'a>: Copy { { Res::Def(kind, id) }, - QPath::Resolved(..) | QPath::TypeRelative(..) | QPath::LangItem(..) => Res::Err, + QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err, } } match self.opt_qpath() { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 581c2b02839dc..5945a0c7b5587 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -59,7 +59,7 @@ impl<'a> Sugg<'a> { pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { let ctxt = expr.span.ctxt(); let get_snippet = |span| snippet_with_context(cx, span, ctxt, "", &mut Applicability::Unspecified).0; - snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(expr, get_snippet)) + snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(cx, expr, get_snippet)) } /// Convenience function around `hir_opt` for suggestions with a default @@ -115,7 +115,7 @@ impl<'a> Sugg<'a> { Box::new(Self::hir_with_context(cx, inner, ctxt, default, applicability)), ) } else { - Self::hir_from_snippet(expr, |span| { + Self::hir_from_snippet(cx, expr, |span| { snippet_with_context(cx, span, ctxt, default, applicability).0 }) } @@ -127,8 +127,8 @@ impl<'a> Sugg<'a> { /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*` /// function variants of `Sugg`, since these use different snippet functions. - fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self { - if let Some(range) = higher::Range::hir(expr) { + fn hir_from_snippet(cx: &LateContext<'_>, expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self { + if let Some(range) = higher::Range::hir(cx, expr) { let op = AssocOp::Range(range.limits); let start = range.start.map_or("".into(), |expr| get_snippet(expr.span)); let end = range.end.map_or("".into(), |expr| get_snippet(expr.span)); @@ -166,7 +166,7 @@ impl<'a> Sugg<'a> { | ExprKind::Use(..) | ExprKind::Err(_) | ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)), - ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet), + ExprKind::DropTemps(inner) => Self::hir_from_snippet(cx, inner, get_snippet), ExprKind::Assign(lhs, rhs, _) => { Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span)) }, diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index d46c7bdcd4c1d..eadb07a11be02 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -197,19 +197,6 @@ fn qpath_certainty(cx: &LateContext<'_>, qpath: &QPath<'_>, resolves_to_type: bo QPath::TypeRelative(ty, path_segment) => { path_segment_certainty(cx, type_certainty(cx, ty), path_segment, resolves_to_type) }, - - QPath::LangItem(lang_item, ..) => cx - .tcx - .lang_items() - .get(*lang_item) - .map_or(Certainty::Uncertain, |def_id| { - let generics = cx.tcx.generics_of(def_id); - if generics.is_empty() { - Certainty::Certain(if resolves_to_type { Some(def_id) } else { None }) - } else { - Certainty::Uncertain - } - }), }; debug_assert!(resolves_to_type || certainty.to_def_id().is_none()); certainty diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout index 79794cec92698..6a3159939dd1e 100644 --- a/src/tools/clippy/tests/ui/author/loop.stdout +++ b/src/tools/clippy/tests/ui/author/loop.stdout @@ -2,7 +2,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo && let PatKind::Binding(BindingMode::NONE, _, name, None) = pat.kind && name.as_str() == "y" && let ExprKind::Struct(qpath, fields, None) = arg.kind - && matches!(qpath, QPath::LangItem(LangItem::Range, _)) + && let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id() + && paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed && fields.len() == 2 && fields[0].ident.as_str() == "start" && let ExprKind::Lit(ref lit) = fields[0].expr.kind @@ -23,7 +24,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr) && let PatKind::Wild = pat.kind && let ExprKind::Struct(qpath, fields, None) = arg.kind - && matches!(qpath, QPath::LangItem(LangItem::Range, _)) + && let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id() + && paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed && fields.len() == 2 && fields[0].ident.as_str() == "start" && let ExprKind::Lit(ref lit) = fields[0].expr.kind @@ -43,7 +45,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr) && let PatKind::Wild = pat.kind && let ExprKind::Struct(qpath, fields, None) = arg.kind - && matches!(qpath, QPath::LangItem(LangItem::Range, _)) + && let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id() + && paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed && fields.len() == 2 && fields[0].ident.as_str() == "start" && let ExprKind::Lit(ref lit) = fields[0].expr.kind diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout index 80717900b5255..ba3b7e2442043 100644 --- a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout +++ b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout @@ -2,7 +2,8 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo && let PatKind::Binding(BindingMode::NONE, _, name, None) = pat.kind && name.as_str() == "i" && let ExprKind::Struct(qpath, fields, None) = arg.kind - && matches!(qpath, QPath::LangItem(LangItem::Range, _)) + && let Some(def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id() + && paths::CORE_OPS_RANGE_RANGE.matches(cx, def_id) // Add the path to `clippy_utils::paths` if needed && fields.len() == 2 && fields[0].ident.as_str() == "start" && let ExprKind::Lit(ref lit) = fields[0].expr.kind diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp index 00c052d3f7986..e8b1741891304 100644 --- a/tests/pretty/hir-lifetimes.pp +++ b/tests/pretty/hir-lifetimes.pp @@ -29,11 +29,9 @@ fn d<'a>(&self, x: &'a u32) { } // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh - fn iter1<'a>(&self) - -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } } + fn iter1<'a>(&self) -> /*impl Trait*/ { Range { start: 0, end: 1 } } - fn iter2(&self) - -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } } + fn iter2(&self) -> /*impl Trait*/ { Range { start: 0, end: 1 } } } fn a(x: Foo<'_>) { } diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 27cba6560300a..ee22c3aeba9df 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -167,12 +167,12 @@ mod expressions { let x; { let _t = - match #[lang = "into_iter"](x) { + match into_iter(x) { mut iter => loop { - match #[lang = "next"](&mut iter) { - #[lang = "None"] {} => break, - #[lang = "Some"] { 0: _ } => { } + match next(&mut iter) { + None {} => break, + Some { 0: _ } => { } } }, }; @@ -180,12 +180,12 @@ mod expressions { }; { let _t = - match #[lang = "into_iter"](x) { + match into_iter(x) { mut iter => 'a: loop { - match #[lang = "next"](&mut iter) { - #[lang = "None"] {} => break, - #[lang = "Some"] { 0: _ } => { } + match next(&mut iter) { + None {} => break, + Some { 0: _ } => { } } }, }; @@ -253,10 +253,7 @@ mod expressions { } /// ExprKind::TryBlock - fn expr_try_block() { - { #[lang = "from_output"](()) } - { return; #[lang = "from_output"](()) } - } + fn expr_try_block() { { from_output(()) } { return; from_output(()) } } /// ExprKind::Assign fn expr_assign() { let expr; expr = true; } @@ -273,14 +270,14 @@ mod expressions { /// ExprKind::Range fn expr_range() { let (lo, hi); - #[lang = "RangeFull"] { }; - #[lang = "RangeTo"] { end: hi }; - #[lang = "RangeFrom"] { start: lo }; - #[lang = "Range"] { start: lo, end: hi }; - #[lang = "Range"] { start: lo, end: hi }; - #[lang = "RangeToInclusive"] { end: hi }; - #[lang = "range_inclusive_new"](lo, hi); - #[lang = "range_inclusive_new"](-2, -1); + RangeFull { }; + RangeTo { end: hi }; + RangeFrom { start: lo }; + Range { start: lo, end: hi }; + Range { start: lo, end: hi }; + RangeToInclusive { end: hi }; + range_inclusive_new(lo, hi); + range_inclusive_new(-2, -1); } /// ExprKind::Underscore @@ -373,20 +370,17 @@ mod expressions { /// ExprKind::Try fn expr_try() { let expr; - match #[lang = "branch"](expr) { - #[lang = "Break"] { 0: residual } => #[allow(unreachable_code)] - return #[lang = "from_residual"](residual), - #[lang = "Continue"] { 0: val } => #[allow(unreachable_code)] + match branch(expr) { + Break { 0: residual } => #[allow(unreachable_code)] + return from_residual(residual), + Continue { 0: val } => #[allow(unreachable_code)] val, }; } /// ExprKind::Yield fn expr_yield() { yield (); yield true; } /// ExprKind::Yeet - fn expr_yeet() { - return #[lang = "from_yeet"](()); - return #[lang = "from_yeet"](0); - } + fn expr_yeet() { return from_yeet(()); return from_yeet(0); } /// ExprKind::Become fn expr_become() { become true; } /// ExprKind::IncludedBytes