diff --git a/compiler/rustc_ast_lowering/src/contract.rs b/compiler/rustc_ast_lowering/src/contract.rs index bafc49607f410..56413160e04de 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; @@ -128,7 +130,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, @@ -143,8 +145,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 7e1130d9f233d..2be2fca87c3c5 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)), }; @@ -1479,7 +1480,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]) } @@ -1565,7 +1566,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, ) @@ -1715,8 +1716,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), ); @@ -1728,7 +1734,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 { @@ -2161,7 +2167,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) } @@ -2198,16 +2204,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_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index f09b02251e4d0..3c6db4b1e46f6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy}; +use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy}; use rustc_session::parse::feature_err; use super::prelude::*; @@ -592,7 +592,8 @@ impl SingleAttributeParser for SanitizeParser { r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, - r#"thread = "on|off""# + r#"thread = "on|off""#, + r#"realtime = "nonblocking|blocking|caller""#, ]); const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; @@ -606,6 +607,7 @@ impl SingleAttributeParser for SanitizeParser { let mut on_set = SanitizerSet::empty(); let mut off_set = SanitizerSet::empty(); + let mut rtsan = None; for item in list.mixed() { let Some(item) = item.meta_item() else { @@ -654,6 +656,17 @@ impl SingleAttributeParser for SanitizeParser { Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK), Some(sym::thread) => apply(SanitizerSet::THREAD), Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS), + Some(sym::realtime) => match value.value_as_str() { + Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking), + Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking), + Some(sym::caller) => rtsan = Some(RtsanSetting::Caller), + _ => { + cx.expected_specific_argument_strings( + value.value_span, + &[sym::nonblocking, sym::blocking, sym::caller], + ); + } + }, _ => { cx.expected_specific_argument_strings( item.path().span(), @@ -666,6 +679,7 @@ impl SingleAttributeParser for SanitizeParser { sym::shadow_call_stack, sym::thread, sym::hwaddress, + sym::realtime, ], ); continue; @@ -673,6 +687,6 @@ impl SingleAttributeParser for SanitizeParser { } } - Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span }) + Some(AttributeKind::Sanitize { on_set, off_set, rtsan, span: cx.attr_span }) } } 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_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 209b8efa2c3b3..7f53bdfee237d 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -1,8 +1,8 @@ //! Set and unset common attributes on LLVM values. -use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSetting}; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, }; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet}; @@ -98,10 +98,10 @@ fn patchable_function_entry_attrs<'ll>( pub(crate) fn sanitize_attrs<'ll, 'tcx>( cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>, - no_sanitize: SanitizerSet, + sanitizer_fn_attr: SanitizerFnAttrs, ) -> SmallVec<[&'ll Attribute; 4]> { let mut attrs = SmallVec::new(); - let enabled = tcx.sess.opts.unstable_opts.sanitizer - no_sanitize; + let enabled = tcx.sess.opts.unstable_opts.sanitizer - sanitizer_fn_attr.disabled; if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) { attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx)); } @@ -131,6 +131,18 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( if enabled.contains(SanitizerSet::SAFESTACK) { attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx)); } + if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::REALTIME) { + match sanitizer_fn_attr.rtsan_setting { + RtsanSetting::Nonblocking => { + attrs.push(llvm::AttributeKind::SanitizeRealtimeNonblocking.create_attr(cx.llcx)) + } + RtsanSetting::Blocking => { + attrs.push(llvm::AttributeKind::SanitizeRealtimeBlocking.create_attr(cx.llcx)) + } + // caller is the default, so no llvm attribute + RtsanSetting::Caller => (), + } + } attrs } @@ -417,7 +429,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( // not used. } else { // Do not set sanitizer attributes for naked functions. - to_add.extend(sanitize_attrs(cx, tcx, codegen_fn_attrs.no_sanitize)); + to_add.extend(sanitize_attrs(cx, tcx, codegen_fn_attrs.sanitizers)); // For non-naked functions, set branch protection attributes on aarch64. if let Some(BranchProtection { bti, pac_ret, gcs }) = diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index d18030b1574c5..8d526435add6b 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -630,6 +630,7 @@ pub(crate) unsafe fn llvm_optimize( sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY), sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY), sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int, + sanitize_realtime: config.sanitizer.contains(SanitizerSet::REALTIME), sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD), sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS), sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS), diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 4523d629b1ef6..6cbddfec46318 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -20,7 +20,7 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::attrs::Linkage; use rustc_middle::dep_graph; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; @@ -105,7 +105,7 @@ pub(crate) fn compile_codegen_unit( if let Some(entry) = maybe_create_entry_wrapper::>(&cx, cx.codegen_unit) { - let attrs = attributes::sanitize_attrs(&cx, tcx, SanitizerSet::empty()); + let attrs = attributes::sanitize_attrs(&cx, tcx, SanitizerFnAttrs::default()); attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs); } @@ -191,10 +191,10 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { } pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) { - if attrs.no_sanitize.contains(SanitizerSet::ADDRESS) { + if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS) { unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) }; } - if attrs.no_sanitize.contains(SanitizerSet::HWADDRESS) { + if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS) { unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) }; } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index c082a82306848..bcca90046a4ce 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1803,7 +1803,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { && is_indirect_call { if let Some(fn_attrs) = fn_attrs - && fn_attrs.no_sanitize.contains(SanitizerSet::CFI) + && fn_attrs.sanitizers.disabled.contains(SanitizerSet::CFI) { return; } @@ -1861,7 +1861,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { && is_indirect_call { if let Some(fn_attrs) = fn_attrs - && fn_attrs.no_sanitize.contains(SanitizerSet::KCFI) + && fn_attrs.sanitizers.disabled.contains(SanitizerSet::KCFI) { return None; } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 53f0f9ff9d01b..95baa28f96405 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -290,6 +290,8 @@ pub(crate) enum AttributeKind { DeadOnReturn = 44, CapturesReadOnly = 45, CapturesNone = 46, + SanitizeRealtimeNonblocking = 47, + SanitizeRealtimeBlocking = 48, } /// LLVMIntPredicate @@ -482,6 +484,7 @@ pub(crate) struct SanitizerOptions { pub sanitize_memory: bool, pub sanitize_memory_recover: bool, pub sanitize_memory_track_origins: c_int, + pub sanitize_realtime: bool, pub sanitize_thread: bool, pub sanitize_hwaddress: bool, pub sanitize_hwaddress_recover: bool, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ea538d3d46981..4f8b5afb19cf3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1251,6 +1251,9 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::SAFESTACK) { link_sanitizer_runtime(sess, flavor, linker, "safestack"); } + if sanitizer.contains(SanitizerSet::REALTIME) { + link_sanitizer_runtime(sess, flavor, linker, "rtsan"); + } } fn link_sanitizer_runtime( diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 44de48a3ada51..720f8061c4e66 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -3,12 +3,12 @@ use std::str::FromStr; use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; -use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy}; +use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, RtsanSetting, UsedBy}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, }; use rustc_middle::query::Providers; use rustc_middle::span_bug; @@ -16,7 +16,6 @@ use rustc_middle::ty::{self as ty, TyCtxt}; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::{Ident, Span, sym}; -use rustc_target::spec::SanitizerSet; use crate::errors; use crate::target_features::{ @@ -350,8 +349,10 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); - // Compute the disabled sanitizers. - codegen_fn_attrs.no_sanitize |= tcx.disabled_sanitizers_for(did); + // Passed in sanitizer settings are always the default. + assert!(codegen_fn_attrs.sanitizers == SanitizerFnAttrs::default()); + // Replace with #[sanitize] value + codegen_fn_attrs.sanitizers = tcx.sanitizer_settings_for(did); // On trait methods, inherit the `#[align]` of the trait's method prototype. codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did)); @@ -455,18 +456,40 @@ fn check_result( } // warn that inline has no effect when no_sanitize is present - if !codegen_fn_attrs.no_sanitize.is_empty() + if codegen_fn_attrs.sanitizers != SanitizerFnAttrs::default() && codegen_fn_attrs.inline.always() - && let (Some(no_sanitize_span), Some(inline_span)) = + && let (Some(sanitize_span), Some(inline_span)) = (interesting_spans.sanitize, interesting_spans.inline) { let hir_id = tcx.local_def_id_to_hir_id(did); - tcx.node_span_lint(lint::builtin::INLINE_NO_SANITIZE, hir_id, no_sanitize_span, |lint| { - lint.primary_message("setting `sanitize` off will have no effect after inlining"); + tcx.node_span_lint(lint::builtin::INLINE_NO_SANITIZE, hir_id, sanitize_span, |lint| { + lint.primary_message("non-default `sanitize` will have no effect after inlining"); lint.span_note(inline_span, "inlining requested here"); }) } + // warn for nonblocking async fn. + // This doesn't behave as expected, because the executor can run blocking code without the sanitizer noticing. + if codegen_fn_attrs.sanitizers.rtsan_setting == RtsanSetting::Nonblocking + && let Some(sanitize_span) = interesting_spans.sanitize + // async function + && (tcx.asyncness(did).is_async() || (tcx.is_closure_like(did.into()) + // async block + && (tcx.coroutine_is_async(did.into()) + // async closure + || tcx.coroutine_is_async(tcx.coroutine_for_closure(did))))) + { + let hir_id = tcx.local_def_id_to_hir_id(did); + tcx.node_span_lint( + lint::builtin::RTSAN_NONBLOCKING_ASYNC, + hir_id, + sanitize_span, + |lint| { + lint.primary_message(r#"the async executor can run blocking code, without realtime sanitizer catching it"#); + } + ); + } + // error when specifying link_name together with link_ordinal if let Some(_) = codegen_fn_attrs.symbol_name && let Some(_) = codegen_fn_attrs.link_ordinal @@ -576,30 +599,35 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs } -fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet { +fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs { // Backtrack to the crate root. - let mut disabled = match tcx.opt_local_parent(did) { + let mut settings = match tcx.opt_local_parent(did) { // Check the parent (recursively). - Some(parent) => tcx.disabled_sanitizers_for(parent), + Some(parent) => tcx.sanitizer_settings_for(parent), // We reached the crate root without seeing an attribute, so // there is no sanitizers to exclude. - None => SanitizerSet::empty(), + None => SanitizerFnAttrs::default(), }; // Check for a sanitize annotation directly on this def. - if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set)) + if let Some((on_set, off_set, rtsan)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, rtsan, ..} => (on_set, off_set, rtsan)) { // the on set is the set of sanitizers explicitly enabled. // we mask those out since we want the set of disabled sanitizers here - disabled &= !*on_set; + settings.disabled &= !*on_set; // the off set is the set of sanitizers explicitly disabled. // we or those in here. - disabled |= *off_set; + settings.disabled |= *off_set; // the on set and off set are distjoint since there's a third option: unset. // a node may not set the sanitizer setting in which case it inherits from parents. // the code above in this function does this backtracking + + // if rtsan was specified here override the parent + if let Some(rtsan) = rtsan { + settings.rtsan_setting = *rtsan; + } } - disabled + settings } /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller @@ -731,7 +759,7 @@ pub(crate) fn provide(providers: &mut Providers) { codegen_fn_attrs, should_inherit_track_caller, inherited_align, - disabled_sanitizers_for, + sanitizer_settings_for, ..*providers }; } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 828c15cc391dd..b14fd5e7ce266 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -382,6 +382,16 @@ pub struct DebugVisualizer { pub path: Symbol, } +#[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)] +#[derive(HashStable_Generic, PrintAttribute)] +#[derive_const(Default)] +pub enum RtsanSetting { + Nonblocking, + Blocking, + #[default] + Caller, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -683,7 +693,13 @@ pub enum AttributeKind { /// /// the on set and off set are distjoint since there's a third option: unset. /// a node may not set the sanitizer setting in which case it inherits from parents. - Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span }, + /// rtsan is unset if None + Sanitize { + on_set: SanitizerSet, + off_set: SanitizerSet, + rtsan: Option, + span: Span, + }, /// Represents `#[should_panic]` ShouldPanic { reason: Option, span: Span }, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 8b55a0d732994..d26e289bc0d28 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/src/lib.rs b/compiler/rustc_hir/src/lib.rs index eb630fc801863..2fc2572c80924 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -5,7 +5,10 @@ // tidy-alphabetical-start #![feature(associated_type_defaults)] #![feature(closure_track_caller)] +#![feature(const_default)] +#![feature(const_trait_impl)] #![feature(debug_closure_helpers)] +#![feature(derive_const)] #![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(variant_count)] 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 abdb01bcefb2c..5bd730a811fff 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; @@ -1290,10 +1290,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)) - } } } @@ -2051,8 +2047,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 f7df5dafa184f..09361f046ea89 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_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 5e9cb42365049..56c3f65d8ae8e 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -9,8 +9,9 @@ use rustc_ast as ast; use rustc_attr_parsing::{ShouldEmit, validate_attr}; use rustc_codegen_ssa::back::archive::ArArchiveBuilderBuilder; use rustc_codegen_ssa::back::link::link_binary; +use rustc_codegen_ssa::target_features::{self, cfg_target_feature}; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_codegen_ssa::{CodegenResults, CrateInfo}; +use rustc_codegen_ssa::{CodegenResults, CrateInfo, TargetConfig}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; @@ -354,6 +355,33 @@ impl CodegenBackend for DummyCodegenBackend { "dummy" } + fn target_config(&self, sess: &Session) -> TargetConfig { + let (target_features, unstable_target_features) = cfg_target_feature(sess, |feature| { + // This is a standin for the list of features a backend is expected to enable. + // It would be better to parse target.features instead and handle implied features, + // but target.features is a list of LLVM target features, not Rust target features. + // The dummy backend doesn't know the mapping between LLVM and Rust target features. + sess.target.abi_required_features().required.contains(&feature) + }); + + // To report warnings about unknown features + target_features::flag_to_backend_features::<0>( + sess, + true, + |_| Default::default(), + |_, _| {}, + ); + + TargetConfig { + target_features, + unstable_target_features, + has_reliable_f16: true, + has_reliable_f16_math: true, + has_reliable_f128: true, + has_reliable_f128_math: true, + } + } + fn supported_crate_types(&self, _sess: &Session) -> Vec { // This includes bin despite failing on the link step to ensure that you // can still get the frontend handling for binaries. For all library 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_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8c474ed28240c..dc7634c7f853e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -87,6 +87,7 @@ declare_lint_pass! { REFINING_IMPL_TRAIT_REACHABLE, RENAMED_AND_REMOVED_LINTS, REPR_TRANSPARENT_NON_ZST_FIELDS, + RTSAN_NONBLOCKING_ASYNC, RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, RUST_2021_INCOMPATIBLE_OR_PATTERNS, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, @@ -2332,6 +2333,35 @@ declare_lint! { r#"detects incompatible use of `#[inline(always)]` and `#[sanitize(... = "off")]`"#, } +declare_lint! { + /// The `rtsan_nonblocking_async` lint detects incompatible use of + /// [`#[sanitize(realtime = "nonblocking")]`][sanitize] on async functions. + /// + /// [sanitize]: https://doc.rust-lang.org/nightly/unstable-book/language-features/no-sanitize.html + /// ### Example + /// + /// ```rust,no_run + /// #![feature(sanitize)] + /// + /// #[sanitize(realtime = "nonblocking")] + /// async fn x() {} + /// + /// fn main() { + /// x(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The sanitizer only considers the async function body nonblocking. The executor, which runs on + /// every `.await` point can run non-realtime code, without the sanitizer catching it. + pub RTSAN_NONBLOCKING_ASYNC, + Warn, + r#"detects incompatible uses of `#[sanitize(realtime = "nonblocking")]` on async functions"#, +} + declare_lint! { /// The `asm_sub_register` lint detects using only a subset of a register /// for inline asm inputs. diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 616c8a17dd66d..18fd2125dfb0c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -38,6 +38,7 @@ #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" +#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Scalar/AnnotationRemarks.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" @@ -511,6 +512,7 @@ struct LLVMRustSanitizerOptions { bool SanitizeMemory; bool SanitizeMemoryRecover; int SanitizeMemoryTrackOrigins; + bool SanitizerRealtime; bool SanitizeThread; bool SanitizeHWAddress; bool SanitizeHWAddressRecover; @@ -766,6 +768,13 @@ extern "C" LLVMRustResult LLVMRustOptimize( MPM.addPass(HWAddressSanitizerPass(opts)); }); } + if (SanitizerOptions->SanitizerRealtime) { + OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM, + OptimizationLevel Level, + ThinOrFullLTOPhase phase) { + MPM.addPass(RealtimeSanitizerPass()); + }); + } } ModulePassManager MPM; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index ad459986826a5..0d63b5173e636 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -246,6 +246,8 @@ enum class LLVMRustAttributeKind { DeadOnReturn = 44, CapturesReadOnly = 45, CapturesNone = 46, + SanitizeRealtimeNonblocking = 47, + SanitizeRealtimeBlocking = 48, }; static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { @@ -342,6 +344,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { case LLVMRustAttributeKind::CapturesReadOnly: case LLVMRustAttributeKind::CapturesNone: report_fatal_error("Should be handled separately"); + case LLVMRustAttributeKind::SanitizeRealtimeNonblocking: + return Attribute::SanitizeRealtime; + case LLVMRustAttributeKind::SanitizeRealtimeBlocking: + return Attribute::SanitizeRealtimeBlocking; } report_fatal_error("bad LLVMRustAttributeKind"); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 778007854b772..f47e349ac391d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2598,8 +2598,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/lib.rs b/compiler/rustc_middle/src/lib.rs index 754a258eef93d..708566130d76d 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -38,6 +38,8 @@ #![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] +#![feature(const_default)] +#![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(debug_closure_helpers)] #![feature(decl_macro)] diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index d47d811610a74..5a28d56d4e549 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use rustc_abi::Align; -use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr}; +use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr, RtsanSetting}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Symbol; use rustc_target::spec::SanitizerSet; @@ -80,9 +80,9 @@ pub struct CodegenFnAttrs { /// The `#[link_section = "..."]` attribute, or what executable section this /// should be placed in. pub link_section: Option, - /// The `#[sanitize(xyz = "off")]` attribute. Indicates sanitizers for which - /// instrumentation should be disabled inside the function. - pub no_sanitize: SanitizerSet, + /// The `#[sanitize(xyz = "off")]` attribute. Indicates the settings for each + /// sanitizer for this function. + pub sanitizers: SanitizerFnAttrs, /// The `#[instruction_set(set)]` attribute. Indicates if the generated code should /// be generated against a specific instruction set. Only usable on architectures which allow /// switching between multiple instruction sets. @@ -209,7 +209,7 @@ impl CodegenFnAttrs { linkage: None, import_linkage: None, link_section: None, - no_sanitize: SanitizerSet::empty(), + sanitizers: SanitizerFnAttrs::default(), instruction_set: None, alignment: None, patchable_function_entry: None, @@ -241,3 +241,15 @@ impl CodegenFnAttrs { } } } + +#[derive(Clone, Copy, Debug, HashStable, TyEncodable, TyDecodable, Eq, PartialEq)] +pub struct SanitizerFnAttrs { + pub disabled: SanitizerSet, + pub rtsan_setting: RtsanSetting, +} + +impl const Default for SanitizerFnAttrs { + fn default() -> Self { + Self { disabled: SanitizerSet::empty(), rtsan_setting: RtsanSetting::default() } + } +} diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 46100358c7d76..404330a9a45a0 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -348,6 +348,7 @@ trivial! { rustc_middle::ty::UnusedGenericParams, rustc_middle::ty::util::AlwaysRequiresDrop, rustc_middle::ty::Visibility, + rustc_middle::middle::codegen_fn_attrs::SanitizerFnAttrs, rustc_session::config::CrateType, rustc_session::config::EntryFnType, rustc_session::config::OptLevel, @@ -365,7 +366,6 @@ trivial! { rustc_span::Symbol, rustc_span::Ident, rustc_target::spec::PanicStrategy, - rustc_target::spec::SanitizerSet, rustc_type_ir::Variance, u32, usize, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 30d4cc8b3c8d6..22d4676e9733a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -97,7 +97,7 @@ use rustc_session::lint::LintExpectationId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span, Symbol}; -use rustc_target::spec::{PanicStrategy, SanitizerSet}; +use rustc_target::spec::PanicStrategy; use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; @@ -105,7 +105,7 @@ pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsur use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::CodegenFnAttrs; +use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::deduced_param_attrs::DeducedParamAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; @@ -2729,8 +2729,8 @@ rustc_queries! { /// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the /// crate root. /// - /// Returns the set of sanitizers that is explicitly disabled for this def. - query disabled_sanitizers_for(key: LocalDefId) -> SanitizerSet { + /// Returns the sanitizer settings for this def. + query sanitizer_settings_for(key: LocalDefId) -> SanitizerFnAttrs { desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } feedable } 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_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 2ccd8178e667b..54ed2a95174ee 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -52,7 +52,7 @@ mod by_move_body; mod drop; -use std::{iter, ops}; +use std::ops; pub(super) use by_move_body::coroutine_by_move_body_def_id; use drop::{ @@ -60,6 +60,7 @@ use drop::{ create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, expand_async_drops, has_expandable_async_drops, insert_clean_drop, }; +use itertools::izip; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; @@ -752,53 +753,53 @@ fn locals_live_across_suspend_points<'tcx>( let mut live_locals_at_any_suspension_point = DenseBitSet::new_empty(body.local_decls.len()); for (block, data) in body.basic_blocks.iter_enumerated() { - if let TerminatorKind::Yield { .. } = data.terminator().kind { - let loc = Location { block, statement_index: data.statements.len() }; - - liveness.seek_to_block_end(block); - let mut live_locals = liveness.get().clone(); - - if !movable { - // The `liveness` variable contains the liveness of MIR locals ignoring borrows. - // This is correct for movable coroutines since borrows cannot live across - // suspension points. However for immovable coroutines we need to account for - // borrows, so we conservatively assume that all borrowed locals are live until - // we find a StorageDead statement referencing the locals. - // To do this we just union our `liveness` result with `borrowed_locals`, which - // contains all the locals which has been borrowed before this suspension point. - // If a borrow is converted to a raw reference, we must also assume that it lives - // forever. Note that the final liveness is still bounded by the storage liveness - // of the local, which happens using the `intersect` operation below. - borrowed_locals_cursor2.seek_before_primary_effect(loc); - live_locals.union(borrowed_locals_cursor2.get()); - } + let TerminatorKind::Yield { .. } = data.terminator().kind else { continue }; + + let loc = Location { block, statement_index: data.statements.len() }; + + liveness.seek_to_block_end(block); + let mut live_locals = liveness.get().clone(); + + if !movable { + // The `liveness` variable contains the liveness of MIR locals ignoring borrows. + // This is correct for movable coroutines since borrows cannot live across + // suspension points. However for immovable coroutines we need to account for + // borrows, so we conservatively assume that all borrowed locals are live until + // we find a StorageDead statement referencing the locals. + // To do this we just union our `liveness` result with `borrowed_locals`, which + // contains all the locals which has been borrowed before this suspension point. + // If a borrow is converted to a raw reference, we must also assume that it lives + // forever. Note that the final liveness is still bounded by the storage liveness + // of the local, which happens using the `intersect` operation below. + borrowed_locals_cursor2.seek_before_primary_effect(loc); + live_locals.union(borrowed_locals_cursor2.get()); + } - // Store the storage liveness for later use so we can restore the state - // after a suspension point - storage_live.seek_before_primary_effect(loc); - storage_liveness_map[block] = Some(storage_live.get().clone()); + // Store the storage liveness for later use so we can restore the state + // after a suspension point + storage_live.seek_before_primary_effect(loc); + storage_liveness_map[block] = Some(storage_live.get().clone()); - // Locals live are live at this point only if they are used across - // suspension points (the `liveness` variable) - // and their storage is required (the `storage_required` variable) - requires_storage_cursor.seek_before_primary_effect(loc); - live_locals.intersect(requires_storage_cursor.get()); + // Locals live are live at this point only if they are used across + // suspension points (the `liveness` variable) + // and their storage is required (the `storage_required` variable) + requires_storage_cursor.seek_before_primary_effect(loc); + live_locals.intersect(requires_storage_cursor.get()); - // The coroutine argument is ignored. - live_locals.remove(SELF_ARG); + // The coroutine argument is ignored. + live_locals.remove(SELF_ARG); - debug!("loc = {:?}, live_locals = {:?}", loc, live_locals); + debug!(?loc, ?live_locals); - // Add the locals live at this suspension point to the set of locals which live across - // any suspension points - live_locals_at_any_suspension_point.union(&live_locals); + // Add the locals live at this suspension point to the set of locals which live across + // any suspension points + live_locals_at_any_suspension_point.union(&live_locals); - live_locals_at_suspension_points.push(live_locals); - source_info_at_suspension_points.push(data.terminator().source_info); - } + live_locals_at_suspension_points.push(live_locals); + source_info_at_suspension_points.push(data.terminator().source_info); } - debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point); + debug!(?live_locals_at_any_suspension_point); let saved_locals = CoroutineSavedLocals(live_locals_at_any_suspension_point); // Renumber our liveness_map bitsets to include only the locals we are @@ -999,8 +1000,8 @@ fn compute_layout<'tcx>( } = liveness; // Gather live local types and their indices. - let mut locals = IndexVec::::new(); - let mut tys = IndexVec::::new(); + let mut locals = IndexVec::::with_capacity(saved_locals.domain_size()); + let mut tys = IndexVec::::with_capacity(saved_locals.domain_size()); for (saved_local, local) in saved_locals.iter_enumerated() { debug!("coroutine saved local {:?} => {:?}", saved_local, local); @@ -1034,38 +1035,39 @@ fn compute_layout<'tcx>( // In debuginfo, these will correspond to the beginning (UNRESUMED) or end // (RETURNED, POISONED) of the function. let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span; - let mut variant_source_info: IndexVec = [ + let mut variant_source_info: IndexVec = IndexVec::with_capacity( + CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), + ); + variant_source_info.extend([ SourceInfo::outermost(body_span.shrink_to_lo()), SourceInfo::outermost(body_span.shrink_to_hi()), SourceInfo::outermost(body_span.shrink_to_hi()), - ] - .iter() - .copied() - .collect(); + ]); // Build the coroutine variant field list. // Create a map from local indices to coroutine struct indices. - let mut variant_fields: IndexVec> = - iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect(); + let mut variant_fields: IndexVec = IndexVec::from_elem_n( + IndexVec::new(), + CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), + ); let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size()); - for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() { - let variant_index = - VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx); - let mut fields = IndexVec::new(); - for (idx, saved_local) in live_locals.iter().enumerate() { - fields.push(saved_local); + for (live_locals, &source_info_at_suspension_point, (variant_index, fields)) in izip!( + &live_locals_at_suspension_points, + &source_info_at_suspension_points, + variant_fields.iter_enumerated_mut().skip(CoroutineArgs::RESERVED_VARIANTS) + ) { + *fields = live_locals.iter().collect(); + for (idx, &saved_local) in fields.iter_enumerated() { // Note that if a field is included in multiple variants, we will // just use the first one here. That's fine; fields do not move // around inside coroutines, so it doesn't matter which variant // index we access them by. - let idx = FieldIdx::from_usize(idx); remap[locals[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); } - variant_fields.push(fields); - variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]); + variant_source_info.push(source_info_at_suspension_point); } - debug!("coroutine variant_fields = {:?}", variant_fields); - debug!("coroutine storage_conflicts = {:#?}", storage_conflicts); + debug!(?variant_fields); + debug!(?storage_conflicts); let mut field_names = IndexVec::from_elem(None, &tys); for var in &body.var_debug_info { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 8eae80e235ccd..48663c4a52f61 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -921,7 +921,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } } - if projection.is_owned() { + if Cow::is_owned(&projection) { place.projection = self.tcx.mk_place_elems(&projection); } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index dc6088849bf5e..793060f626e41 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -818,7 +818,7 @@ fn check_codegen_attributes<'tcx, I: Inliner<'tcx>>( } let codegen_fn_attrs = tcx.codegen_fn_attrs(inliner.caller_def_id()); - if callee_attrs.no_sanitize != codegen_fn_attrs.no_sanitize { + if callee_attrs.sanitizers != codegen_fn_attrs.sanitizers { return Err("incompatible sanitizer set"); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ef42c42f68b37..856d587d452fd 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -212,7 +212,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => { self.check_custom_mir(dialect, phase, attr_span) } - &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => { + &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, rtsan: _, span: attr_span}) => { self.check_sanitize(attr_span, on_set | off_set, span, target); }, Attribute::Parsed(AttributeKind::Link(_, attr_span)) => { 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_public/src/compiler_interface.rs b/compiler/rustc_public/src/compiler_interface.rs index 5a09c3b24f0f1..b17d31f2b91ab 100644 --- a/compiler/rustc_public/src/compiler_interface.rs +++ b/compiler/rustc_public/src/compiler_interface.rs @@ -3,11 +3,11 @@ //! rustc_public users should not use any of the items in this module directly. //! These APIs have no stability guarantee. -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use rustc_hir::def::DefKind; use rustc_public_bridge::context::CompilerCtxt; -use rustc_public_bridge::{Bridge, Container}; +use rustc_public_bridge::{Bridge, Tables}; use tracing::debug; use crate::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; @@ -68,256 +68,17 @@ impl Bridge for BridgeTys { /// Public API for querying compiler information. /// -/// All queries are delegated to [`rustc_public_bridge::context::CompilerCtxt`] that provides -/// similar APIs but based on internal rustc constructs. +/// All queries are delegated to [`rustc_public_bridge::context::CompilerCtxt`] +/// that provides similar APIs but based on internal rustc constructs. /// /// Do not use this directly. This is currently used in the macro expansion. -pub(crate) trait CompilerInterface { - fn entry_fn(&self) -> Option; - /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&self) -> CrateItems; - /// Retrieve the body of a function. - /// This function will panic if the body is not available. - fn mir_body(&self, item: DefId) -> mir::Body; - /// Check whether the body of a function is available. - fn has_body(&self, item: DefId) -> bool; - fn foreign_modules(&self, crate_num: CrateNum) -> Vec; - - /// Retrieve all functions defined in this crate. - fn crate_functions(&self, crate_num: CrateNum) -> Vec; - - /// Retrieve all static items defined in this crate. - fn crate_statics(&self, crate_num: CrateNum) -> Vec; - fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule; - fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec; - fn all_trait_decls(&self) -> TraitDecls; - fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls; - fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; - fn all_trait_impls(&self) -> ImplTraitDecls; - fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls; - fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; - fn generics_of(&self, def_id: DefId) -> Generics; - fn predicates_of(&self, def_id: DefId) -> GenericPredicates; - fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; - - /// Get information about the local crate. - fn local_crate(&self) -> Crate; - /// Retrieve a list of all external crates. - fn external_crates(&self) -> Vec; - - /// Find a crate with the given name. - fn find_crates(&self, name: &str) -> Vec; - - /// Returns the name of given `DefId` - fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol; - - /// Return registered tool attributes with the given attribute name. - /// - /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool - /// attributes will simply return an empty list. - /// - /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`. - /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`. - fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec; - - /// Get all tool attributes of a definition. - fn all_tool_attrs(&self, def_id: DefId) -> Vec; - - /// Returns printable, human readable form of `Span` - fn span_to_string(&self, span: Span) -> String; - - /// Return filename from given `Span`, for diagnostic purposes - fn get_filename(&self, span: &Span) -> Filename; - - /// Return lines corresponding to this `Span` - fn get_lines(&self, span: &Span) -> LineInfo; - - /// Returns the `kind` of given `DefId` - fn item_kind(&self, item: CrateItem) -> ItemKind; - - /// Returns whether this is a foreign item. - fn is_foreign_item(&self, item: DefId) -> bool; - - /// Returns the kind of a given foreign item. - fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind; - - /// Returns the kind of a given algebraic data type - fn adt_kind(&self, def: AdtDef) -> AdtKind; - - /// Returns if the ADT is a box. - fn adt_is_box(&self, def: AdtDef) -> bool; - - /// Returns whether this ADT is simd. - fn adt_is_simd(&self, def: AdtDef) -> bool; - - /// Returns whether this definition is a C string. - fn adt_is_cstr(&self, def: AdtDef) -> bool; - - /// Returns the representation options for this ADT. - fn adt_repr(&self, def: AdtDef) -> ReprOptions; - - /// Retrieve the function signature for the given generic arguments. - fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig; - - /// Retrieve the intrinsic definition if the item corresponds one. - fn intrinsic(&self, item: DefId) -> Option; - - /// Retrieve the plain function name of an intrinsic. - fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol; - - /// Retrieve the closure signature for the given generic arguments. - fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig; - - /// The number of variants in this ADT. - fn adt_variants_len(&self, def: AdtDef) -> usize; - - /// Discriminant for a given variant index of AdtDef. - fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr; - - /// Discriminant for a given variand index and args of a coroutine. - fn coroutine_discr_for_variant( - &self, - coroutine: CoroutineDef, - args: &GenericArgs, - variant: VariantIdx, - ) -> Discr; - - /// The name of a variant. - fn variant_name(&self, def: VariantDef) -> Symbol; - fn variant_fields(&self, def: VariantDef) -> Vec; - - /// Evaluate constant as a target usize. - fn eval_target_usize(&self, cnst: &MirConst) -> Result; - fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result; - - /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result; - - /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> MirConst; - - /// Create a new constant that represents the given boolean value. - fn new_const_bool(&self, value: bool) -> MirConst; - - /// Create a new constant that represents the given value. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; - fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; - - /// Create a new type from the given kind. - fn new_rigid_ty(&self, kind: RigidTy) -> Ty; - - /// Create a new box type, `Box`, for the given inner type `T`. - fn new_box_ty(&self, ty: Ty) -> Ty; - - /// Returns the type of given crate item. - fn def_ty(&self, item: DefId) -> Ty; - - /// Returns the type of given definition instantiated with the given arguments. - fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty; - - /// Returns literal value of a const as a string. - fn mir_const_pretty(&self, cnst: &MirConst) -> String; - - /// `Span` of an item - fn span_of_an_item(&self, def_id: DefId) -> Span; - - fn ty_const_pretty(&self, ct: TyConstId) -> String; - - /// Obtain the representation of a type. - fn ty_pretty(&self, ty: Ty) -> String; - - /// Obtain the kind of a type. - fn ty_kind(&self, ty: Ty) -> TyKind; - - // Get the discriminant Ty for this Ty if there's one. - fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty; - - /// Get the body of an Instance which is already monomorphized. - fn instance_body(&self, instance: InstanceDef) -> Option; - - /// Get the instance type with generic instantiations applied and lifetimes erased. - fn instance_ty(&self, instance: InstanceDef) -> Ty; - - /// Get the instantiation types. - fn instance_args(&self, def: InstanceDef) -> GenericArgs; - - /// Get the instance. - fn instance_def_id(&self, instance: InstanceDef) -> DefId; - - /// Get the instance mangled name. - fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol; - - /// Check if this is an empty DropGlue shim. - fn is_empty_drop_shim(&self, def: InstanceDef) -> bool; - - /// Convert a non-generic crate item into an instance. - /// This function will panic if the item is generic. - fn mono_instance(&self, def_id: DefId) -> Instance; - - /// Item requires monomorphization. - fn requires_monomorphization(&self, def_id: DefId) -> bool; - - /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option; - - /// Resolve an instance for drop_in_place for the given type. - fn resolve_drop_in_place(&self, ty: Ty) -> Instance; - - /// Resolve instance for a function pointer. - fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option; - - /// Resolve instance for a closure with the requested type. - fn resolve_closure( - &self, - def: ClosureDef, - args: &GenericArgs, - kind: ClosureKind, - ) -> Option; - - /// Evaluate a static's initializer. - fn eval_static_initializer(&self, def: StaticDef) -> Result; - - /// Try to evaluate an instance into a constant. - fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result; - - /// Retrieve global allocation for the given allocation ID. - fn global_alloc(&self, id: AllocId) -> GlobalAlloc; - - /// Retrieve the id for the virtual table. - fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option; - fn krate(&self, def_id: DefId) -> Crate; - fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; - - /// Return information about the target machine. - fn target_info(&self) -> MachineInfo; - - /// Get an instance ABI. - fn instance_abi(&self, def: InstanceDef) -> Result; - - /// Get the ABI of a function pointer. - fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result; - - /// Get the layout of a type. - fn ty_layout(&self, ty: Ty) -> Result; - - /// Get the layout shape. - fn layout_shape(&self, id: Layout) -> LayoutShape; - - /// Get a debug string representation of a place. - fn place_pretty(&self, place: &Place) -> String; - - /// Get the resulting type of binary operation. - fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty; - - /// Get the resulting type of unary operation. - fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; - - /// Get all associated items of a definition. - fn associated_items(&self, def_id: DefId) -> AssocItems; +pub(crate) struct CompilerInterface<'tcx> { + pub tables: RefCell>, + pub cx: RefCell>, } -impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { - fn entry_fn(&self) -> Option { +impl<'tcx> CompilerInterface<'tcx> { + pub(crate) fn entry_fn(&self) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = cx.entry_fn(); @@ -325,7 +86,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&self) -> CrateItems { + pub(crate) fn all_local_items(&self) -> CrateItems { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.all_local_items().iter().map(|did| tables.crate_item(*did)).collect() @@ -333,7 +94,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { /// Retrieve the body of a function. /// This function will panic if the body is not available. - fn mir_body(&self, item: DefId) -> mir::Body { + pub(crate) fn mir_body(&self, item: DefId) -> mir::Body { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[item]; @@ -341,14 +102,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Check whether the body of a function is available. - fn has_body(&self, item: DefId) -> bool { + pub(crate) fn has_body(&self, item: DefId) -> bool { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def = item.internal(&mut *tables, cx.tcx); cx.has_body(def) } - fn foreign_modules(&self, crate_num: CrateNum) -> Vec { + pub(crate) fn foreign_modules(&self, crate_num: CrateNum) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.foreign_modules(crate_num.internal(&mut *tables, cx.tcx)) @@ -358,7 +119,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve all functions defined in this crate. - fn crate_functions(&self, crate_num: CrateNum) -> Vec { + pub(crate) fn crate_functions(&self, crate_num: CrateNum) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let krate = crate_num.internal(&mut *tables, cx.tcx); @@ -366,75 +127,75 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve all static items defined in this crate. - fn crate_statics(&self, crate_num: CrateNum) -> Vec { + pub(crate) fn crate_statics(&self, crate_num: CrateNum) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let krate = crate_num.internal(&mut *tables, cx.tcx); cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect() } - fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule { + pub(crate) fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[mod_def.def_id()]; cx.foreign_module(did).stable(&mut *tables, cx) } - fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec { + pub(crate) fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[mod_def.def_id()]; cx.foreign_items(did).iter().map(|did| tables.foreign_def(*did)).collect() } - fn all_trait_decls(&self) -> TraitDecls { + pub(crate) fn all_trait_decls(&self) -> TraitDecls { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.all_trait_decls().map(|did| tables.trait_def(did)).collect() } - fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls { + pub(crate) fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let krate = crate_num.internal(&mut *tables, cx.tcx); cx.trait_decls(krate).iter().map(|did| tables.trait_def(*did)).collect() } - fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl { + pub(crate) fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[trait_def.0]; cx.trait_decl(did).stable(&mut *tables, cx) } - fn all_trait_impls(&self) -> ImplTraitDecls { + pub(crate) fn all_trait_impls(&self) -> ImplTraitDecls { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.all_trait_impls().iter().map(|did| tables.impl_def(*did)).collect() } - fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls { + pub(crate) fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let krate = crate_num.internal(&mut *tables, cx.tcx); cx.trait_impls(krate).iter().map(|did| tables.impl_def(*did)).collect() } - fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait { + pub(crate) fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[trait_impl.0]; cx.trait_impl(did).stable(&mut *tables, cx) } - fn generics_of(&self, def_id: DefId) -> Generics { + pub(crate) fn generics_of(&self, def_id: DefId) -> Generics { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; cx.generics_of(did).stable(&mut *tables, cx) } - fn predicates_of(&self, def_id: DefId) -> GenericPredicates { + pub(crate) fn predicates_of(&self, def_id: DefId) -> GenericPredicates { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -448,7 +209,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } } - fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates { + pub(crate) fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -463,25 +224,25 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get information about the local crate. - fn local_crate(&self) -> Crate { + pub(crate) fn local_crate(&self) -> Crate { let cx = &*self.cx.borrow(); smir_crate(cx, cx.local_crate_num()) } /// Retrieve a list of all external crates. - fn external_crates(&self) -> Vec { + pub(crate) fn external_crates(&self) -> Vec { let cx = &*self.cx.borrow(); cx.external_crates().iter().map(|crate_num| smir_crate(cx, *crate_num)).collect() } /// Find a crate with the given name. - fn find_crates(&self, name: &str) -> Vec { + pub(crate) fn find_crates(&self, name: &str) -> Vec { let cx = &*self.cx.borrow(); cx.find_crates(name).iter().map(|crate_num| smir_crate(cx, *crate_num)).collect() } /// Returns the name of given `DefId`. - fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol { + pub(crate) fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -495,7 +256,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { /// /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`. /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`. - fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec { + pub(crate) fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -506,7 +267,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get all tool attributes of a definition. - fn all_tool_attrs(&self, def_id: DefId) -> Vec { + pub(crate) fn all_tool_attrs(&self, def_id: DefId) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -517,7 +278,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns printable, human readable form of `Span`. - fn span_to_string(&self, span: Span) -> String { + pub(crate) fn span_to_string(&self, span: Span) -> String { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sp = tables.spans[span]; @@ -525,7 +286,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Return filename from given `Span`, for diagnostic purposes. - fn get_filename(&self, span: &Span) -> Filename { + pub(crate) fn get_filename(&self, span: &Span) -> Filename { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sp = tables.spans[*span]; @@ -533,7 +294,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Return lines corresponding to this `Span`. - fn get_lines(&self, span: &Span) -> LineInfo { + pub(crate) fn get_lines(&self, span: &Span) -> LineInfo { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sp = tables.spans[*span]; @@ -542,7 +303,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the `kind` of given `DefId`. - fn item_kind(&self, item: CrateItem) -> ItemKind { + pub(crate) fn item_kind(&self, item: CrateItem) -> ItemKind { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[item.0]; @@ -550,7 +311,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns whether this is a foreign item. - fn is_foreign_item(&self, item: DefId) -> bool { + pub(crate) fn is_foreign_item(&self, item: DefId) -> bool { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[item]; @@ -558,7 +319,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the kind of a given foreign item. - fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { + pub(crate) fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = tables[def.def_id()]; @@ -575,42 +336,42 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the kind of a given algebraic data type. - fn adt_kind(&self, def: AdtDef) -> AdtKind { + pub(crate) fn adt_kind(&self, def: AdtDef) -> AdtKind { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_kind(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx) } /// Returns if the ADT is a box. - fn adt_is_box(&self, def: AdtDef) -> bool { + pub(crate) fn adt_is_box(&self, def: AdtDef) -> bool { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_is_box(def.internal(&mut *tables, cx.tcx)) } /// Returns whether this ADT is simd. - fn adt_is_simd(&self, def: AdtDef) -> bool { + pub(crate) fn adt_is_simd(&self, def: AdtDef) -> bool { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_is_simd(def.internal(&mut *tables, cx.tcx)) } /// Returns whether this definition is a C string. - fn adt_is_cstr(&self, def: AdtDef) -> bool { + pub(crate) fn adt_is_cstr(&self, def: AdtDef) -> bool { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_is_cstr(def.0.internal(&mut *tables, cx.tcx)) } /// Returns the representation options for this ADT - fn adt_repr(&self, def: AdtDef) -> ReprOptions { + pub(crate) fn adt_repr(&self, def: AdtDef) -> ReprOptions { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_repr(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx) } /// Retrieve the function signature for the given generic arguments. - fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { + pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = def.0.internal(&mut *tables, cx.tcx); @@ -619,7 +380,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the intrinsic definition if the item corresponds one. - fn intrinsic(&self, item: DefId) -> Option { + pub(crate) fn intrinsic(&self, item: DefId) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = item.internal(&mut *tables, cx.tcx); @@ -627,7 +388,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the plain function name of an intrinsic. - fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { + pub(crate) fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = def.0.internal(&mut *tables, cx.tcx); @@ -635,7 +396,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the closure signature for the given generic arguments. - fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { + pub(crate) fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let args_ref = args.internal(&mut *tables, cx.tcx); @@ -643,14 +404,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// The number of variants in this ADT. - fn adt_variants_len(&self, def: AdtDef) -> usize { + pub(crate) fn adt_variants_len(&self, def: AdtDef) -> usize { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_variants_len(def.internal(&mut *tables, cx.tcx)) } /// Discriminant for a given variant index of AdtDef. - fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + pub(crate) fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.adt_discr_for_variant( @@ -661,7 +422,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Discriminant for a given variand index and args of a coroutine. - fn coroutine_discr_for_variant( + pub(crate) fn coroutine_discr_for_variant( &self, coroutine: CoroutineDef, args: &GenericArgs, @@ -677,13 +438,13 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// The name of a variant. - fn variant_name(&self, def: VariantDef) -> Symbol { + pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.variant_name(def.internal(&mut *tables, cx.tcx)) } - fn variant_fields(&self, def: VariantDef) -> Vec { + pub(crate) fn variant_fields(&self, def: VariantDef) -> Vec { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); def.internal(&mut *tables, cx.tcx) @@ -694,14 +455,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Evaluate constant as a target usize. - fn eval_target_usize(&self, mir_const: &MirConst) -> Result { + pub(crate) fn eval_target_usize(&self, mir_const: &MirConst) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let cnst = mir_const.internal(&mut *tables, cx.tcx); cx.eval_target_usize(cnst) } - fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result { + pub(crate) fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let cnst = ty_const.internal(&mut *tables, cx.tcx); @@ -709,7 +470,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result { + pub(crate) fn try_new_const_zst(&self, ty: Ty) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let ty_internal = ty.internal(&mut *tables, cx.tcx); @@ -717,28 +478,36 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> MirConst { + pub(crate) fn new_const_str(&self, value: &str) -> MirConst { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.new_const_str(value).stable(&mut *tables, cx) } /// Create a new constant that represents the given boolean value. - fn new_const_bool(&self, value: bool) -> MirConst { + pub(crate) fn new_const_bool(&self, value: bool) -> MirConst { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.new_const_bool(value).stable(&mut *tables, cx) } /// Create a new constant that represents the given value. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + pub(crate) fn try_new_const_uint( + &self, + value: u128, + uint_ty: UintTy, + ) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx)); cx.try_new_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx)) } - fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + pub(crate) fn try_new_ty_const_uint( + &self, + value: u128, + uint_ty: UintTy, + ) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx)); @@ -746,7 +515,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new type from the given kind. - fn new_rigid_ty(&self, kind: RigidTy) -> Ty { + pub(crate) fn new_rigid_ty(&self, kind: RigidTy) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let internal_kind = kind.internal(&mut *tables, cx.tcx); @@ -754,7 +523,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new box type, `Box`, for the given inner type `T`. - fn new_box_ty(&self, ty: Ty) -> Ty { + pub(crate) fn new_box_ty(&self, ty: Ty) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let inner = ty.internal(&mut *tables, cx.tcx); @@ -762,7 +531,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the type of given crate item. - fn def_ty(&self, item: DefId) -> Ty { + pub(crate) fn def_ty(&self, item: DefId) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let inner = item.internal(&mut *tables, cx.tcx); @@ -770,7 +539,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the type of given definition instantiated with the given arguments. - fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty { + pub(crate) fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let inner = item.internal(&mut *tables, cx.tcx); @@ -779,42 +548,42 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns literal value of a const as a string. - fn mir_const_pretty(&self, cnst: &MirConst) -> String { + pub(crate) fn mir_const_pretty(&self, cnst: &MirConst) -> String { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cnst.internal(&mut *tables, cx.tcx).to_string() } /// `Span` of an item. - fn span_of_an_item(&self, def_id: DefId) -> Span { + pub(crate) fn span_of_an_item(&self, def_id: DefId) -> Span { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; cx.span_of_an_item(did).stable(&mut *tables, cx) } - fn ty_const_pretty(&self, ct: TyConstId) -> String { + pub(crate) fn ty_const_pretty(&self, ct: TyConstId) -> String { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.ty_const_pretty(tables.ty_consts[ct]) } /// Obtain the representation of a type. - fn ty_pretty(&self, ty: Ty) -> String { + pub(crate) fn ty_pretty(&self, ty: Ty) -> String { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.ty_pretty(tables.types[ty]) } /// Obtain the kind of a type. - fn ty_kind(&self, ty: Ty) -> TyKind { + pub(crate) fn ty_kind(&self, ty: Ty) -> TyKind { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); cx.ty_kind(tables.types[ty]).stable(&mut *tables, cx) } /// Get the discriminant Ty for this Ty if there's one. - fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty { + pub(crate) fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let internal_kind = ty.internal(&mut *tables, cx.tcx); @@ -822,7 +591,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the body of an Instance which is already monomorphized. - fn instance_body(&self, instance: InstanceDef) -> Option { + pub(crate) fn instance_body(&self, instance: InstanceDef) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -830,7 +599,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instance type with generic instantiations applied and lifetimes erased. - fn instance_ty(&self, instance: InstanceDef) -> Ty { + pub(crate) fn instance_ty(&self, instance: InstanceDef) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -838,7 +607,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instantiation types. - fn instance_args(&self, def: InstanceDef) -> GenericArgs { + pub(crate) fn instance_args(&self, def: InstanceDef) -> GenericArgs { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[def]; @@ -846,7 +615,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instance. - fn instance_def_id(&self, instance: InstanceDef) -> DefId { + pub(crate) fn instance_def_id(&self, instance: InstanceDef) -> DefId { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -854,7 +623,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instance mangled name. - fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { + pub(crate) fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -862,7 +631,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Check if this is an empty DropGlue shim. - fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { + pub(crate) fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[def]; @@ -871,7 +640,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. - fn mono_instance(&self, def_id: DefId) -> Instance { + pub(crate) fn mono_instance(&self, def_id: DefId) -> Instance { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -879,7 +648,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Item requires monomorphization. - fn requires_monomorphization(&self, def_id: DefId) -> bool { + pub(crate) fn requires_monomorphization(&self, def_id: DefId) -> bool { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -887,7 +656,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option { + pub(crate) fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = def.0.internal(&mut *tables, cx.tcx); @@ -896,7 +665,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve an instance for drop_in_place for the given type. - fn resolve_drop_in_place(&self, ty: Ty) -> Instance { + pub(crate) fn resolve_drop_in_place(&self, ty: Ty) -> Instance { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let internal_ty = ty.internal(&mut *tables, cx.tcx); @@ -905,7 +674,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve instance for a function pointer. - fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option { + pub(crate) fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = def.0.internal(&mut *tables, cx.tcx); @@ -914,7 +683,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve instance for a closure with the requested type. - fn resolve_closure( + pub(crate) fn resolve_closure( &self, def: ClosureDef, args: &GenericArgs, @@ -929,7 +698,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Evaluate a static's initializer. - fn eval_static_initializer(&self, def: StaticDef) -> Result { + pub(crate) fn eval_static_initializer(&self, def: StaticDef) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let def_id = def.0.internal(&mut *tables, cx.tcx); @@ -938,7 +707,11 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Try to evaluate an instance into a constant. - fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result { + pub(crate) fn eval_instance( + &self, + def: InstanceDef, + const_ty: Ty, + ) -> Result { let mut tables = self.tables.borrow_mut(); let instance = tables.instances[def]; let cx = &*self.cx.borrow(); @@ -949,7 +722,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve global allocation for the given allocation ID. - fn global_alloc(&self, id: AllocId) -> GlobalAlloc { + pub(crate) fn global_alloc(&self, id: AllocId) -> GlobalAlloc { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let alloc_id = id.internal(&mut *tables, cx.tcx); @@ -957,7 +730,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the id for the virtual table. - fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option { + pub(crate) fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option { let mut tables = self.tables.borrow_mut(); let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None; @@ -969,13 +742,13 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { Some(alloc_id.stable(&mut *tables, cx)) } - fn krate(&self, def_id: DefId) -> Crate { + pub(crate) fn krate(&self, def_id: DefId) -> Crate { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); smir_crate(cx, tables[def_id].krate) } - fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { + pub(crate) fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[def]; @@ -983,7 +756,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Return information about the target machine. - fn target_info(&self) -> MachineInfo { + pub(crate) fn target_info(&self) -> MachineInfo { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); MachineInfo { @@ -993,7 +766,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get an instance ABI. - fn instance_abi(&self, def: InstanceDef) -> Result { + pub(crate) fn instance_abi(&self, def: InstanceDef) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[def]; @@ -1001,7 +774,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the ABI of a function pointer. - fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result { + pub(crate) fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sig = fn_ptr.internal(&mut *tables, cx.tcx); @@ -1009,7 +782,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the layout of a type. - fn ty_layout(&self, ty: Ty) -> Result { + pub(crate) fn ty_layout(&self, ty: Ty) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let internal_ty = ty.internal(&mut *tables, cx.tcx); @@ -1017,14 +790,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the layout shape. - fn layout_shape(&self, id: Layout) -> LayoutShape { + pub(crate) fn layout_shape(&self, id: Layout) -> LayoutShape { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); id.internal(&mut *tables, cx.tcx).0.stable(&mut *tables, cx) } /// Get a debug string representation of a place. - fn place_pretty(&self, place: &Place) -> String { + pub(crate) fn place_pretty(&self, place: &Place) -> String { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); @@ -1032,7 +805,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the resulting type of binary operation. - fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { + pub(crate) fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let rhs_internal = rhs.internal(&mut *tables, cx.tcx); @@ -1042,7 +815,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the resulting type of unary operation. - fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { + pub(crate) fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let un_op = un_op.internal(&mut *tables, cx.tcx); @@ -1051,7 +824,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get all associated items of a definition. - fn associated_items(&self, def_id: DefId) -> AssocItems { + pub(crate) fn associated_items(&self, def_id: DefId) -> AssocItems { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -1062,7 +835,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { // A thread local variable that stores a pointer to [`CompilerInterface`]. scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>); -pub(crate) fn run(interface: &dyn CompilerInterface, f: F) -> Result +pub(crate) fn run<'tcx, F, T>(interface: &CompilerInterface<'tcx>, f: F) -> Result where F: FnOnce() -> T, { @@ -1078,12 +851,12 @@ where /// /// I.e., This function will load the current interface and calls a function with it. /// Do not nest these, as that will ICE. -pub(crate) fn with(f: impl FnOnce(&dyn CompilerInterface) -> R) -> R { +pub(crate) fn with(f: impl for<'tcx> FnOnce(&CompilerInterface<'tcx>) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - f(unsafe { *(ptr as *const &dyn CompilerInterface) }) + f(unsafe { *(ptr as *const &CompilerInterface<'_>) }) }) } diff --git a/compiler/rustc_public/src/rustc_internal/mod.rs b/compiler/rustc_public/src/rustc_internal/mod.rs index 225c811ab3a54..7772a3982a7cb 100644 --- a/compiler/rustc_public/src/rustc_internal/mod.rs +++ b/compiler/rustc_public/src/rustc_internal/mod.rs @@ -3,15 +3,15 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until rustc_public's IR is complete. -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use rustc_middle::ty::TyCtxt; +use rustc_public_bridge::Tables; use rustc_public_bridge::context::CompilerCtxt; -use rustc_public_bridge::{Bridge, Container, Tables}; use rustc_span::def_id::CrateNum; -use scoped_tls::scoped_thread_local; use crate::Error; +use crate::compiler_interface::{BridgeTys, CompilerInterface, with}; use crate::unstable::{RustcInternal, Stable}; pub mod pretty; @@ -28,7 +28,7 @@ pub mod pretty; /// /// This function will panic if rustc_public has not been properly initialized. pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { - with_container(|tables, cx| item.stable(tables, cx)) + with_bridge(|tables, cx| item.stable(tables, cx)) } /// Convert a stable item into its internal Rust compiler counterpart, if one exists. @@ -49,38 +49,21 @@ where // The tcx argument ensures that the item won't outlive the type context. // See https://github.com/rust-lang/rust/pull/120128/commits/9aace6723572438a94378451793ca37deb768e72 // for more details. - with_container(|tables, _| item.internal(tables, tcx)) + with_bridge(|tables, _| item.internal(tables, tcx)) } pub fn crate_num(item: &crate::Crate) -> CrateNum { item.id.into() } -// A thread local variable that stores a pointer to the tables mapping between TyCtxt -// datastructures and rustc_public's IR datastructures -scoped_thread_local! (static TLV: Cell<*const ()>); - -pub(crate) fn init<'tcx, F, T, B: Bridge>(container: &Container<'tcx, B>, f: F) -> T -where - F: FnOnce() -> T, -{ - assert!(!TLV.is_set()); - let ptr = container as *const _ as *const (); - TLV.set(&Cell::new(ptr), || f()) -} - /// Loads the current context and calls a function with it. /// Do not nest these, as that will ICE. -pub(crate) fn with_container( - f: impl for<'tcx> FnOnce(&mut Tables<'tcx, B>, &CompilerCtxt<'tcx, B>) -> R, +pub(crate) fn with_bridge( + f: impl for<'tcx> FnOnce(&mut Tables<'tcx, BridgeTys>, &CompilerCtxt<'tcx, BridgeTys>) -> R, ) -> R { - assert!(TLV.is_set()); - TLV.with(|tlv| { - let ptr = tlv.get(); - assert!(!ptr.is_null()); - let container = ptr as *const Container<'_, B>; - let mut tables = unsafe { (*container).tables.borrow_mut() }; - let cx = unsafe { (*container).cx.borrow() }; + with(|compiler| { + let mut tables = compiler.tables.borrow_mut(); + let cx = compiler.cx.borrow(); f(&mut *tables, &*cx) }) } @@ -90,9 +73,10 @@ where F: FnOnce() -> T, { let compiler_cx = RefCell::new(CompilerCtxt::new(tcx)); - let container = Container { tables: RefCell::new(Tables::default()), cx: compiler_cx }; + let compiler_interface = + CompilerInterface { tables: RefCell::new(Tables::default()), cx: compiler_cx }; - crate::compiler_interface::run(&container, || init(&container, f)) + crate::compiler_interface::run(&compiler_interface, || f()) } /// Instantiate and run the compiler with the provided arguments and callback. diff --git a/compiler/rustc_public_bridge/src/lib.rs b/compiler/rustc_public_bridge/src/lib.rs index 1c38cb6c4bdfc..d0b417c550dc9 100644 --- a/compiler/rustc_public_bridge/src/lib.rs +++ b/compiler/rustc_public_bridge/src/lib.rs @@ -24,7 +24,6 @@ #![feature(trait_alias)] // tidy-alphabetical-end -use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; @@ -49,12 +48,6 @@ pub mod rustc_internal {} /// Trait alias for types that can be cached in [`Tables`]. pub trait Cacheable = Copy + Debug + PartialEq + IndexedVal; -/// A container which is used for TLS. -pub struct Container<'tcx, B: Bridge> { - pub tables: RefCell>, - pub cx: RefCell>, -} - pub struct Tables<'tcx, B: Bridge> { pub def_ids: IndexMap, pub alloc_ids: IndexMap, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b89aec7d22a91..e4511809a5245 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -808,7 +808,7 @@ mod desc { pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; pub(crate) const parse_oom_strategy: &str = "either `panic` or `abort`"; pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`"; + pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'"; pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub(crate) const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; @@ -1253,6 +1253,7 @@ pub mod parse { "thread" => SanitizerSet::THREAD, "hwaddress" => SanitizerSet::HWADDRESS, "safestack" => SanitizerSet::SAFESTACK, + "realtime" => SanitizerSet::REALTIME, _ => return false, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 223d818a2949b..342bd2c8b46f5 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, @@ -578,6 +579,7 @@ symbols! { bitxor_assign, black_box, block, + blocking, bool, bool_then, borrowck_graphviz_format, @@ -610,6 +612,7 @@ symbols! { call_once, call_once_future, call_ref_future, + caller, caller_location, capture_disjoint_fields, carrying_mul_add, @@ -1545,6 +1548,7 @@ symbols! { non_exhaustive_omitted_patterns_lint, non_lifetime_binders, non_modrs_mods, + nonblocking, none, nontemporal_store, noop_method_borrow, @@ -1780,6 +1784,7 @@ symbols! { read_via_copy, readonly, realloc, + realtime, reason, reborrow, receiver, diff --git a/compiler/rustc_target/src/spec/base/redox.rs b/compiler/rustc_target/src/spec/base/redox.rs index e0a0c20c56d63..e9b47f3fa3fdb 100644 --- a/compiler/rustc_target/src/spec/base/redox.rs +++ b/compiler/rustc_target/src/spec/base/redox.rs @@ -12,7 +12,7 @@ pub(crate) fn opts() -> TargetOptions { has_thread_local: true, crt_static_default: true, crt_static_respected: true, - crt_static_allows_dylibs: true, + crt_static_allows_dylibs: false, late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-lgcc"]), ..Default::default() } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1638c87c9ca9a..176eac2c0e577 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1177,6 +1177,7 @@ bitflags::bitflags! { const KERNELADDRESS = 1 << 9; const SAFESTACK = 1 << 10; const DATAFLOW = 1 << 11; + const REALTIME = 1 << 12; } } rustc_data_structures::external_bitflags_debug! { SanitizerSet } @@ -1227,6 +1228,7 @@ impl SanitizerSet { SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack", SanitizerSet::THREAD => "thread", SanitizerSet::HWADDRESS => "hwaddress", + SanitizerSet::REALTIME => "realtime", _ => return None, }) } @@ -1271,6 +1273,7 @@ impl FromStr for SanitizerSet { "shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK, "thread" => SanitizerSet::THREAD, "hwaddress" => SanitizerSet::HWADDRESS, + "realtime" => SanitizerSet::REALTIME, s => return Err(format!("unknown sanitizer {s}")), }) } @@ -1553,6 +1556,7 @@ supported_targets! { ("aarch64-unknown-redox", aarch64_unknown_redox), ("i586-unknown-redox", i586_unknown_redox), + ("riscv64gc-unknown-redox", riscv64gc_unknown_redox), ("x86_64-unknown-redox", x86_64_unknown_redox), ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index e19604725559a..ecfd6ebba8638 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -20,7 +20,10 @@ pub(crate) fn target() -> Target { cpu: "apple-m1".into(), max_atomic_width: Some(128), // FIXME: The leak sanitizer currently fails the tests, see #88132. - supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, supports_xray: true, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 3b522c34522b0..85b4a0614a85c 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -18,7 +18,9 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index d366ed264820b..2924ba5ebb105 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -18,7 +18,9 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs index 4220d74dfc890..5f123ed9e37fc 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs @@ -30,7 +30,8 @@ pub(crate) fn target() -> Target { | SanitizerSet::MEMORY | SanitizerSet::MEMTAG | SanitizerSet::THREAD - | SanitizerSet::HWADDRESS, + | SanitizerSet::HWADDRESS + | SanitizerSet::REALTIME, supports_xray: true, ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs new file mode 100644 index 0000000000000..01276a8be465e --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs @@ -0,0 +1,25 @@ +use crate::spec::{CodeModel, Target, TargetMetadata, base}; + +pub(crate) fn target() -> Target { + let mut base = base::redox::opts(); + base.code_model = Some(CodeModel::Medium); + base.cpu = "generic-rv64".into(); + base.features = "+m,+a,+f,+d,+c".into(); + base.llvm_abiname = "lp64d".into(); + base.plt_by_default = false; + base.max_atomic_width = Some(64); + + Target { + llvm_target: "riscv64-unknown-redox".into(), + metadata: TargetMetadata { + description: Some("Redox OS".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + arch: "riscv64".into(), + options: base, + } +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 8892c50d84478..cb517b2a357a5 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -21,7 +21,8 @@ pub(crate) fn target() -> Target { supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK - | SanitizerSet::THREAD, + | SanitizerSet::THREAD + | SanitizerSet::REALTIME, supports_xray: true, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 59bb7f5962101..39c30d66ab353 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -17,7 +17,8 @@ pub(crate) fn target() -> Target { | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::SAFESTACK - | SanitizerSet::THREAD; + | SanitizerSet::THREAD + | SanitizerSet::REALTIME; base.supports_xray = true; Target { 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/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index d2ab5412eeabc..aa973e0bb0240 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -215,6 +215,10 @@ impl Clone for Cow<'_, B> { impl Cow<'_, B> { /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. /// + /// Note: this is an associated function, which means that you have to call + /// it as `Cow::is_borrowed(&c)` instead of `c.is_borrowed()`. This is so + /// that there is no conflict with a method on the inner type. + /// /// # Examples /// /// ``` @@ -222,14 +226,14 @@ impl Cow<'_, B> { /// use std::borrow::Cow; /// /// let cow = Cow::Borrowed("moo"); - /// assert!(cow.is_borrowed()); + /// assert!(Cow::is_borrowed(&cow)); /// /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); - /// assert!(!bull.is_borrowed()); + /// assert!(!Cow::is_borrowed(&bull)); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - pub const fn is_borrowed(&self) -> bool { - match *self { + pub const fn is_borrowed(c: &Self) -> bool { + match *c { Borrowed(_) => true, Owned(_) => false, } @@ -237,6 +241,10 @@ impl Cow<'_, B> { /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. /// + /// Note: this is an associated function, which means that you have to call + /// it as `Cow::is_owned(&c)` instead of `c.is_owned()`. This is so that + /// there is no conflict with a method on the inner type. + /// /// # Examples /// /// ``` @@ -244,14 +252,14 @@ impl Cow<'_, B> { /// use std::borrow::Cow; /// /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); - /// assert!(cow.is_owned()); + /// assert!(Cow::is_owned(&cow)); /// /// let bull = Cow::Borrowed("...moo?"); - /// assert!(!bull.is_owned()); + /// assert!(!Cow::is_owned(&bull)); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - pub const fn is_owned(&self) -> bool { - !self.is_borrowed() + pub const fn is_owned(c: &Self) -> bool { + !Cow::is_borrowed(c) } /// Acquires a mutable reference to the owned form of the data. diff --git a/library/alloctests/tests/borrow.rs b/library/alloctests/tests/borrow.rs index af7efb7d78223..19695d424db2d 100644 --- a/library/alloctests/tests/borrow.rs +++ b/library/alloctests/tests/borrow.rs @@ -52,9 +52,9 @@ fn cow_const() { const COW: Cow<'_, str> = Cow::Borrowed("moo"); - const IS_BORROWED: bool = COW.is_borrowed(); + const IS_BORROWED: bool = Cow::is_borrowed(&COW); assert!(IS_BORROWED); - const IS_OWNED: bool = COW.is_owned(); + const IS_OWNED: bool = Cow::is_owned(&COW); assert!(!IS_OWNED); } diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index b70d452b427c8..e79391a107aac 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/139931 +Last change is for: https://github.com/rust-lang/rust/pull/147935 diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index d43d261ad6c3f..7e1b59351e042 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1262,13 +1262,13 @@ fn supported_sanitizers( }; match &*target.triple { - "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), - "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]), - "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]), + "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan", "rtsan"]), + "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan", "rtsan"]), + "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan", "rtsan"]), "aarch64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]), "aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]), "aarch64-unknown-linux-gnu" => { - common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) + common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan"]) } "aarch64-unknown-linux-ohos" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) @@ -1276,7 +1276,7 @@ fn supported_sanitizers( "loongarch64-unknown-linux-gnu" | "loongarch64-unknown-linux-musl" => { common_libs("linux", "loongarch64", &["asan", "lsan", "msan", "tsan"]) } - "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), + "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan", "rtsan"]), "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]), "x86_64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]), @@ -1286,9 +1286,11 @@ fn supported_sanitizers( } "x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]), "x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]), - "x86_64-unknown-linux-gnu" => { - common_libs("linux", "x86_64", &["asan", "dfsan", "lsan", "msan", "safestack", "tsan"]) - } + "x86_64-unknown-linux-gnu" => common_libs( + "linux", + "x86_64", + &["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan"], + ), "x86_64-unknown-linux-musl" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index d0405270f6634..08e5abc0a03b1 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,6 +34,7 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "riscv64gc-unknown-redox", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 34c78d4d952d5..3c6bc702557b6 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -45,7 +45,7 @@ implementation: [marked][sanitizer-attribute] with appropriate LLVM attribute: `SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or `SanitizeThread`. By default all functions are instrumented, but this - behaviour can be changed with `#[sanitize(xyz = "on|off")]`. + behaviour can be changed with `#[sanitize(xyz = "on|off|")]`. * The decision whether to perform instrumentation or not is possible only at a function granularity. In the cases were those decision differ between diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 4eb0dabe5952c..99739ee734e4c 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -393,6 +393,7 @@ target | std | host | notes [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 +[`riscv64gc-unknown-redox`](platform-support/redox.md) | ✓ | | RISC-V 64bit Redox OS [`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39) [`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ | | S390x Linux (kernel 3.2, musl 1.2.3) diff --git a/src/doc/rustc/src/platform-support/redox.md b/src/doc/rustc/src/platform-support/redox.md index fc36a551c8617..02ba5254d196c 100644 --- a/src/doc/rustc/src/platform-support/redox.md +++ b/src/doc/rustc/src/platform-support/redox.md @@ -10,6 +10,7 @@ Target triplets available so far: - `x86_64-unknown-redox` (tier 2) - `aarch64-unknown-redox` (tier 3) - `i586-unknown-redox` (tier 3) +- `riscv64gc-unknown-redox` (tier 3) ## Target maintainers @@ -37,6 +38,7 @@ target = [ "x86_64-unknown-redox", "aarch64-unknown-redox", "i586-unknown-redox", + "riscv64gc-unknown-redox", ] ``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 04d3c0cd630f5..a26ae7d284443 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -362,7 +362,7 @@ Using `index-page` option enables `enable-index-page` option as well. This feature allows the generation of a default index-page which lists the generated crates. -## `--nocapture`: disable output capture for test +## `--no-capture`: disable output capture for test When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be captured by rustdoc. Instead, the output will be directed to your terminal, diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 493256de99d52..f32013d75e500 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -24,6 +24,8 @@ This feature allows for use of one of following sanitizers: AddressSanitizer, but based on partial hardware assistance. * [LeakSanitizer](#leaksanitizer) a run-time memory leak detector. * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads. + * [RealtimeSanitizer](#realtimesanitizer) a detector of calls to function with + non-deterministic execution time in realtime contexts. * [ThreadSanitizer](#threadsanitizer) a fast data race detector. * Those that apart from testing, may be used in production: @@ -43,11 +45,11 @@ This feature allows for use of one of following sanitizers: To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=cfi`, `-Zsanitizer=dataflow`,`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, -`-Zsanitizer=memory`, `-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or -`-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. -If you're working with other languages that are also instrumented with sanitizers, -you might need the `external-clangrt` flag. See the section on -[working with other languages](#working-with-other-languages). +`-Zsanitizer=memory`, `-Zsanitizer=memtag`, `-Zsanitizer=realtime`, +`-Zsanitizer=shadow-call-stack` or `-Zsanitizer=thread`. You might also need the +`--target` and `build-std` flags. If you're working with other languages that are also +instrumented with sanitizers, you might need the `external-clangrt` flag. See +the section on [working with other languages](#working-with-other-languages). Example: ```shell @@ -865,6 +867,70 @@ WARNING: ThreadSanitizer: data race (pid=10574) Location is global 'example::A::h43ac149ddf992709' of size 8 at 0x5632dfe3d030 (example+0x000000bd9030) ``` +# RealtimeSanitizer +RealtimeSanitizer detects non-deterministic execution time calls in real-time contexts. +Functions marked with the `#[sanitize(realtime = "nonblocking")]` attribute are considered real-time functions. +When RTSan detects a call to a function with a non-deterministic execution time, like `malloc` or `free` +while in a real-time context, it reports an error. + +Besides "nonblocking" the attribute can also be used with "blocking" and "caller". +- "blocking" allows the programmer to mark their own functions as having a non-deterministic execution time. +When reaching such a function while in a real-time context a violation will be reported. A typical use +case is a userland spinlock. +- functions marked with "caller" will be sanitized if they were called from a real-time context. +If no attribute is set, this is the default. Between entering a "nonblocking" function and exiting that +function again the program will get sanitized. + +The santizer checks can be disabled using the external functions `__rtsan_disable()` and `__rtsan_enable()`. +Each call to `__rtsan_disable()` must be paired with one following call to `__rtsan_enable()`, otherwise the behaviour is undefined. + +```rust +unsafe extern "C" { + fn __rtsan_disable(); + fn __rtsan_enable(); +} +``` + +```rust,ignore (log is just a example and doesn't exist) +// in a real-time context +#[cfg(debug_assertions)] +{ + unsafe { __rtsan_disable() }; + log!("logging xyz"); + unsafe { __rtsan_enable() }; +} +``` + +See the [Clang RealtimeSanitizer documentation][clang-rtsan] for more details. + +## Example + +```rust,no_run +#![feature(sanitize)] +#[sanitize(realtime = "nonblocking")] +fn real_time() { + let vec = vec![0, 1, 2]; // call to malloc is detected and reported as an error +} +``` + +```shell +==8670==ERROR: RealtimeSanitizer: unsafe-library-call +Intercepted call to real-time unsafe function `malloc` in real-time context! + #0 0x00010107b0d8 in malloc rtsan_interceptors_posix.cpp:792 + #1 0x000100d94e70 in alloc::alloc::Global::alloc_impl::h9e1fc3206c868eea+0xa0 (realtime_vec:arm64+0x100000e70) + #2 0x000100d94d90 in alloc::alloc::exchange_malloc::hd45b5788339eb5c8+0x48 (realtime_vec:arm64+0x100000d90) + #3 0x000100d95020 in realtime_vec::main::hea6bd69b03eb9ca1+0x24 (realtime_vec:arm64+0x100001020) + #4 0x000100d94a28 in core::ops::function::FnOnce::call_once::h493b6cb9dd87d87c+0xc (realtime_vec:arm64+0x100000a28) + #5 0x000100d949b8 in std::sys::backtrace::__rust_begin_short_backtrace::hfcddb06c73c19eea+0x8 (realtime_vec:arm64+0x1000009b8) + #6 0x000100d9499c in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h202288c05a2064f0+0xc (realtime_vec:arm64+0x10000099c) + #7 0x000100d9fa34 in std::rt::lang_start_internal::h6c763158a05ac05f+0x6c (realtime_vec:arm64+0x10000ba34) + #8 0x000100d94980 in std::rt::lang_start::h1c29cc56df0598b4+0x38 (realtime_vec:arm64+0x100000980) + #9 0x000100d95118 in main+0x20 (realtime_vec:arm64+0x100001118) + #10 0x000183a46b94 in start+0x17b8 (dyld:arm64+0xfffffffffff3ab94) + +SUMMARY: RealtimeSanitizer: unsafe-library-call rtsan_interceptors_posix.cpp:792 in malloc +``` + # Instrumentation of external dependencies and std The sanitizers to varying degrees work correctly with partially instrumented @@ -918,6 +984,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [MemorySanitizer in Clang][clang-msan] * [MemTagSanitizer in LLVM][llvm-memtag] * [ThreadSanitizer in Clang][clang-tsan] +* [RealtimeSanitizer in Clang][clang-rtsan] [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html [clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html @@ -926,6 +993,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html +[clan-rtsan]: https://clang.llvm.org/docs/RealtimeSanitizer.html [clang-safestack]: https://clang.llvm.org/docs/SafeStack.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html 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/config.rs b/src/librustdoc/config.rs index 630b2a6e5c18b..55e04671b83ca 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -155,7 +155,7 @@ pub(crate) struct Options { /// Whether doctests should emit unused externs pub(crate) json_unused_externs: JsonUnusedExterns, /// Whether to skip capturing stdout and stderr of tests. - pub(crate) nocapture: bool, + pub(crate) no_capture: bool, /// Configuration for scraping examples from the current crate. If this option is Some(..) then /// the compiler will scrape examples and not generate documentation. @@ -211,7 +211,7 @@ impl fmt::Debug for Options { .field("no_run", &self.no_run) .field("test_builder_wrappers", &self.test_builder_wrappers) .field("remap-file-prefix", &self.remap_path_prefix) - .field("nocapture", &self.nocapture) + .field("no_capture", &self.no_capture) .field("scrape_examples_options", &self.scrape_examples_options) .field("unstable_features", &self.unstable_features) .finish() @@ -783,7 +783,7 @@ impl Options { let run_check = matches.opt_present("check"); let generate_redirect_map = matches.opt_present("generate-redirect-map"); let show_type_layout = matches.opt_present("show-type-layout"); - let nocapture = matches.opt_present("nocapture"); + let no_capture = matches.opt_present("no-capture"); let generate_link_to_definition = matches.opt_present("generate-link-to-definition"); let generate_macro_expansion = matches.opt_present("generate-macro-expansion"); let extern_html_root_takes_precedence = @@ -854,7 +854,7 @@ impl Options { no_run, test_builder_wrappers, remap_path_prefix, - nocapture, + no_capture, crate_name, output_format, json_unused_externs, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 0d551a969d632..c9cd9f7fd4b11 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -326,8 +326,8 @@ pub(crate) fn run_tests( let mut test_args = Vec::with_capacity(rustdoc_options.test_args.len() + 1); test_args.insert(0, "rustdoctest".to_string()); test_args.extend_from_slice(&rustdoc_options.test_args); - if rustdoc_options.nocapture { - test_args.push("--nocapture".to_string()); + if rustdoc_options.no_capture { + test_args.push("--no-capture".to_string()); } let mut nb_errors = 0; @@ -644,8 +644,8 @@ fn run_test( // tested as standalone tests. return (Duration::default(), Err(TestFailure::CompileError)); } - if !rustdoc_options.nocapture { - // If `nocapture` is disabled, then we don't display rustc's output when compiling + if !rustdoc_options.no_capture { + // If `no_capture` is disabled, then we don't display rustc's output when compiling // the merged doctests. compiler.stderr(Stdio::null()); } @@ -721,8 +721,8 @@ fn run_test( // tested as standalone tests. return (instant.elapsed(), Err(TestFailure::CompileError)); } - if !rustdoc_options.nocapture { - // If `nocapture` is disabled, then we don't display rustc's output when compiling + if !rustdoc_options.no_capture { + // If `no_capture` is disabled, then we don't display rustc's output when compiling // the merged doctests. runner_compiler.stderr(Stdio::null()); } @@ -821,7 +821,7 @@ fn run_test( cmd.current_dir(run_directory); } - let result = if doctest.is_multiple_tests() || rustdoc_options.nocapture { + let result = if doctest.is_multiple_tests() || rustdoc_options.no_capture { cmd.status().map(|status| process::Output { status, stdout: Vec::new(), @@ -1016,7 +1016,7 @@ impl CreateRunnableDocTests { .span(scraped_test.span) .build(dcx); let is_standalone = !doctest.can_be_merged - || self.rustdoc_options.nocapture + || self.rustdoc_options.no_capture || self.rustdoc_options.test_args.iter().any(|arg| arg == "--show-output"); if is_standalone { let test_desc = self.generate_test_desc_and_fn(doctest, scraped_test); 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/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 337c973a2c84f..0a73d32dac2de 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3904,6 +3904,8 @@ class DocSearch { return name === "primitive" || name === "associatedtype"; case "trait": return name === "traitalias"; + case "macro": + return name === "attr" || name === "derive"; } // No match diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index dd6378b25def7..6c280c0736b18 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -586,7 +586,7 @@ fn opts() -> Vec { "Include the memory layout of types in the docs", "", ), - opt(Unstable, Flag, "", "nocapture", "Don't capture stdout and stderr of tests", ""), + opt(Unstable, Flag, "", "no-capture", "Don't capture stdout and stderr of tests", ""), opt( Unstable, Flag, 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/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 8e47d51ee4dbd..c623e3b901c66 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -174,6 +174,7 @@ pub enum Sanitizer { ShadowCallStack, Thread, Hwaddress, + Realtime, } #[derive(Clone, Copy, Debug, PartialEq)] diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 3a46dbc704e87..cdf83af78f6ab 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -165,6 +165,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-leak", "needs-sanitizer-memory", "needs-sanitizer-memtag", + "needs-sanitizer-realtime", "needs-sanitizer-safestack", "needs-sanitizer-shadow-call-stack", "needs-sanitizer-support", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index 5e9fe59d8d1c3..713a63317b721 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -69,6 +69,11 @@ pub(super) fn handle_needs( condition: cache.sanitizer_memtag, ignore_reason: "ignored on targets without memory tagging sanitizer", }, + Need { + name: "needs-sanitizer-realtime", + condition: cache.sanitizer_realtime, + ignore_reason: "ignored on targets without realtime sanitizer", + }, Need { name: "needs-sanitizer-shadow-call-stack", condition: cache.sanitizer_shadow_call_stack, @@ -320,6 +325,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_thread: bool, sanitizer_hwaddress: bool, sanitizer_memtag: bool, + sanitizer_realtime: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, xray: bool, @@ -346,6 +352,7 @@ impl CachedNeedsConditions { sanitizer_thread: sanitizers.contains(&Sanitizer::Thread), sanitizer_hwaddress: sanitizers.contains(&Sanitizer::Hwaddress), sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), + sanitizer_realtime: sanitizers.contains(&Sanitizer::Realtime), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), xray: config.target_cfg().xray, diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index e26c213837066..6c85dbcfed1a5 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -505,6 +505,9 @@ //@ revisions: riscv64gc_unknown_openbsd //@ [riscv64gc_unknown_openbsd] compile-flags: --target riscv64gc-unknown-openbsd //@ [riscv64gc_unknown_openbsd] needs-llvm-components: riscv +//@ revisions: riscv64gc_unknown_redox +//@ [riscv64gc_unknown_redox] compile-flags: --target riscv64gc-unknown-redox +//@ [riscv64gc_unknown_redox] needs-llvm-components: riscv //@ revisions: riscv64imac_unknown_none_elf //@ [riscv64imac_unknown_none_elf] compile-flags: --target riscv64imac-unknown-none-elf //@ [riscv64imac_unknown_none_elf] needs-llvm-components: riscv 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/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index 3afe0ca3ca8f5..49eaf7e2e1e0e 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -158,7 +158,7 @@ Options: Remap source names in compiler messages --show-type-layout Include the memory layout of types in the docs - --nocapture Don't capture stdout and stderr of tests + --no-capture Don't capture stdout and stderr of tests --generate-link-to-definition Make the identifiers in the HTML source code pages navigable diff --git a/tests/rustdoc-js-std/filter-macro-attr-derive.js b/tests/rustdoc-js-std/filter-macro-attr-derive.js new file mode 100644 index 0000000000000..4c8ec77030b42 --- /dev/null +++ b/tests/rustdoc-js-std/filter-macro-attr-derive.js @@ -0,0 +1,9 @@ +// This test ensures that filtering on "macro" will also include attribute and derive +// macros. + +const EXPECTED = { + 'query': 'macro:debug', + 'others': [ + { 'path': 'std::fmt', 'name': 'Debug', 'href': '../std/fmt/derive.Debug.html' }, + ], +}; diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.rs b/tests/rustdoc-ui/doctest/check-cfg-test.rs index 39fdb3a5853fc..201d6d60672d2 100644 --- a/tests/rustdoc-ui/doctest/check-cfg-test.rs +++ b/tests/rustdoc-ui/doctest/check-cfg-test.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --test --nocapture --check-cfg=cfg(feature,values("test")) -Z unstable-options +//@ compile-flags: --test --no-capture --check-cfg=cfg(feature,values("test")) -Z unstable-options //@ normalize-stderr: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.rs b/tests/rustdoc-ui/doctest/no-capture-fail.rs similarity index 83% rename from tests/rustdoc-ui/doctest/nocapture-fail.rs rename to tests/rustdoc-ui/doctest/no-capture-fail.rs index 8c64a49f65005..c58d2495aee0d 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.rs +++ b/tests/rustdoc-ui/doctest/no-capture-fail.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:--test -Zunstable-options --nocapture +//@ compile-flags:--test -Zunstable-options --no-capture //@ normalize-stderr: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stderr b/tests/rustdoc-ui/doctest/no-capture-fail.stderr similarity index 89% rename from tests/rustdoc-ui/doctest/nocapture-fail.stderr rename to tests/rustdoc-ui/doctest/no-capture-fail.stderr index c6a5785a24fe4..2817a66b514ce 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.stderr +++ b/tests/rustdoc-ui/doctest/no-capture-fail.stderr @@ -1,5 +1,5 @@ error: struct literal body without path - --> $DIR/nocapture-fail.rs:8:10 + --> $DIR/no-capture-fail.rs:8:10 | LL | fn foo() { | __________^ diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stdout b/tests/rustdoc-ui/doctest/no-capture-fail.stdout similarity index 62% rename from tests/rustdoc-ui/doctest/nocapture-fail.stdout rename to tests/rustdoc-ui/doctest/no-capture-fail.stdout index 754f77db53ca3..ee94540e37b43 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.stdout +++ b/tests/rustdoc-ui/doctest/no-capture-fail.stdout @@ -1,6 +1,6 @@ running 1 test -test $DIR/nocapture-fail.rs - Foo (line 7) - compile fail ... ok +test $DIR/no-capture-fail.rs - Foo (line 7) - compile fail ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/nocapture.rs b/tests/rustdoc-ui/doctest/no-capture.rs similarity index 79% rename from tests/rustdoc-ui/doctest/nocapture.rs rename to tests/rustdoc-ui/doctest/no-capture.rs index c4360341864fd..b1e3014798f9a 100644 --- a/tests/rustdoc-ui/doctest/nocapture.rs +++ b/tests/rustdoc-ui/doctest/no-capture.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:--test -Zunstable-options --nocapture +//@ compile-flags:--test -Zunstable-options --no-capture //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/doctest/nocapture.stderr b/tests/rustdoc-ui/doctest/no-capture.stderr similarity index 100% rename from tests/rustdoc-ui/doctest/nocapture.stderr rename to tests/rustdoc-ui/doctest/no-capture.stderr diff --git a/tests/rustdoc-ui/doctest/nocapture.stdout b/tests/rustdoc-ui/doctest/no-capture.stdout similarity index 72% rename from tests/rustdoc-ui/doctest/nocapture.stdout rename to tests/rustdoc-ui/doctest/no-capture.stdout index 4880e75da7062..9916d3d1f8095 100644 --- a/tests/rustdoc-ui/doctest/nocapture.stdout +++ b/tests/rustdoc-ui/doctest/no-capture.stdout @@ -1,7 +1,7 @@ running 1 test hello! -test $DIR/nocapture.rs - Foo (line 6) ... ok +test $DIR/no-capture.rs - Foo (line 6) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/non_local_defs.rs b/tests/rustdoc-ui/doctest/non_local_defs.rs index ce65ad2cf72c2..1b87b04148a88 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.rs +++ b/tests/rustdoc-ui/doctest/non_local_defs.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:--test --test-args --test-threads=1 --nocapture -Zunstable-options +//@ compile-flags:--test --test-args --test-threads=1 --no-capture -Zunstable-options //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stderr: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 5627cb452a815..d8d9c182529e7 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -513,7 +513,7 @@ LL | #[sanitize(hwaddress = "on|off")] | ++++++++++++++++++++++ LL | #[sanitize(kcfi = "on|off")] | +++++++++++++++++ - = and 5 other candidates + = and 6 other candidates error[E0565]: malformed `no_implicit_prelude` attribute input --> $DIR/malformed-attrs.rs:101:1 diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 3f14c7b08eac6..77d45b43f361b 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -120,7 +120,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, and `thread` + = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/sanitize-attr/invalid-sanitize.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs index 957ce780ad0fd..63eef51664845 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.rs +++ b/tests/ui/sanitize-attr/invalid-sanitize.rs @@ -1,3 +1,4 @@ +//@ edition:2018 #![feature(sanitize)] #[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input @@ -19,3 +20,21 @@ fn name_value() {} #[sanitize] //~ ERROR malformed `sanitize` attribute input fn just_word() {} + +#[sanitize(realtime = "on")] //~ ERROR malformed `sanitize` attribute input +fn wrong_value_realtime() {} + +#[sanitize(realtime = "nonblocking")] //~ WARN: the async executor can run blocking code, without realtime sanitizer catching it [rtsan_nonblocking_async] +async fn async_nonblocking() {} + +fn test() { + let _async_block = { + #[sanitize(realtime = "nonblocking")] //~ WARN: the async executor can run blocking code, without realtime sanitizer catching it [rtsan_nonblocking_async] + async {} + }; + + let _async_closure = { + #[sanitize(realtime = "nonblocking")] //~ WARN: the async executor can run blocking code, without realtime sanitizer catching it [rtsan_nonblocking_async] + async || {} + }; +} diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index ec0a93be1420e..9c1a6e5c45285 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.stderr +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -1,10 +1,10 @@ error[E0539]: malformed `sanitize` attribute input - --> $DIR/invalid-sanitize.rs:3:1 + --> $DIR/invalid-sanitize.rs:4:1 | LL | #[sanitize(brontosaurus = "off")] | ^^^^^^^^^^^------------^^^^^^^^^^ | | - | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread" or "hwaddress" + | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime" | help: try changing it to one of the following valid forms of the attribute | @@ -20,34 +20,34 @@ LL + #[sanitize(hwaddress = "on|off")] LL - #[sanitize(brontosaurus = "off")] LL + #[sanitize(kcfi = "on|off")] | - = and 5 other candidates + = and 6 other candidates error: multiple `sanitize` attributes - --> $DIR/invalid-sanitize.rs:6:1 + --> $DIR/invalid-sanitize.rs:7:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-sanitize.rs:7:1 + --> $DIR/invalid-sanitize.rs:8:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: multiple `sanitize` attributes - --> $DIR/invalid-sanitize.rs:10:1 + --> $DIR/invalid-sanitize.rs:11:1 | LL | #[sanitize(address = "on")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-sanitize.rs:11:1 + --> $DIR/invalid-sanitize.rs:12:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0539]: malformed `sanitize` attribute input - --> $DIR/invalid-sanitize.rs:14:1 + --> $DIR/invalid-sanitize.rs:15:1 | LL | #[sanitize(address = "bogus")] | ^^^^^^^^^^^^^^^^^^^^^-------^^ @@ -68,10 +68,10 @@ LL + #[sanitize(hwaddress = "on|off")] LL - #[sanitize(address = "bogus")] LL + #[sanitize(kcfi = "on|off")] | - = and 5 other candidates + = and 6 other candidates error[E0539]: malformed `sanitize` attribute input - --> $DIR/invalid-sanitize.rs:17:1 + --> $DIR/invalid-sanitize.rs:18:1 | LL | #[sanitize = "off"] | ^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -90,10 +90,10 @@ LL + #[sanitize(hwaddress = "on|off")] LL - #[sanitize = "off"] LL + #[sanitize(kcfi = "on|off")] | - = and 5 other candidates + = and 6 other candidates error[E0539]: malformed `sanitize` attribute input - --> $DIR/invalid-sanitize.rs:20:1 + --> $DIR/invalid-sanitize.rs:21:1 | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list @@ -108,8 +108,52 @@ LL | #[sanitize(hwaddress = "on|off")] | ++++++++++++++++++++++ LL | #[sanitize(kcfi = "on|off")] | +++++++++++++++++ - = and 5 other candidates + = and 6 other candidates + +error[E0539]: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:24:1 + | +LL | #[sanitize(realtime = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^----^^ + | | + | valid arguments are "nonblocking", "blocking" or "caller" + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(address = "on|off")] + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(cfi = "on|off")] + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(hwaddress = "on|off")] + | +LL - #[sanitize(realtime = "on")] +LL + #[sanitize(kcfi = "on|off")] + | + = and 6 other candidates + +warning: the async executor can run blocking code, without realtime sanitizer catching it + --> $DIR/invalid-sanitize.rs:27:1 + | +LL | #[sanitize(realtime = "nonblocking")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(rtsan_nonblocking_async)]` on by default + +warning: the async executor can run blocking code, without realtime sanitizer catching it + --> $DIR/invalid-sanitize.rs:32:9 + | +LL | ... #[sanitize(realtime = "nonblocking")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: the async executor can run blocking code, without realtime sanitizer catching it + --> $DIR/invalid-sanitize.rs:37:9 + | +LL | ... #[sanitize(realtime = "nonblocking")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors; 3 warnings emitted For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/sanitizer/inline-always-sanitize.rs b/tests/ui/sanitizer/inline-always-sanitize.rs index d6ee214e9b374..97bb60df72a6d 100644 --- a/tests/ui/sanitizer/inline-always-sanitize.rs +++ b/tests/ui/sanitizer/inline-always-sanitize.rs @@ -5,7 +5,7 @@ #[inline(always)] //~^ NOTE inlining requested here #[sanitize(address = "off")] -//~^ WARN setting `sanitize` off will have no effect after inlining +//~^ WARN non-default `sanitize` will have no effect after inlining //~| NOTE on by default fn x() { } diff --git a/tests/ui/sanitizer/inline-always-sanitize.stderr b/tests/ui/sanitizer/inline-always-sanitize.stderr index ed47947216950..fbfe5378c0922 100644 --- a/tests/ui/sanitizer/inline-always-sanitize.stderr +++ b/tests/ui/sanitizer/inline-always-sanitize.stderr @@ -1,4 +1,4 @@ -warning: setting `sanitize` off will have no effect after inlining +warning: non-default `sanitize` will have no effect after inlining --> $DIR/inline-always-sanitize.rs:7:1 | LL | #[sanitize(address = "off")] diff --git a/tests/ui/sanitizer/realtime-alloc.rs b/tests/ui/sanitizer/realtime-alloc.rs new file mode 100644 index 0000000000000..49274251e5b06 --- /dev/null +++ b/tests/ui/sanitizer/realtime-alloc.rs @@ -0,0 +1,20 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-realtime +// +//@ compile-flags: -Z sanitizer=realtime +//@ run-flags: abort-on-error=0 +// +//@ run-fail +//@ error-pattern: Intercepted call to real-time unsafe function `malloc` in real-time context! +//@ ignore-backends: gcc +#![feature(sanitize)] + +#[sanitize(realtime = "nonblocking")] +fn sanitizer_on() { + let mut vec = vec![0, 1, 2]; + println!("alloc not detected"); +} + +fn main() { + sanitizer_on(); +} diff --git a/tests/ui/sanitizer/realtime-blocking.rs b/tests/ui/sanitizer/realtime-blocking.rs new file mode 100644 index 0000000000000..099f93cc48eda --- /dev/null +++ b/tests/ui/sanitizer/realtime-blocking.rs @@ -0,0 +1,25 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-realtime +// +//@ compile-flags: -Z sanitizer=realtime +//@ run-flags: abort-on-error=0 +// +//@ run-fail +//@ error-pattern: Call to blocking function +//@ error-pattern: realtime_blocking::blocking:: +//@ ignore-backends: gcc +#![feature(sanitize)] + +#[sanitize(realtime = "nonblocking")] +fn sanitizer_on() { + blocking(); +} + +#[sanitize(realtime = "blocking")] +fn blocking() { + println!("blocking call not detected"); +} + +fn main() { + sanitizer_on(); +} diff --git a/tests/ui/sanitizer/realtime-caller.rs b/tests/ui/sanitizer/realtime-caller.rs new file mode 100644 index 0000000000000..0b00e290ee569 --- /dev/null +++ b/tests/ui/sanitizer/realtime-caller.rs @@ -0,0 +1,28 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-realtime +// +//@ compile-flags: -Z sanitizer=realtime +//@ run-flags: abort-on-error=0 +// +//@ run-fail +//@ error-pattern: RealtimeSanitizer: blocking-call +//@ ignore-backends: gcc +#![feature(sanitize)] + +#[sanitize(realtime = "nonblocking")] +fn sanitizer_on() { + caller(); +} + +fn caller() { + blocking() +} + +#[sanitize(realtime = "blocking")] +fn blocking() { + println!("blocking call not detected"); +} + +fn main() { + sanitizer_on(); +} 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