diff --git a/Cargo.lock b/Cargo.lock index 71ae559bd129a..89392631127fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -315,7 +315,7 @@ dependencies = [ "serde_json", "sha2", "tar", - "toml 0.5.11", + "toml 0.7.8", "xz2", ] @@ -336,7 +336,7 @@ dependencies = [ "curl", "indexmap", "serde", - "toml 0.5.11", + "toml 0.7.8", ] [[package]] @@ -1129,16 +1129,16 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ - "dirs-sys 0.5.0", + "dirs-sys", ] [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "dirs-sys 0.4.1", + "dirs-sys", ] [[package]] @@ -1151,18 +1151,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users 0.4.6", - "windows-sys 0.48.0", -] - [[package]] name = "dirs-sys" version = "0.5.0" @@ -5545,15 +5533,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.7.8" diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 91053811a0b8c..b884f8f38328c 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, UsedBy}; +use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy}; use rustc_session::parse::feature_err; use super::prelude::*; @@ -464,6 +464,12 @@ impl CombineAttributeParser for ForceTargetFeatureParser { was_forced: true, }; const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, @@ -471,11 +477,106 @@ impl CombineAttributeParser for ForceTargetFeatureParser { ) -> impl IntoIterator + 'c { parse_tf_attribute(cx, args) } +} - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ - Allow(Target::Fn), - Allow(Target::Method(MethodKind::Inherent)), - Allow(Target::Method(MethodKind::Trait { body: true })), - Allow(Target::Method(MethodKind::TraitImpl)), +pub(crate) struct SanitizeParser; + +impl SingleAttributeParser for SanitizeParser { + const PATH: &[Symbol] = &[sym::sanitize]; + + // FIXME: still checked in check_attrs.rs + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + + const TEMPLATE: AttributeTemplate = template!(List: &[ + r#"address = "on|off""#, + r#"kernel_address = "on|off""#, + r#"cfi = "on|off""#, + r#"hwaddress = "on|off""#, + r#"kcfi = "on|off""#, + r#"memory = "on|off""#, + r#"memtag = "on|off""#, + r#"shadow_call_stack = "on|off""#, + r#"thread = "on|off""# ]); + + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span); + return None; + }; + + let mut on_set = SanitizerSet::empty(); + let mut off_set = SanitizerSet::empty(); + + for item in list.mixed() { + let Some(item) = item.meta_item() else { + cx.expected_name_value(item.span(), None); + continue; + }; + + let path = item.path().word_sym(); + let Some(value) = item.args().name_value() else { + cx.expected_name_value(item.span(), path); + continue; + }; + + let mut apply = |s: SanitizerSet| { + let is_on = match value.value_as_str() { + Some(sym::on) => true, + Some(sym::off) => false, + Some(_) => { + cx.expected_specific_argument_strings( + value.value_span, + &[sym::on, sym::off], + ); + return; + } + None => { + cx.expected_string_literal(value.value_span, Some(value.value_as_lit())); + return; + } + }; + + if is_on { + on_set |= s; + } else { + off_set |= s; + } + }; + + match path { + Some(sym::address) | Some(sym::kernel_address) => { + apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS) + } + Some(sym::cfi) => apply(SanitizerSet::CFI), + Some(sym::kcfi) => apply(SanitizerSet::KCFI), + Some(sym::memory) => apply(SanitizerSet::MEMORY), + Some(sym::memtag) => apply(SanitizerSet::MEMTAG), + Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK), + Some(sym::thread) => apply(SanitizerSet::THREAD), + Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS), + _ => { + cx.expected_specific_argument_strings( + item.path().span(), + &[ + sym::address, + sym::cfi, + sym::kcfi, + sym::memory, + sym::memtag, + sym::shadow_call_stack, + sym::thread, + sym::hwaddress, + ], + ); + continue; + } + } + } + + Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span }) + } } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b9c415e8085f7..bb701df6053c6 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -20,7 +20,8 @@ use crate::attributes::allow_unstable::{ use crate::attributes::body::CoroutineParser; use crate::attributes::codegen_attrs::{ ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser, - NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser, + NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser, + UsedParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -184,6 +185,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 42ba01541920b..44b9941691a6b 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -171,9 +171,6 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphizati codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` -codegen_ssa_invalid_sanitize = invalid argument for `sanitize` - .note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread` - codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64 diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 23e2abd6de3a6..6b0bd64102c65 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -293,6 +293,9 @@ fn process_builtin_attrs( codegen_fn_attrs.linkage = linkage; } } + AttributeKind::Sanitize { span, .. } => { + interesting_spans.sanitize = Some(*span); + } _ => {} } } @@ -310,7 +313,6 @@ fn process_builtin_attrs( codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::sanitize => interesting_spans.sanitize = Some(attr.span()), sym::instruction_set => { codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr) } @@ -560,79 +562,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { } } -/// For an attr that has the `sanitize` attribute, read the list of -/// disabled sanitizers. `current_attr` holds the information about -/// previously parsed attributes. -fn parse_sanitize_attr( - tcx: TyCtxt<'_>, - attr: &Attribute, - current_attr: SanitizerSet, -) -> SanitizerSet { - let mut result = current_attr; - if let Some(list) = attr.meta_item_list() { - for item in list.iter() { - let MetaItemInner::MetaItem(set) = item else { - tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() }); - break; - }; - let segments = set.path.segments.iter().map(|x| x.ident.name).collect::>(); - match segments.as_slice() { - // Similar to clang, sanitize(address = ..) and - // sanitize(kernel_address = ..) control both ASan and KASan - // Source: https://reviews.llvm.org/D44981. - [sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => { - result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS - } - [sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => { - result &= !SanitizerSet::ADDRESS; - result &= !SanitizerSet::KERNELADDRESS; - } - [sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI, - [sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI, - [sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI, - [sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI, - [sym::memory] if set.value_str() == Some(sym::off) => { - result |= SanitizerSet::MEMORY - } - [sym::memory] if set.value_str() == Some(sym::on) => { - result &= !SanitizerSet::MEMORY - } - [sym::memtag] if set.value_str() == Some(sym::off) => { - result |= SanitizerSet::MEMTAG - } - [sym::memtag] if set.value_str() == Some(sym::on) => { - result &= !SanitizerSet::MEMTAG - } - [sym::shadow_call_stack] if set.value_str() == Some(sym::off) => { - result |= SanitizerSet::SHADOWCALLSTACK - } - [sym::shadow_call_stack] if set.value_str() == Some(sym::on) => { - result &= !SanitizerSet::SHADOWCALLSTACK - } - [sym::thread] if set.value_str() == Some(sym::off) => { - result |= SanitizerSet::THREAD - } - [sym::thread] if set.value_str() == Some(sym::on) => { - result &= !SanitizerSet::THREAD - } - [sym::hwaddress] if set.value_str() == Some(sym::off) => { - result |= SanitizerSet::HWADDRESS - } - [sym::hwaddress] if set.value_str() == Some(sym::on) => { - result &= !SanitizerSet::HWADDRESS - } - _ => { - tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() }); - } - } - } - } - result -} - fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet { // Backtrack to the crate root. - let disabled = match tcx.opt_local_parent(did) { + let mut disabled = match tcx.opt_local_parent(did) { // Check the parent (recursively). Some(parent) => tcx.disabled_sanitizers_for(parent), // We reached the crate root without seeing an attribute, so @@ -641,8 +573,17 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet { }; // Check for a sanitize annotation directly on this def. - if let Some(attr) = tcx.get_attr(did, sym::sanitize) { - return parse_sanitize_attr(tcx, attr, disabled); + if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set)) + { + // 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; + // the off set is the set of sanitizers explicitly disabled. + // we or those in here. + 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 } disabled } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 209c78ddeda4c..fb5a82051405d 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1120,14 +1120,6 @@ impl IntoDiagArg for ExpectedPointerMutability { } } -#[derive(Diagnostic)] -#[diag(codegen_ssa_invalid_sanitize)] -#[note] -pub(crate) struct InvalidSanitize { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_target_feature_safe_trait)] pub(crate) struct TargetFeatureSafeTrait { diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 084d45cf2cbbf..23d362de308f3 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -2,6 +2,8 @@ //! //! The main entry point is the `step` method. +use std::iter; + use either::Either; use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_data_structures::fx::FxHashSet; @@ -426,6 +428,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, args: &[Spanned>], + dest: &mir::Place<'tcx>, ) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> { let func = self.eval_operand(func, None)?; @@ -435,14 +438,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // protection, but then we'd force *a lot* of arguments into memory. So we do some syntactic // pre-processing here where if all `move` arguments are syntactically distinct local // variables (and none is indirect), we can skip the in-memory forcing. + // We have to include `dest` in that list so that we can detect aliasing of an in-place + // argument with the return place. let move_definitely_disjoint = 'move_definitely_disjoint: { let mut previous_locals = FxHashSet::::default(); - for arg in args { - let mir::Operand::Move(place) = arg.node else { - continue; // we can skip non-`Move` arguments. - }; + for place in args + .iter() + .filter_map(|a| { + // We only have to care about `Move` arguments. + if let mir::Operand::Move(place) = &a.node { Some(place) } else { None } + }) + .chain(iter::once(dest)) + { if place.is_indirect_first_projection() { - // An indirect `Move` argument could alias with anything else... + // An indirect in-place argument could alias with anything else... break 'move_definitely_disjoint false; } if !previous_locals.insert(place.local) { @@ -544,7 +553,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let old_loc = self.frame().loc; let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } = - self.eval_callee_and_args(terminator, func, args)?; + self.eval_callee_and_args(terminator, func, args, &destination)?; let destination = self.eval_place(destination)?; self.init_fn_call( @@ -567,7 +576,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let old_frame_idx = self.frame_idx(); let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } = - self.eval_callee_and_args(terminator, func, args)?; + self.eval_callee_and_args(terminator, func, args, &mir::Place::return_place())?; self.init_fn_tail_call(callee, (fn_sig.abi, fn_abi), &args, with_caller_location)?; diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 2209b18df3fa1..1e73bb6f5fd26 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -10,6 +10,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute}; use rustc_span::def_id::DefId; use rustc_span::hygiene::Transparency; use rustc_span::{Ident, Span, Symbol}; +pub use rustc_target::spec::SanitizerSet; use thin_vec::ThinVec; use crate::attrs::pretty_printing::PrintAttribute; @@ -505,6 +506,12 @@ pub enum AttributeKind { /// Represents `#[rustc_object_lifetime_default]`. RustcObjectLifetimeDefault, + /// Represents `#[sanitize]` + /// + /// 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 }, + /// Represents `#[should_panic]` ShouldPanic { reason: Option, span: Span }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 485ded3981fc2..77c6faa7acd9f 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -73,6 +73,7 @@ impl AttributeKind { RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcObjectLifetimeDefault => No, + Sanitize { .. } => No, ShouldPanic { .. } => No, SkipDuringMethodDispatch { .. } => No, SpecializationTrait(..) => No, diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs index e44b29141da9a..e65de25b45117 100644 --- a/compiler/rustc_hir/src/attrs/pretty_printing.rs +++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs @@ -6,6 +6,7 @@ use rustc_ast::{AttrStyle, IntTy, UintTy}; use rustc_ast_pretty::pp::Printer; use rustc_span::hygiene::Transparency; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol}; +use rustc_target::spec::SanitizerSet; use thin_vec::ThinVec; /// This trait is used to print attributes in `rustc_hir_pretty`. @@ -146,4 +147,14 @@ macro_rules! print_tup { print_tup!(A B C D E F G H); print_skip!(Span, (), ErrorGuaranteed); print_disp!(u16, bool, NonZero); -print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency); +print_debug!( + Symbol, + Ident, + UintTy, + IntTy, + Align, + AttrStyle, + CommentKind, + Transparency, + SanitizerSet, +); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index ea8596ea28658..dbbd95408c8ab 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -120,6 +120,17 @@ impl ProvenanceMap { } } + /// Gets the provenances of all bytes (including from pointers) in a range. + pub fn get_range( + &self, + cx: &impl HasDataLayout, + range: AllocRange, + ) -> impl Iterator { + let ptr_provs = self.range_ptrs_get(range, cx).iter().map(|(_, p)| *p); + let byte_provs = self.range_bytes_get(range).iter().map(|(_, (p, _))| *p); + ptr_provs.chain(byte_provs) + } + /// Attempt to merge per-byte provenance back into ptr chunks, if the right fragments /// sit next to each other. Return `false` is that is not possible due to partial pointers. pub fn merge_bytes(&mut self, cx: &impl HasDataLayout) -> bool { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 49a4733de3b0a..c215e44a9650b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -33,7 +33,7 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, LintEmitter, MultiSpan, }; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::{CtorKind, DefKind}; +use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; use rustc_hir::intravisit::VisitorExt; @@ -445,7 +445,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } fn fn_is_const(self, def_id: DefId) -> bool { - debug_assert_matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn); + debug_assert_matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) + ); self.is_conditionally_const(def_id) } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 9a22bf58c0352..b7ae9994c6273 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; -use rustc_type_ir::{self as ty, Interner, elaborate}; +use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate}; use tracing::instrument; use super::assembly::{Candidate, structural_traits}; @@ -135,12 +135,16 @@ where } let impl_polarity = cx.impl_polarity(impl_def_id); - match impl_polarity { + let certainty = match impl_polarity { ty::ImplPolarity::Negative => return Err(NoSolution), - ty::ImplPolarity::Reservation => { - unimplemented!("reservation impl for const trait: {:?}", goal) - } - ty::ImplPolarity::Positive => {} + ty::ImplPolarity::Reservation => match ecx.typing_mode() { + TypingMode::Coherence => Certainty::AMBIGUOUS, + TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => return Err(NoSolution), + }, + ty::ImplPolarity::Positive => Certainty::Yes, }; if !cx.impl_is_const(impl_def_id) { @@ -171,7 +175,7 @@ where }); ecx.add_goals(GoalSource::ImplWhereBound, const_conditions); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.evaluate_added_goals_and_make_canonical_response(certainty) }) } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 077afd6dd2371..c610ce4fc8599 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -18,7 +18,7 @@ use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, }; -use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr}; +use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr, SanitizerSet}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; @@ -197,6 +197,9 @@ 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}) => { + self.check_sanitize(attr_span, on_set | off_set, span, target); + }, Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect @@ -258,9 +261,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target) } - [sym::sanitize, ..] => { - self.check_sanitize(attr, span, target) - } [sym::thread_local, ..] => self.check_thread_local(attr, span, target), [sym::doc, ..] => self.check_doc_attrs( attr, @@ -483,42 +483,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that the `#[sanitize(..)]` attribute is applied to a /// function/closure/method, or to an impl block or module. - fn check_sanitize(&self, attr: &Attribute, target_span: Span, target: Target) { + fn check_sanitize( + &self, + attr_span: Span, + set: SanitizerSet, + target_span: Span, + target: Target, + ) { let mut not_fn_impl_mod = None; let mut no_body = None; - if let Some(list) = attr.meta_item_list() { - for item in list.iter() { - let MetaItemInner::MetaItem(set) = item else { - return; - }; - let segments = set.path.segments.iter().map(|x| x.ident.name).collect::>(); - match target { - Target::Fn - | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) - | Target::Impl { .. } - | Target::Mod => return, - Target::Static if matches!(segments.as_slice(), [sym::address]) => return, - - // These are "functions", but they aren't allowed because they don't - // have a body, so the usual explanation would be confusing. - Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { - no_body = Some(target_span); - } + match target { + Target::Fn + | Target::Closure + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) + | Target::Impl { .. } + | Target::Mod => return, + Target::Static + // if we mask out the address bits, i.e. *only* address was set, + // we allow it + if set & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS) + == SanitizerSet::empty() => + { + return; + } - _ => { - not_fn_impl_mod = Some(target_span); - } - } + // These are "functions", but they aren't allowed because they don't + // have a body, so the usual explanation would be confusing. + Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { + no_body = Some(target_span); + } + + _ => { + not_fn_impl_mod = Some(target_span); } - self.dcx().emit_err(errors::SanitizeAttributeNotAllowed { - attr_span: attr.span(), - not_fn_impl_mod, - no_body, - help: (), - }); } + + self.dcx().emit_err(errors::SanitizeAttributeNotAllowed { + attr_span, + not_fn_impl_mod, + no_body, + help: (), + }); } /// Checks if `#[naked]` is applied to a function definition. diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs index 7649f72f8681b..cdf62c2553de1 100644 --- a/compiler/rustc_pattern_analysis/src/rustc/print.rs +++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs @@ -101,23 +101,11 @@ pub(crate) fn write_struct_like<'tcx>( let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len()); if num_fields != 0 || variant_and_name.is_none() { write!(f, "(")?; - for i in 0..num_fields { - write!(f, "{}", start_or_comma())?; - - // Common case: the field is where we expect it. - if let Some(p) = subpatterns.get(i) { - if p.field.index() == i { - write!(f, "{}", p.pattern)?; - continue; - } - } - - // Otherwise, we have to go looking for it. - if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) { - write!(f, "{}", p.pattern)?; - } else { - write!(f, "_")?; - } + for FieldPat { pattern, .. } in subpatterns { + write!(f, "{}{pattern}", start_or_comma())?; + } + if matches!(ty.kind(), ty::Tuple(..)) && num_fields == 1 { + write!(f, ",")?; } write!(f, ")")?; } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 7ee0962721f5b..985e669c92d79 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1872,28 +1872,33 @@ pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) { // SAFETY: The caller must guarantee that the buffer pointed to by `dst` // is at least `len` bytes long. unsafe { - match len { - 1 => { - *dst = code as u8; - } - 2 => { - *dst = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - *dst.add(1) = (code & 0x3F) as u8 | TAG_CONT; - } - 3 => { - *dst = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *dst.add(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *dst.add(2) = (code & 0x3F) as u8 | TAG_CONT; - } - 4 => { - *dst = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - *dst.add(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *dst.add(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *dst.add(3) = (code & 0x3F) as u8 | TAG_CONT; - } - // SAFETY: `char` always takes between 1 and 4 bytes to encode in UTF-8. - _ => crate::hint::unreachable_unchecked(), + if len == 1 { + *dst = code as u8; + return; + } + + let last1 = (code >> 0 & 0x3F) as u8 | TAG_CONT; + let last2 = (code >> 6 & 0x3F) as u8 | TAG_CONT; + let last3 = (code >> 12 & 0x3F) as u8 | TAG_CONT; + let last4 = (code >> 18 & 0x3F) as u8 | TAG_FOUR_B; + + if len == 2 { + *dst = last2 | TAG_TWO_B; + *dst.add(1) = last1; + return; } + + if len == 3 { + *dst = last3 | TAG_THREE_B; + *dst.add(1) = last2; + *dst.add(2) = last1; + return; + } + + *dst = last4; + *dst.add(1) = last3; + *dst.add(2) = last2; + *dst.add(3) = last1; } } diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index cdca73cdca11e..a12f692e7543b 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -37,10 +37,10 @@ pub struct FileDesc(OwnedFd); // // On Apple targets however, apparently the 64-bit libc is either buggy or // intentionally showing odd behavior by rejecting any read with a size -// larger than or equal to INT_MAX. To handle both of these the read -// size is capped on both platforms. +// larger than INT_MAX. To handle both of these the read size is capped on +// both platforms. const READ_LIMIT: usize = if cfg!(target_vendor = "apple") { - libc::c_int::MAX as usize - 1 + libc::c_int::MAX as usize } else { libc::ssize_t::MAX as usize }; diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f579bdd847f66..84c9f9cc4d209 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -327,59 +327,6 @@ pub struct Config { } impl Config { - #[cfg_attr( - feature = "tracing", - instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::default_opts") - )] - pub fn default_opts() -> Config { - #[cfg(feature = "tracing")] - span!(target: "CONFIG_HANDLING", tracing::Level::TRACE, "constructing default config"); - - Config { - bypass_bootstrap_lock: false, - llvm_optimize: true, - ninja_in_file: true, - llvm_static_stdcpp: false, - llvm_libzstd: false, - backtrace: true, - rust_optimize: RustOptimize::Bool(true), - rust_optimize_tests: true, - rust_randomize_layout: false, - submodules: None, - docs: true, - docs_minification: true, - rust_rpath: true, - rust_strip: false, - channel: "dev".to_string(), - codegen_tests: true, - rust_dist_src: true, - rust_codegen_backends: vec![CodegenBackendKind::Llvm], - deny_warnings: true, - bindir: "bin".into(), - dist_include_mingw_linker: true, - dist_compression_profile: "fast".into(), - - stdout_is_tty: std::io::stdout().is_terminal(), - stderr_is_tty: std::io::stderr().is_terminal(), - - // set by build.rs - host_target: get_host_target(), - - src: { - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - // Undo `src/bootstrap` - manifest_dir.parent().unwrap().parent().unwrap().to_owned() - }, - out: PathBuf::from("build"), - - // This is needed by codegen_ssa on macOS to ship `llvm-objcopy` aliased to - // `rust-objcopy` to workaround bad `strip`s on macOS. - llvm_tools_enabled: true, - - ..Default::default() - } - } - pub fn set_dry_run(&mut self, dry_run: DryRun) { self.exec_ctx.set_dry_run(dry_run); } diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 62974be2dbe8c..8ba8f1ab564b2 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -75,7 +75,7 @@ fn format_build_step_diffs(current: &BuildStep, parent: &BuildStep) -> String { } } - fn get_steps(step: &BuildStep) -> Vec { + fn get_steps(step: &BuildStep) -> Vec> { step.linearize_steps().into_iter().map(|v| StepByName(v)).collect() } diff --git a/src/ci/citool/src/test_dashboard.rs b/src/ci/citool/src/test_dashboard.rs index 8fbd0d3f200d4..c9de38852e5a8 100644 --- a/src/ci/citool/src/test_dashboard.rs +++ b/src/ci/citool/src/test_dashboard.rs @@ -33,7 +33,7 @@ fn write_page(dir: &Path, name: &str, template: &T) -> anyhow::Resu Ok(()) } -fn gather_test_suites(job_metrics: &HashMap) -> TestSuites { +fn gather_test_suites(job_metrics: &HashMap) -> TestSuites<'_> { struct CoarseTestSuite<'a> { tests: BTreeMap>, } diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index 0367d349a1ef4..3176cb62f6066 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -31,6 +31,6 @@ where } /// Normalizes Windows-style path delimiters to Unix-style paths. -pub fn normalize_path_delimiters(name: &str) -> Cow { +pub fn normalize_path_delimiters(name: &str) -> Cow<'_, str> { if name.contains("\\") { name.replace('\\', "/").into() } else { name.into() } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8d7f05775064f..673947ad30832 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1029,6 +1029,7 @@ fn assoc_const( ) -> impl fmt::Display { let tcx = cx.tcx(); fmt::from_fn(move |w| { + render_attributes_in_code(w, it, &" ".repeat(indent), cx); write!( w, "{indent}{vis}const {name}{generics}: {ty}", @@ -1136,10 +1137,10 @@ fn assoc_method( let (indent, indent_str, end_newline) = if parent == ItemType::Trait { header_len += 4; let indent_str = " "; - write!(w, "{}", render_attributes_in_pre(meth, indent_str, cx))?; + render_attributes_in_code(w, meth, indent_str, cx); (4, indent_str, Ending::NoNewline) } else { - render_attributes_in_code(w, meth, cx); + render_attributes_in_code(w, meth, "", cx); (0, "", Ending::Newline) }; write!( @@ -1309,28 +1310,28 @@ fn render_assoc_item( }) } -// When an attribute is rendered inside a `
` tag, it is formatted using
-// a whitespace prefix and newline.
-fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
-    fmt::from_fn(move |f| {
-        for a in it.attributes(cx.tcx(), cx.cache()) {
-            writeln!(f, "{prefix}{a}")?;
-        }
-        Ok(())
-    })
-}
-
 struct CodeAttribute(String);
 
-fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) {
-    write!(w, "
{}
", code_attr.0).unwrap(); +fn render_code_attribute(prefix: &str, code_attr: CodeAttribute, w: &mut impl fmt::Write) { + write!( + w, + "
{prefix}{attr}
", + prefix = prefix, + attr = code_attr.0 + ) + .unwrap(); } // When an attribute is rendered inside a tag, it is formatted using // a div to produce a newline after it. -fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) { +fn render_attributes_in_code( + w: &mut impl fmt::Write, + it: &clean::Item, + prefix: &str, + cx: &Context<'_>, +) { for attr in it.attributes(cx.tcx(), cx.cache()) { - render_code_attribute(CodeAttribute(attr), w); + render_code_attribute(prefix, CodeAttribute(attr), w); } } @@ -1342,7 +1343,7 @@ fn render_repr_attributes_in_code( item_type: ItemType, ) { if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) { - render_code_attribute(CodeAttribute(repr), w); + render_code_attribute("", CodeAttribute(repr), w); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 407238d66b8cd..2618ec272ca5a 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -20,8 +20,8 @@ use super::{ AssocItemLink, AssocItemRender, Context, ImplRenderingParameters, RenderMode, collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference, item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, - render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, - render_impl, render_repr_attributes_in_code, render_rightside, render_stability_since_raw, + render_assoc_item, render_assoc_items, render_attributes_in_code, render_impl, + render_repr_attributes_in_code, render_rightside, render_stability_since_raw, render_stability_since_raw_with_extra, write_section_heading, }; use crate::clean; @@ -107,13 +107,6 @@ macro_rules! item_template_methods { } item_template_methods!($($rest)*); }; - (render_attributes_in_pre $($rest:tt)*) => { - fn render_attributes_in_pre(&self) -> impl fmt::Display { - let (item, cx) = self.item_and_cx(); - render_attributes_in_pre(item, "", cx) - } - item_template_methods!($($rest)*); - }; (render_assoc_items $($rest:tt)*) => { fn render_assoc_items(&self) -> impl fmt::Display { let (item, cx) = self.item_and_cx(); @@ -457,7 +450,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i write!( w, "\ - {vis}{imp}{stab_tags}\ + " + )?; + render_attributes_in_code(w, myitem, "", cx); + write!( + w, + "{vis}{imp}{stab_tags}\ ", vis = visibility_print_with_space(myitem, cx), imp = import.print(cx) @@ -625,11 +623,11 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display(); wrap_item(w, |w| { + render_attributes_in_code(w, it, "", cx); write!( w, - "{attrs}{vis}{constness}{asyncness}{safety}{abi}fn \ + "{vis}{constness}{asyncness}{safety}{abi}fn \ {name}{generics}{decl}{notable_traits}{where_clause}", - attrs = render_attributes_in_pre(it, "", cx), vis = visibility, constness = constness, asyncness = asyncness, @@ -666,10 +664,10 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt: // Output the trait definition wrap_item(w, |mut w| { + render_attributes_in_code(&mut w, it, "", cx); write!( w, - "{attrs}{vis}{safety}{is_auto}trait {name}{generics}{bounds}", - attrs = render_attributes_in_pre(it, "", cx), + "{vis}{safety}{is_auto}trait {name}{generics}{bounds}", vis = visibility_print_with_space(it, cx), safety = t.safety(tcx).print_with_space(), is_auto = if t.is_auto(tcx) { "auto " } else { "" }, @@ -1240,10 +1238,10 @@ fn item_trait_alias( ) -> impl fmt::Display { fmt::from_fn(|w| { wrap_item(w, |w| { + render_attributes_in_code(w, it, "", cx); write!( w, - "{attrs}trait {name}{generics} = {bounds}{where_clause};", - attrs = render_attributes_in_pre(it, "", cx), + "trait {name}{generics} = {bounds}{where_clause};", name = it.name.unwrap(), generics = t.generics.print(cx), bounds = print_bounds(&t.bounds, true, cx), @@ -1268,10 +1266,10 @@ fn item_trait_alias( fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display { fmt::from_fn(|w| { wrap_item(w, |w| { + render_attributes_in_code(w, it, "", cx); write!( w, - "{attrs}{vis}type {name}{generics}{where_clause} = {type_};", - attrs = render_attributes_in_pre(it, "", cx), + "{vis}type {name}{generics}{where_clause} = {type_};", vis = visibility_print_with_space(it, cx), name = it.name.unwrap(), generics = t.generics.print(cx), @@ -1452,7 +1450,14 @@ item_template!( impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union(&self) -> impl Display { - render_union(self.it, Some(self.generics), self.fields, self.cx) + render_union( + self.it, + Some(self.generics), + self.fields, + self.def_id, + self.is_type_alias, + self.cx, + ) } fn document_field(&self, field: &'a clean::Item) -> impl Display { @@ -1479,27 +1484,6 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { _ => None, }) } - - fn render_attributes_in_pre(&self) -> impl fmt::Display { - fmt::from_fn(move |f| { - if self.is_type_alias { - // For now the only attributes we render for type aliases are `repr` attributes. - if let Some(repr) = clean::repr_attributes( - self.cx.tcx(), - self.cx.cache(), - self.def_id, - ItemType::Union, - ) { - writeln!(f, "{repr}")?; - }; - } else { - for a in self.it.attributes(self.cx.tcx(), self.cx.cache()) { - writeln!(f, "{a}")?; - } - } - Ok(()) - }) - } } fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display { @@ -1563,7 +1547,7 @@ impl<'clean> DisplayEnum<'clean> { // For now the only attributes we render for type aliases are `repr` attributes. render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum); } else { - render_attributes_in_code(w, it, cx); + render_attributes_in_code(w, it, "", cx); } write!( w, @@ -1702,7 +1686,7 @@ fn render_enum_fields( if v.is_stripped() { continue; } - write!(w, "{}", render_attributes_in_pre(v, TAB, cx))?; + render_attributes_in_code(w, v, TAB, cx); w.write_str(TAB)?; match v.kind { clean::VariantItem(ref var) => match var.kind { @@ -1882,6 +1866,7 @@ fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt: fmt::from_fn(|w| { wrap_item(w, |w| { // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`. + render_attributes_in_code(w, it, "", cx); if !t.macro_rules { write!(w, "{}", visibility_print_with_space(it, cx))?; } @@ -1950,7 +1935,7 @@ fn item_constant( fmt::from_fn(|w| { wrap_item(w, |w| { let tcx = cx.tcx(); - render_attributes_in_code(w, it, cx); + render_attributes_in_code(w, it, "", cx); write!( w, @@ -2018,7 +2003,7 @@ impl<'a> DisplayStruct<'a> { // For now the only attributes we render for type aliases are `repr` attributes. render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct); } else { - render_attributes_in_code(w, it, cx); + render_attributes_in_code(w, it, "", cx); } write!( w, @@ -2115,7 +2100,7 @@ fn item_static( ) -> impl fmt::Display { fmt::from_fn(move |w| { wrap_item(w, |w| { - render_attributes_in_code(w, it, cx); + render_attributes_in_code(w, it, "", cx); write!( w, "{vis}{safe}static {mutability}{name}: {typ}", @@ -2135,7 +2120,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display { fmt::from_fn(|w| { wrap_item(w, |w| { w.write_str("extern {\n")?; - render_attributes_in_code(w, it, cx); + render_attributes_in_code(w, it, "", cx); write!(w, " {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap(),) })?; @@ -2358,9 +2343,17 @@ fn render_union( it: &clean::Item, g: Option<&clean::Generics>, fields: &[clean::Item], + def_id: DefId, + is_type_alias: bool, cx: &Context<'_>, ) -> impl Display { fmt::from_fn(move |mut f| { + if is_type_alias { + // For now the only attributes we render for type aliases are `repr` attributes. + render_repr_attributes_in_code(f, cx, def_id, ItemType::Union); + } else { + render_attributes_in_code(f, it, "", cx); + } write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?; let where_displayed = if let Some(generics) = g { @@ -2390,6 +2383,7 @@ fn render_union( for field in fields { if let clean::StructFieldItem(ref ty) = field.kind { + render_attributes_in_code(&mut f, field, " ", cx); writeln!( f, " {}{}: {},", @@ -2481,11 +2475,15 @@ fn render_struct_fields( if toggle { toggle_open(&mut *w, format_args!("{count_fields} fields")); } + if has_visible_fields { + writeln!(w)?; + } for field in fields { if let clean::StructFieldItem(ref ty) = field.kind { - write!( + render_attributes_in_code(w, field, &format!("{tab} "), cx); + writeln!( w, - "\n{tab} {vis}{name}: {ty},", + "{tab} {vis}{name}: {ty},", vis = visibility_print_with_space(field, cx), name = field.name.unwrap(), ty = ty.print(cx) @@ -2495,12 +2493,12 @@ fn render_struct_fields( if has_visible_fields { if has_stripped_entries { - write!( + writeln!( w, - "\n{tab} /* private fields */" + "{tab} /* private fields */" )?; } - write!(w, "\n{tab}")?; + write!(w, "{tab}")?; } else if has_stripped_entries { write!(w, " /* private fields */ ")?; } diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index b5d3367a6a10b..5dba43ca255c7 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -1,5 +1,4 @@

-    {{ self.render_attributes_in_pre()|safe }}
     {{ self.render_union()|safe }}
 
{% if !self.is_type_alias %} diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 7e0c4bee2b3cc..efa99f181b3a1 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -toml = "0.5" +toml = "0.7" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" anyhow = "1.0.32" diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml index 6ee7a831839f9..b7f3625da91b7 100644 --- a/src/tools/bump-stage0/Cargo.toml +++ b/src/tools/bump-stage0/Cargo.toml @@ -11,4 +11,4 @@ build_helper = { path = "../../build_helper" } curl = "0.4.38" indexmap = { version = "2.0.0", features = ["serde"] } serde = { version = "1.0.125", features = ["derive"] } -toml = "0.5.7" +toml = "0.7" diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 2add525b7e8ae..b3618932ded7d 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -65,13 +65,6 @@ harness = false name = "dogfood" harness = false -# quine-mc_cluskey makes up a significant part of the runtime in dogfood -# due to the number of conditions in the clippy_lints crate -# and enabling optimizations for that specific dependency helps a bit -# without increasing total build times. -[profile.dev.package.quine-mc_cluskey] -opt-level = 3 - [lints.rust.unexpected_cfgs] level = "warn" check-cfg = ['cfg(bootstrap)'] diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index e2a0bdbd9b408..74b9b704fea5e 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -242,14 +242,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { match evt { AccessEvent::Read(_) => { - // FIXME: ProvenanceMap should have something like get_range(). - let p_map = alloc.provenance(); - for idx in overlap { - // If a provenance was read by the foreign code, expose it. - if let Some((prov, _idx)) = p_map.get_byte(Size::from_bytes(idx), this) - { - this.expose_provenance(prov)?; - } + // If a provenance was read by the foreign code, expose it. + for prov in alloc.provenance().get_range(this, overlap.into()) { + this.expose_provenance(prov)?; } } AccessEvent::Write(_, certain) => { diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs index b91a41d7650e1..744d64b9b1e88 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs @@ -1,3 +1,5 @@ +//! Ensure we detect aliasing of two in-place arguments for the tricky case where they do not +//! live in memory. //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows // Validation forces more things into memory, which we can't have here. diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs new file mode 100644 index 0000000000000..dff724f8d9657 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs @@ -0,0 +1,34 @@ +//! Ensure we detect aliasing of a in-place argument with the return place for the tricky case where +//! they do not live in memory. +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +// Validation forces more things into memory, which we can't have here. +//@compile-flags: -Zmiri-disable-validation +#![feature(custom_mir, core_intrinsics)] +use std::intrinsics::mir::*; + +#[allow(unused)] +pub struct S(i32); + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let _unit: (); + { + let staging = S(42); // This forces `staging` into memory... + let _non_copy = staging; // ... so we move it to a non-inmemory local here. + // This specifically uses a type with scalar representation to tempt Miri to use the + // efficient way of storing local variables (outside adressable memory). + Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue()) + //~[stack]^ ERROR: not granting access + //~[tree]| ERROR: /reborrow .* forbidden/ + } + after_call = { + Return() + } + } +} + +pub fn callee(x: S) -> S { + x +} diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr new file mode 100644 index 0000000000000..fcd5b8752e7d2 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created here, as the root tag for ALLOC + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: is this argument + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | x + | ^ + = note: BACKTRACE (of the first span): + = note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr new file mode 100644 index 0000000000000..b7f514de0af98 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr @@ -0,0 +1,34 @@ +error: Undefined Behavior: reborrow through (root of the allocation) at ALLOC[0x0] is forbidden + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag (root of the allocation) is foreign to the protected tag (i.e., it is not a child) + = help: this reborrow (acting as a foreign read access) would cause the protected tag (currently Active) to become Disabled + = help: protected tags must never be Disabled +help: the accessed tag was created here + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: the protected tag was created here, in the initial state Reserved + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | x + | ^ +help: the protected tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + | +LL | x + | ^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference + = note: BACKTRACE (of the first span): + = note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs index a8d4c93d160cc..a3935f9835956 100644 --- a/src/tools/opt-dist/src/exec.rs +++ b/src/tools/opt-dist/src/exec.rs @@ -189,6 +189,12 @@ impl Bootstrap { self } + /// Rebuild rustc in case of statically linked LLVM + pub fn rustc_rebuild(mut self) -> Self { + self.cmd = self.cmd.arg("--keep-stage").arg("0"); + self + } + pub fn run(self, timer: &mut TimerSection) -> anyhow::Result<()> { self.cmd.run()?; let metrics = load_metrics(&self.metrics_path)?; diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 19706b4a4f0b3..339c25552adad 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -375,8 +375,14 @@ fn execute_pipeline( let mut dist = Bootstrap::dist(env, &dist_args) .llvm_pgo_optimize(llvm_pgo_profile.as_ref()) - .rustc_pgo_optimize(&rustc_pgo_profile) - .avoid_rustc_rebuild(); + .rustc_pgo_optimize(&rustc_pgo_profile); + + // if LLVM is not built we'll have PGO optimized rustc + dist = if env.supports_shared_llvm() || !env.build_llvm() { + dist.avoid_rustc_rebuild() + } else { + dist.rustc_rebuild() + }; for bolt_profile in bolt_profiles { dist = dist.with_bolt_profile(bolt_profile); diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml index e497b79234202..6392ffbe409ff 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml @@ -40,7 +40,7 @@ cargo_metadata = "0.18" clap = { version = "4.4.2", features = ["derive"] } clap-cargo = "0.12.0" diff = "0.1" -dirs = "5.0" +dirs = "6.0" getopts = "0.2" ignore = "0.4" itertools = "0.12" diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs index bf9b81077f356..fb40d0a9887cf 100644 --- a/tests/rustdoc/attribute-rendering.rs +++ b/tests/rustdoc/attribute-rendering.rs @@ -1,7 +1,8 @@ #![crate_name = "foo"] //@ has 'foo/fn.f.html' -//@ has - //*[@'class="rust item-decl"]' '#[unsafe(export_name = "f")] pub fn f()' +//@ has - //*[@'class="code-attribute"]' '#[unsafe(export_name = "f")]' +//@ has - //*[@'class="rust item-decl"]' 'pub fn f()' #[unsafe(export_name = "\ f")] pub fn f() {} diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs index 34487a8912778..db5f89ed46e4a 100644 --- a/tests/rustdoc/attributes.rs +++ b/tests/rustdoc/attributes.rs @@ -1,18 +1,77 @@ //@ edition: 2024 #![crate_name = "foo"] -//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]' +//@ has foo/fn.f.html '//*[@class="code-attribute"]' '#[unsafe(no_mangle)]' #[unsafe(no_mangle)] pub extern "C" fn f() {} -//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]' +//@ has foo/fn.g.html '//*[@class="code-attribute"]' '#[unsafe(export_name = "bar")]' #[unsafe(export_name = "bar")] pub extern "C" fn g() {} -//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]' +//@ has foo/fn.example.html '//*[@class="code-attribute"]' '#[unsafe(link_section = ".text")]' #[unsafe(link_section = ".text")] pub extern "C" fn example() {} -//@ has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]' +//@ has foo/struct.Repr.html '//*[@class="code-attribute"]' '#[repr(C, align(8))]' #[repr(C, align(8))] pub struct Repr; + +//@ has foo/macro.macro_rule.html '//*[@class="code-attribute"]' '#[unsafe(link_section = ".text")]' +#[unsafe(link_section = ".text")] +#[macro_export] +macro_rules! macro_rule { + () => {}; +} + +//@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "enum")]' +#[unsafe(link_section = "enum")] +pub enum Enum { + //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "a")]' + #[unsafe(link_section = "a")] + A, + //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "quz")]' + #[unsafe(link_section = "quz")] + Quz { + //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "b")]' + #[unsafe(link_section = "b")] + b: (), + }, +} + +//@ has 'foo/trait.Trait.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "trait")]' +#[unsafe(link_section = "trait")] +pub trait Trait { + //@ has 'foo/trait.Trait.html' + //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]/*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]' + //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0u32' + #[unsafe(link_section = "bar")] + const BAR: u32 = 0; + + //@ has - '//*[@class="code-attribute"]' '#[unsafe(link_section = "foo")]' + #[unsafe(link_section = "foo")] + fn foo() {} +} + +//@ has 'foo/union.Union.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "union")]' +#[unsafe(link_section = "union")] +pub union Union { + //@ has 'foo/union.Union.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]' + #[unsafe(link_section = "x")] + pub x: u32, + y: f32, +} + +//@ has 'foo/struct.Struct.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "struct")]' +#[unsafe(link_section = "struct")] +pub struct Struct { + //@ has 'foo/struct.Struct.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]' + #[unsafe(link_section = "x")] + pub x: u32, + y: f32, +} + +// Check that the attributes from the trait items show up consistently in the impl. +//@ has 'foo/struct.Struct.html' '//*[@id="trait-implementations-list"]//*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]' +//@ has 'foo/struct.Struct.html' '//*[@id="trait-implementations-list"]//*[@class="code-attribute"]' '#[unsafe(link_section = "foo")]' +impl Trait for Struct {} diff --git a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html index 04eea709079d7..e8b8e93beb45e 100644 --- a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html +++ b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html @@ -1,4 +1,4 @@ pub enum TypeAlias { - #[non_exhaustive] +
#[non_exhaustive]
Variant, -}
\ No newline at end of file +}
diff --git a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html index 6c8851ea5df47..51763c824ebd2 100644 --- a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html +++ b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html @@ -1,4 +1,4 @@ pub enum Type { - #[non_exhaustive] +
#[non_exhaustive]
Variant, -}
\ No newline at end of file +} diff --git a/tests/rustdoc/type-alias/repr.rs b/tests/rustdoc/type-alias/repr.rs index cf90798036099..884ed74264a58 100644 --- a/tests/rustdoc/type-alias/repr.rs +++ b/tests/rustdoc/type-alias/repr.rs @@ -22,7 +22,8 @@ pub union Foo2 { } //@ has 'foo/type.Bar2.html' -//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]\npub union Bar2 \{*' +//@ matches - '//*[@class="code-attribute"]' '#\[repr\(C\)\]' +//@ matches - '//*[@class="rust item-decl"]' 'pub union Bar2 \{*' // Ensures that we see the doc comment of the type alias and not of the aliased type. //@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar' /// bar diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 98ff578918b04..11e01ac29be23 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -49,24 +49,6 @@ LL | #[crate_name] | = note: for more information, visit -error: malformed `sanitize` attribute input - --> $DIR/malformed-attrs.rs:92:1 - | -LL | #[sanitize] - | ^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL | #[sanitize(address = "on|off")] - | ++++++++++++++++++++ -LL | #[sanitize(cfi = "on|off")] - | ++++++++++++++++ -LL | #[sanitize(hwaddress = "on|off")] - | ++++++++++++++++++++++ -LL | #[sanitize(kcfi = "on|off")] - | +++++++++++++++++ - = and 5 other candidates - error: malformed `instruction_set` attribute input --> $DIR/malformed-attrs.rs:106:1 | @@ -543,6 +525,24 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error[E0539]: malformed `sanitize` attribute input + --> $DIR/malformed-attrs.rs:92:1 + | +LL | #[sanitize] + | ^^^^^^^^^^^ expected this to be a list + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[sanitize(address = "on|off")] + | ++++++++++++++++++++ +LL | #[sanitize(cfi = "on|off")] + | ++++++++++++++++ +LL | #[sanitize(hwaddress = "on|off")] + | ++++++++++++++++++++++ +LL | #[sanitize(kcfi = "on|off")] + | +++++++++++++++++ + = and 5 other candidates + error[E0565]: malformed `no_implicit_prelude` attribute input --> $DIR/malformed-attrs.rs:97:1 | diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs index 5999e04e0e2dd..9c0b26483849e 100644 --- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs +++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs @@ -7,11 +7,11 @@ fn main() { (0 | 1, 2 | 3) => {} } match ((0u8,),) { - //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX))` + //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX,),)` ((0 | 1,) | (2 | 3,),) => {} } match (Some(0u8),) { - //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` + //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)` (None | Some(0 | 1),) => {} } } diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr index 9f691aea8a79c..fe3a4aa2afc73 100644 --- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr +++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr @@ -11,30 +11,30 @@ LL ~ (0 | 1, 2 | 3) => {}, LL + (2_u8..=u8::MAX, _) => todo!() | -error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered +error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX,),)` not covered --> $DIR/exhaustiveness-non-exhaustive.rs:9:11 | LL | match ((0u8,),) { - | ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered + | ^^^^^^^^^ pattern `((4_u8..=u8::MAX,),)` not covered | = note: the matched value is of type `((u8,),)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ ((0 | 1,) | (2 | 3,),) => {}, -LL + ((4_u8..=u8::MAX)) => todo!() +LL + ((4_u8..=u8::MAX,),) => todo!() | -error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered +error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)` not covered --> $DIR/exhaustiveness-non-exhaustive.rs:13:11 | LL | match (Some(0u8),) { - | ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered + | ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX),)` not covered | = note: the matched value is of type `(Option,)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ (None | Some(0 | 1),) => {}, -LL + (Some(2_u8..=u8::MAX)) => todo!() +LL + (Some(2_u8..=u8::MAX),) => todo!() | error: aborting due to 3 previous errors diff --git a/tests/ui/sanitize-attr/invalid-sanitize.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs index 49dc01c8daaf4..957ce780ad0fd 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.rs +++ b/tests/ui/sanitize-attr/invalid-sanitize.rs @@ -1,8 +1,7 @@ #![feature(sanitize)] -#[sanitize(brontosaurus = "off")] //~ ERROR invalid argument -fn main() { -} +#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input +fn main() {} #[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes #[sanitize(address = "off")] @@ -12,11 +11,11 @@ fn multiple_consistent() {} #[sanitize(address = "off")] fn multiple_inconsistent() {} -#[sanitize(address = "bogus")] //~ ERROR invalid argument for `sanitize` +#[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input fn wrong_value() {} #[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input -fn name_value () {} +fn name_value() {} #[sanitize] //~ ERROR malformed `sanitize` attribute input fn just_word() {} diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index 4bf81770b89c0..ec0a93be1420e 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.stderr +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -1,82 +1,115 @@ -error: malformed `sanitize` attribute input - --> $DIR/invalid-sanitize.rs:18:1 +error[E0539]: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:3:1 | -LL | #[sanitize = "off"] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[sanitize(brontosaurus = "off")] + | ^^^^^^^^^^^------------^^^^^^^^^^ + | | + | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread" or "hwaddress" | -help: the following are the possible correct uses +help: try changing it to one of the following valid forms of the attribute | -LL - #[sanitize = "off"] +LL - #[sanitize(brontosaurus = "off")] LL + #[sanitize(address = "on|off")] | -LL - #[sanitize = "off"] +LL - #[sanitize(brontosaurus = "off")] LL + #[sanitize(cfi = "on|off")] | -LL - #[sanitize = "off"] +LL - #[sanitize(brontosaurus = "off")] LL + #[sanitize(hwaddress = "on|off")] | -LL - #[sanitize = "off"] +LL - #[sanitize(brontosaurus = "off")] LL + #[sanitize(kcfi = "on|off")] | = and 5 other candidates -error: malformed `sanitize` attribute input - --> $DIR/invalid-sanitize.rs:21:1 - | -LL | #[sanitize] - | ^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL | #[sanitize(address = "on|off")] - | ++++++++++++++++++++ -LL | #[sanitize(cfi = "on|off")] - | ++++++++++++++++ -LL | #[sanitize(hwaddress = "on|off")] - | ++++++++++++++++++++++ -LL | #[sanitize(kcfi = "on|off")] - | +++++++++++++++++ - = and 5 other candidates - error: multiple `sanitize` attributes - --> $DIR/invalid-sanitize.rs:7:1 + --> $DIR/invalid-sanitize.rs:6:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-sanitize.rs:8:1 + --> $DIR/invalid-sanitize.rs:7:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: multiple `sanitize` attributes - --> $DIR/invalid-sanitize.rs:11:1 + --> $DIR/invalid-sanitize.rs:10:1 | LL | #[sanitize(address = "on")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-sanitize.rs:12:1 + --> $DIR/invalid-sanitize.rs:11:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: invalid argument for `sanitize` - --> $DIR/invalid-sanitize.rs:3:1 +error[E0539]: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:14:1 | -LL | #[sanitize(brontosaurus = "off")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[sanitize(address = "bogus")] + | ^^^^^^^^^^^^^^^^^^^^^-------^^ + | | + | valid arguments are "on" or "off" + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[sanitize(address = "bogus")] +LL + #[sanitize(address = "on|off")] + | +LL - #[sanitize(address = "bogus")] +LL + #[sanitize(cfi = "on|off")] + | +LL - #[sanitize(address = "bogus")] +LL + #[sanitize(hwaddress = "on|off")] + | +LL - #[sanitize(address = "bogus")] +LL + #[sanitize(kcfi = "on|off")] | - = note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread` + = and 5 other candidates -error: invalid argument for `sanitize` - --> $DIR/invalid-sanitize.rs:15:1 +error[E0539]: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:17:1 | -LL | #[sanitize(address = "bogus")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[sanitize = "off"] + | ^^^^^^^^^^^^^^^^^^^ expected this to be a list + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[sanitize = "off"] +LL + #[sanitize(address = "on|off")] + | +LL - #[sanitize = "off"] +LL + #[sanitize(cfi = "on|off")] + | +LL - #[sanitize = "off"] +LL + #[sanitize(hwaddress = "on|off")] + | +LL - #[sanitize = "off"] +LL + #[sanitize(kcfi = "on|off")] + | + = and 5 other candidates + +error[E0539]: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:20:1 | - = note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread` +LL | #[sanitize] + | ^^^^^^^^^^^ expected this to be a list + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[sanitize(address = "on|off")] + | ++++++++++++++++++++ +LL | #[sanitize(cfi = "on|off")] + | ++++++++++++++++ +LL | #[sanitize(hwaddress = "on|off")] + | ++++++++++++++++++++++ +LL | #[sanitize(kcfi = "on|off")] + | +++++++++++++++++ + = and 5 other candidates error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/traits/const-traits/constructor-const-fn.rs b/tests/ui/traits/const-traits/constructor-const-fn.rs new file mode 100644 index 0000000000000..4a7bf531df234 --- /dev/null +++ b/tests/ui/traits/const-traits/constructor-const-fn.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![feature(const_trait_impl)] +const fn impls_fn Foo>(_: &F) {} + +struct Foo(u32); + +const fn foo() { + // This previously triggered an incorrect assert + // when checking whether the constructor of `Foo` + // is const. + impls_fn(&Foo) +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.rs b/tests/ui/traits/const-traits/reservation-impl-ice.rs new file mode 100644 index 0000000000000..efaea1cc6b2bf --- /dev/null +++ b/tests/ui/traits/const-traits/reservation-impl-ice.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -Znext-solver +#![feature(const_from, never_type, const_trait_impl)] + +const fn impls_from>() {} + +const fn foo() { + // This previously ICE'd when encountering the reservation impl + // from the standard library. + impls_from::<()>(); + //~^ ERROR the trait bound `(): From` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.stderr b/tests/ui/traits/const-traits/reservation-impl-ice.stderr new file mode 100644 index 0000000000000..a3fdcbac69e39 --- /dev/null +++ b/tests/ui/traits/const-traits/reservation-impl-ice.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `(): From` is not satisfied + --> $DIR/reservation-impl-ice.rs:9:18 + | +LL | impls_from::<()>(); + | ^^ the trait `From` is not implemented for `()` + | + = help: the following other types implement trait `From`: + `(T, T)` implements `From<[T; 2]>` + `(T, T, T)` implements `From<[T; 3]>` + `(T, T, T, T)` implements `From<[T; 4]>` + `(T, T, T, T, T)` implements `From<[T; 5]>` + `(T, T, T, T, T, T)` implements `From<[T; 6]>` + `(T, T, T, T, T, T, T)` implements `From<[T; 7]>` + `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` + `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` + and 4 others +note: required by a bound in `impls_from` + --> $DIR/reservation-impl-ice.rs:4:24 + | +LL | const fn impls_from>() {} + | ^^^^^^^^^^^^^^ required by this bound in `impls_from` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.