diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 89fca8e89a200..d70ee74a9b2aa 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -979,6 +979,32 @@ impl<'tcx> ItemCtxt<'tcx> { ) -> Vec<(ty::Clause<'tcx>, Span)> { let mut bounds = Vec::new(); + if let PredicateFilter::All = filter { + for param in hir_generics.params { + match param.kind { + hir::GenericParamKind::Type { .. } => { + let param_ty = self.lowerer().lower_ty_param(param.hir_id); + self.lowerer().add_implicit_sizedness_bounds( + &mut bounds, + param_ty, + &[], + ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), + param.span, + ); + self.lowerer().add_default_traits( + &mut bounds, + param_ty, + &[], + ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), + param.span, + ); + } + hir::GenericParamKind::Lifetime { .. } + | hir::GenericParamKind::Const { .. } => {} + } + } + } + for predicate in hir_generics.predicates { let hir_id = predicate.hir_id; let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d1f95591b92d6..23a055e1e26f4 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -304,8 +304,7 @@ fn configure_and_expand( resolver.resolve_crate(&krate); - CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate); - CStore::from_tcx(tcx).report_incompatible_async_drop_feature(tcx, &krate); + CStore::from_tcx(tcx).report_session_incompatibilities(tcx, &krate); krate } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f36485cf03382..feeb38830e0a9 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,5 +1,6 @@ //! Validates all used crates and extern libraries and loads their metadata +use std::collections::BTreeMap; use std::error::Error; use std::path::Path; use std::str::FromStr; @@ -23,6 +24,7 @@ use rustc_middle::bug; use rustc_middle::ty::data_structures::IndexSet; use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_proc_macro::bridge::client::ProcMacro; +use rustc_session::config::mitigation_coverage::DeniedPartialMitigationLevel; use rustc_session::config::{ CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers, TargetModifier, @@ -463,6 +465,12 @@ impl CStore { } } + pub fn report_session_incompatibilities(&self, tcx: TyCtxt<'_>, krate: &Crate) { + self.report_incompatible_target_modifiers(tcx, krate); + self.report_incompatible_partial_mitigations(tcx, krate); + self.report_incompatible_async_drop_feature(tcx, krate); + } + pub fn report_incompatible_target_modifiers(&self, tcx: TyCtxt<'_>, krate: &Crate) { for flag_name in &tcx.sess.opts.cg.unsafe_allow_abi_mismatch { if !OptionsTargetModifiers::is_target_modifier(flag_name) { @@ -484,6 +492,43 @@ impl CStore { } } + pub fn report_incompatible_partial_mitigations(&self, tcx: TyCtxt<'_>, krate: &Crate) { + let my_mitigations = tcx.sess.gather_enabled_denied_partial_mitigations(); + let mut my_mitigations: BTreeMap<_, _> = + my_mitigations.iter().map(|mitigation| (mitigation.kind, mitigation)).collect(); + for skipped_mitigation in tcx.sess.opts.allowed_partial_mitigations(tcx.sess.edition()) { + my_mitigations.remove(&skipped_mitigation); + } + const MAX_ERRORS_PER_MITIGATION: usize = 5; + let mut errors_per_mitigation = BTreeMap::new(); + for (_cnum, data) in self.iter_crate_data() { + if data.is_proc_macro_crate() { + continue; + } + let their_mitigations = data.enabled_denied_partial_mitigations(); + for my_mitigation in my_mitigations.values() { + let their_mitigation = their_mitigations + .iter() + .find(|mitigation| mitigation.kind == my_mitigation.kind) + .map_or(DeniedPartialMitigationLevel::Enabled(false), |m| m.level); + if their_mitigation < my_mitigation.level { + let errors = errors_per_mitigation.entry(my_mitigation.kind).or_insert(0); + if *errors >= MAX_ERRORS_PER_MITIGATION { + continue; + } + *errors += 1; + + tcx.dcx().emit_err(errors::MitigationLessStrictInDependency { + span: krate.spans.inner_span.shrink_to_lo(), + mitigation_name: my_mitigation.kind.to_string(), + mitigation_level: my_mitigation.level.level_str().to_string(), + extern_crate: data.name(), + }); + } + } + } + } + // Report about async drop types in dependency if async drop feature is disabled pub fn report_incompatible_async_drop_feature(&self, tcx: TyCtxt<'_>, krate: &Crate) { if tcx.features().async_drop() { diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 8b2895d70004a..a6f35a179d703 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -696,3 +696,21 @@ pub(crate) struct UnusedCrateDependency { pub extern_crate: Symbol, pub local_crate: Symbol, } + +#[derive(Diagnostic)] +#[diag( + "your program uses the crate `{$extern_crate}`, that is not compiled with `{$mitigation_name}{$mitigation_level}` enabled" +)] +#[note( + "recompile `{$extern_crate}` with `{$mitigation_name}{$mitigation_level}` enabled, or use `-Z allow-partial-mitigations={$mitigation_name}` to allow creating an artifact that has the mitigation partially enabled " +)] +#[help( + "it is possible to disable `-Z allow-partial-mitigations={$mitigation_name}` via `-Z deny-partial-mitigations={$mitigation_name}`" +)] +pub struct MitigationLessStrictInDependency { + #[primary_span] + pub span: Span, + pub mitigation_name: String, + pub mitigation_level: String, + pub extern_crate: Symbol, +} diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index fc541f952d229..280b3b12e5c85 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -30,6 +30,7 @@ use rustc_proc_macro::bridge::client::ProcMacro; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::{Decodable, Decoder}; use rustc_session::config::TargetModifier; +use rustc_session::config::mitigation_coverage::DeniedPartialMitigation; use rustc_session::cstore::{CrateSource, ExternCrate}; use rustc_span::hygiene::HygieneDecodeContext; use rustc_span::{ @@ -78,9 +79,15 @@ impl MetadataBlob { /// own crate numbers. pub(crate) type CrateNumMap = IndexVec; -/// Target modifiers - abi or exploit mitigations flags +/// Target modifiers - abi or exploit mitigations options that may cause unsoundness when mixed or +/// partially enabled. pub(crate) type TargetModifiers = Vec; +/// The set of mitigations that cannot be partially enabled (see +/// [RFC 3855](https://github.com/rust-lang/rfcs/pull/3855)), but are currently enabled for this +/// crate. +pub(crate) type DeniedPartialMitigations = Vec; + pub(crate) struct CrateMetadata { /// The primary crate data - binary metadata blob. blob: MetadataBlob, @@ -959,6 +966,13 @@ impl CrateRoot { ) -> impl ExactSizeIterator { self.target_modifiers.decode(metadata) } + + pub(crate) fn decode_denied_partial_mitigations<'a>( + &self, + metadata: &'a MetadataBlob, + ) -> impl ExactSizeIterator { + self.denied_partial_mitigations.decode(metadata) + } } impl<'a> CrateMetadataRef<'a> { @@ -1941,6 +1955,10 @@ impl CrateMetadata { self.root.decode_target_modifiers(&self.blob).collect() } + pub(crate) fn enabled_denied_partial_mitigations(&self) -> DeniedPartialMitigations { + self.root.decode_denied_partial_mitigations(&self.blob).collect() + } + /// Keep `new_extern_crate` if it looks better in diagnostics pub(crate) fn update_extern_crate_diagnostics( &mut self, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 05eaf54f5d468..eb966417afdf7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -27,6 +27,7 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, TreatParams}; use rustc_middle::{bug, span_bug}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque}; +use rustc_session::config::mitigation_coverage::DeniedPartialMitigation; use rustc_session::config::{CrateType, OptLevel, TargetModifier}; use rustc_span::hygiene::HygieneEncodeContext; use rustc_span::{ @@ -715,6 +716,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // `SourceFiles` we actually need to encode. let source_map = stat!("source-map", || self.encode_source_map()); let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers()); + let denied_partial_mitigations = stat!("denied-partial-mitigations", || self + .encode_enabled_denied_partial_mitigations()); let root = stat!("final", || { let attrs = tcx.hir_krate_attrs(); @@ -758,6 +761,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { foreign_modules, source_map, target_modifiers, + denied_partial_mitigations, traits, impls, incoherent_impls, @@ -2107,6 +2111,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_array(tcx.sess.opts.gather_target_modifiers()) } + fn encode_enabled_denied_partial_mitigations(&mut self) -> LazyArray { + empty_proc_macro!(self); + let tcx = self.tcx; + self.lazy_array(tcx.sess.gather_enabled_denied_partial_mitigations()) + } + fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> { empty_proc_macro!(self); let tcx = self.tcx; diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9dee913e8389c..781d3c6d18372 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,6 +36,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_serialize::opaque::FileEncoder; +use rustc_session::config::mitigation_coverage::DeniedPartialMitigation; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; @@ -286,6 +287,7 @@ pub(crate) struct CrateRoot { source_map: LazyTable>>, target_modifiers: LazyArray, + denied_partial_mitigations: LazyArray, compiler_builtins: bool, needs_allocator: bool, diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 8a9de07836db4..1531584e99788 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -120,6 +120,7 @@ trivially_parameterized_over_tcx! { rustc_middle::ty::adjustment::CoerceUnsizedInfo, rustc_middle::ty::fast_reject::SimplifiedType, rustc_session::config::TargetModifier, + rustc_session::config::mitigation_coverage::DeniedPartialMitigation, rustc_session::cstore::ForeignModule, rustc_session::cstore::LinkagePreference, rustc_session::cstore::NativeLib, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 34168760151c1..3c0b3b4876659 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1449,6 +1449,7 @@ impl Default for Options { logical_env: FxIndexMap::default(), verbose: false, target_modifiers: BTreeMap::default(), + mitigation_coverage_map: Default::default(), } } } @@ -2469,9 +2470,9 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let crate_types = parse_crate_types_from_list(unparsed_crate_types) .unwrap_or_else(|e| early_dcx.early_fatal(e)); - let mut target_modifiers = BTreeMap::::new(); + let mut collected_options = Default::default(); - let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut target_modifiers); + let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut collected_options); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); if !unstable_opts.unstable_options && json_timings { @@ -2487,7 +2488,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let output_types = parse_output_types(early_dcx, &unstable_opts, matches); - let mut cg = CodegenOptions::build(early_dcx, matches, &mut target_modifiers); + let mut cg = CodegenOptions::build(early_dcx, matches, &mut collected_options); let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto( early_dcx, &output_types, @@ -2638,7 +2639,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // -Zretpoline-external-thunk also requires -Zretpoline if unstable_opts.retpoline_external_thunk { unstable_opts.retpoline = true; - target_modifiers.insert( + collected_options.target_modifiers.insert( OptionsTargetModifiers::UnstableOptions(UnstableOptionsTargetModifiers::retpoline), "true".to_string(), ); @@ -2798,7 +2799,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M color, logical_env, verbose, - target_modifiers, + target_modifiers: collected_options.target_modifiers, + mitigation_coverage_map: collected_options.mitigations, } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 027a7045791e4..9fc6036b98b34 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -84,6 +84,8 @@ pub struct TargetModifier { pub value_name: String, } +pub mod mitigation_coverage; + mod target_modifier_consistency_check { use super::*; pub(super) fn sanitizer(l: &TargetModifier, r: Option<&TargetModifier>) -> bool { @@ -198,15 +200,15 @@ macro_rules! gather_tmods { tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals) }; ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, - [SUBSTRUCT], []) => { + [SUBSTRUCT], [$(MITIGATION)?]) => { $opt_expr.gather_target_modifiers($mods, $tmod_vals); }; ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, - [UNTRACKED], []) => {{}}; + [UNTRACKED], [$(MITIGATION)?]) => {{}}; ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, - [TRACKED], []) => {{}}; + [TRACKED], [$(MITIGATION)?]) => {{}}; ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, - [TRACKED_NO_CRATE_HASH], []) => {{}}; + [TRACKED_NO_CRATE_HASH], [$(MITIGATION)?]) => {{}}; } macro_rules! gather_tmods_top_level { @@ -216,7 +218,7 @@ macro_rules! gather_tmods_top_level { ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident TARGET_MODIFIER]) => { compile_error!("Top level option can't be target modifier"); }; - ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident]) => {}; + ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident $(MITIGATION)?]) => {}; } /// Macro for generating OptionsTargetsModifiers top-level enum with impl. @@ -321,6 +323,7 @@ macro_rules! top_level_options { pub $opt: $t ),*, pub target_modifiers: BTreeMap, + pub mitigation_coverage_map: mitigation_coverage::MitigationCoverageMap, } impl Options { @@ -503,11 +506,20 @@ top_level_options!( } ); +macro_rules! mitigation_enum_opt { + ($opt:ident, MITIGATION) => { + Some(mitigation_coverage::DeniedPartialMitigationKind::$opt) + }; + ($opt:ident, $(TARGET_MODIFIER)?) => { + None + }; +} + macro_rules! tmod_enum_opt { - ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, $v:ident) => { + ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, TARGET_MODIFIER) => { Some(OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt)) }; - ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, ) => { + ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, $(MITIGATION)?) => { None }; } @@ -579,7 +591,7 @@ macro_rules! tmod_enum { ( $tmod_enum_name:ident, $prefix:expr, @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*}; - $opt:ident, $parse:ident, $t:ty, [] | + $opt:ident, $parse:ident, $t:ty, [$(MITIGATION)?] | $($tail:tt)* ) => { tmod_enum! { @@ -596,6 +608,47 @@ macro_rules! tmod_enum { }; } +#[derive(Default)] +pub struct CollectedOptions { + pub target_modifiers: BTreeMap, + pub mitigations: mitigation_coverage::MitigationCoverageMap, +} + +macro_rules! setter_for { + // the allow/deny-mitigations options use collected/index instead of the cg, since they + // work across option groups + (allow_partial_mitigations, $struct_name:ident, $parse:ident) => { + pub(super) fn allow_partial_mitigations( + _cg: &mut super::$struct_name, + collected: &mut super::CollectedOptions, + v: Option<&str>, + index: usize, + ) -> bool { + collected.mitigations.handle_allowdeny_mitigation_option(v, index, true) + } + }; + (deny_partial_mitigations, $struct_name:ident, $parse:ident) => { + pub(super) fn deny_partial_mitigations( + _cg: &mut super::$struct_name, + collected: &mut super::CollectedOptions, + v: Option<&str>, + index: usize, + ) -> bool { + collected.mitigations.handle_allowdeny_mitigation_option(v, index, false) + } + }; + ($opt:ident, $struct_name:ident, $parse:ident) => { + pub(super) fn $opt( + cg: &mut super::$struct_name, + _collected: &mut super::CollectedOptions, + v: Option<&str>, + _index: usize, + ) -> bool { + super::parse::$parse(&mut redirect_field!(cg.$opt), v) + } + }; +} + /// Defines all `CodegenOptions`/`DebuggingOptions` fields and parsers all at once. The goal of this /// macro is to define an interface that can be programmatically used by the option parser /// to initialize the struct without hardcoding field names all over the place. @@ -609,7 +662,7 @@ macro_rules! options { $($( #[$attr:meta] )* $opt:ident : $t:ty = ( $init:expr, $parse:ident, - [$dep_tracking_marker:ident $( $tmod:ident )?], + [$dep_tracking_marker:ident $( $modifier_kind:ident )?], $desc:expr $(, removed: $removed:ident )?) ),* ,) => @@ -618,7 +671,7 @@ macro_rules! options { #[rustc_lint_opt_ty] pub struct $struct_name { $( $( #[$attr] )* pub $opt: $t),* } - tmod_enum!( $tmod_enum_name, $prefix, {$($opt, $parse, $t, [$($tmod),*])|*} ); + tmod_enum!( $tmod_enum_name, $prefix, {$($opt, $parse, $t, [$($modifier_kind),*])|*} ); impl Default for $struct_name { fn default() -> $struct_name { @@ -630,7 +683,7 @@ macro_rules! options { pub fn build( early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches, - target_modifiers: &mut BTreeMap, + target_modifiers: &mut CollectedOptions, ) -> $struct_name { build_options(early_dcx, matches, target_modifiers, $stat, $prefix, $outputname) } @@ -660,7 +713,7 @@ macro_rules! options { ) { $({ gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, $init, _mods, _tmod_vals, - [$dep_tracking_marker], [$($tmod),*]); + [$dep_tracking_marker], [$($modifier_kind),*]); })* } } @@ -668,13 +721,13 @@ macro_rules! options { pub const $stat: OptionDescrs<$struct_name> = &[ $( OptionDesc{ name: stringify!($opt), setter: $optmod::$opt, type_desc: desc::$parse, desc: $desc, removed: None $( .or(Some(RemovedOption::$removed)) )?, - tmod: tmod_enum_opt!($struct_name, $tmod_enum_name, $opt, $($tmod),*) } ),* ]; + tmod: tmod_enum_opt!($struct_name, $tmod_enum_name, $opt, $($modifier_kind),*), + mitigation: mitigation_enum_opt!($opt, $($modifier_kind),*), + } ),* ]; mod $optmod { $( - pub(super) fn $opt(cg: &mut super::$struct_name, v: Option<&str>) -> bool { - super::parse::$parse(&mut redirect_field!(cg.$opt), v) - } + setter_for!($opt, $struct_name, $parse); )* } @@ -702,7 +755,7 @@ macro_rules! redirect_field { }; } -type OptionSetter = fn(&mut O, v: Option<&str>) -> bool; +type OptionSetter = fn(&mut O, &mut CollectedOptions, v: Option<&str>, pos: usize) -> bool; type OptionDescrs = &'static [OptionDesc]; /// Indicates whether a removed option should warn or error. @@ -720,6 +773,7 @@ pub struct OptionDesc { desc: &'static str, removed: Option, tmod: Option, + mitigation: Option, } impl OptionDesc { @@ -735,13 +789,13 @@ impl OptionDesc { fn build_options( early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches, - target_modifiers: &mut BTreeMap, + collected_options: &mut CollectedOptions, descrs: OptionDescrs, prefix: &str, outputname: &str, ) -> O { let mut op = O::default(); - for option in matches.opt_strs(prefix) { + for (index, option) in matches.opt_strs_pos(prefix) { let (key, value) = match option.split_once('=') { None => (option, None), Some((k, v)) => (k.to_string(), Some(v)), @@ -749,7 +803,7 @@ fn build_options( let option_to_lookup = key.replace('-', "_"); match descrs.iter().find(|opt_desc| opt_desc.name == option_to_lookup) { - Some(OptionDesc { name: _, setter, type_desc, desc, removed, tmod }) => { + Some(OptionDesc { name: _, setter, type_desc, desc, removed, tmod, mitigation }) => { if let Some(removed) = removed { // deprecation works for prefixed options only assert!(!prefix.is_empty()); @@ -762,7 +816,7 @@ fn build_options( } } } - if !setter(&mut op, value) { + if !setter(&mut op, collected_options, value, index) { match value { None => early_dcx.early_fatal( format!( @@ -778,7 +832,10 @@ fn build_options( } if let Some(tmod) = *tmod { let v = value.map_or(String::new(), ToOwned::to_owned); - target_modifiers.insert(tmod, v); + collected_options.target_modifiers.insert(tmod, v); + } + if let Some(mitigation) = mitigation { + collected_options.mitigations.reset_mitigation(*mitigation, index); } } None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")), @@ -889,6 +946,10 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)"; pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 2^29"; pub(crate) const parse_assert_incr_state: &str = "one of: `loaded`, `not-loaded`"; + pub(crate) const parse_allow_partial_mitigations: &str = + super::mitigation_coverage::DeniedPartialMitigationKind::KINDS; + pub(crate) const parse_deny_partial_mitigations: &str = + super::mitigation_coverage::DeniedPartialMitigationKind::KINDS; } pub mod parse { @@ -2095,7 +2156,7 @@ options! { collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified, parse_collapse_macro_debuginfo, [TRACKED], "set option to collapse debuginfo for macros"), - control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], + control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED MITIGATION], "use Windows Control Flow Guard (default: no)"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), @@ -2237,6 +2298,10 @@ options! { // tidy-alphabetical-start allow_features: Option> = (None, parse_opt_comma_list, [TRACKED], "only allow the listed language features to be enabled in code (comma separated)"), + // the real parser is at the `setter_for` macro, to allow `-Z` and `-C` options to + // work together. + allow_partial_mitigations: () = ((), parse_allow_partial_mitigations, [UNTRACKED], + "Allow mitigations not enabled for all dependency crates (comma separated list)"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata (default: no)"), annotate_moves: AnnotateMoves = (AnnotateMoves::Disabled, parse_annotate_moves, [TRACKED], @@ -2304,6 +2369,8 @@ options! { "deduplicate identical diagnostics (default: yes)"), default_visibility: Option = (None, parse_opt_symbol_visibility, [TRACKED], "overrides the `default_visibility` setting of the target"), + deny_partial_mitigations: () = ((), parse_deny_partial_mitigations, [UNTRACKED], + "Deny mitigations not enabled for all dependency crates (comma separated list)"), dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves (default: no)"), @@ -2693,7 +2760,7 @@ written to standard error output)"), src_hash_algorithm: Option = (None, parse_src_file_hash, [TRACKED], "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")] - stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED], + stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED MITIGATION], "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED], "allow staticlibs to have rust dylib dependencies"), diff --git a/compiler/rustc_session/src/options/mitigation_coverage.rs b/compiler/rustc_session/src/options/mitigation_coverage.rs new file mode 100644 index 0000000000000..f396392cd2638 --- /dev/null +++ b/compiler/rustc_session/src/options/mitigation_coverage.rs @@ -0,0 +1,244 @@ +use std::collections::{BTreeMap, BTreeSet}; +use std::str::FromStr; + +use rustc_macros::{BlobDecodable, Encodable}; +use rustc_span::edition::Edition; +use rustc_target::spec::StackProtector; + +use crate::Session; +use crate::config::Options; +use crate::options::CFGuard; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Encodable, BlobDecodable)] +pub enum DeniedPartialMitigationLevel { + // Enabled(false) should be the bottom of the Ord hierarchy + Enabled(bool), + StackProtector(StackProtector), +} + +impl DeniedPartialMitigationLevel { + pub fn level_str(&self) -> &'static str { + match self { + DeniedPartialMitigationLevel::StackProtector(StackProtector::All) => "=all", + DeniedPartialMitigationLevel::StackProtector(StackProtector::Basic) => "=basic", + DeniedPartialMitigationLevel::StackProtector(StackProtector::Strong) => "=strong", + // currently `=disabled` should not appear + DeniedPartialMitigationLevel::Enabled(false) => "=disabled", + DeniedPartialMitigationLevel::StackProtector(StackProtector::None) + | DeniedPartialMitigationLevel::Enabled(true) => "", + } + } +} + +impl std::fmt::Display for DeniedPartialMitigationLevel { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DeniedPartialMitigationLevel::StackProtector(StackProtector::All) => { + write!(f, "all") + } + DeniedPartialMitigationLevel::StackProtector(StackProtector::Basic) => { + write!(f, "basic") + } + DeniedPartialMitigationLevel::StackProtector(StackProtector::Strong) => { + write!(f, "strong") + } + DeniedPartialMitigationLevel::Enabled(true) => { + write!(f, "enabled") + } + DeniedPartialMitigationLevel::StackProtector(StackProtector::None) + | DeniedPartialMitigationLevel::Enabled(false) => { + write!(f, "disabled") + } + } + } +} + +impl From for DeniedPartialMitigationLevel { + fn from(value: bool) -> Self { + DeniedPartialMitigationLevel::Enabled(value) + } +} + +impl From for DeniedPartialMitigationLevel { + fn from(value: StackProtector) -> Self { + DeniedPartialMitigationLevel::StackProtector(value) + } +} + +#[derive(Copy, Clone)] +struct MitigationStatus { + // This is the index of the option in the command line. This is needed because + // re-enabling a mitigation resets the partial mitigation status if it's later in the command + // line, and this works across `-C` and `-Z` args. + // + // e.g. `-Z stack-protector=strong` resets `-C allow-partial-mitigations=stack-protector`. + index: usize, + allowed: Option, +} + +#[derive(Clone, Default)] +pub struct MitigationCoverageMap { + map: BTreeMap, +} + +impl MitigationCoverageMap { + fn apply_mitigation( + &mut self, + kind: DeniedPartialMitigationKind, + index: usize, + allowed: Option, + ) { + self.map + .entry(kind) + .and_modify(|e| { + if index >= e.index { + *e = MitigationStatus { index, allowed } + } + }) + .or_insert(MitigationStatus { index, allowed }); + } + + pub(crate) fn handle_allowdeny_mitigation_option( + &mut self, + v: Option<&str>, + index: usize, + allowed: bool, + ) -> bool { + match v { + Some(s) => { + for sub in s.split(',') { + match sub.parse() { + Ok(kind) => self.apply_mitigation(kind, index, Some(allowed)), + Err(_) => return false, + } + } + true + } + None => false, + } + } + + pub(crate) fn reset_mitigation(&mut self, kind: DeniedPartialMitigationKind, index: usize) { + self.apply_mitigation(kind, index, None); + } +} + +pub struct DeniedPartialMitigationKindParseError; + +macro_rules! intersperse { + ($sep:expr, ($first:expr $(, $rest:expr)* $(,)?)) => { + concat!($first $(, $sep, $rest)*) + }; +} + +macro_rules! denied_partial_mitigations { + ([$self:ident] enum $kind:ident {$(($name:ident, $text:expr, $since:ident, $code:expr)),*}) => { + #[allow(non_camel_case_types)] + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Encodable, BlobDecodable)] + pub enum DeniedPartialMitigationKind { + $($name),* + } + + impl std::fmt::Display for DeniedPartialMitigationKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + $(DeniedPartialMitigationKind::$name => write!(f, $text)),* + } + } + } + + impl DeniedPartialMitigationKind { + pub(crate) const KINDS: &'static str = concat!("comma-separated list of mitigation kinds (available: ", + intersperse!(", ", ($(concat!("`", $text, "`")),*)), ")"); + } + + impl FromStr for DeniedPartialMitigationKind { + type Err = DeniedPartialMitigationKindParseError; + + fn from_str(v: &str) -> Result { + match v { + $($text => Ok(DeniedPartialMitigationKind::$name)),* + , + _ => Err(DeniedPartialMitigationKindParseError), + } + } + } + + #[allow(unused)] + impl DeniedPartialMitigationKind { + pub fn allowed_by_default_at(&self, edition: Edition) -> bool { + let denied_since = match self { + // Should change the denied-since edition of StackProtector to 2015 + // (all editions) when `-C stack-protector` is stabilized. + $(DeniedPartialMitigationKind::$name => Edition::$since),* + }; + edition < denied_since + } + } + + impl Options { + pub fn all_denied_partial_mitigations(&self) -> impl Iterator { + [$(DeniedPartialMitigationKind::$name),*].into_iter() + } + } + + impl Session { + pub fn gather_enabled_denied_partial_mitigations(&$self) -> Vec { + let mut mitigations = [ + $( + DeniedPartialMitigation { + kind: DeniedPartialMitigationKind::$name, + level: From::from($code), + } + ),* + ]; + mitigations.sort(); + mitigations.into_iter().collect() + } + } + } +} + +denied_partial_mitigations! { + [self] + enum DeniedPartialMitigationKind { + // The mitigation name should match the option name in rustc_session::options, + // to allow for resetting the mitigation + (stack_protector, "stack-protector", EditionFuture, self.stack_protector()), + (control_flow_guard, "control-flow-guard", EditionFuture, self.opts.cg.control_flow_guard == CFGuard::Checks) + } +} + +/// A mitigation that cannot be partially enabled (see +/// [RFC 3855](https://github.com/rust-lang/rfcs/pull/3855)), but are currently enabled for this +/// crate. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Encodable, BlobDecodable)] +pub struct DeniedPartialMitigation { + pub kind: DeniedPartialMitigationKind, + pub level: DeniedPartialMitigationLevel, +} + +impl Options { + // Return the list of mitigations that are allowed to be partial + pub fn allowed_partial_mitigations( + &self, + edition: Edition, + ) -> impl Iterator { + let mut result: BTreeSet<_> = self + .all_denied_partial_mitigations() + .filter(|mitigation| mitigation.allowed_by_default_at(edition)) + .collect(); + for (kind, MitigationStatus { index: _, allowed }) in &self.mitigation_coverage_map.map { + match allowed { + Some(true) => { + result.insert(*kind); + } + Some(false) => { + result.remove(kind); + } + None => {} + } + } + result.into_iter() + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index e8ef1d986062a..768e43146a0c1 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1347,6 +1347,7 @@ impl FramePointer { crate::target_spec_enum! { /// Controls use of stack canaries. + #[derive(Encodable, BlobDecodable, HashStable_Generic)] pub enum StackProtector { /// Disable stack canary generation. None = "none", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 43ab4a64fbedc..04c9edc25d172 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -39,9 +39,7 @@ use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym}; use tracing::{debug, instrument}; use super::suggestions::get_explanation_based_on_obligation; -use super::{ - ArgKind, CandidateSimilarity, FindExprBySpan, GetSafeTransmuteErrorAndReason, ImplCandidate, -}; +use super::{ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate}; use crate::error_reporting::TypeErrCtxt; use crate::error_reporting::infer::TyCategory; use crate::error_reporting::traits::report_dyn_incompatibility; @@ -452,50 +450,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate); - let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate); - suggested = if let &[cand] = &impl_candidates[..] { - let cand = cand.trait_ref; - if let (ty::FnPtr(..), ty::FnDef(..)) = - (cand.self_ty().kind(), main_trait_predicate.self_ty().skip_binder().kind()) - { - // Wrap method receivers and `&`-references in parens - let suggestion = if self.tcx.sess.source_map().span_followed_by(span, ".").is_some() { - vec![ - (span.shrink_to_lo(), format!("(")), - (span.shrink_to_hi(), format!(" as {})", cand.self_ty())), - ] - } else if let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) { - let mut expr_finder = FindExprBySpan::new(span, self.tcx); - expr_finder.visit_expr(body.value); - if let Some(expr) = expr_finder.result && - let hir::ExprKind::AddrOf(_, _, expr) = expr.kind { - vec![ - (expr.span.shrink_to_lo(), format!("(")), - (expr.span.shrink_to_hi(), format!(" as {})", cand.self_ty())), - ] - } else { - vec![(span.shrink_to_hi(), format!(" as {}", cand.self_ty()))] - } - } else { - vec![(span.shrink_to_hi(), format!(" as {}", cand.self_ty()))] - }; - let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path()); - let ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path()); - err.multipart_suggestion( - format!( - "the trait `{trait_}` is implemented for fn pointer \ - `{ty}`, try casting using `as`", - ), - suggestion, - Applicability::MaybeIncorrect, - ); - true - } else { - false - } - } else { - false - } || suggested; + suggested |= self.suggest_cast_to_fn_pointer( + &obligation, + &mut err, + leaf_trait_predicate, + main_trait_predicate, + span, + ); suggested |= self.suggest_remove_reference(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_semicolon_removal( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index fc611a0a2da5e..9a9238f5c7994 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -29,7 +29,8 @@ use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::{ PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _, - with_forced_trimmed_paths, with_no_trimmed_paths, with_types_for_suggestion, + PrintTraitRefExt as _, with_forced_trimmed_paths, with_no_trimmed_paths, + with_types_for_suggestion, }; use rustc_middle::ty::{ self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, @@ -1142,6 +1143,62 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { true } + pub(super) fn suggest_cast_to_fn_pointer( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diag<'_>, + leaf_trait_predicate: ty::PolyTraitPredicate<'tcx>, + main_trait_predicate: ty::PolyTraitPredicate<'tcx>, + span: Span, + ) -> bool { + let &[candidate] = &self.find_similar_impl_candidates(leaf_trait_predicate)[..] else { + return false; + }; + let candidate = candidate.trait_ref; + + if !matches!( + (candidate.self_ty().kind(), main_trait_predicate.self_ty().skip_binder().kind(),), + (ty::FnPtr(..), ty::FnDef(..)) + ) { + return false; + } + + let parenthesized_cast = |span: Span| { + vec![ + (span.shrink_to_lo(), "(".to_string()), + (span.shrink_to_hi(), format!(" as {})", candidate.self_ty())), + ] + }; + // Wrap method receivers and `&`-references in parens. + let suggestion = if self.tcx.sess.source_map().span_followed_by(span, ".").is_some() { + parenthesized_cast(span) + } else if let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) { + let mut expr_finder = FindExprBySpan::new(span, self.tcx); + expr_finder.visit_expr(body.value); + if let Some(expr) = expr_finder.result + && let hir::ExprKind::AddrOf(_, _, expr) = expr.kind + { + parenthesized_cast(expr.span) + } else { + vec![(span.shrink_to_hi(), format!(" as {}", candidate.self_ty()))] + } + } else { + vec![(span.shrink_to_hi(), format!(" as {}", candidate.self_ty()))] + }; + + let trait_ = self.tcx.short_string(candidate.print_trait_sugared(), err.long_ty_path()); + let self_ty = self.tcx.short_string(candidate.self_ty(), err.long_ty_path()); + err.multipart_suggestion( + format!( + "the trait `{trait_}` is implemented for fn pointer \ + `{self_ty}`, try casting using `as`", + ), + suggestion, + Applicability::MaybeIncorrect, + ); + true + } + pub(super) fn check_for_binding_assigned_block_without_tail_expression( &self, obligation: &PredicateObligation<'tcx>, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 3caff6edd504a..15c86b552bba2 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -413,9 +413,9 @@ impl Options { config::parse_error_format(early_dcx, matches, color, json_color, json_rendered); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); - let mut target_modifiers = BTreeMap::::new(); - let codegen_options = CodegenOptions::build(early_dcx, matches, &mut target_modifiers); - let unstable_opts = UnstableOptions::build(early_dcx, matches, &mut target_modifiers); + let mut collected_options = Default::default(); + let codegen_options = CodegenOptions::build(early_dcx, matches, &mut collected_options); + let unstable_opts = UnstableOptions::build(early_dcx, matches, &mut collected_options); let remap_path_prefix = match parse_remap_path_prefix(matches) { Ok(prefix_mappings) => prefix_mappings, @@ -756,10 +756,12 @@ impl Options { } let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s)); - if let Some(ref index_page) = index_page - && !index_page.is_file() - { - dcx.fatal("option `--index-page` argument must be a file"); + if let Some(ref index_page) = index_page { + if index_page.is_file() { + loaded_paths.push(index_page.clone()); + } else { + dcx.fatal("option `--index-page` argument must be a file"); + } } let target = parse_target_triple(early_dcx, matches); @@ -894,7 +896,7 @@ impl Options { scrape_examples_options, unstable_features, doctest_build_args, - target_modifiers, + target_modifiers: collected_options.target_modifiers, }; let render_options = RenderOptions { output, diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index b1c77063ca94e..8cb43e0028708 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -118,8 +118,9 @@ pub(crate) fn write_shared( let mut md_opts = opt.clone(); md_opts.output = cx.dst.clone(); md_opts.external_html = cx.shared.layout.external_html.clone(); + let file = try_err!(cx.sess().source_map().load_file(&index_page), &index_page); try_err!( - crate::markdown::render_and_write(index_page, md_opts, cx.shared.edition()), + crate::markdown::render_and_write(file, md_opts, cx.shared.edition()), &index_page ); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 751db71ceff00..7fa716a9eb3f6 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -70,12 +70,14 @@ use std::io::{self, IsTerminal}; use std::path::Path; use std::process::ExitCode; +use rustc_ast::ast; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::LOCAL_CRATE; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option}; use rustc_session::{EarlyDiagCtxt, getopts}; +use rustc_span::{BytePos, Span, SyntaxContext}; use tracing::info; use crate::clean::utils::DOC_RUST_LANG_ORG_VERSION; @@ -836,8 +838,39 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { // `run_compiler`. return wrap_return( dcx, - interface::run_compiler(config, |_compiler| { - markdown::render_and_write(&md_input, render_options, edition) + interface::run_compiler(config, |compiler| { + // construct a phony "crate" without actually running the parser + // allows us to use other compiler infrastructure like dep-info + let file = + compiler.sess.source_map().load_file(&md_input).map_err(|e| { + format!("{md_input}: {e}", md_input = md_input.display()) + })?; + let inner_span = Span::new( + file.start_pos, + BytePos(file.start_pos.0 + file.normalized_source_len.0), + SyntaxContext::root(), + None, + ); + let krate = ast::Crate { + attrs: Default::default(), + items: Default::default(), + spans: ast::ModSpans { inner_span, ..Default::default() }, + id: ast::DUMMY_NODE_ID, + is_placeholder: false, + }; + rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| { + let has_dep_info = render_options.dep_info().is_some(); + markdown::render_and_write(file, render_options, edition)?; + if has_dep_info { + // Register the loaded external files in the source map so they show up in depinfo. + // We can't load them via the source map because it gets created after we process the options. + for external_path in &loaded_paths { + let _ = compiler.sess.source_map().load_binary_file(external_path); + } + rustc_interface::passes::write_dep_info(tcx); + } + Ok(()) + }) }), ); } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 4ca2c104888bb..594c9b1af3397 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -9,10 +9,12 @@ //! [docs]: https://doc.rust-lang.org/stable/rustdoc/#using-standalone-markdown-files use std::fmt::{self, Write as _}; -use std::fs::{File, create_dir_all, read_to_string}; +use std::fs::{File, create_dir_all}; use std::io::prelude::*; -use std::path::Path; +use std::path::PathBuf; +use std::sync::Arc; +use rustc_span::SourceFile; use rustc_span::edition::Edition; use crate::config::RenderOptions; @@ -43,8 +45,8 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { /// (e.g., output = "bar" => "bar/foo.html"). /// /// Requires session globals to be available, for symbol interning. -pub(crate) fn render_and_write>( - input: P, +pub(crate) fn render_and_write( + input: Arc, options: RenderOptions, edition: Edition, ) -> Result<(), String> { @@ -52,9 +54,9 @@ pub(crate) fn render_and_write>( return Err(format!("{output}: {e}", output = options.output.display())); } - let input = input.as_ref(); + let input_path = input.name.clone().into_local_path().unwrap_or(PathBuf::new()); let mut output = options.output; - output.push(input.file_name().unwrap()); + output.push(input_path.file_name().unwrap()); output.set_extension("html"); let mut css = String::new(); @@ -63,8 +65,7 @@ pub(crate) fn render_and_write>( .expect("Writing to a String can't fail"); } - let input_str = - read_to_string(input).map_err(|err| format!("{input}: {err}", input = input.display()))?; + let input_str = input.src.as_ref().map(|src| &src[..]).unwrap_or(""); let playground_url = options.markdown_playground_url.or(options.playground_url); let playground = playground_url.map(|url| markdown::Playground { crate_name: None, url }); diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 77c15672e0022..d144ffa222097 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -602,11 +602,34 @@ pub fn check(path: &Path, tidy_ctx: TidyCtx) { err(DOUBLE_SPACE_AFTER_DOT) } - if trimmed.contains("//") { + // Heuristics for matching unbalanced backticks by trying to find comments and + // comment blocks. Technically, this can have false negatives (or false positives), + // but as a heuristic this is fine. + let likely_comment = |trimmed: &str| { + // Line comments, doc comments + trimmed.contains("//") + // Also account for `#[cfg_attr(bootstrap, doc = "")]` cases. + || (trimmed.contains("cfg_attr") && trimmed.contains("doc")) + }; + + if likely_comment(trimmed) { let (start_line, mut backtick_count) = comment_block.unwrap_or((i + 1, 0)); let line_backticks = trimmed.chars().filter(|ch| *ch == '`').count(); - let comment_text = trimmed.split("//").nth(1).unwrap(); - // This check ensures that we don't lint for code that has `//` in a string literal + + // Try to split `//`-like comments or `#[cfg_attr(bootstrap), doc = ""]`-like + // doc attributes. Fuzzy, but probably good enough. + let comment_text = match trimmed.split("//").nth(1) { + Some(text) => text, + None => { + // Fallback to try look for RHS of doc attr bits. + let (_doc, rest) = + trimmed.split_once("doc").expect("failed to find `doc` attribute"); + rest + } + }; + + // If backticks on a given comment line is not balanced, add to backtick count. + // This is to account for wrapped backticks and code blocks. if line_backticks % 2 == 1 { backtick_count += comment_text.chars().filter(|ch| *ch == '`').count(); } diff --git a/tests/run-make/rustdoc-dep-info/example.md b/tests/run-make/rustdoc-dep-info/example.md new file mode 100644 index 0000000000000..b4970b4bc3cfc --- /dev/null +++ b/tests/run-make/rustdoc-dep-info/example.md @@ -0,0 +1,3 @@ +% My Example + +First and only paragraph. diff --git a/tests/run-make/rustdoc-dep-info/index-page.md b/tests/run-make/rustdoc-dep-info/index-page.md new file mode 100644 index 0000000000000..95fa11ed0b76a --- /dev/null +++ b/tests/run-make/rustdoc-dep-info/index-page.md @@ -0,0 +1,3 @@ +% Index page + +Index page diff --git a/tests/run-make/rustdoc-dep-info/rmake.rs b/tests/run-make/rustdoc-dep-info/rmake.rs index 11901c97fd6a0..233225fde8696 100644 --- a/tests/run-make/rustdoc-dep-info/rmake.rs +++ b/tests/run-make/rustdoc-dep-info/rmake.rs @@ -3,7 +3,7 @@ //@ needs-target-std -use run_make_support::assertion_helpers::assert_contains; +use run_make_support::assertion_helpers::{assert_contains, assert_not_contains}; use run_make_support::{path, rfs, rustdoc}; fn main() { @@ -19,6 +19,7 @@ fn main() { .arg("--markdown-after-content=after.md") .arg("--extend-css=extend.css") .arg("--theme=theme.css") + .arg("--index-page=index-page.md") .emit("dep-info") .run(); @@ -31,6 +32,7 @@ fn main() { assert_contains(&content, "before.html:"); assert_contains(&content, "extend.css:"); assert_contains(&content, "theme.css:"); + assert_contains(&content, "index-page.md:"); // Now we check that we can provide a file name to the `dep-info` argument. rustdoc().input("lib.rs").arg("-Zunstable-options").emit("dep-info=bla.d").run(); @@ -58,4 +60,40 @@ fn main() { assert!(!path("precedence1.d").exists()); assert!(!path("-").exists()); // `-` shouldn't be treated as a file path assert!(!result.stdout().is_empty()); // Something emitted to stdout + + // test --emit=dep-info combined with plain markdown input + rustdoc().input("example.md").arg("-Zunstable-options").emit("dep-info").run(); + let content = rfs::read_to_string("doc/example.d"); + assert_contains(&content, "example.md:"); + assert_not_contains(&content, "lib.rs:"); + assert_not_contains(&content, "foo.rs:"); + assert_not_contains(&content, "bar.rs:"); + assert_not_contains(&content, "doc.md:"); + assert_not_contains(&content, "after.md:"); + assert_not_contains(&content, "before.html:"); + assert_not_contains(&content, "extend.css:"); + assert_not_contains(&content, "theme.css:"); + + // combine --emit=dep-info=filename with plain markdown input + rustdoc() + .input("example.md") + .arg("-Zunstable-options") + .arg("--html-before-content=before.html") + .arg("--markdown-after-content=after.md") + .arg("--extend-css=extend.css") + .arg("--theme=theme.css") + .arg("--index-page=index-page.md") + .emit("dep-info=example.d") + .run(); + let content = rfs::read_to_string("example.d"); + assert_contains(&content, "example.md:"); + assert_not_contains(&content, "lib.rs:"); + assert_not_contains(&content, "foo.rs:"); + assert_not_contains(&content, "bar.rs:"); + assert_not_contains(&content, "doc.md:"); + assert_contains(&content, "after.md:"); + assert_contains(&content, "before.html:"); + assert_contains(&content, "extend.css:"); + assert_contains(&content, "theme.css:"); + assert_contains(&content, "index-page.md:"); } diff --git a/tests/ui/README.md b/tests/ui/README.md index 7c2df5048fc1b..9ef331698d2b6 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -22,6 +22,12 @@ These tests exercise `#![feature(allocator_api)]` and the `#[global_allocator]` See [Allocator traits and `std::heap` #32838](https://github.com/rust-lang/rust/issues/32838). +## `tests/ui/allow-partial-mitigations` + +These tests exercise the support for mitigation coverage and the `allow-partial-mitigations` and `deny-partial-mitigations` options. + +See [RFC 3855](https://github.com/rust-lang/rfcs/pull/3855). + ## `tests/ui/annotate-moves` These tests exercise the `annotate-moves` feature. diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.control-flow-guard-future-allow-reset-by-mitigation.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.control-flow-guard-future-allow-reset-by-mitigation.stderr new file mode 100644 index 0000000000000..1103e17a17f59 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.control-flow-guard-future-allow-reset-by-mitigation.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `core`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `alloc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `unwind/libc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.rs b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.rs new file mode 100644 index 0000000000000..f4c5e56da53cb --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.rs @@ -0,0 +1,42 @@ +// ignore-tidy-linelength +//@ revisions: stack-protector-future stack-protector-future-explicit-deny stack-protector-future-deny-reset-by-mitigation stack-protector-allow-then-deny stack-protector-but-allow-control-flow-guard control-flow-guard-future-allow-reset-by-mitigation stack-protector-future-allow-reset-by-mitigation stack-protector-future-deny-allow-reset-by-mitigation +//@ check-fail +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown stack protector is not supported +//@ edition:future + +// msvc has an extra unwind dependency of std, normalize it in the error messages +//@ normalize-stderr: "\b(unwind|libc)\b" -> "unwind/libc" + +// test that stack-protector is denied-partial in edition=future +//@ [stack-protector-future] compile-flags: -Z unstable-options -Z stack-protector=all + +// same, but with explicit deny +//@ [stack-protector-future-explicit-deny] compile-flags: -Z unstable-options -Z stack-protector=all -Z deny-partial-mitigations=stack-protector + +// same, but with explicit deny before the enable. The `-Z stack-protector=all` resets the mitigation status +// to default which is deny at edition=future. +// at edition=2024, this would be allowed, see ok-allow-partial-mitigations-current-edition scenario stack-protector-future-deny-reset-by-mitigation +//@ [stack-protector-future-deny-reset-by-mitigation] compile-flags: -Z unstable-options -Z deny-partial-mitigations=stack-protector -Z stack-protector=all + +// same, but with explicit allow followed by explicit deny +//@ [stack-protector-allow-then-deny] compile-flags: -Z unstable-options -Z stack-protector=all -Z allow-partial-mitigations=stack-protector -Z deny-partial-mitigations=stack-protector + +// check that allowing an unrelated mitigation (control-flow-guard) does not allow a different mitigation (stack-protector) +//@ [stack-protector-but-allow-control-flow-guard] compile-flags: -Z unstable-options -Z stack-protector=all -Z allow-partial-mitigations=control-flow-guard + +// check that `-C control-flow-guard` overrides the `-Z allow-partial-mitigations=control-flow-guard` (to the default, which is deny at edition=future) +//@ [control-flow-guard-future-allow-reset-by-mitigation] compile-flags: -Z unstable-options -Z allow-partial-mitigations=control-flow-guard -C control-flow-guard=on + +// check that `-Z stack-protector` overrides the `-Z allow-partial-mitigations=stack-protector` (to the default, which is deny at edition=future) +//@ [stack-protector-future-allow-reset-by-mitigation] compile-flags: -Z unstable-options -Z allow-partial-mitigations=stack-protector -Z stack-protector=all + +// check that this is the case even if there was a "deny" before the "allow" +//@ [stack-protector-future-deny-allow-reset-by-mitigation] compile-flags: -Z unstable-options -Z deny-partial-mitigations=stack-protector -Z allow-partial-mitigations=stack-protector -Z stack-protector=all + +fn main() {} +//~^ ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-allow-then-deny.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-allow-then-deny.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-allow-then-deny.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-but-allow-control-flow-guard.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-but-allow-control-flow-guard.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-but-allow-control-flow-guard.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-allow-reset-by-mitigation.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-allow-reset-by-mitigation.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-allow-reset-by-mitigation.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-deny-allow-reset-by-mitigation.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-deny-allow-reset-by-mitigation.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-deny-allow-reset-by-mitigation.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-deny-reset-by-mitigation.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-deny-reset-by-mitigation.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-deny-reset-by-mitigation.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-explicit-deny.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-explicit-deny.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future-explicit-deny.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future.stderr new file mode 100644 index 0000000000000..3fde64abb2f36 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-1-error.stack-protector-future.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-1-error.rs:37:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.both.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.both.stderr new file mode 100644 index 0000000000000..acc9dd234c693 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.both.stderr @@ -0,0 +1,92 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `std`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.enable-separately-disable-together.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.enable-separately-disable-together.stderr new file mode 100644 index 0000000000000..acc9dd234c693 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.enable-separately-disable-together.stderr @@ -0,0 +1,92 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `std`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.enable-together-disable-separately.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.enable-together-disable-separately.stderr new file mode 100644 index 0000000000000..acc9dd234c693 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.enable-together-disable-separately.stderr @@ -0,0 +1,92 @@ +error: your program uses the crate `std`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `std`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `core`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `core`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `alloc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `alloc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `unwind/libc`, that is not compiled with `stack-protector=all` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `stack-protector=all` enabled, or use `-Z allow-partial-mitigations=stack-protector` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=stack-protector` via `-Z deny-partial-mitigations=stack-protector` + +error: your program uses the crate `unwind/libc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-2-errors.rs:21:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.rs b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.rs new file mode 100644 index 0000000000000..a1c7eba08ebec --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-2-errors.rs @@ -0,0 +1,31 @@ +// ignore-tidy-linelength +//@ revisions: both enable-separately-disable-together enable-together-disable-separately +//@ check-fail +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown stack protector is not supported +//@ edition:future + +// msvc has an extra unwind dependency of std, normalize it in the error messages +//@ normalize-stderr: "\b(unwind|libc)\b" -> "unwind/libc" + +// just use 2 partial mitigations, without any allow/deny flag. Should be denied at edition=future. +//@ [both] compile-flags: -Z unstable-options -C control-flow-guard=on -Z stack-protector=all + +// check that mitigations are denied if they are enabled separately and then disabled in a single command, +// to test the "foo,bar" syntax +//@ [enable-separately-disable-together] compile-flags: -Z unstable-options -C control-flow-guard=on -Z stack-protector=all -Z allow-partial-mitigations=stack-protector -Z allow-partial-mitigations=control-flow-guard -Z deny-partial-mitigations=control-flow-guard,stack-protector + +// same, but for allow +//@ [enable-together-disable-separately] compile-flags: -Z unstable-options -C control-flow-guard=on -Z stack-protector=all -Z allow-partial-mitigations=stack-protector,control-flow-guard -Z deny-partial-mitigations=control-flow-guard -Z deny-partial-mitigations=stack-protector + +fn main() {} +//~^ ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-bad-cli.rs b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-bad-cli.rs new file mode 100644 index 0000000000000..c5fe5b0e1158c --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-bad-cli.rs @@ -0,0 +1,12 @@ +// ignore-tidy-linelength +//@ check-fail +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown stack protector is not supported +//@ edition:future +//@ compile-flags: -Z unstable-options -Z deny-partial-mitigations=garbage + +// test that the list of mitigations in the error message is generated correctly + +//~? ERROR incorrect value `garbage` for unstable option `deny-partial-mitigations` - comma-separated list of mitigation kinds (available: + +fn main() {} diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-bad-cli.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-bad-cli.stderr new file mode 100644 index 0000000000000..9af53a1689aec --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-bad-cli.stderr @@ -0,0 +1,2 @@ +error: incorrect value `garbage` for unstable option `deny-partial-mitigations` - comma-separated list of mitigation kinds (available: `stack-protector`, `control-flow-guard`) was expected + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-current-edition.control-flow-2024-explicit-deny.stderr b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-current-edition.control-flow-2024-explicit-deny.stderr new file mode 100644 index 0000000000000..8f19f30d76569 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-current-edition.control-flow-2024-explicit-deny.stderr @@ -0,0 +1,47 @@ +error: your program uses the crate `std`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-current-edition.rs:18:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `std` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `core`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-current-edition.rs:18:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `core` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `alloc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-current-edition.rs:18:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `alloc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `compiler_builtins`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-current-edition.rs:18:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `compiler_builtins` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: your program uses the crate `unwind/libc`, that is not compiled with `control-flow-guard` enabled + --> $DIR/err-allow-partial-mitigations-current-edition.rs:18:1 + | +LL | fn main() {} + | ^ + | + = note: recompile `unwind/libc` with `control-flow-guard` enabled, or use `-Z allow-partial-mitigations=control-flow-guard` to allow creating an artifact that has the mitigation partially enabled + = help: it is possible to disable `-Z allow-partial-mitigations=control-flow-guard` via `-Z deny-partial-mitigations=control-flow-guard` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-current-edition.rs b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-current-edition.rs new file mode 100644 index 0000000000000..fd3ff94923539 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/err-allow-partial-mitigations-current-edition.rs @@ -0,0 +1,23 @@ +// ignore-tidy-linelength +//@ revisions: control-flow-2024-explicit-deny +//@ check-fail +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown stack protector is not supported +//@ edition: 2024 + +// msvc has an extra unwind dependency of std, normalize it in the error messages +//@ normalize-stderr: "\b(unwind|libc)\b" -> "unwind/libc" + +// check that in edition 2024, it is still possible to explicitly +// disallow partial mitigations (in edition=future, they are +// disallowed by default) + +//@ [control-flow-2024-explicit-deny] compile-flags: -C control-flow-guard=on -Z deny-partial-mitigations=control-flow-guard + + +fn main() {} +//~^ ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with +//~| ERROR that is not compiled with diff --git a/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations-current-edition.rs b/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations-current-edition.rs new file mode 100644 index 0000000000000..dddad265aff4a --- /dev/null +++ b/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations-current-edition.rs @@ -0,0 +1,25 @@ +// ignore-tidy-linelength +//@ revisions: control-flow-guard-2024-default control-flow-guard-2024-deny-reset-by-mitigation stack-protector-2024-deny-reset-by-mitigation stack-protector-2024-allow-deny-reset-by-mitigation +//@ check-pass +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown stack protector is not supported +//@ edition: 2024 + +// check that the `-C control-flow-guard=on` overrides the `-Z deny-partial-mitigations=control-flow-guard`, +// which in edition 2024 leads to partial mitigations being allowed. Test with both an explicit +// deny and without one. + +// just test control-flow-guard at edition 2024. allowed-partial due to backwards compatibility. +//@ [control-flow-guard-2024-default] compile-flags: -C control-flow-guard=on + +// test that -C control-flow-guard=on resets -Z deny-partial-mitigations=control-flow-guard +//@ [control-flow-guard-2024-deny-reset-by-mitigation] compile-flags: -Z deny-partial-mitigations=control-flow-guard -C control-flow-guard=on + +// same but for stack-protector, to match the stack-protector-future-deny-reset-by-mitigation test in +// err-allow-partial-mitigations-1-error (which has the same args but on edition=future). +//@ [stack-protector-2024-deny-reset-by-mitigation] compile-flags: -Z deny-partial-mitigations=stack-protector -Z stack-protector=all + +// check that this is the case even if there was an "allow" then a "deny" +//@ [stack-protector-2024-allow-deny-reset-by-mitigation] compile-flags: -Z unstable-options -Z allow-partial-mitigations=stack-protector -Z deny-partial-mitigations=stack-protector -Z stack-protector=all + +fn main() {} diff --git a/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations-minicore.rs b/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations-minicore.rs new file mode 100644 index 0000000000000..bc8aaa3cb2e61 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations-minicore.rs @@ -0,0 +1,18 @@ +// ignore-tidy-linelength +//@ check-pass +//@ add-minicore +//@ edition:future +//@ revisions: default deny +//@[default] compile-flags: -Z unstable-options -Z stack-protector=all +//@[deny] compile-flags: -Z deny-partial-mitigations=stack-protector -Z unstable-options -Z stack-protector=all + +// ^ enables stack-protector for both minicore and this crate + +#![crate_type = "lib"] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate minicore; + +pub fn foo() {} diff --git a/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations.rs b/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations.rs new file mode 100644 index 0000000000000..f9f013e44cc62 --- /dev/null +++ b/tests/ui/allow-partial-mitigations/ok-allow-partial-mitigations.rs @@ -0,0 +1,18 @@ +// ignore-tidy-linelength +//@ revisions: stack-protector-explicit-allow stack-protector-and-control-flow-guard-explicit-allow stack-protector-deny-then-allow +//@ check-pass +//@ edition:future +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown stack protector is not supported + +// requesting both stack-protector and control-flow-guard and then allow-partial-mitigations it +//@ [stack-protector-and-control-flow-guard-explicit-allow] compile-flags: -Z unstable-options -Z stack-protector=all -C control-flow-guard=on -Z allow-partial-mitigations=stack-protector,control-flow-guard + +// requesting stack-protector and then allow-partial-mitigations it +//@ [stack-protector-explicit-allow] compile-flags: -Z unstable-options -Z stack-protector=all -Z allow-partial-mitigations=stack-protector + +// testing that the later allow-partial-mitigations overrides the earlier deny-partial-mitigations +// see also the stack-protector-allow-then-deny test (in the error tests) for the other order +//@ [stack-protector-deny-then-allow] compile-flags: -Z unstable-options -Z stack-protector=all -Z deny-partial-mitigations=stack-protector -Z allow-partial-mitigations=stack-protector + +fn main() {} diff --git a/tests/ui/traits/alias/default-trait-bounds.fail.stderr b/tests/ui/traits/alias/default-trait-bounds.fail.stderr new file mode 100644 index 0000000000000..9216a1443b647 --- /dev/null +++ b/tests/ui/traits/alias/default-trait-bounds.fail.stderr @@ -0,0 +1,44 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/default-trait-bounds.rs:26:34 + | +LL | #[cfg(fail)] fn a1_fail() { a1::; } + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for `()` to implement `A1` +note: required by a bound in `a1` + --> $DIR/default-trait-bounds.rs:25:30 + | +LL | fn a1() where (): A1 { ensure_is_sized::; } + | ^^^^^ required by this bound in `a1` + +error[E0277]: the size for values of type `ExternTy` cannot be known + --> $DIR/default-trait-bounds.rs:49:34 + | +LL | #[cfg(fail)] fn b1_fail() { b1::; } + | ^^^^^^^^ doesn't have a known size + | + = help: the nightly-only, unstable trait `MetaSized` is not implemented for `ExternTy` + = note: required for `()` to implement `B1` +note: required by a bound in `b1` + --> $DIR/default-trait-bounds.rs:47:36 + | +LL | fn b1() where (): B1 { ensure_is_meta_sized::(); } + | ^^^^^ required by this bound in `b1` + +error[E0277]: the trait bound `ExternTy: C1` is not satisfied + --> $DIR/default-trait-bounds.rs:65:34 + | +LL | #[cfg(fail)] fn c1_fail() { c1::; } + | ^^^^^^^^ the nightly-only, unstable trait `MetaSized` is not implemented for `ExternTy` + | + = note: required for `ExternTy` to implement `C1` +note: required by a bound in `c1` + --> $DIR/default-trait-bounds.rs:63:35 + | +LL | fn c1() where T: C1 { ensure_is_meta_sized::; } + | ^^ required by this bound in `c1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/default-trait-bounds.rs b/tests/ui/traits/alias/default-trait-bounds.rs new file mode 100644 index 0000000000000..5b82dd8b1ba41 --- /dev/null +++ b/tests/ui/traits/alias/default-trait-bounds.rs @@ -0,0 +1,71 @@ +// Check that trait alias bounds also imply default trait bounds to ensure that +// default and user-written bounds behave the same wrt. trait solving. +// +// Previously, we would only imply default trait bounds on +// *`Self`* type params, not on regular type params however. +// issue: +// +//@ revisions: pass fail +//@[pass] check-pass + +#![feature(trait_alias)] +#![feature(sized_hierarchy, extern_types)] // only used for the `MetaSized` test cases + +//------------------------- `Sized` + +trait A0 =; // has a user-written `T: Sized` boun + +// `(): A0` requires+implies `T: Sized` +fn a0() where (): A0 { ensure_is_sized::; } + + +trait A1 =; // has a default `T: Sized` bound + +// `(): A1` requires+implies `T: Sized` +fn a1() where (): A1 { ensure_is_sized::; } +#[cfg(fail)] fn a1_fail() { a1::; } +//[fail]~^ ERROR the size for values of type `str` cannot be known at compilation time + + +fn ensure_is_sized() {} + +//------------------------- `MetaSized` + +use std::marker::{MetaSized, PointeeSized}; +unsafe extern "C" { type ExternTy; } + + +trait B0 =; // has a user-written `T: MetaSized` bounds + +// `(): B0` requires+implies `T: MetaSized` +fn b0() where (): B0 { ensure_is_meta_sized::(); } + + +trait B1 =; // has a default `T: MetaSized` bound + +// `(): B1` requires+implies `T: MetaSized` +fn b1() where (): B1 { ensure_is_meta_sized::(); } + +#[cfg(fail)] fn b1_fail() { b1::; } +//[fail]~^ ERROR the size for values of type `ExternTy` cannot be known + +// For completeness, let's also check default trait bounds on `Self`. + +trait C0 = MetaSized; // has a user-written `Self: MetaSized` bound + +// `T: C0` requires+implies `T: MetaSized` +fn c0() where T: C0 { ensure_is_meta_sized::; } + + +trait C1 =; // has a default `Self: MetaSized` bound + +// `T: C1` requires+implies `T: MetaSized` +fn c1() where T: C1 { ensure_is_meta_sized::; } + +#[cfg(fail)] fn c1_fail() { c1::; } +//[fail]~^ ERROR the trait bound `ExternTy: C1` is not satisfied + + +fn ensure_is_meta_sized() {} + +fn main() {} diff --git a/tests/ui/traits/alias/more-default-trait-bounds.fail.stderr b/tests/ui/traits/alias/more-default-trait-bounds.fail.stderr new file mode 100644 index 0000000000000..35672b14c73b3 --- /dev/null +++ b/tests/ui/traits/alias/more-default-trait-bounds.fail.stderr @@ -0,0 +1,39 @@ +error[E0277]: the trait bound `Unmarked: Mark` is not satisfied + --> $DIR/more-default-trait-bounds.rs:27:34 + | +LL | #[cfg(fail)] fn a1_fail() { a1::; } + | ^^^^^^^^ unsatisfied trait bound + | +help: the trait `Mark` is not implemented for `Unmarked` + --> $DIR/more-default-trait-bounds.rs:47:1 + | +LL | enum Unmarked {} + | ^^^^^^^^^^^^^ + = note: required for `()` to implement `A1` +note: required by a bound in `a1` + --> $DIR/more-default-trait-bounds.rs:25:29 + | +LL | fn a1() where (): A1 { ensure_has_mark::; } + | ^^^^^ required by this bound in `a1` + +error[E0277]: the trait bound `Unmarked: B1` is not satisfied + --> $DIR/more-default-trait-bounds.rs:41:34 + | +LL | #[cfg(fail)] fn b1_fail() { b1::; } + | ^^^^^^^^ unsatisfied trait bound + | +help: the trait `Mark` is not implemented for `Unmarked` + --> $DIR/more-default-trait-bounds.rs:47:1 + | +LL | enum Unmarked {} + | ^^^^^^^^^^^^^ + = note: required for `Unmarked` to implement `B1` +note: required by a bound in `b1` + --> $DIR/more-default-trait-bounds.rs:39:28 + | +LL | fn b1() where T: B1 { ensure_has_mark::; } + | ^^ required by this bound in `b1` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/more-default-trait-bounds.rs b/tests/ui/traits/alias/more-default-trait-bounds.rs new file mode 100644 index 0000000000000..dc1f171823a57 --- /dev/null +++ b/tests/ui/traits/alias/more-default-trait-bounds.rs @@ -0,0 +1,50 @@ +// Check that trait alias bounds also imply default trait bounds to ensure_has_mark that +// default and user-written bounds behave the same wrt. trait solving. +// +// Previously, we would only imply default trait bounds on +// *`Self`* type params, not on regular type params however. +// issue: +// +//@ revisions: pass fail +//@ compile-flags: -Zexperimental-default-bounds +//@[pass] check-pass + +#![feature(trait_alias, more_maybe_bounds, lang_items, auto_traits, negative_impls)] + +#[lang = "default_trait1"] +auto trait Mark {} + + +trait A0 = ?Mark; // has a user-written `T: Mark` bound + +fn a0() where (): A0 { ensure_has_mark::; } + + +trait A1 = ?Mark; // has a default `T: Mark` bound + +fn a1() where (): A1 { ensure_has_mark::; } + +#[cfg(fail)] fn a1_fail() { a1::; } +//[fail]~^ ERROR the trait bound `Unmarked: Mark` is not satisfied + +// For completeness, let's also check default trait bounds on `Self`. + +trait B0 = Mark; // has a user-written `Self: Mark` bound + +fn b0() where T: B0 { ensure_has_mark::; } + + +trait B1 =; // has a default `Self: Mark` bound + +fn b1() where T: B1 { ensure_has_mark::; } + +#[cfg(fail)] fn b1_fail() { b1::; } +//[fail]~^ ERROR the trait bound `Unmarked: B1` is not satisfied + + +fn ensure_has_mark() {} + +enum Unmarked {} +impl !Mark for Unmarked {} + +fn main() {}