diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 885b35d353ef7..1f88d2ab95e9b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -223,13 +223,6 @@ pub(crate) enum OnDuplicate { /// Ignore duplicates Ignore, - - /// Custom function called when a duplicate attribute is found. - /// - /// - `unused` is the span of the attribute that was unused or bad because of some - /// duplicate reason - /// - `used` is the span of the attribute that was used in favor of the unused attribute - Custom(fn(cx: &AcceptContext<'_, '_>, used: Span, unused: Span)), } impl OnDuplicate { @@ -252,7 +245,6 @@ impl OnDuplicate { }); } OnDuplicate::Ignore => {} - OnDuplicate::Custom(f) => f(cx, used, unused), } } } diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 7f5cceb501acd..9060637e53953 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -7,9 +7,7 @@ pub(crate) struct RustcMacroTransparencyParser; impl SingleAttributeParser for RustcMacroTransparencyParser { const PATH: &[Symbol] = &[sym::rustc_macro_transparency]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Custom(|cx, used, unused| { - cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes"); - }); + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const STABILITY: AttributeStability = unstable!(rustc_attrs); const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 10414ae0736d6..77b2c9c73f69f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -10,7 +10,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty}; use rustc_middle::{bug, mir, ty}; -use rustc_session::config::{DebugInfo, OptLevel}; +use rustc_session::config::DebugInfo; use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, hygiene, sym}; use super::operand::{OperandRef, OperandValue}; @@ -460,18 +460,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::UnsizedPlace(_) => return, }; - // FIXME(arm-maintainers): LLVM uses GlobalISel with -O0 that doesn't support scalable - // vectors. It normally falls back to SDAG which does support scalable vectors, but there's - // a bug that means that isn't happening for debuginfo - so temporarily don't emit debuginfo - // for scalable vector locals when there are no optimisations until that bug is - // fixed. See . - if base.layout.peel_transparent_wrappers(bx).ty.is_scalable_vector() - && bx.tcx().backend_optimization_level(()) == OptLevel::No - && bx.sess().opts.debuginfo != DebugInfo::None - { - return; - } - let vars = vars.iter().cloned().chain(fallback_var); for var in vars { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index ecc7b170818d2..b8d5bfe7b650f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -13,21 +13,22 @@ use rustc_infer::infer::{self, InferCtxt, RegionResolutionError, SubregionOrigin use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::print::PrintTraitRefExt as _; -use rustc_middle::ty::relate::solver_relating::RelateExt; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, suggest_constraining_type_params, }; -use rustc_span::{DUMMY_SP, Span, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::misc::{ ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason, type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy, }; -use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCause, ObligationCtxt}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt}; use tracing::debug; use crate::diagnostics; +mod coerce_shared; + pub(super) fn check_trait<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, @@ -267,7 +268,7 @@ fn visit_implementation_of_coerce_shared(checker: &Checker<'_>) -> Result<(), Er // Just compute this for the side-effects, in particular reporting // errors; other parts of the code may demand it for the info of // course. - coerce_shared_info(tcx, impl_did) + coerce_shared::coerce_shared_info(tcx, impl_did) } fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool { @@ -490,7 +491,7 @@ pub(crate) fn reborrow_info<'tcx>( }; let lifetimes_count = generic_lifetime_params_count(args); - let data_fields = collect_struct_data_fields(tcx, def, args); + let data_fields = collect_reborrow_data_fields(tcx, def, args); if lifetimes_count != 1 { let item = tcx.hir_expect_item(impl_did); @@ -509,217 +510,29 @@ pub(crate) fn reborrow_info<'tcx>( let ocx = ObligationCtxt::new_with_diagnostics(&infcx); // We've found some data fields. They must all be either be Copy or Reborrow. - for (field, span) in data_fields { - let field = ocx - .deeply_normalize(&traits::ObligationCause::misc(span, impl_did), param_env, field) + for mut field in data_fields { + field.ty = ocx + .deeply_normalize( + &traits::ObligationCause::misc(field.span, impl_did), + param_env, + Unnormalized::new_wip(field.ty), + ) .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?; - if assert_field_type_is_reborrow( + if field_type_is_reborrow( tcx, &infcx, reborrow_trait, impl_did, param_env, - field, - span, - ) - .is_ok() - { + field.ty, + field.span, + ) { // Field implements Reborrow, check remaining fields. continue; } // Field does not implement Reborrow: it must be Copy. - assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, field, span)?; - } - - Ok(()) -} - -fn assert_field_type_is_reborrow<'tcx>( - tcx: TyCtxt<'tcx>, - infcx: &InferCtxt<'tcx>, - reborrow_trait: DefId, - impl_did: LocalDefId, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, -) -> Result<(), Vec>> { - if ty.ref_mutability() == Some(ty::Mutability::Mut) { - // Mutable references are Reborrow but not really. - return Ok(()); - } - let ocx = ObligationCtxt::new_with_diagnostics(infcx); - let cause = traits::ObligationCause::misc(span, impl_did); - let obligation = - Obligation::new(tcx, cause, param_env, ty::TraitRef::new(tcx, reborrow_trait, [ty])); - ocx.register_obligation(obligation); - let errors = ocx.evaluate_obligations_error_on_ambiguity(); - - if !errors.is_empty() { Err(errors) } else { Ok(()) } -} - -pub(crate) fn coerce_shared_info<'tcx>( - tcx: TyCtxt<'tcx>, - impl_did: LocalDefId, -) -> Result<(), ErrorGuaranteed> { - debug!("compute_coerce_shared_info(impl_did={:?})", impl_did); - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - let span = tcx.def_span(impl_did); - let trait_name = "CoerceShared"; - - let coerce_shared_trait = tcx.require_lang_item(LangItem::CoerceShared, span); - - let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip(); - let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip(); - - if trait_impl_lifetime_params_count(tcx, impl_did) != 1 { - return Err(tcx - .dcx() - .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name })); - } - - assert_eq!(trait_ref.def_id, coerce_shared_trait); - let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let param_env = tcx.param_env(impl_did); - let (source, target) = ocx - .deeply_normalize( - &traits::ObligationCause::misc(span, impl_did), - param_env, - Unnormalized::new_wip((source, trait_ref.args.type_at(1))), - ) - .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?; - - assert!(!source.has_escaping_bound_vars()); - - let data = match (source.kind(), target.kind()) { - (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b)) - if def_a.is_struct() && def_b.is_struct() => - { - // Check that both A and B have exactly one lifetime argument, and that they have the - // same number of data fields that is not more than 1. The eventual intention is to - // support multiple lifetime arguments (with the reborrowed lifetimes inferred from - // usage one way or another) and multiple data fields with B allowed to leave out fields - // from A. The current state is just the simplest choice. - let a_lifetimes_count = generic_lifetime_params_count(args_a); - let a_data_fields = collect_struct_data_fields(tcx, def_a, args_a); - let b_lifetimes_count = generic_lifetime_params_count(args_b); - let b_data_fields = collect_struct_data_fields(tcx, def_b, args_b); - - if a_lifetimes_count != 1 - || b_lifetimes_count != 1 - || a_data_fields.len() > 1 - || b_data_fields.len() > 1 - || a_data_fields.len() != b_data_fields.len() - { - let item = tcx.hir_expect_item(impl_did); - let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = - &item.kind - { - of_trait.trait_ref.path.span - } else { - tcx.def_span(impl_did) - }; - - return Err(tcx - .dcx() - .emit_err(diagnostics::CoerceSharedMulti { span, trait_name })); - } - - if a_data_fields.len() == 1 { - // We found one data field for both: we'll attempt to perform CoerceShared between - // them below. - let (a, span_a) = a_data_fields[0]; - let (b, span_b) = b_data_fields[0]; - let a = ocx - .deeply_normalize( - &traits::ObligationCause::misc(span_a, impl_did), - param_env, - a, - ) - .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?; - let b = ocx - .deeply_normalize( - &traits::ObligationCause::misc(span_b, impl_did), - param_env, - b, - ) - .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?; - - Some((a, b, coerce_shared_trait, span_a, span_b)) - } else { - // We found no data fields in either: this is a reborrowable marker type being - // coerced into a shared marker. That is fine too. - None - } - } - - _ => { - // Note: reusing CoerceUnsizedNonStruct error as it takes trait_name as argument. - return Err(tcx - .dcx() - .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name })); - } - }; - - // We've proven that we have two types with one lifetime each and 0 or 1 data fields each. - if let Some((source, target, trait_def_id, source_field_span, _target_field_span)) = data { - // struct Source(SourceData); - // struct Target(TargetData); - // - // 1 data field each; they must be the same type and Copy, or relate to one another using - // CoerceShared. - // - // FIXME(reborrow): we should do the relating inside `probe` so the region constraint - // doesn't affect later result in case that this relating fails. - // We should resolve regions if the relating succeeds. - // Besides, the regions of `Ref`s are not checked here so `&'a mut T -> &'static T` is - // allowed. - if source.ref_mutability() == Some(ty::Mutability::Mut) - && target.ref_mutability() == Some(ty::Mutability::Not) - && infcx - .relate( - param_env, - source.peel_refs(), - ty::Variance::Invariant, - target.peel_refs(), - source_field_span, - ) - .is_ok() - { - // &mut T implements CoerceShared to &T, except not really. - return Ok(()); - } - - // FIXME(reborrow): we should do the relating inside `probe` so the region constraint - // doesn't affect later result in case that this relating fails. - if infcx - .relate(param_env, source, ty::Variance::Invariant, target, source_field_span) - .is_err() - { - // The two data fields don't agree on a common type; this means - // that they must be `A: CoerceShared`. Register an obligation - // for that. - let cause = traits::ObligationCause::misc(span, impl_did); - let obligation = Obligation::new( - tcx, - cause, - param_env, - ty::TraitRef::new(tcx, trait_def_id, [source, target]), - ); - ocx.register_obligation(obligation); - let errors = ocx.evaluate_obligations_error_on_ambiguity(); - - if !errors.is_empty() { - return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); - } - // Finally, resolve all regions. - ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?; - } else { - // Types match: check that it is Copy. - // - // FIXME(reborrow): We should resolve regions here. - assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, source, source_field_span)?; - } + assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, field.ty, field.span)?; } Ok(()) @@ -737,27 +550,79 @@ fn generic_lifetime_params_count(args: &[ty::GenericArg<'_>]) -> usize { args.iter().filter(|arg| arg.as_region().is_some()).count() } -fn collect_struct_data_fields<'tcx>( +#[derive(Clone, Copy)] +struct ReborrowDataField<'tcx> { + ident: Ident, + name: Symbol, + ty: Ty<'tcx>, + span: Span, +} + +fn collect_reborrow_data_fields<'tcx>( tcx: TyCtxt<'tcx>, def: ty::AdtDef<'tcx>, args: ty::GenericArgsRef<'tcx>, -) -> Vec<(Unnormalized<'tcx, Ty<'tcx>>, Span)> { +) -> Vec> { def.non_enum_variant() .fields .iter() - .filter_map(|f| { - // Ignore PhantomData fields - let ty = f.ty(tcx, args); - // FIXME(#155345): alias might be normalized to PhantomData. - // We probably should normalize here instead. - if ty.skip_norm_wip().is_phantom_data() { - return None; - } - Some((ty, tcx.def_span(f.did))) + .filter_map(|field| { + let ty = field.ty(tcx, args).skip_norm_wip(); + (!ty.is_phantom_data()).then_some(ReborrowDataField { + ident: field.ident(tcx), + name: field.name, + ty, + span: tcx.def_span(field.did), + }) }) .collect() } +fn field_type_is_reborrow<'tcx>( + tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, + reborrow_trait: DefId, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, +) -> bool { + if ty.ref_mutability() == Some(ty::Mutability::Mut) { + // Mutable references are Reborrow but not really. + return true; + } + + let ocx = ObligationCtxt::new(infcx); + let cause = traits::ObligationCause::misc(span, impl_did); + ocx.register_obligation(Obligation::new( + tcx, + cause, + param_env, + ty::TraitRef::new(tcx, reborrow_trait, [ty]), + )); + ocx.evaluate_obligations_error_on_ambiguity().is_empty() +} + +fn field_type_is_copy<'tcx>( + tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, +) -> bool { + let copy_trait = tcx.require_lang_item(LangItem::Copy, span); + let ocx = ObligationCtxt::new(infcx); + let cause = traits::ObligationCause::misc(span, impl_did); + ocx.register_obligation(Obligation::new( + tcx, + cause, + param_env, + ty::TraitRef::new(tcx, copy_trait, [ty]), + )); + ocx.evaluate_obligations_error_on_ambiguity().is_empty() +} + fn assert_field_type_is_copy<'tcx>( tcx: TyCtxt<'tcx>, infcx: &InferCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs new file mode 100644 index 0000000000000..dd4448b2d1fa5 --- /dev/null +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -0,0 +1,812 @@ +use rustc_errors::ErrorGuaranteed; +use rustc_hir as hir; +use rustc_hir::ItemKind; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::lang_items::LangItem; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::Obligation; +use rustc_middle::ty::relate::solver_relating::RelateExt; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized}; +use rustc_span::Span; +use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::traits::{self, ObligationCtxt}; +use tracing::debug; + +use super::{ + ReborrowDataField, assert_field_type_is_copy, collect_reborrow_data_fields, field_type_is_copy, + field_type_is_reborrow, trait_impl_lifetime_params_count, +}; +use crate::diagnostics; + +#[derive(Clone, Copy)] +struct CoerceSharedDiagnosticContext { + impl_span: Span, + trait_span: Span, + source_ty_span: Span, + target_ty_span: Span, + source_lifetime_span: Option, + target_lifetime_span: Option, +} + +#[derive(Clone, Copy)] +enum CoerceSharedTypeRole { + Source, + Target, +} + +impl CoerceSharedTypeRole { + fn as_str(self) -> &'static str { + match self { + CoerceSharedTypeRole::Source => "source", + CoerceSharedTypeRole::Target => "target", + } + } + + fn type_span(self, diagnostic_context: CoerceSharedDiagnosticContext) -> Span { + match self { + CoerceSharedTypeRole::Source => diagnostic_context.source_ty_span, + CoerceSharedTypeRole::Target => diagnostic_context.target_ty_span, + } + } +} + +fn coerce_shared_diagnostic_context( + tcx: TyCtxt<'_>, + impl_did: LocalDefId, +) -> CoerceSharedDiagnosticContext { + let item = tcx.hir_expect_item(impl_did); + let fallback_span = tcx.def_span(impl_did); + let mut diagnostic_context = CoerceSharedDiagnosticContext { + impl_span: item.span, + trait_span: fallback_span, + source_ty_span: fallback_span, + target_ty_span: fallback_span, + source_lifetime_span: None, + target_lifetime_span: None, + }; + + let ItemKind::Impl(impl_) = &item.kind else { + return diagnostic_context; + }; + let Some(of_trait) = impl_.of_trait else { + return diagnostic_context; + }; + + diagnostic_context.trait_span = of_trait.trait_ref.path.span; + diagnostic_context.source_ty_span = impl_.self_ty.span; + diagnostic_context.source_lifetime_span = first_explicit_lifetime_span_in_ty(impl_.self_ty) + .or_else(|| first_explicit_impl_lifetime_param_span(impl_.generics)); + + if let Some(target_ty) = coerce_shared_target_ty_from_path(of_trait.trait_ref.path) { + diagnostic_context.target_ty_span = target_ty.span; + diagnostic_context.target_lifetime_span = + first_explicit_lifetime_span_in_ambig_ty(target_ty); + } else { + diagnostic_context.target_ty_span = diagnostic_context.trait_span; + } + + diagnostic_context +} + +fn coerce_shared_target_ty_from_path<'hir>( + path: &'hir hir::Path<'hir>, +) -> Option<&'hir hir::Ty<'hir, hir::AmbigArg>> { + path.segments.last()?.args().args.iter().find_map(|arg| match arg { + hir::GenericArg::Type(ty) => Some(*ty), + hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) | hir::GenericArg::Infer(_) => { + None + } + }) +} + +fn first_explicit_impl_lifetime_param_span(generics: &hir::Generics<'_>) -> Option { + generics.params.iter().find_map(|param| match param.kind { + hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } => { + Some(param.span) + } + hir::GenericParamKind::Lifetime { .. } + | hir::GenericParamKind::Type { .. } + | hir::GenericParamKind::Const { .. } => None, + }) +} + +fn first_explicit_lifetime_span(lifetime: &hir::Lifetime) -> Option { + match lifetime.kind { + hir::LifetimeKind::Param(_) | hir::LifetimeKind::Static + if !lifetime.ident.span.is_dummy() => + { + Some(lifetime.ident.span) + } + hir::LifetimeKind::Param(_) + | hir::LifetimeKind::Static + | hir::LifetimeKind::ImplicitObjectLifetimeDefault + | hir::LifetimeKind::Error(_) + | hir::LifetimeKind::Infer => None, + } +} + +fn first_explicit_lifetime_span_in_ambig_ty(ty: &hir::Ty<'_, hir::AmbigArg>) -> Option { + first_explicit_lifetime_span_in_ty(ty.as_unambig_ty()) +} + +fn first_explicit_lifetime_span_in_ty(ty: &hir::Ty<'_>) -> Option { + match ty.kind { + hir::TyKind::Ref(lifetime, mut_ty) => first_explicit_lifetime_span(lifetime) + .or_else(|| first_explicit_lifetime_span_in_ty(mut_ty.ty)), + hir::TyKind::Slice(ty) + | hir::TyKind::Array(ty, _) + | hir::TyKind::Pat(ty, _) + | hir::TyKind::FieldOf(ty, _) + | hir::TyKind::View(ty, _) => first_explicit_lifetime_span_in_ty(ty), + hir::TyKind::Ptr(mut_ty) => first_explicit_lifetime_span_in_ty(mut_ty.ty), + hir::TyKind::Tup(tys) => tys.iter().find_map(first_explicit_lifetime_span_in_ty), + hir::TyKind::Path(qpath) => first_explicit_lifetime_span_in_qpath(qpath), + hir::TyKind::TraitObject(bounds, lifetime) => bounds + .iter() + .find_map(|bound| first_explicit_lifetime_span_in_path(bound.trait_ref.path)) + .or_else(|| first_explicit_lifetime_span(&lifetime)), + hir::TyKind::OpaqueDef(opaque) => first_explicit_lifetime_span_in_bounds(opaque.bounds), + hir::TyKind::TraitAscription(bounds) => first_explicit_lifetime_span_in_bounds(bounds), + hir::TyKind::FnPtr(fn_ptr) => { + fn_ptr.generic_params.iter().find_map(|param| match param.kind { + hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } => { + Some(param.span) + } + hir::GenericParamKind::Lifetime { .. } + | hir::GenericParamKind::Type { .. } + | hir::GenericParamKind::Const { .. } => None, + }) + } + hir::TyKind::UnsafeBinder(binder) => binder + .generic_params + .iter() + .find_map(|param| match param.kind { + hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } => { + Some(param.span) + } + hir::GenericParamKind::Lifetime { .. } + | hir::GenericParamKind::Type { .. } + | hir::GenericParamKind::Const { .. } => None, + }) + .or_else(|| first_explicit_lifetime_span_in_ty(binder.inner_ty)), + hir::TyKind::InferDelegation(_) + | hir::TyKind::Never + | hir::TyKind::Infer(()) + | hir::TyKind::Err(_) => None, + } +} + +fn first_explicit_lifetime_span_in_bounds(bounds: hir::GenericBounds<'_>) -> Option { + bounds.iter().find_map(|bound| match bound { + hir::GenericBound::Trait(poly_trait_ref) => { + first_explicit_lifetime_span_in_path(poly_trait_ref.trait_ref.path) + } + hir::GenericBound::Outlives(lifetime) => first_explicit_lifetime_span(lifetime), + hir::GenericBound::Use(args, _) => args.iter().find_map(|arg| match arg { + hir::PreciseCapturingArgKind::Lifetime(lifetime) => { + first_explicit_lifetime_span(lifetime) + } + hir::PreciseCapturingArgKind::Param(_) => None, + }), + }) +} + +fn first_explicit_lifetime_span_in_qpath(qpath: hir::QPath<'_>) -> Option { + match qpath { + hir::QPath::Resolved(qself, path) => qself + .and_then(first_explicit_lifetime_span_in_ty) + .or_else(|| first_explicit_lifetime_span_in_path(path)), + hir::QPath::TypeRelative(qself, segment) => first_explicit_lifetime_span_in_ty(qself) + .or_else(|| first_explicit_lifetime_span_in_path_segment(segment)), + } +} + +fn first_explicit_lifetime_span_in_path(path: &hir::Path<'_>) -> Option { + path.segments.iter().find_map(first_explicit_lifetime_span_in_path_segment) +} + +fn first_explicit_lifetime_span_in_path_segment(segment: &hir::PathSegment<'_>) -> Option { + first_explicit_lifetime_span_in_generic_args(segment.args()) +} + +fn first_explicit_lifetime_span_in_generic_args(args: &hir::GenericArgs<'_>) -> Option { + args.args + .iter() + .find_map(|arg| match arg { + hir::GenericArg::Lifetime(lifetime) => first_explicit_lifetime_span(lifetime), + hir::GenericArg::Type(ty) => first_explicit_lifetime_span_in_ambig_ty(ty), + hir::GenericArg::Const(_) | hir::GenericArg::Infer(_) => None, + }) + .or_else(|| { + args.constraints.iter().find_map(|constraint| { + first_explicit_lifetime_span_in_generic_args(constraint.gen_args) + .or_else(|| constraint.ty().and_then(first_explicit_lifetime_span_in_ty)) + }) + }) +} + +pub(super) fn coerce_shared_info<'tcx>( + tcx: TyCtxt<'tcx>, + impl_did: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + debug!("compute_coerce_shared_info(impl_did={:?})", impl_did); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let span = tcx.def_span(impl_did); + let diagnostic_context = coerce_shared_diagnostic_context(tcx, impl_did); + let trait_name = "CoerceShared"; + + let coerce_shared_trait = tcx.require_lang_item(LangItem::CoerceShared, span); + + let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip(); + let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip(); + + if trait_impl_lifetime_params_count(tcx, impl_did) != 1 { + return Err(tcx + .dcx() + .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name })); + } + + assert_eq!(trait_ref.def_id, coerce_shared_trait); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + let param_env = tcx.param_env(impl_did); + let (source, target) = ocx + .deeply_normalize( + &traits::ObligationCause::misc(span, impl_did), + param_env, + Unnormalized::new_wip((source, trait_ref.args.type_at(1))), + ) + .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?; + let errors = ocx.evaluate_obligations_error_on_ambiguity(); + if !errors.is_empty() { + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); + } + + assert!(!source.has_escaping_bound_vars()); + + match (source.kind(), target.kind()) { + (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b)) + if def_a.is_struct() && def_b.is_struct() => + { + let a_lifetime = single_region_arg(args_a); + let b_lifetime = single_region_arg(args_b); + + if a_lifetime.is_none() || b_lifetime.is_none() { + return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedMulti { + span: diagnostic_context.trait_span, + trait_name, + })); + } + + if a_lifetime != b_lifetime { + return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedLifetimeMismatch { + span: diagnostic_context.trait_span, + source_lifetime_span: diagnostic_context.source_lifetime_span, + target_lifetime_span: diagnostic_context.target_lifetime_span, + trait_name, + })); + } + + validate_reborrow_field_access( + tcx, + impl_did, + def_a, + trait_name, + diagnostic_context, + CoerceSharedTypeRole::Source, + )?; + validate_reborrow_field_access( + tcx, + impl_did, + def_b, + trait_name, + diagnostic_context, + CoerceSharedTypeRole::Target, + )?; + + validate_coerce_shared_fields( + &infcx, + impl_did, + param_env, + coerce_shared_trait, + trait_name, + span, + diagnostic_context, + def_a, + args_a, + def_b, + args_b, + ) + } + + _ => { + // Note: reusing CoerceUnsizedNonStruct error as it takes trait_name as argument. + Err(tcx.dcx().emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name })) + } + } +} + +#[derive(Clone, Copy)] +struct CoerceSharedFieldPair<'tcx> { + source: ReborrowDataField<'tcx>, + target: ReborrowDataField<'tcx>, +} + +struct CoerceSharedFields<'tcx> { + pairs: Vec>, + unpaired_sources: Vec>, +} + +#[derive(Clone, Copy)] +enum CoerceSharedFieldPairError<'tcx> { + FieldStyleMismatch, + MissingSourceField { target: ReborrowDataField<'tcx> }, +} + +fn single_region_arg<'tcx>(args: ty::GenericArgsRef<'tcx>) -> Option> { + let mut lifetimes = args.iter().filter_map(|arg| arg.as_region()); + let lifetime = lifetimes.next()?; + lifetimes.next().is_none().then_some(lifetime) +} + +// This is a coherence/WF check only. It verifies that the CoerceShared impl +// describes a structurally valid field-wise relation. Runtime lowering of the +// operation is not modeled here. +fn collect_coerce_shared_field_pairs<'tcx>( + tcx: TyCtxt<'tcx>, + source_def: ty::AdtDef<'tcx>, + source_args: ty::GenericArgsRef<'tcx>, + target_def: ty::AdtDef<'tcx>, + target_args: ty::GenericArgsRef<'tcx>, +) -> Result, CoerceSharedFieldPairError<'tcx>> { + let source_variant = source_def.non_enum_variant(); + let target_variant = target_def.non_enum_variant(); + if source_variant.ctor_kind() != target_variant.ctor_kind() { + return Err(CoerceSharedFieldPairError::FieldStyleMismatch); + } + + let source_fields = collect_reborrow_data_fields(tcx, source_def, source_args); + let target_fields = collect_reborrow_data_fields(tcx, target_def, target_args); + + let mut pairs = Vec::with_capacity(target_fields.len()); + + for target in &target_fields { + let source = source_fields + .iter() + .find(|source| tcx.hygienic_eq(target.ident, source.ident, source_variant.def_id)) + .ok_or(CoerceSharedFieldPairError::MissingSourceField { target: *target })?; + + pairs.push(CoerceSharedFieldPair { source: *source, target: *target }); + } + + let unpaired_sources = source_fields + .into_iter() + .filter(|source| { + !target_fields + .iter() + .any(|target| tcx.hygienic_eq(target.ident, source.ident, source_variant.def_id)) + }) + .collect(); + + Ok(CoerceSharedFields { pairs, unpaired_sources }) +} + +fn validate_reborrow_field_access( + tcx: TyCtxt<'_>, + impl_did: LocalDefId, + def: ty::AdtDef<'_>, + trait_name: &'static str, + diagnostic_context: CoerceSharedDiagnosticContext, + role: CoerceSharedTypeRole, +) -> Result<(), ErrorGuaranteed> { + let module = tcx.parent_module_from_def_id(impl_did); + let variant = def.non_enum_variant(); + if variant.field_list_has_applicable_non_exhaustive() { + return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedInaccessibleField { + span: diagnostic_context.impl_span, + type_span: role.type_span(diagnostic_context), + trait_name, + role: role.as_str(), + type_name: tcx.item_name(def.did()), + })); + } + + for field in &variant.fields { + if !field.vis.is_accessible_from(module, tcx) { + return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedInaccessibleField { + span: diagnostic_context.impl_span, + type_span: role.type_span(diagnostic_context), + trait_name, + role: role.as_str(), + type_name: tcx.item_name(def.did()), + })); + } + } + + Ok(()) +} + +fn validate_coerce_shared_fields<'tcx>( + infcx: &InferCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + coerce_shared_trait: DefId, + trait_name: &'static str, + span: Span, + diagnostic_context: CoerceSharedDiagnosticContext, + source_def: ty::AdtDef<'tcx>, + source_args: ty::GenericArgsRef<'tcx>, + target_def: ty::AdtDef<'tcx>, + target_args: ty::GenericArgsRef<'tcx>, +) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; + let fields = match collect_coerce_shared_field_pairs( + tcx, + source_def, + source_args, + target_def, + target_args, + ) { + Ok(fields) => fields, + Err(CoerceSharedFieldPairError::FieldStyleMismatch) => { + return Err(tcx + .dcx() + .emit_err(diagnostics::CoerceSharedFieldStyleMismatch { span, trait_name })); + } + Err(CoerceSharedFieldPairError::MissingSourceField { target }) => { + return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedMissingField { + span: target.span, + source_ty_span: diagnostic_context.source_ty_span, + trait_name, + source_ty_name: tcx.item_name(source_def.did()), + field_name: target.name, + })); + } + }; + + for field_pair in fields.pairs { + validate_coerce_shared_field( + infcx, + impl_did, + param_env, + coerce_shared_trait, + trait_name, + span, + diagnostic_context, + field_pair.source, + field_pair.target, + )?; + } + + let reborrow_trait = tcx.require_lang_item(LangItem::Reborrow, span); + for source in fields.unpaired_sources { + validate_coerce_shared_unpaired_source_field( + infcx, + impl_did, + param_env, + reborrow_trait, + trait_name, + diagnostic_context, + source, + )?; + } + + // FIXME(reborrow): remove this temporary WF-side memcpy-ability guard once + // the downstream CoerceShared implementation can correctly handle source and + // target types that are not trivially memcpy-able. Refer to #157489 + validate_coerce_shared_fields_are_memcpy_compatible( + infcx, + impl_did, + param_env, + coerce_shared_trait, + trait_name, + span, + diagnostic_context, + source_def, + source_args, + target_def, + target_args, + )?; + + Ok(()) +} + +fn validate_coerce_shared_fields_are_memcpy_compatible<'tcx>( + infcx: &InferCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + coerce_shared_trait: DefId, + trait_name: &'static str, + span: Span, + diagnostic_context: CoerceSharedDiagnosticContext, + source_def: ty::AdtDef<'tcx>, + source_args: ty::GenericArgsRef<'tcx>, + target_def: ty::AdtDef<'tcx>, + target_args: ty::GenericArgsRef<'tcx>, +) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; + let source_non_zst_fields = + non_zst_reborrow_data_fields(infcx, param_env, source_def, source_args); + let target_non_zst_fields = + non_zst_reborrow_data_fields(infcx, param_env, target_def, target_args); + + match (&source_non_zst_fields[..], &target_non_zst_fields[..]) { + ([], []) => Ok(()), + ([source], [target]) => { + if field_tys_satisfy_relation_after_normalization_and_resolution( + tcx, + impl_did, + param_env, + source.ty, + target.ty, + source.span, + FieldRelation::Equal, + ) { + return Ok(()); + } + + if matches!( + (source.ty.kind(), target.ty.kind()), + (&ty::Ref(_, _, ty::Mutability::Mut), &ty::Ref(_, _, ty::Mutability::Not)) + | (&ty::Alias(..), _) + | (_, &ty::Alias(..)) + ) && field_tys_satisfy_relation_after_normalization_and_resolution( + tcx, + impl_did, + param_env, + source.ty, + target.ty, + source.span, + FieldRelation::MutRefToSharedRef, + ) { + return Ok(()); + } + + validate_field_tys_satisfy_coerce_shared_relation( + infcx, + impl_did, + param_env, + coerce_shared_trait, + trait_name, + span, + diagnostic_context, + *source, + *target, + ) + } + _ => Err(tcx.dcx().emit_err(diagnostics::CoerceSharedMultipleNonZstFields { + span: diagnostic_context.impl_span, + source_ty_span: diagnostic_context.source_ty_span, + target_ty_span: diagnostic_context.target_ty_span, + trait_name, + source_count: source_non_zst_fields.len(), + target_count: target_non_zst_fields.len(), + })), + } +} + +fn non_zst_reborrow_data_fields<'tcx>( + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + def: ty::AdtDef<'tcx>, + args: ty::GenericArgsRef<'tcx>, +) -> Vec> { + let tcx = infcx.tcx; + collect_reborrow_data_fields(tcx, def, args) + .into_iter() + .filter(|field| { + !matches!( + tcx.layout_of(infcx.typing_env(param_env).as_query_input(field.ty)), + Ok(layout) if layout.is_zst() + ) + }) + .collect() +} + +fn validate_coerce_shared_field<'tcx>( + infcx: &InferCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + coerce_shared_trait: DefId, + trait_name: &'static str, + span: Span, + diagnostic_context: CoerceSharedDiagnosticContext, + source: ReborrowDataField<'tcx>, + target: ReborrowDataField<'tcx>, +) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; + if matches!( + (source.ty.kind(), target.ty.kind()), + (&ty::Ref(_, _, ty::Mutability::Mut), &ty::Ref(_, _, ty::Mutability::Not)) + | (&ty::Alias(..), _) + | (_, &ty::Alias(..)) + ) && field_tys_satisfy_relation_after_normalization_and_resolution( + tcx, + impl_did, + param_env, + source.ty, + target.ty, + source.span, + FieldRelation::MutRefToSharedRef, + ) { + return Ok(()); + } + + if field_tys_satisfy_relation_after_normalization_and_resolution( + tcx, + impl_did, + param_env, + source.ty, + target.ty, + source.span, + FieldRelation::Equal, + ) { + return assert_field_type_is_copy(tcx, infcx, impl_did, param_env, source.ty, source.span); + } + + validate_field_tys_satisfy_coerce_shared_relation( + infcx, + impl_did, + param_env, + coerce_shared_trait, + trait_name, + span, + diagnostic_context, + source, + target, + ) +} + +fn validate_coerce_shared_unpaired_source_field<'tcx>( + infcx: &InferCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + reborrow_trait: DefId, + trait_name: &'static str, + diagnostic_context: CoerceSharedDiagnosticContext, + mut source: ReborrowDataField<'tcx>, +) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; + let ocx = ObligationCtxt::new_with_diagnostics(infcx); + source.ty = ocx + .deeply_normalize( + &traits::ObligationCause::misc(source.span, impl_did), + param_env, + Unnormalized::new_wip(source.ty), + ) + .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?; + + if field_type_is_reborrow( + tcx, + infcx, + reborrow_trait, + impl_did, + param_env, + source.ty, + source.span, + ) || field_type_is_copy(tcx, infcx, impl_did, param_env, source.ty, source.span) + { + return Ok(()); + } + + Err(tcx.dcx().emit_err(diagnostics::CoerceSharedOmittedSourceFieldNotCopyOrReborrow { + span: source.span, + impl_span: diagnostic_context.impl_span, + trait_name, + field_name: source.name, + field_ty: source.ty, + })) +} + +fn validate_field_tys_satisfy_coerce_shared_relation<'tcx>( + infcx: &InferCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + coerce_shared_trait: DefId, + trait_name: &'static str, + span: Span, + diagnostic_context: CoerceSharedDiagnosticContext, + source: ReborrowDataField<'tcx>, + target: ReborrowDataField<'tcx>, +) -> Result<(), ErrorGuaranteed> { + let tcx = infcx.tcx; + let ocx = ObligationCtxt::new_with_diagnostics(infcx); + let cause = traits::ObligationCause::misc(span, impl_did); + ocx.register_obligation(Obligation::new( + tcx, + cause, + param_env, + ty::TraitRef::new(tcx, coerce_shared_trait, [source.ty, target.ty]), + )); + let errors = ocx.evaluate_obligations_error_on_ambiguity(); + + if !errors.is_empty() { + return Err(emit_coerce_shared_field_mismatch( + tcx, + trait_name, + diagnostic_context, + source, + target, + )); + } + + ocx.resolve_regions_and_report_errors(impl_did, param_env, []) +} + +fn emit_coerce_shared_field_mismatch<'tcx>( + tcx: TyCtxt<'tcx>, + trait_name: &'static str, + diagnostic_context: CoerceSharedDiagnosticContext, + source: ReborrowDataField<'tcx>, + target: ReborrowDataField<'tcx>, +) -> ErrorGuaranteed { + tcx.dcx().emit_err(diagnostics::CoerceSharedFieldMismatch { + span: target.span, + source_span: source.span, + impl_span: diagnostic_context.impl_span, + source_name: source.name, + source_ty: source.ty, + target_name: target.name, + target_ty: target.ty, + trait_name, + }) +} + +enum FieldRelation { + Equal, + MutRefToSharedRef, +} + +// Normalizing the outer `CoerceShared` types does not normalize their fields: +// instantiating a field can expose projections. Each candidate relation uses a +// fresh inference context, so failed checks cannot affect the next one; this +// intentionally normalizes the fields for each check. +fn field_tys_satisfy_relation_after_normalization_and_resolution<'tcx>( + tcx: TyCtxt<'tcx>, + impl_did: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + source_ty: Ty<'tcx>, + target_ty: Ty<'tcx>, + span: Span, + relation: FieldRelation, +) -> bool { + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let cause = traits::ObligationCause::misc(span, impl_did); + let ocx = ObligationCtxt::new(&infcx); + + let Ok((source_ty, target_ty)) = + ocx.deeply_normalize(&cause, param_env, Unnormalized::new_wip((source_ty, target_ty))) + else { + return false; + }; + + if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() { + return false; + } + + match relation { + FieldRelation::Equal => { + if infcx.relate(param_env, source_ty, ty::Variance::Invariant, target_ty, span).is_err() + { + return false; + } + } + FieldRelation::MutRefToSharedRef => { + let ( + &ty::Ref(source_region, source_referent_ty, ty::Mutability::Mut), + &ty::Ref(target_region, target_referent_ty, ty::Mutability::Not), + ) = (source_ty.kind(), target_ty.kind()) + else { + return false; + }; + if source_region != target_region { + return false; + } + if ocx.sup(&cause, param_env, target_referent_ty, source_referent_ty).is_err() { + return false; + } + } + }; + + ocx.evaluate_obligations_error_on_ambiguity().is_empty() + && ocx.resolve_regions(impl_did, param_env, []).is_empty() +} diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index ab6fa34be9fbb..9b629e17942c4 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -1362,13 +1362,128 @@ pub(crate) struct CoerceSharedNotSingleLifetimeParam { } #[derive(Diagnostic)] -#[diag("implementing `{$trait_name}` does not allow multiple lifetimes or fields to be coerced")] +#[diag( + "implementing `{$trait_name}` requires exactly one lifetime argument in the reborrowed type" +)] pub(crate) struct CoerceSharedMulti { #[primary_span] pub span: Span, pub trait_name: &'static str, } +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` requires source and target to use the same reborrow lifetime \ + argument" +)] +pub(crate) struct CoerceSharedLifetimeMismatch { + #[primary_span] + pub span: Span, + #[label("source reborrow lifetime")] + pub source_lifetime_span: Option, + #[label("target reborrow lifetime")] + pub target_lifetime_span: Option, + pub trait_name: &'static str, +} + +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` requires corresponding fields to match, \ + be reborrowable with `CoerceShared`, or coerce a mutable reference field \ + to a shared reference field" +)] +pub(crate) struct CoerceSharedFieldMismatch<'tcx> { + #[primary_span] + #[label("target field `{$target_name}` has type `{$target_ty}`")] + pub span: Span, + #[label("source field `{$source_name}` has type `{$source_ty}`")] + pub source_span: Span, + #[label("required by this `CoerceShared` implementation")] + pub impl_span: Span, + pub source_name: Symbol, + pub source_ty: Ty<'tcx>, + pub target_name: Symbol, + pub target_ty: Ty<'tcx>, + pub trait_name: &'static str, +} + +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` requires every target field to have a corresponding source field" +)] +pub(crate) struct CoerceSharedMissingField { + #[primary_span] + #[label("target field `{$field_name}` has no corresponding source field")] + pub span: Span, + #[label("source type `{$source_ty_name}` does not contain field `{$field_name}`")] + pub source_ty_span: Span, + pub trait_name: &'static str, + pub source_ty_name: Symbol, + pub field_name: Symbol, +} + +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` requires source fields omitted from the target to be `Copy` or \ + `Reborrow`" +)] +pub(crate) struct CoerceSharedOmittedSourceFieldNotCopyOrReborrow<'tcx> { + #[primary_span] + #[label("source field `{$field_name}` has type `{$field_ty}`")] + pub span: Span, + #[label("required by this `CoerceShared` implementation")] + pub impl_span: Span, + pub trait_name: &'static str, + pub field_name: Symbol, + pub field_ty: Ty<'tcx>, +} + +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` requires source and target structs to use the same field style" +)] +pub(crate) struct CoerceSharedFieldStyleMismatch { + #[primary_span] + pub span: Span, + pub trait_name: &'static str, +} + +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` requires all {$role} type fields to be accessible from the impl" +)] +pub(crate) struct CoerceSharedInaccessibleField { + #[primary_span] + pub span: Span, + #[label("{$role} type `{$type_name}` has inaccessible reborrow data fields")] + pub type_span: Span, + pub trait_name: &'static str, + pub role: &'static str, + pub type_name: Symbol, +} + +#[derive(Diagnostic)] +#[diag( + "implementing `{$trait_name}` currently requires source and target to have at most one \ + non-ZST reborrow data field" +)] +#[note( + "this is a temporary restriction until `CoerceShared` lowering supports non-trivially \ + memcpy-compatible field layouts" +)] +pub(crate) struct CoerceSharedMultipleNonZstFields { + #[primary_span] + #[label("in this `CoerceShared` implementation")] + pub span: Span, + #[label("source type has {$source_count} non-ZST reborrow data fields")] + pub source_ty_span: Span, + #[label("target type has {$target_count} non-ZST reborrow data fields")] + pub target_ty_span: Span, + pub trait_name: &'static str, + pub source_count: usize, + pub target_count: usize, +} + #[derive(Diagnostic)] #[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)] pub(crate) struct CoerceUnsizedNonStruct { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index fb2d200cd638f..3382bbd761455 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -54,11 +54,11 @@ use crate::lints::{ BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, - BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, - BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds, - BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, - BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, - BuiltinUnusedDocCommentSub, BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel, + BuiltinMutablesTransmutes, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, + BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, + BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, + BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, + BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -870,36 +870,7 @@ declare_lint! { "const items will not have their symbols exported" } -declare_lint! { - /// The `no_mangle_generic_items` lint detects generic items that must be - /// mangled. - /// - /// ### Example - /// - /// ```rust - /// #[unsafe(no_mangle)] - /// fn foo(t: T) {} - /// - /// #[unsafe(export_name = "bar")] - /// fn bar(t: T) {} - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// A function with generics must have its symbol mangled to accommodate - /// the generic parameter. The [`no_mangle`] and [`export_name`] attributes - /// have no effect in this situation, and should be removed. - /// - /// [`no_mangle`]: https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute - /// [`export_name`]: https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute - NO_MANGLE_GENERIC_ITEMS, - Warn, - "generic items must be mangled" -} - -declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]); +declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS]); impl InvalidNoMangleItems { fn check_no_mangle_on_generic_fn( @@ -910,11 +881,10 @@ impl InvalidNoMangleItems { ) { let generics = cx.tcx.generics_of(def_id); if generics.requires_monomorphization(cx.tcx) { - cx.emit_span_lint( - NO_MANGLE_GENERIC_ITEMS, - cx.tcx.def_span(def_id), - BuiltinNoMangleGeneric { suggestion: attr_span }, - ); + cx.tcx.dcx().emit_err(crate::diagnostics::BuiltinNoMangleGeneric { + span: cx.tcx.def_span(def_id), + suggestion: attr_span, + }); } } } @@ -1553,7 +1523,6 @@ pub mod soft { ANONYMOUS_PARAMETERS, UNUSED_DOC_COMMENTS, NO_MANGLE_CONST_ITEMS, - NO_MANGLE_GENERIC_ITEMS, MUTABLE_TRANSMUTES, UNSTABLE_FEATURES, UNREACHABLE_PUB, diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 8fec30816bd13..37aa7bccc6745 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -74,6 +74,22 @@ pub(crate) struct UnknownToolInScopedLint { pub is_nightly_build: bool, } +#[derive(Diagnostic)] +#[diag("functions generic over types or consts must be mangled")] +pub(crate) struct BuiltinNoMangleGeneric { + #[primary_span] + pub span: Span, + // Use of `#[no_mangle]` suggests FFI intent; correct + // fix may be to monomorphize source by hand + #[suggestion( + "remove this attribute", + style = "short", + code = "", + applicability = "maybe-incorrect" + )] + pub suggestion: Span, +} + #[derive(Diagnostic)] #[diag("`...` range patterns are deprecated", code = E0783)] pub(crate) struct BuiltinEllipsisInclusiveRangePatterns { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4669328cb28c9..fb7d5b6a3133d 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -698,6 +698,11 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, \ see for more information", ); + store.register_removed( + "no_mangle_generic_items", + "converted into hard error, \ + generic items must always be mangled", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 07279a04b0c8c..a652ea753e421 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -225,20 +225,6 @@ pub(crate) enum BuiltinUnusedDocCommentSub { BlockHelp, } -#[derive(Diagnostic)] -#[diag("functions generic over types or consts must be mangled")] -pub(crate) struct BuiltinNoMangleGeneric { - // Use of `#[no_mangle]` suggests FFI intent; correct - // fix may be to monomorphize source by hand - #[suggestion( - "remove this attribute", - style = "short", - code = "", - applicability = "maybe-incorrect" - )] - pub suggestion: Span, -} - #[derive(Diagnostic)] #[diag("const items should never be `#[no_mangle]`")] pub(crate) struct BuiltinConstNoMangle { diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index e4807f10805c9..3ad59c53a5bf3 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -603,6 +603,27 @@ struct LLVMRustSanitizerOptions { extern "C" typedef void (*registerEnzymeAndPassPipelineFn)( llvm::PassBuilder &PB, bool augment); +/// Forces the bitcode writer to emit full LTO summary instead of thin LTO +/// summary for embedded bitcode under Fat LTO. +/// +/// Note the bitcode writer will only emit the full LTO block ID if the +/// "ThinLTO" metadata is defined and explicitly set to zero. Otherwise, the +/// thin LTO block ID will be emitted. +static void forceFullLTOSummary(Module *M) { + // This function may be called twice, such as if you call it with `-C lto=fat + // --emit=llvm-bc`, so exit early if if we've already set up the module to + // emit full LTO summaries. + if (auto *Existing = M->getModuleFlag("ThinLTO")) { + auto *Const = mdconst::extract(Existing); + assert(Const->getZExtValue() == 0 && + "ThinLTO flag already set to non-zero"); + return; + } + + auto *Zero = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0); + M->addModuleFlag(Module::Error, "ThinLTO", Zero); +} + extern "C" LLVMRustResult LLVMRustOptimize( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, LLVMRustPassBuilderOptLevel OptLevelRust, LLVMRustOptStage OptStage, @@ -943,14 +964,17 @@ extern "C" LLVMRustResult LLVMRustOptimize( } // For `-Copt-level=0`, and the pre-link fat/thin LTO stages. if (ThinLTOBufferRef && *ThinLTOBufferRef == nullptr) { - // thin lto summaries prevent fat lto, so do not emit them if fat - // lto is requested. See PR #136840 for background information. + // thin lto summaries prevent fat lto, so emit a full summary instead if + // fat lto is requested. See PR #136840 for background information. if (OptStage != LLVMRustOptStage::PreLinkFatLTO) { MPM.addPass(ThinLTOBitcodeWriterPass( ThinLTODataOS, ThinLTOSummaryBufferRef ? &ThinLinkDataOS : nullptr)); } else { - MPM.addPass(BitcodeWriterPass(ThinLTODataOS)); + forceFullLTOSummary(TheModule); + MPM.addPass(BitcodeWriterPass(ThinLTODataOS, + /*ShouldPreserveUseListOrder=*/false, + /*EmitSummaryIndex=*/true)); } *ThinLTOBufferRef = ThinLTOBuffer.release(); if (ThinLTOSummaryBufferRef) { @@ -1469,26 +1493,30 @@ extern "C" LLVMRustBuffer *LLVMRustModuleSerialize(LLVMModuleRef M, { auto OS = raw_string_ostream(Ret->data); { - if (is_thin) { - PassBuilder PB; - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - ModulePassManager MPM; + PassBuilder PB; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + ModulePassManager MPM; #if LLVM_VERSION_GE(23, 0) - MPM.addPass(AssignGUIDPass()); + MPM.addPass(AssignGUIDPass()); #endif + + if (is_thin) { MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); - MPM.run(*unwrap(M), MAM); } else { - WriteBitcodeToFile(*unwrap(M), OS); + forceFullLTOSummary(unwrap(M)); + MPM.addPass(BitcodeWriterPass(OS, /*ShouldPreserveUseListOrder=*/false, + /*EmitSummaryIndex=*/true)); } + MPM.run(*unwrap(M), MAM); } } return Ret.release(); diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 5759b4afada7e..044ec5345cdcd 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -96,7 +96,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { if tcx.sess.opts.json_artifact_notifications { tcx.dcx().emit_artifact_notification(out_filename.as_path(), "metadata"); } - (filename, None) + (filename, Some(metadata_tmpdir)) } else { (metadata_filename, Some(metadata_tmpdir)) }; diff --git a/library/alloc/src/io/read.rs b/library/alloc/src/io/read.rs index 1fe8417d90761..58d3e7005f288 100644 --- a/library/alloc/src/io/read.rs +++ b/library/alloc/src/io/read.rs @@ -84,7 +84,7 @@ use crate::vec::Vec; #[stable(feature = "rust1", since = "1.0.0")] #[doc(notable_trait)] #[cfg_attr(not(test), rustc_diagnostic_item = "IoRead")] -#[rustc_must_implement_one_of(read, read_buf)] +#[rustc_must_implement_one_of(read_buf, read)] // Keep this order, it's important for rust-analyzer (the preferred-to-implement method should come first). pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. diff --git a/library/core/src/os/darwin/objc.rs b/library/core/src/os/darwin/objc.rs index df3aab867e83d..7be07891085a3 100644 --- a/library/core/src/os/darwin/objc.rs +++ b/library/core/src/os/darwin/objc.rs @@ -67,7 +67,8 @@ pub type SEL = *mut objc_selector; /// /// # Example /// -/// ```no_run +#[cfg_attr(target_os = "macos", doc = "```no_run")] +#[cfg_attr(not(target_os = "macos"), doc = "```ignore (needs macos)")] /// #![feature(darwin_objc)] /// use core::os::darwin::objc; /// @@ -93,7 +94,8 @@ pub macro class($classname:expr) {{ /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_os = "macos", doc = "```no_run")] +#[cfg_attr(not(target_os = "macos"), doc = "```ignore (needs macos)")] /// #![feature(darwin_objc)] /// use core::os::darwin::objc; /// diff --git a/library/std/src/os/aix/fs.rs b/library/std/src/os/aix/fs.rs index 36e56f23cc555..1a56736a38d54 100644 --- a/library/std/src/os/aix/fs.rs +++ b/library/std/src/os/aix/fs.rs @@ -16,7 +16,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -33,7 +34,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -50,7 +52,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -67,7 +70,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -84,7 +88,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -101,7 +106,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -118,7 +124,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -138,7 +145,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -155,7 +163,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -174,7 +183,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -191,7 +201,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -210,7 +221,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -227,7 +239,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -246,7 +259,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -263,7 +277,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; @@ -280,7 +295,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "aix", doc = "```no_run")] + #[cfg_attr(not(target_os = "aix"), doc = "```ignore (needs aix)")] /// use std::fs; /// use std::io; /// use std::os::aix::fs::MetadataExt; diff --git a/library/std/src/os/fortanix_sgx/ffi.rs b/library/std/src/os/fortanix_sgx/ffi.rs index ac1db0e5e39cc..c2d71eada095f 100644 --- a/library/std/src/os/fortanix_sgx/ffi.rs +++ b/library/std/src/os/fortanix_sgx/ffi.rs @@ -2,7 +2,11 @@ //! //! # Examples //! -//! ``` +#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), doc = "```")] +#![cfg_attr( + not(all(target_vendor = "fortanix", target_env = "sgx")), + doc = "```ignore (needs aix)" +)] //! use std::ffi::OsString; //! use std::os::fortanix_sgx::ffi::OsStringExt; //! @@ -17,7 +21,11 @@ //! assert_eq!(bytes, b"foo"); //! ``` //! -//! ``` +#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), doc = "```")] +#![cfg_attr( + not(all(target_vendor = "fortanix", target_env = "sgx")), + doc = "```ignore (needs aix)" +)] //! use std::ffi::OsStr; //! use std::os::fortanix_sgx::ffi::OsStrExt; //! diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs index 68f39ab349a72..550696e9536dd 100644 --- a/library/std/src/os/freebsd/net.rs +++ b/library/std/src/os/freebsd/net.rs @@ -27,7 +27,8 @@ pub impl(self) trait UnixSocketExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "freebsd", doc = "```no_run")] + #[cfg_attr(not(target_os = "freebsd"), doc = "```ignore (needs freebsd)")] /// #![feature(unix_socket_ancillary_data)] /// use std::os::freebsd::net::UnixSocketExt; /// use std::os::unix::net::UnixDatagram; diff --git a/library/std/src/os/hermit/ffi.rs b/library/std/src/os/hermit/ffi.rs index 01a54e1ac8df8..d6be3c4615816 100644 --- a/library/std/src/os/hermit/ffi.rs +++ b/library/std/src/os/hermit/ffi.rs @@ -2,7 +2,8 @@ //! //! # Examples //! -//! ``` +#![cfg_attr(target_os = "hermit", doc = "```")] +#![cfg_attr(not(target_os = "hermit"), doc = "```ignore (needs hermit)")] //! use std::ffi::OsString; //! use std::os::hermit::ffi::OsStringExt; //! @@ -17,7 +18,8 @@ //! assert_eq!(bytes, b"foo"); //! ``` //! -//! ``` +#![cfg_attr(target_os = "hermit", doc = "```")] +#![cfg_attr(not(target_os = "hermit"), doc = "```ignore (needs hermit)")] //! use std::ffi::OsStr; //! use std::os::hermit::ffi::OsStrExt; //! diff --git a/library/std/src/os/hurd/fs.rs b/library/std/src/os/hurd/fs.rs index e0fc544fed1db..dc6f61180cb1b 100644 --- a/library/std/src/os/hurd/fs.rs +++ b/library/std/src/os/hurd/fs.rs @@ -16,7 +16,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -33,7 +34,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -50,7 +52,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -67,7 +70,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -84,7 +88,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -101,7 +106,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -118,7 +124,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -138,7 +145,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -155,7 +163,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -174,7 +183,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -191,7 +201,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -210,7 +221,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -227,7 +239,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -246,7 +259,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -263,7 +277,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; @@ -280,7 +295,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "hurd", doc = "```no_run")] + #[cfg_attr(not(target_os = "hurd"), doc = "```ignore (needs hurd)")] /// use std::fs; /// use std::io; /// use std::os::hurd::fs::MetadataExt; diff --git a/library/std/src/os/l4re/fs.rs b/library/std/src/os/l4re/fs.rs index 1f0bacae1ca68..491e04a4d25cf 100644 --- a/library/std/src/os/l4re/fs.rs +++ b/library/std/src/os/l4re/fs.rs @@ -25,7 +25,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -45,7 +46,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -62,7 +64,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -79,7 +82,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -96,7 +100,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -113,7 +118,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -130,7 +136,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -147,7 +154,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -167,7 +175,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -184,7 +193,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -203,7 +213,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -220,7 +231,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -239,7 +251,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -256,7 +269,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -275,7 +289,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -292,7 +307,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -309,7 +325,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "l4re", doc = "```no_run")] + #[cfg_attr(not(target_os = "l4re"), doc = "```ignore (needs l4re)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; diff --git a/library/std/src/os/linux/fs.rs b/library/std/src/os/linux/fs.rs index e52a63bc798ea..0e8fa0a15da09 100644 --- a/library/std/src/os/linux/fs.rs +++ b/library/std/src/os/linux/fs.rs @@ -25,7 +25,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -45,7 +46,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -62,7 +64,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -79,7 +82,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -96,7 +100,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -113,7 +118,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -130,7 +136,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -147,7 +154,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -167,7 +175,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -184,7 +193,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -203,7 +213,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -220,7 +231,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -239,7 +251,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -256,7 +269,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -275,7 +289,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -292,7 +307,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; @@ -309,7 +325,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "linux", doc = "```no_run")] + #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// use std::fs; /// use std::io; /// use std::os::linux::fs::MetadataExt; diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index e4ab7622cfbd9..e0ddaa85cb82e 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -20,8 +20,10 @@ struct InnerPidFd; /// with [`create_pidfd`]. Subsequently, the created pidfd can be retrieved /// from the [`Child`] by calling [`pidfd`] or [`into_pidfd`]. /// -/// Example: -/// ```no_run +/// # Examples +/// +#[cfg_attr(target_os = "linux", doc = "```no_run")] +#[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")] /// #![feature(linux_pidfd)] /// use std::os::linux::process::{CommandExt, ChildExt}; /// use std::process::Command; diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs index ea7e436d11129..07adee90b0bc0 100644 --- a/library/std/src/os/net/linux_ext/addr.rs +++ b/library/std/src/os/net/linux_ext/addr.rs @@ -20,7 +20,14 @@ pub impl(in crate::os) trait SocketAddrExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "android", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "android", target_os = "cygwin")), + doc = "```ignore (needs linux)" + )] /// use std::os::unix::net::{UnixListener, SocketAddr}; /// #[cfg(target_os = "linux")] /// use std::os::linux::net::SocketAddrExt; @@ -48,7 +55,14 @@ pub impl(in crate::os) trait SocketAddrExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "android", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "android", target_os = "cygwin")), + doc = "```ignore (needs linux)" + )] /// use std::os::unix::net::{UnixListener, SocketAddr}; /// #[cfg(target_os = "linux")] /// use std::os::linux::net::SocketAddrExt; diff --git a/library/std/src/os/net/linux_ext/socket.rs b/library/std/src/os/net/linux_ext/socket.rs index b7bee94128534..777587fe4ce7c 100644 --- a/library/std/src/os/net/linux_ext/socket.rs +++ b/library/std/src/os/net/linux_ext/socket.rs @@ -24,7 +24,14 @@ pub impl(self) trait UnixSocketExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "android", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "android", target_os = "cygwin")), + doc = "```ignore (needs linux)" + )] /// #![feature(unix_socket_ancillary_data)] /// #[cfg(target_os = "linux")] /// use std::os::linux::net::UnixSocketExt; diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs index dd3a5ad7342b7..2fc6b2769568e 100644 --- a/library/std/src/os/net/linux_ext/tcp.rs +++ b/library/std/src/os/net/linux_ext/tcp.rs @@ -23,7 +23,14 @@ pub impl(self) trait TcpStreamExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "android", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "android", target_os = "cygwin")), + doc = "```ignore (needs linux)" + )] /// use std::net::TcpStream; /// #[cfg(target_os = "linux")] /// use std::os::linux::net::TcpStreamExt; @@ -43,7 +50,14 @@ pub impl(self) trait TcpStreamExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "android", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "android", target_os = "cygwin")), + doc = "```ignore (needs linux)" + )] /// use std::net::TcpStream; /// #[cfg(target_os = "linux")] /// use std::os::linux::net::TcpStreamExt; @@ -92,7 +106,14 @@ pub impl(self) trait TcpStreamExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "android", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "android", target_os = "cygwin")), + doc = "```ignore (needs linux)" + )] /// #![feature(tcp_deferaccept)] /// use std::net::TcpStream; /// use std::os::linux::net::TcpStreamExt; diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs index a77302ddbc675..a0e9ba3f7cf7c 100644 --- a/library/std/src/os/netbsd/net.rs +++ b/library/std/src/os/netbsd/net.rs @@ -27,7 +27,8 @@ pub impl(self) trait UnixSocketExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "netbsd", doc = "```no_run")] + #[cfg_attr(not(target_os = "netbsd"), doc = "```ignore (needs netbsd)")] /// #![feature(unix_socket_ancillary_data)] /// use std::os::netbsd::net::UnixSocketExt; /// use std::os::unix::net::UnixDatagram; diff --git a/library/std/src/os/redox/fs.rs b/library/std/src/os/redox/fs.rs index 0451e91071bcf..ed6c8cb08677d 100644 --- a/library/std/src/os/redox/fs.rs +++ b/library/std/src/os/redox/fs.rs @@ -21,7 +21,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -45,7 +46,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -62,7 +64,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -79,7 +82,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -96,7 +100,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -113,7 +118,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -130,7 +136,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -147,7 +154,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -167,7 +175,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -184,7 +193,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -203,7 +213,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -220,7 +231,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -239,7 +251,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -256,7 +269,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -275,7 +289,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -292,7 +307,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; @@ -309,7 +325,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "redox", doc = "```no_run")] + #[cfg_attr(not(target_os = "redox"), doc = "```ignore (needs redox)")] /// use std::fs; /// use std::io; /// use std::os::redox::fs::MetadataExt; diff --git a/library/std/src/os/rtems/fs.rs b/library/std/src/os/rtems/fs.rs index 97a0c9004c00a..ab662e5654071 100644 --- a/library/std/src/os/rtems/fs.rs +++ b/library/std/src/os/rtems/fs.rs @@ -12,7 +12,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -30,7 +31,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -48,7 +50,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -66,7 +69,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -84,7 +88,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -102,7 +107,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -120,7 +126,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -141,7 +148,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -159,7 +167,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -179,7 +188,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -197,7 +207,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -217,7 +228,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -235,7 +247,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -255,7 +268,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -273,7 +287,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; @@ -291,7 +306,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_os = "rtems", doc = "```no_run")] + #[cfg_attr(not(target_os = "rtems"), doc = "```ignore (needs rtems)")] /// use std::fs; /// use std::io; /// use std::os::rtems::fs::MetadataExt; diff --git a/library/std/src/os/solid/ffi.rs b/library/std/src/os/solid/ffi.rs index aaa2070a6abe9..d4c287ca70407 100644 --- a/library/std/src/os/solid/ffi.rs +++ b/library/std/src/os/solid/ffi.rs @@ -2,7 +2,8 @@ //! //! # Examples //! -//! ``` +#![cfg_attr(target_os = "solid", doc = "```")] +#![cfg_attr(not(target_os = "solid"), doc = "```ignore (needs solid)")] //! use std::ffi::OsString; //! use std::os::solid::ffi::OsStringExt; //! @@ -17,7 +18,8 @@ //! assert_eq!(bytes, b"foo"); //! ``` //! -//! ``` +#![cfg_attr(target_os = "solid", doc = "```")] +#![cfg_attr(not(target_os = "solid"), doc = "```ignore (needs solid)")] //! use std::ffi::OsStr; //! use std::os::solid::ffi::OsStrExt; //! diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 808e0b874ebbf..d4defb5f47fb0 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -257,7 +257,8 @@ macro_rules! impl_owned_fd_traits { impl_owned_fd_traits! { TcpStream TcpListener UdpSocket } /// This impl allows implementing traits that require `AsFd` on Arc. -/// ``` +#[cfg_attr(target_os = "solid", doc = "```")] +#[cfg_attr(not(target_os = "solid"), doc = "```ignore (needs solid)")] /// # #[cfg(target_os = "solid_asp3")] mod group_cfg { /// # use std::os::solid::io::AsFd; /// use std::net::UdpSocket; diff --git a/library/std/src/os/unix/ffi/mod.rs b/library/std/src/os/unix/ffi/mod.rs index 5b49f50763d74..7736c8598ec45 100644 --- a/library/std/src/os/unix/ffi/mod.rs +++ b/library/std/src/os/unix/ffi/mod.rs @@ -2,7 +2,8 @@ //! //! # Examples //! -//! ``` +#![cfg_attr(target_family = "unix", doc = "```")] +#![cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] //! use std::ffi::OsString; //! use std::os::unix::ffi::OsStringExt; //! @@ -17,7 +18,8 @@ //! assert_eq!(bytes, b"foo"); //! ``` //! -//! ``` +#![cfg_attr(target_family = "unix", doc = "```")] +#![cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] //! use std::ffi::OsStr; //! use std::os::unix::ffi::OsStrExt; //! diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 9b08f0cb3829f..90ad137dac178 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -40,7 +40,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::fs::File; /// use std::os::unix::prelude::FileExt; @@ -98,7 +99,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::fs::File; /// use std::os::unix::prelude::FileExt; @@ -138,7 +140,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(core_io_borrowed_buf)] /// #![feature(read_buf_at)] /// @@ -174,7 +177,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(core_io_borrowed_buf)] /// #![feature(read_buf_at)] /// @@ -245,7 +249,8 @@ pub trait FileExt { /// Therefore, it is important to be vigilant while changing options to mitigate /// unexpected behavior. /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::File; /// use std::io; /// use std::os::unix::prelude::FileExt; @@ -268,7 +273,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::File; /// use std::io; /// use std::os::unix::prelude::FileExt; @@ -317,7 +323,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::File; /// use std::io; /// use std::os::unix::prelude::FileExt; @@ -372,7 +379,8 @@ impl FileExt for fs::File { /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::{File, Permissions}; /// use std::io::{ErrorKind, Result as IoResult}; /// use std::os::unix::fs::PermissionsExt; @@ -427,7 +435,8 @@ impl FileExt for fs::File { /// } /// ``` /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::Permissions; /// use std::os::unix::fs::PermissionsExt; /// @@ -485,7 +494,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// @@ -508,7 +518,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// # mod libc { pub const O_NOFOLLOW: i32 = 0; } /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; @@ -544,7 +555,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::fs; /// use std::os::unix::fs::MetadataExt; @@ -561,7 +573,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -578,7 +591,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -599,7 +613,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -616,7 +631,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -633,7 +649,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -650,7 +667,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -667,7 +685,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -684,7 +703,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -703,7 +723,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -720,7 +741,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -739,7 +761,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -756,7 +779,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -775,7 +799,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -792,7 +817,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -811,7 +837,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// use std::io; @@ -895,7 +922,8 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::FileTypeExt; /// use std::io; @@ -913,7 +941,8 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::FileTypeExt; /// use std::io; @@ -931,7 +960,8 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::FileTypeExt; /// use std::io; @@ -949,7 +979,8 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::FileTypeExt; /// use std::io; @@ -989,7 +1020,8 @@ pub trait DirEntryExt { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs; /// use std::os::unix::fs::DirEntryExt; /// @@ -1020,7 +1052,8 @@ pub impl(self) trait DirEntryExt2 { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(dir_entry_ext2)] /// use std::os::unix::fs::DirEntryExt2; /// use std::{fs, io}; @@ -1052,7 +1085,8 @@ impl DirEntryExt2 for fs::DirEntry { /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::fs; /// /// fn main() -> std::io::Result<()> { @@ -1073,7 +1107,8 @@ pub trait DirBuilderExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::fs::DirBuilder; /// use std::os::unix::fs::DirBuilderExt; /// @@ -1110,7 +1145,8 @@ impl DirBuilderExt for fs::DirBuilder { /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::fs; /// /// fn main() -> std::io::Result<()> { @@ -1129,7 +1165,8 @@ pub fn chown>(dir: P, uid: Option, gid: Option) -> io:: /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::fs; /// /// fn main() -> std::io::Result<()> { @@ -1150,7 +1187,8 @@ pub fn fchown(fd: F, uid: Option, gid: Option) -> io::Result< /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::fs; /// /// fn main() -> std::io::Result<()> { @@ -1172,7 +1210,8 @@ pub fn lchown>(dir: P, uid: Option, gid: Option) -> io: /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::fs; /// /// fn main() -> std::io::Result<()> { @@ -1192,7 +1231,8 @@ pub fn chroot>(dir: P) -> io::Result<()> { /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// # #![feature(unix_mkfifo)] /// # #[cfg(not(unix))] /// # fn main() {} diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 19fdf8ba2fb03..618e0dca7659b 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -119,7 +119,8 @@ pub impl(self) trait StdioExt { /// /// [currently]: crate::io#platform-specific-behavior /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(stdio_swap)] /// use std::io::{self, Read, Write}; /// use std::os::unix::io::StdioExt; diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 25aa3bf7893f4..c994174b744dd 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -11,7 +11,8 @@ //! //! # Examples //! -//! ```no_run +#![cfg_attr(target_family = "unix", doc = "```no_run")] +#![cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] //! use std::fs::File; //! use std::os::unix::prelude::*; //! diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index e13f44d6fc9bd..08cd6138591e4 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -76,7 +76,8 @@ enum AddressKind<'a> { /// /// # Examples /// -/// ``` +#[cfg_attr(target_family = "unix", doc = "```")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// let socket = match UnixListener::bind("/tmp/sock") { @@ -145,7 +146,8 @@ impl SocketAddr { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::SocketAddr; /// use std::path::Path; /// @@ -158,7 +160,8 @@ impl SocketAddr { /// /// Creating a `SocketAddr` with a NULL byte results in an error. /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::SocketAddr; /// /// assert!(SocketAddr::from_pathname("/path/with/\0/bytes").is_err()); @@ -177,7 +180,8 @@ impl SocketAddr { /// /// A named address: /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// fn main() -> std::io::Result<()> { @@ -190,7 +194,8 @@ impl SocketAddr { /// /// An unnamed address: /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -212,7 +217,8 @@ impl SocketAddr { /// /// With a pathname: /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// use std::path::Path; /// @@ -226,7 +232,8 @@ impl SocketAddr { /// /// Without a pathname: /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index d0984bdfb99d1..a9029f7fa0bfb 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -576,7 +576,15 @@ impl<'a> Iterator for Messages<'a> { /// A Unix socket Ancillary data struct. /// /// # Example -/// ```no_run +/// +#[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "cygwin"), + doc = "```no_run" +)] +#[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "cygwin")), + doc = "```ignore (needs unix)" +)] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData}; /// use std::io::IoSliceMut; @@ -615,7 +623,14 @@ impl<'a> SocketAncillary<'a> { /// /// # Example /// - /// ```no_run + #[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "cygwin")), + doc = "```ignore (needs unix)" + )] /// # #![allow(unused_mut)] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::SocketAncillary; @@ -658,7 +673,14 @@ impl<'a> SocketAncillary<'a> { /// /// # Example /// - /// ```no_run + #[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "cygwin")), + doc = "```ignore (needs unix)" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::{UnixStream, SocketAncillary}; /// use std::io::IoSliceMut; @@ -692,7 +714,14 @@ impl<'a> SocketAncillary<'a> { /// /// # Example /// - /// ```no_run + #[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "cygwin")), + doc = "```ignore (needs unix)" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::{UnixStream, SocketAncillary}; /// use std::os::unix::io::AsRawFd; @@ -759,7 +788,14 @@ impl<'a> SocketAncillary<'a> { /// /// # Example /// - /// ```no_run + #[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "cygwin"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "cygwin")), + doc = "```ignore (needs unix)" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData}; /// use std::io::IoSliceMut; diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index e7bcd70140d67..e03ecd7eed9ea 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -46,7 +46,8 @@ const MSG_NOSIGNAL: core::ffi::c_int = 0x0; /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -81,7 +82,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// let sock = match UnixDatagram::bind("/path/to/the/socket") { @@ -108,7 +110,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -142,7 +145,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// let sock = match UnixDatagram::unbound() { @@ -165,7 +169,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// let (sock1, sock2) = match UnixDatagram::pair() { @@ -193,7 +198,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -222,7 +228,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -260,7 +267,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -278,7 +286,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -300,7 +309,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -350,7 +360,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -372,7 +383,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -505,7 +517,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -539,7 +552,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -575,7 +589,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -696,7 +711,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// use std::time::Duration; /// @@ -711,7 +727,8 @@ impl UnixDatagram { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::os::unix::net::UnixDatagram; /// use std::time::Duration; @@ -740,7 +757,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// use std::time::Duration; /// @@ -755,7 +773,8 @@ impl UnixDatagram { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::os::unix::net::UnixDatagram; /// use std::time::Duration; @@ -777,7 +796,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// use std::time::Duration; /// @@ -798,7 +818,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// use std::time::Duration; /// @@ -819,7 +840,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -862,7 +884,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { @@ -884,7 +907,8 @@ impl UnixDatagram { /// specified portions to immediately return with an appropriate value /// (see the documentation of [`Shutdown`]). /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixDatagram; /// use std::net::Shutdown; /// @@ -908,7 +932,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(unix_socket_peek)] /// /// use std::os::unix::net::UnixDatagram; @@ -940,7 +965,8 @@ impl UnixDatagram { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(unix_socket_peek)] /// /// use std::os::unix::net::UnixDatagram; diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 99eef7f4013d6..b7f8d25a85ae5 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -9,7 +9,8 @@ use crate::{fmt, io, mem}; /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// @@ -56,7 +57,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// let listener = match UnixListener::bind("/path/to/the/socket") { @@ -115,7 +117,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::{UnixListener}; /// /// fn main() -> std::io::Result<()> { @@ -160,7 +163,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// fn main() -> std::io::Result<()> { @@ -190,7 +194,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// fn main() -> std::io::Result<()> { @@ -208,7 +213,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// fn main() -> std::io::Result<()> { @@ -232,7 +238,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// fn main() -> std::io::Result<()> { @@ -250,7 +257,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixListener; /// /// fn main() -> std::io::Result<()> { @@ -277,7 +285,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// @@ -372,7 +381,8 @@ impl<'a> IntoIterator for &'a UnixListener { /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index a50b10539ebf5..8567e2fbb783d 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -44,7 +44,8 @@ use crate::time::Duration; /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_family = "unix", doc = "```no_run")] +#[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// use std::io::prelude::*; /// @@ -93,7 +94,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// let socket = match UnixStream::connect("/tmp/sock") { @@ -121,7 +123,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::{UnixListener, UnixStream}; /// /// fn main() -> std::io::Result<()> { @@ -137,7 +140,7 @@ impl UnixStream { /// }; /// Ok(()) /// } - /// ```` + /// ``` #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { @@ -157,7 +160,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// let (sock1, sock2) = match UnixStream::pair() { @@ -183,7 +187,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// fn main() -> std::io::Result<()> { @@ -201,7 +206,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// fn main() -> std::io::Result<()> { @@ -219,7 +225,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// fn main() -> std::io::Result<()> { @@ -237,7 +244,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(peer_credentials_unix_socket)] /// use std::os::unix::net::UnixStream; /// @@ -274,7 +282,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// @@ -288,7 +297,8 @@ impl UnixStream { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::os::unix::net::UnixStream; /// use std::time::Duration; @@ -316,7 +326,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// @@ -331,7 +342,8 @@ impl UnixStream { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::io; /// use std::os::unix::net::UnixStream; /// use std::time::Duration; @@ -353,7 +365,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// @@ -373,7 +386,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// @@ -394,7 +408,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// fn main() -> std::io::Result<()> { @@ -437,7 +452,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// /// fn main() -> std::io::Result<()> { @@ -464,7 +480,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::os::unix::net::UnixStream; /// use std::net::Shutdown; /// @@ -488,7 +505,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(unix_socket_peek)] /// /// use std::os::unix::net::UnixStream; diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index f55c821dfb7bc..9fa731de82691 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -188,7 +188,8 @@ pub impl(self) trait CommandExt { /// /// A process group ID of 0 will use the process ID as the PGID. /// - /// ```no_run + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// use std::process::Command; /// use std::os::unix::process::CommandExt; /// @@ -303,7 +304,8 @@ pub impl(self) trait ExitStatusExt { /// status. The following example relies on that convention and is therefore not guaranteed to /// hold on every target: /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// # if cfg!(target_os = "fuchsia") { return; } /// use std::os::unix::process::ExitStatusExt; /// use std::process::ExitStatus; @@ -324,7 +326,8 @@ pub impl(self) trait ExitStatusExt { /// 8-bit exit code in bits 8..16, so a status built with `(code & 0xff) << 8` will usually /// round-trip back to the original exit code: /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// # if cfg!(target_os = "fuchsia") { return; } /// use std::os::unix::process::ExitStatusExt; /// use std::process::ExitStatus; @@ -350,7 +353,8 @@ pub impl(self) trait ExitStatusExt { /// In other words, if [`WIFSIGNALED`][`wait`], this returns [`WTERMSIG`][`wait`]. For such a status, /// [`ExitStatus::code`] returns `None`: /// - /// ``` + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// # if cfg!(target_os = "fuchsia") { return; } /// use std::os::unix::process::ExitStatusExt; /// use std::process::ExitStatus; @@ -475,7 +479,8 @@ pub impl(self) trait ChildExt { /// /// # Examples /// - /// ```rust + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(unix_send_signal)] /// /// use std::{io, os::unix::process::ChildExt, process::{Command, Stdio}}; @@ -503,7 +508,8 @@ pub impl(self) trait ChildExt { /// /// # Examples /// - /// ```rust + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(unix_send_signal)] /// /// use std::{io, os::unix::process::{ChildExt, CommandExt}, process::{Command, Stdio}}; @@ -535,7 +541,8 @@ pub impl(self) trait ChildExt { /// /// # Examples /// - /// ```rust + #[cfg_attr(target_family = "unix", doc = "```no_run")] + #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] /// #![feature(unix_kill_process_group)] /// /// use std::{os::unix::process::{ChildExt, CommandExt}, process::{Command, Stdio}}; diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 2ee6aa4660094..1db9ec906726f 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -11,7 +11,8 @@ //! //! # Examples //! -//! ```no_run +#![cfg_attr(target_os = "wasi", doc = "```no_run")] +#![cfg_attr(not(target_os = "wasi"), doc = "```ignore (needs wasi)")] //! use std::fs::File; //! use std::os::wasi::prelude::*; //! diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs index ed933975bd5a5..3cda3e25fb544 100644 --- a/library/std/src/os/windows/ffi.rs +++ b/library/std/src/os/windows/ffi.rs @@ -72,7 +72,8 @@ pub impl(self) trait OsStringExt { /// /// # Examples /// - /// ``` + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::ffi::OsString; /// use std::os::windows::prelude::*; /// @@ -104,7 +105,8 @@ pub impl(self) trait OsStrExt { /// /// # Examples /// - /// ``` + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::ffi::OsString; /// use std::os::windows::prelude::*; /// diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index dfa9236a7e428..7b4f5e7a40055 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -31,7 +31,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs::File; /// use std::os::windows::prelude::*; @@ -59,7 +60,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(core_io_borrowed_buf)] /// #![feature(read_buf_at)] /// @@ -104,7 +106,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::File; /// use std::os::windows::prelude::*; /// @@ -151,7 +154,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; /// @@ -176,7 +180,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; /// @@ -202,7 +207,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// # #![allow(unexpected_cfgs)] /// # #[cfg(for_demonstration_only)] /// extern crate winapi; @@ -240,7 +246,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// # #![allow(unexpected_cfgs)] /// # #[cfg(for_demonstration_only)] /// extern crate winapi; @@ -282,7 +289,8 @@ pub trait OpenOptionsExt { /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// # #![allow(unexpected_cfgs)] /// # #[cfg(for_demonstration_only)] /// extern crate winapi; @@ -377,7 +385,8 @@ impl OpenOptionsExt2 for OpenOptions { /// /// # Example /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_permissions_ext)] /// use std::fs::Permissions; /// use std::os::windows::fs::PermissionsExt; @@ -440,7 +449,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -470,7 +480,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -505,7 +516,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -538,7 +550,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -561,7 +574,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -700,7 +714,8 @@ impl FileTimesExt for fs::FileTimes { /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::os::windows::fs; /// /// fn main() -> std::io::Result<()> { @@ -739,7 +754,8 @@ pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io: /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::os::windows::fs; /// /// fn main() -> std::io::Result<()> { diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index e58f94253bdf7..29697bbb5f8fc 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -424,7 +424,8 @@ pub trait AsHandle { /// /// # Example /// - /// ```rust,no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::File; /// # use std::io; /// use std::os::windows::io::{AsHandle, BorrowedHandle}; diff --git a/library/std/src/os/windows/io/mod.rs b/library/std/src/os/windows/io/mod.rs index db0ec8f2fbb2e..bf0605aa08a95 100644 --- a/library/std/src/os/windows/io/mod.rs +++ b/library/std/src/os/windows/io/mod.rs @@ -83,7 +83,8 @@ pub impl(self) trait StdioExt { /// (e.g. C stdio) or libraries that acquire a clone of the file handle /// will not be aware of this change. /// - /// ``` + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(stdio_swap)] /// use std::io::{self, Read, Write}; /// use std::os::windows::io::StdioExt; diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs index 53c33d17a9f65..a7e032dbf4d4d 100644 --- a/library/std/src/os/windows/mod.rs +++ b/library/std/src/os/windows/mod.rs @@ -8,7 +8,8 @@ //! //! # Examples //! -//! ```no_run +#![cfg_attr(windows, doc = "```no_run")] +#![cfg_attr(not(windows), doc = "```ignore (needs windows)")] //! use std::fs::File; //! use std::os::windows::prelude::*; //! diff --git a/library/std/src/os/windows/net/addr.rs b/library/std/src/os/windows/net/addr.rs index ef2263edcf617..c330432039a8f 100644 --- a/library/std/src/os/windows/net/addr.rs +++ b/library/std/src/os/windows/net/addr.rs @@ -79,7 +79,8 @@ impl SocketAddr { /// /// With a pathname: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// use std::path::Path; @@ -104,7 +105,8 @@ impl SocketAddr { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::SocketAddr; /// use std::path::Path; @@ -118,7 +120,8 @@ impl SocketAddr { /// /// Creating a `SocketAddr` with a NULL byte results in an error. /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::SocketAddr; /// @@ -151,7 +154,8 @@ impl SocketAddr { /// /// A named address: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// diff --git a/library/std/src/os/windows/net/listener.rs b/library/std/src/os/windows/net/listener.rs index 345cfe8d22ba9..19f5254e08bf9 100644 --- a/library/std/src/os/windows/net/listener.rs +++ b/library/std/src/os/windows/net/listener.rs @@ -16,7 +16,8 @@ use crate::{fmt, io}; /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::thread; /// use std::os::windows::net::{UnixStream, UnixListener}; @@ -61,7 +62,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -84,7 +86,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::{UnixListener}; /// @@ -122,7 +125,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -148,7 +152,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -170,7 +175,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -194,7 +200,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -212,7 +219,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -236,7 +244,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::thread; /// use std::os::windows::net::{UnixStream, UnixListener}; @@ -272,7 +281,8 @@ impl UnixListener { /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::thread; /// use std::os::windows::net::{UnixStream, UnixListener}; diff --git a/library/std/src/os/windows/net/stream.rs b/library/std/src/os/windows/net/stream.rs index f2d0f7c09e9f1..c0f32e75411e9 100644 --- a/library/std/src/os/windows/net/stream.rs +++ b/library/std/src/os/windows/net/stream.rs @@ -21,7 +21,8 @@ use crate::{fmt, io}; /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::io::prelude::*; @@ -54,7 +55,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -77,7 +79,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::{UnixListener, UnixStream}; /// @@ -112,7 +115,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -130,7 +134,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -148,7 +153,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; @@ -168,7 +174,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -192,7 +199,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; @@ -207,7 +215,8 @@ impl UnixStream { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::io; /// use std::os::windows::net::UnixStream; @@ -235,7 +244,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; @@ -251,7 +261,8 @@ impl UnixStream { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::io; /// use std::os::windows::net::UnixStream; @@ -277,7 +288,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::net::Shutdown; @@ -296,7 +308,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -321,7 +334,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -339,7 +353,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 3332714ae4bb7..41dcb70c59c9f 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -273,7 +273,8 @@ pub impl(self) trait CommandExt { /// /// # Example /// - /// ``` + #[cfg_attr(windows, doc = "```")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_process_extensions_async_pipes)] /// use std::os::windows::process::CommandExt; /// use std::process::{Command, Stdio}; @@ -304,7 +305,8 @@ pub impl(self) trait CommandExt { /// /// # Example /// - /// ``` + #[cfg_attr(windows, doc = "```")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_process_extensions_raw_attribute)] /// use std::os::windows::io::AsRawHandle; /// use std::os::windows::process::{CommandExt, ProcThreadAttributeList}; @@ -563,8 +565,9 @@ impl<'a> ProcThreadAttributeListBuilder<'a> { /// /// # Example /// - #[cfg_attr(target_vendor = "win7", doc = "```no_run")] - #[cfg_attr(not(target_vendor = "win7"), doc = "```")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] + #[cfg_attr(all(windows, target_vendor = "win7"), doc = "```no_run")] + #[cfg_attr(all(windows, not(target_vendor = "win7")), doc = "```")] /// #![feature(windows_process_extensions_raw_attribute)] /// use std::ffi::c_void; /// use std::os::windows::process::{CommandExt, ProcThreadAttributeList}; diff --git a/library/stdarch/crates/core_arch/src/amdgpu/mod.rs b/library/stdarch/crates/core_arch/src/amdgpu/mod.rs index 374f582696947..91dfbd1a16c0f 100644 --- a/library/stdarch/crates/core_arch/src/amdgpu/mod.rs +++ b/library/stdarch/crates/core_arch/src/amdgpu/mod.rs @@ -351,13 +351,13 @@ pub unsafe fn sched_barrier() { /// Combining multiple `sched_group_barrier` intrinsics enables an ordering of specific instruction types during instruction scheduling. /// For example, the following enforces a sequence of 1 VMEM read, followed by 1 VALU instruction, followed by 5 MFMA instructions. /// -/// ```rust +/// ```ignore (only available on AMD) /// // 1 VMEM read -/// sched_group_barrier::<32, 1, 0>() +/// sched_group_barrier::<32, 1, 0>(); /// // 1 VALU -/// sched_group_barrier::<2, 1, 0>() +/// sched_group_barrier::<2, 1, 0>(); /// // 5 MFMA -/// sched_group_barrier::<8, 5, 0>() +/// sched_group_barrier::<8, 5, 0>(); /// ``` /// #[doc = include_str!("intrinsic_is_convergent.md")] diff --git a/library/stdarch/crates/core_arch/src/nvptx/mod.rs b/library/stdarch/crates/core_arch/src/nvptx/mod.rs index d22f3a25bf70e..53d53d1e1ef60 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/mod.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/mod.rs @@ -157,10 +157,13 @@ unsafe extern "C" { /// * `format`: A pointer to the format specifier input (uses common `printf` format). /// * `valist`: A pointer to the valist input. /// - /// ``` + /// ```ignore (available only for nvptx) + /// # use std::mem::transmute; /// #[repr(C)] /// struct PrintArgs(f32, f32, f32, i32); /// + /// let a = 0.1f32; + /// let b = 0.2f32; /// vprintf( /// "int(%f + %f) = int(%f) = %d\n".as_ptr(), /// transmute(&PrintArgs(a, b, a + b, (a + b) as i32)), diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs index fbf1002eab8ba..589efbcf872d5 100644 --- a/library/stdarch/crates/core_arch/src/x86/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86/mod.rs @@ -39,7 +39,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -82,7 +86,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -125,7 +133,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -172,7 +184,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -215,7 +231,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -258,7 +278,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 02f3bea8aef01..ec03dba854578 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -210,17 +210,15 @@ This is very easy to use in scripts that manually invoke rustdoc, but it's also performs O(crates) work on every crate, meaning it performs O(crates2) work. When `--write-doc-meta-dir` and/or `--read-doc-meta-dir` are supplied, this is turned off. -When `--write-doc-meta-dir` is supplied, rustdoc will write the crate's metadata to that directory. -If this parameter is supplied but `--read-doc-meta-dir` isn't, it runs in *intermediate mode*: -some pages may be written to the output dir, but there is a lot of functionality that won't work -until rustdoc is run in *finalize mode*. +When `--write-doc-meta-dir` is supplied, rustdoc will write the crate's shared metadata to +that directory. This is an *intermediate mode* where it may write some files to the doc output +directory, but some features won't work until it is finalized. -When `--read-doc-meta-dir` is supplied, rustdoc runs in *finalize mode*. It will read the data from -the supplied directory, and will write it to the doc output directory in the form that the web -frontend will use. +When `--read-doc-meta-dir` is supplied, rustdoc runs in *finalize mode*. No crate source code is +passed to rustdoc when it runs in this mode. Multiple `--read-doc-meta-dir` can be passed to +rustdoc, so your build system can split the state between multiple directories if that helps. -If both `--write-doc-meta-dir` and `--read-doc-meta-dir` are specified, the crate metadata will be -written to both the HTML `--out-dir` and to the supplied `--write-doc-meta-dir`. +`--write-doc-meta-dir` and `--read-doc-meta-dir` cannot both be passed to the same rustdoc invocation. ```console $ rustdoc crate1.rs --out-dir=doc @@ -234,11 +232,30 @@ rd_("fcrate1fcrate2") To delay shared-data merging until the end of a build, so that you only have to perform O(crates) work, use `--write-doc-meta-dir` on every crate, and the last will use `--read-doc-meta-dir`. +You can use separate metadata directories: + ```console -$ rustdoc +nightly crate1.rs --write-doc-meta=crate1.d -Zunstable-options +$ rustdoc +nightly crate1.rs --write-doc-meta-dir=crate1.d -Zunstable-options +$ cat doc/search.index/crateNames/* +cat: 'doc/search.index/crateNames/*': No such file or directory +$ rustdoc +nightly crate2.rs --write-doc-meta-dir=crate2.d -Zunstable-options +$ cat doc/search.index/crateNames/* +cat: 'doc/search.index/crateNames/*': No such file or directory +$ rustdoc +nightly --read-doc-meta-dir=crate1.d --read-doc-meta-dir=crate2.d -Zunstable-options +$ cat doc/search.index/crateNames/* +rd_("fcrate1fcrate2") +``` + +Or you can use a single metadata directory for all of the crates: + +```console +$ rustdoc +nightly crate1.rs --write-doc-meta-dir=meta.d -Zunstable-options +$ cat doc/search.index/crateNames/* +cat: 'doc/search.index/crateNames/*': No such file or directory +$ rustdoc +nightly crate2.rs --write-doc-meta-dir=meta.d -Zunstable-options $ cat doc/search.index/crateNames/* cat: 'doc/search.index/crateNames/*': No such file or directory -$ rustdoc +nightly crate2.rs --read-doc-meta=crate1.d -Zunstable-options +$ rustdoc +nightly --read-doc-meta-dir=meta.d -Zunstable-options $ cat doc/search.index/crateNames/* rd_("fcrate1fcrate2") ``` diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 74a04b4451040..04dd0eaf22899 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -30,7 +30,7 @@ mod tests; // Because `CfgEntry` includes `Span`, we must NEVER use `==`/`!=` operators on `Cfg` and instead // use `is_equivalent_to`. #[cfg_attr(test, derive(PartialEq))] -pub(crate) struct Cfg(CfgEntry); +pub(crate) struct Cfg(pub(crate) CfgEntry); // Similar to `hir::DocCfgHideShow` but allows to handle both `show` and `hide` as with the `except` // field in `Any` variant. @@ -744,7 +744,7 @@ pub(crate) struct CfgInfo { hidden_cfg: FxHashMap, /// Current computed `cfg`. Each time we enter a new item, this field is updated as well while /// taking into account the `hidden_cfg` information. - current_cfg: Cfg, + pub(crate) current_cfg: Cfg, /// Whether the `doc(auto_cfg())` feature is enabled or not at this point. auto_cfg_active: bool, /// If the parent item used `doc(cfg(...))`, then we don't want to overwrite `current_cfg`, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0a3cbf537e5f1..1584cacff688e 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -613,7 +613,10 @@ impl Options { Ok(include_parts_dir) => include_parts_dir, Err(e) => dcx.fatal(e), }; - let mut should_merge = compute_should_merge(matches); + let mut should_merge = match compute_should_merge(matches) { + Ok(should_merge) => should_merge, + Err(e) => dcx.fatal(e), + }; if parts_out_dir.is_none() && include_parts_dir.is_empty() { // we'll need to get rid of this stuff once Cargo stops using them parts_out_dir = @@ -1121,15 +1124,16 @@ pub(crate) struct ShouldMerge { /// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or /// reports an error if an invalid option was provided -fn compute_should_merge(m: &getopts::Matches) -> ShouldMerge { +fn compute_should_merge(m: &getopts::Matches) -> Result { match (m.opt_present("read-doc-meta-dir"), m.opt_present("write-doc-meta-dir")) { // shared mode - (false, false) => ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }, + (false, false) => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), // intermediate mode - (false, true) => ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }, + (false, true) => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }), // finalize mode - (true, false) => ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }, - (true, true) => ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }, + (true, false) => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }), + // not valid + (true, true) => Err("cannot pass both --read-doc-meta-dir and --write-doc-meta-dir"), } } diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index d89fb2ae1767b..13f705f9c3f47 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -6,17 +6,18 @@ use std::sync::Arc; use proc_macro2::{TokenStream, TokenTree}; use rustc_attr_parsing::eval_config_entry; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::attrs::{AttributeKind, CfgEntry}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_hir::{self as hir, Attribute, CRATE_HIR_ID, intravisit}; +use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_resolve::rustdoc::span_of_fragments; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span}; +use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym}; use super::{DocTestVisitor, ScrapedDocTest}; -use crate::clean::{Attributes, CfgInfo, extract_cfg_from_attrs}; +use crate::clean::cfg::Cfg; +use crate::clean::{Attributes, CfgInfo}; use crate::html::markdown::{self, CodeLineMapping, ErrorCodes, LangString, MdRelLine}; struct RustCollector { @@ -118,58 +119,73 @@ impl HirCollector<'_> { sp: Span, nested: F, ) { - let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); - if let Some(ref cfg) = - extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &mut CfgInfo::default()) - && !eval_config_entry(&self.tcx.sess, cfg.inner()).as_bool() - { - return; - } + let hir_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); + + let mut cfg_info = CfgInfo::default(); + let mut found_features = 0; let source_map = self.tcx.sess.source_map(); - // Try collecting `#[doc(test(attr(...)))]` let old_global_crate_attrs_len = self.collector.global_crate_attrs.len(); - for attr in ast_attrs { - let Attribute::Parsed(AttributeKind::Doc(d)) = attr else { continue }; - for attr_span in &d.test_attrs { - // FIXME: This is ugly, remove when `test_attrs` has been ported to new attribute API. - if let Ok(snippet) = source_map.span_to_snippet(*attr_span) - && let Ok(stream) = TokenStream::from_str(&snippet) - { - let mut iter = stream.into_iter().peekable(); - while let Some(token) = iter.next() { - if let TokenTree::Ident(i) = token { - let i = i.to_string(); - let peek = iter.peek(); - // From this ident, we can have things like: - // - // * Group: `allow(...)` - // * Name/value: `crate_name = "..."` - // * Tokens: `html_no_url` - // - // So we peek next element to know what case we are in. - match peek { - Some(TokenTree::Group(g)) => { - let g = g.to_string(); - iter.next(); - // Add the additional attributes to the global_crate_attrs vector - self.collector.global_crate_attrs.push(format!("{i}{g}")); - } - // If next item is `=`, it means it's a name value so we will need - // to get the value as well. - Some(TokenTree::Punct(p)) if p.as_char() == '=' => { - let p = p.to_string(); - iter.next(); - if let Some(last) = iter.next() { - // Add the additional attributes to the global_crate_attrs vector - self.collector - .global_crate_attrs - .push(format!("{i}{p}{last}")); + // This loop does two things: + // + // 1. Collect `#[target_feature(...)]`. + // 2. Collect `#[doc(test(attr(...)))]`. + for attr in hir_attrs.iter() { + let hir::Attribute::Parsed(attr) = attr else { continue }; + if let AttributeKind::TargetFeature { features, .. } = attr { + for (feature, _) in features { + found_features += 1; + cfg_info.current_cfg &= Cfg(CfgEntry::NameValue { + name: sym::target_feature, + value: Some(*feature), + span: DUMMY_SP, + }); + } + } else if let AttributeKind::Doc(d) = attr { + for attr_span in &d.test_attrs { + // FIXME: This is ugly, remove when `test_attrs` has been ported to new + // attribute API. + if let Ok(snippet) = source_map.span_to_snippet(*attr_span) + && let Ok(stream) = TokenStream::from_str(&snippet) + { + let mut iter = stream.into_iter().peekable(); + while let Some(token) = iter.next() { + if let TokenTree::Ident(i) = token { + let i = i.to_string(); + let peek = iter.peek(); + // From this ident, we can have things like: + // + // * Group: `allow(...)` + // * Name/value: `crate_name = "..."` + // * Tokens: `html_no_url` + // + // So we peek next element to know what case we are in. + match peek { + Some(TokenTree::Group(g)) => { + let g = g.to_string(); + iter.next(); + // Add the additional attributes to the `global_crate_attrs` + // vector + self.collector.global_crate_attrs.push(format!("{i}{g}")); + } + // If next item is `=`, it means it's a name value so we will + // need to get the value as well. + Some(TokenTree::Punct(p)) if p.as_char() == '=' => { + let p = p.to_string(); + iter.next(); + if let Some(last) = iter.next() { + // Add the additional attributes to the + // `global_crate_attrs` vector. + self.collector + .global_crate_attrs + .push(format!("{i}{p}{last}")); + } + } + _ => { + // Add the additional attributes to the `global_crate_attrs` + // vector. + self.collector.global_crate_attrs.push(i.to_string()); } - } - _ => { - // Add the additional attributes to the global_crate_attrs vector - self.collector.global_crate_attrs.push(i.to_string()); } } } @@ -178,6 +194,14 @@ impl HirCollector<'_> { } } + // We only look at the `target_feature` attributes as the `cfg` attributes have already been + // applied at this point, so no need to take them into account again. + if found_features != 0 + && !eval_config_entry(&self.tcx.sess, &cfg_info.current_cfg.inner()).as_bool() + { + return; + } + let mut has_name = false; if let Some(name) = name { self.collector.cur_path.push(name); @@ -186,7 +210,7 @@ impl HirCollector<'_> { // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with // anything else, this will combine them for us. - let attrs = Attributes::from_hir(ast_attrs); + let attrs = Attributes::from_hir(hir_attrs); if let Some(doc) = attrs.opt_doc_value() { let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp); self.collector.position = if span.edition().at_least_rust_2024() { @@ -194,7 +218,7 @@ impl HirCollector<'_> { } else { // this span affects filesystem path resolution, // so we need to keep it the same as it was previously - ast_attrs + hir_attrs .iter() .find(|attr| attr.doc_str().is_some()) .map(|attr| { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 9e52b03b3210b..56dd665177a93 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -20,11 +20,11 @@ use tracing::info; use super::print_item::{full_path, print_item, print_item_path, print_ty_path}; use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like}; -use super::{AllTypes, StylePath, scrape_examples_help}; +use super::{AllTypes, StylePath}; use crate::clean::types::ExternalLocation; use crate::clean::utils::has_doc_flag; use crate::clean::{self, ExternalCrate}; -use crate::config::{EmitType, ModuleSorting, RenderOptions, ShouldMerge}; +use crate::config::{EmitType, ModuleSorting, RenderOptions}; use crate::docfs::{DocFS, PathError}; use crate::error::Error; use crate::formats::FormatRenderer; @@ -36,9 +36,9 @@ use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary}; use crate::html::render::write_shared::write_shared; use crate::html::span_map::{LinkFromSrc, Span, collect_spans_and_sources}; use crate::html::url_parts_builder::UrlPartsBuilder; -use crate::html::{layout, sources, static_files}; +use crate::html::{layout, sources}; use crate::scrape_examples::AllCallLocations; -use crate::{DOC_RUST_LANG_ORG_VERSION, try_err}; +use crate::try_err; /// Major driving force in all rustdoc rendering. This contains information /// about where in the tree-like hierarchy rendering is occurring and controls @@ -148,9 +148,6 @@ pub(crate) struct SharedContext<'tcx> { /// The [`Cache`] used during rendering. pub(crate) cache: Cache, pub(crate) call_locations: AllCallLocations, - /// Controls whether we read / write to cci files in the doc root. Defaults read=true, - /// write=true - should_merge: ShouldMerge, } impl SharedContext<'_> { @@ -615,7 +612,6 @@ impl<'tcx> Context<'tcx> { span_correspondence_map: matches, cache, call_locations, - should_merge: options.should_merge, expanded_codes, }; @@ -666,16 +662,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { fn after_krate(mut self) -> Result<(), Error> { let crate_name = self.tcx().crate_name(LOCAL_CRATE); let final_file = self.dst.join(crate_name.as_str()).join("all.html"); - let settings_file = self.dst.join("settings.html"); - let help_file = self.dst.join("help.html"); - let scrape_examples_help_file = self.dst.join("scrape-examples-help.html"); - let mut root_path = self.dst.to_str().expect("invalid path").to_owned(); - if !root_path.ends_with('/') { - root_path.push('/'); - } let shared = &self.shared; - let mut page = layout::Page { + let page = layout::Page { title: "List of all items in this crate", short_title: "All", css_class: "mod sys", @@ -705,106 +694,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let v = layout::render(&shared.layout, &page, sidebar, all.print(), &shared.style_files); shared.fs.write(final_file, v)?; - // if to avoid writing help, settings files to doc root unless we're on the final invocation - if shared.should_merge.write_rendered_cci { - // Generating settings page. - page.title = "Settings"; - page.description = "Settings of Rustdoc"; - page.root_path = "./"; - page.rust_logo = true; - - let sidebar = "

Settings

"; - let v = layout::render( - &shared.layout, - &page, - sidebar, - fmt::from_fn(|buf| { - write!( - buf, - "
\ -

Rustdoc settings

\ - \ - \ - Back\ - \ - \ -
\ - \ - ", - static_root_path = page.get_static_root_path(), - settings_js = static_files::STATIC_FILES.settings_js, - )?; - // Pre-load all theme CSS files, so that switching feels seamless. - // - // When loading settings.html as a popover, the equivalent HTML is - // generated in main.js. - for file in &shared.style_files { - if let Ok(theme) = file.basename() { - write!( - buf, - "", - root_path = page.static_root_path.unwrap_or(""), - suffix = page.resource_suffix, - )?; - } - } - Ok(()) - }), - &shared.style_files, - ); - shared.fs.write(settings_file, v)?; - - // Generating help page. - page.title = "Help"; - page.description = "Documentation for Rustdoc"; - page.root_path = "./"; - page.rust_logo = true; - - let sidebar = "

Help

"; - let v = layout::render( - &shared.layout, - &page, - sidebar, - format_args!( - "
\ -

Rustdoc help

\ - \ - \ - Back\ - \ - \ -
\ - ", - ), - &shared.style_files, - ); - shared.fs.write(help_file, v)?; - } - - // if to avoid writing files to doc root unless we're on the final invocation - if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci { - page.title = "About scraped examples"; - page.description = "How the scraped examples feature works in Rustdoc"; - let v = layout::render( - &shared.layout, - &page, - "", - scrape_examples_help(shared), - &shared.style_files, - ); - shared.fs.write(scrape_examples_help_file, v)?; - } - if let Some(ref redirections) = shared.redirections && !redirections.borrow().is_empty() { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1c31c5b81eb11..152a61beef405 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -663,7 +663,7 @@ impl AllTypes { } } -fn scrape_examples_help(shared: &SharedContext<'_>) -> String { +fn scrape_examples_help() -> String { let mut content = SCRAPE_EXAMPLES_HELP_MD.to_owned(); content.push_str(&format!( "## More information\n\n\ @@ -680,9 +680,10 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { content: &content, links: &[], ids: &mut IdMap::default(), - error_codes: shared.codes, - edition: shared.edition(), - playground: &shared.playground, + // code snippets come from Rust itself, not the crate + error_codes: crate::html::markdown::ErrorCodes::No, + edition: rustc_span::edition::LATEST_STABLE_EDITION, + playground: &Default::default(), heading_offset: HeadingOffset::H1, } .write_into(f)) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 56059c6619954..b3c2563aa3f97 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -30,6 +30,7 @@ use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt; +use rustc_session::Session; use rustc_span::Symbol; use rustc_span::def_id::DefId; use serde::de::DeserializeOwned; @@ -49,10 +50,12 @@ use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::print_item::compare_names; use crate::html::render::search_index::{SerializedSearchIndex, build_index}; use crate::html::render::sorted_template::{self, FileFormat, SortedTemplate}; -use crate::html::render::{AssocItemLink, ImplRenderingParameters, StylePath}; +use crate::html::render::{ + AssocItemLink, ImplRenderingParameters, StylePath, scrape_examples_help, +}; use crate::html::static_files::{self, suffix_path}; use crate::visit::DocVisitor; -use crate::{try_err, try_none}; +use crate::{DOC_RUST_LANG_ORG_VERSION, try_err, try_none}; pub(crate) fn write_shared( cx: &mut Context<'_>, @@ -111,28 +114,9 @@ pub(crate) fn write_shared( cx.shared.layout.css_file_extension.as_deref(), &cx.shared.resource_suffix, cx.info.include_sources, + &cx.shared.layout, + cx.sess(), )?; - match &opt.index_page { - Some(index_page) if opt.enable_index_page => { - 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(file, md_opts, cx.shared.edition()), - &index_page - ); - } - None if opt.enable_index_page => { - write_rendered_cci::( - || CratesIndexPart::blank(cx), - &cx.dst, - &crates, - &opt.should_merge, - )?; - } - _ => {} // they don't want an index page - } } cx.shared.fs.set_sync_only(false); @@ -150,9 +134,148 @@ pub(crate) fn write_not_crate_specific( css_file_extension: Option<&Path>, resource_suffix: &str, include_sources: bool, + layout: &layout::Layout, + sess: &Session, ) -> Result<(), Error> { write_rendered_cross_crate_info(crates, dst, opt, include_sources, resource_suffix)?; write_resources(dst, opt, style_files, css_file_extension, resource_suffix)?; + // index.html + match &opt.index_page { + Some(index_page) if opt.enable_index_page => { + let mut md_opts = opt.clone(); + md_opts.output = dst.to_path_buf(); + md_opts.external_html = layout.external_html.clone(); + let file = try_err!(sess.source_map().load_file(&index_page), &index_page); + try_err!(crate::markdown::render_and_write(file, md_opts, sess.edition()), &index_page); + } + None if opt.enable_index_page => { + write_rendered_cci::( + || CratesIndexPart::blank(layout, opt, style_files), + &dst, + &crates, + &opt.should_merge, + )?; + } + _ => {} // they don't want an index page + } + + if opt.emit.contains(&EmitType::HtmlNonStaticFiles) { + // Standalone pages for the Settings and Help popovers. + // + // Normally, these are pure DHTML popovers, but, for user convenience, + // the buttons that open them are links to these HTML files, which use the same JavaScript + // to populate the page. That way, you can open a new tab, or add a browser bookmark, + // that points at the page. + let settings_file = dst.join("settings.html"); + let help_file = dst.join("help.html"); + let scrape_examples_help_file = dst.join("scrape-examples-help.html"); + + let page = layout::Page { + title: "Settings", + short_title: "Settings", + css_class: "mod sys", + root_path: "./", + static_root_path: opt.static_root_path.as_deref(), + description: "Settings of Rustdoc", + resource_suffix: &opt.resource_suffix, + rust_logo: true, + }; + let sidebar = "

Settings

"; + let v = layout::render( + &layout, + &page, + sidebar, + fmt::from_fn(|buf| { + write!( + buf, + "
\ +

Rustdoc settings

\ + \ + \ + Back\ + \ + \ +
\ + \ + ", + static_root_path = page.get_static_root_path(), + settings_js = static_files::STATIC_FILES.settings_js, + )?; + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a popover, the equivalent HTML is + // generated in main.js. + for file in style_files { + if let Ok(theme) = file.basename() { + write!( + buf, + "", + root_path = page.static_root_path.unwrap_or(""), + suffix = page.resource_suffix, + )?; + } + } + Ok(()) + }), + &style_files, + ); + try_err!(std::fs::write(&settings_file, v), &settings_file); + + let page = layout::Page { + title: "Help", + short_title: "Help", + css_class: "mod sys", + root_path: "./", + static_root_path: opt.static_root_path.as_deref(), + description: "Documentation for Rustdoc", + resource_suffix: &opt.resource_suffix, + rust_logo: true, + }; + let sidebar = "

Help

"; + let v = layout::render( + &layout, + &page, + sidebar, + format_args!( + "
\ +

Rustdoc help

\ + \ + \ + Back\ + \ + \ +
\ + ", + ), + &style_files, + ); + try_err!(std::fs::write(&help_file, v), &help_file); + + if layout.scrape_examples_extension { + let page = layout::Page { + title: "About scraped examples", + short_title: "About scraped examples", + css_class: "mod sys", + root_path: "./", + static_root_path: opt.static_root_path.as_deref(), + description: "How the scraped examples feature works in Rustdoc", + resource_suffix: &opt.resource_suffix, + rust_logo: true, + }; + let v = layout::render(&layout, &page, "", scrape_examples_help(), &style_files); + try_err!(std::fs::write(&scrape_examples_help_file, v), &scrape_examples_help_file); + } + } Ok(()) } @@ -399,19 +522,21 @@ impl CciPart for CratesIndexPart { } impl CratesIndexPart { - fn blank(cx: &Context<'_>) -> SortedTemplate<::FileFormat> { + fn blank( + layout: &layout::Layout, + opt: &RenderOptions, + style_files: &[StylePath], + ) -> SortedTemplate<::FileFormat> { let page = layout::Page { title: "Index of crates", short_title: "Crates", css_class: "mod sys", root_path: "./", - static_root_path: cx.shared.static_root_path.as_deref(), + static_root_path: opt.static_root_path.as_deref(), description: "List of crates", - resource_suffix: &cx.shared.resource_suffix, + resource_suffix: &opt.resource_suffix, rust_logo: true, }; - let layout = &cx.shared.layout; - let style_files = &cx.shared.style_files; const DELIMITER: &str = "\u{FFFC}"; // users are being naughty if they have this let content = format_args!( "
\ diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index fbb8492d8d3ec..215552e8909be 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -68,7 +68,7 @@ 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::config::{ErrorOutputType, Input, RustcOptGroup, make_crate_type_option}; use rustc_session::{EarlyDiagCtxt, getopts}; use rustc_span::{BytePos, Span, SyntaxContext}; use tracing::info; @@ -764,25 +764,40 @@ fn run_renderer< /// Renders and writes cross-crate info files, like the search index. This function exists so that /// we can run rustdoc without a crate root in the `--merge=finalize` mode. Cross-crate info files /// discovered via `--read-doc-meta-dir` are combined and written to the doc root. -fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { +fn run_merge_finalize( + render_options: config::RenderOptions, + compiler: &interface::Compiler, +) -> Result<(), error::Error> { assert!( - opt.should_merge.write_rendered_cci, + render_options.should_merge.write_rendered_cci, "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize" ); assert!( - !opt.should_merge.read_rendered_cci, + !render_options.should_merge.read_rendered_cci, "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize" ); - let crates = html::render::CrateInfo::read_many(&opt.include_parts_dir)?; - let include_sources = !opt.html_no_source; + let crates = html::render::CrateInfo::read_many(&render_options.include_parts_dir)?; + let include_sources = !render_options.html_no_source; + html::render::write_not_crate_specific( &crates, - &opt.output, - &opt, - &opt.themes, - opt.extension_css.as_deref(), - &opt.resource_suffix, + &render_options.output, + &render_options, + &render_options.themes, + render_options.extension_css.as_deref(), + &render_options.resource_suffix, include_sources, + &crate::html::layout::Layout { + logo: String::new(), + favicon: String::new(), + external_html: render_options.external_html.clone(), + default_settings: render_options.default_settings.clone(), + krate: String::new(), + krate_version: String::new(), + css_file_extension: render_options.extension_css.clone(), + scrape_examples_extension: false, + }, + &compiler.sess, )?; Ok(()) } @@ -826,10 +841,18 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { let input = match input { config::InputMode::HasFile(input) => input, config::InputMode::NoInputMergeFinalize => { + let config = core::create_config( + Input::Str { + name: rustc_span::FileName::Custom(String::new()), + input: String::new(), + }, + options, + &render_options, + ); return wrap_return( dcx, - rustc_span::create_session_globals_then(options.edition, &[], None, || { - run_merge_finalize(render_options) + interface::run_compiler(config, |compiler| { + run_merge_finalize(render_options, compiler) .map_err(|e| format!("could not write merged cross-crate info: {e}")) }), ); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 594c9b1af3397..3cdd4a7e707c5 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -69,13 +69,14 @@ pub(crate) fn render_and_write( let playground_url = options.markdown_playground_url.or(options.playground_url); let playground = playground_url.map(|url| markdown::Playground { crate_name: None, url }); - let mut out = - File::create(&output).map_err(|e| format!("{output}: {e}", output = output.display()))?; - let (metadata, text) = extract_leading_metadata(&input_str); if metadata.is_empty() { return Err("invalid markdown file: no initial lines starting with `# ` or `%`".to_owned()); } + + let mut out = + File::create(&output).map_err(|e| format!("{output}: {e}", output = output.display()))?; + let title = metadata[0]; let error_codes = ErrorCodes::from(options.unstable_features.is_nightly_build()); diff --git a/src/tools/enzyme b/src/tools/enzyme index a9b96ed28ed25..50c11dc266ecd 160000 --- a/src/tools/enzyme +++ b/src/tools/enzyme @@ -1 +1 @@ -Subproject commit a9b96ed28ed25bd9e393d7fd14778acef97505ed +Subproject commit 50c11dc266ecdb29b87aeeadc91610bc21f98b89 diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 8dc6b5f07b92e..6953a27a39df8 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -132,15 +132,7 @@ pub fn iter_exported_symbols<'tcx>( if !(used || codegen_attrs.contains_extern_indicator()) { continue; } - // FIXME: `#[no_mangle]` makes no sense on a generic item, but still causes it to be - // considered "extern". Remove this once `no_mangle_generic_items` is a hard error. - let mono = { - let generics = tcx.generics_of(def_id); - !generics.requires_monomorphization(tcx) - }; - if mono { - f(LOCAL_CRATE, def_id.into(), used)?; - } + f(LOCAL_CRATE, def_id.into(), used)?; } // Next, all our dependencies. diff --git a/src/tools/miri/test-cargo-miri/issue-rust-86261/src/lib.rs b/src/tools/miri/test-cargo-miri/issue-rust-86261/src/lib.rs index 1947c38b77455..ab0fa8f013968 100644 --- a/src/tools/miri/test-cargo-miri/issue-rust-86261/src/lib.rs +++ b/src/tools/miri/test-cargo-miri/issue-rust-86261/src/lib.rs @@ -1,4 +1,4 @@ -#![allow(unused_imports, unused_attributes, no_mangle_generic_items)] +#![allow(unused_imports, unused_attributes)] // Regression test for https://github.com/rust-lang/rust/issues/86261: // `#[no_mangle]` on a `use` item. @@ -14,10 +14,6 @@ pub struct NoMangleStruct; #[export_name = "NoMangleStruct"] fn no_mangle_struct() {} -// `#[no_mangle]` on a generic function can also cause ICEs. -#[no_mangle] -fn no_mangle_generic() {} - -// Same as `no_mangle_struct()` but for the `no_mangle_generic()` generic function. -#[export_name = "no_mangle_generic"] -fn no_mangle_generic2() {} +// Same as `no_mangle_struct()` but for the `no_mangle_struct()` function. +#[export_name = "no_mangle_struct"] +fn no_mangle_alias() {} diff --git a/src/tools/miri/test-cargo-miri/src/main.rs b/src/tools/miri/test-cargo-miri/src/main.rs index 1568da43afe30..ed16a14e3d60f 100644 --- a/src/tools/miri/test-cargo-miri/src/main.rs +++ b/src/tools/miri/test-cargo-miri/src/main.rs @@ -87,13 +87,13 @@ mod test { fn assoc_fn_as_exported_symbol() -> i32; fn make_true() -> bool; fn NoMangleStruct(); - fn no_mangle_generic(); + fn no_mangle_struct(); } assert_eq!(unsafe { exported_symbol() }, 123456); assert_eq!(unsafe { assoc_fn_as_exported_symbol() }, -123456); assert!(unsafe { make_true() }); unsafe { NoMangleStruct() } - unsafe { no_mangle_generic() } + unsafe { no_mangle_struct() } } } diff --git a/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs b/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs deleted file mode 100644 index 90fa021863990..0000000000000 --- a/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs +++ /dev/null @@ -1,22 +0,0 @@ -fn main() { - generic_type(123); - generic_const::<456>(); - generic_lifetime(&789); -} - -#[allow(no_mangle_generic_items)] -#[unsafe(no_mangle)] -fn generic_type(value: T) { - println!("{value:?}"); -} - -#[expect(no_mangle_generic_items)] -#[unsafe(no_mangle)] -fn generic_const() { - println!("{N}"); -} - -#[unsafe(no_mangle)] -fn generic_lifetime<'a>(x: &'a i32) { - println!("{x}"); -} diff --git a/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout b/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout deleted file mode 100644 index af7864ba2f038..0000000000000 --- a/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout +++ /dev/null @@ -1,3 +0,0 @@ -123 -456 -789 diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index 74ecbcdf88411..0a054b0ead56e 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit 74ecbcdf88411937a6e39baf2779948565dfd388 +Subproject commit 0a054b0ead56e41a4584bfab6fdc1a5fad2aedc3 diff --git a/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs b/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs index 2e63f282c2307..8ae5f994b6b63 100644 --- a/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs +++ b/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs @@ -1,6 +1,5 @@ //@ assembly-output: emit-asm //@ only-x86_64 -//@ max-llvm-major-version: 22 //@ ignore-windows CHECK patterns use the SysV x86-64 calling convention //@ ignore-sgx Test incompatible with LVI mitigations //@ compile-flags: -Copt-level=3 @@ -16,7 +15,7 @@ pub fn bool_index(a: u32, b: bool, c: bool, d: &mut [u128; 2]) { // CHECK-LABEL: bool_index: // CHECK: testl %esi, %esi // CHECK: je - // CHECK: xorb %dl, %dil + // CHECK: xorb {{%dl, %dil|%dil, %dl}} // CHECK: orb $1, (%rcx) // CHECK-NOT: jmp // CHECK-NOT: andb $1, %dil diff --git a/tests/codegen-llvm/avr/avr-func-addrspace.rs b/tests/codegen-llvm/avr/avr-func-addrspace.rs index 2a40f0f247542..8812992050325 100644 --- a/tests/codegen-llvm/avr/avr-func-addrspace.rs +++ b/tests/codegen-llvm/avr/avr-func-addrspace.rs @@ -30,7 +30,6 @@ fn arbitrary_black_box(ptr: &usize, _: &mut u32) -> Result<(), ()> { } #[inline(never)] -#[no_mangle] fn call_through_fn_trait(a: &mut impl Fn<(), Output = ()>) { (*a)() } @@ -49,7 +48,7 @@ pub extern "C" fn test() { // A call through the Fn trait must use address space 1. // - // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait({{.*}}) + // CHECK: call{{.+}}addrspace(1) void @{{.*call_through_fn_trait.*}}({{.*}}) call_through_fn_trait(&mut update_bar_value); // A call through a global variable must use address space 1. diff --git a/tests/codegen-llvm/naked-fn/generics.rs b/tests/codegen-llvm/naked-fn/generics.rs index b85682699f45f..5031c156e35a1 100644 --- a/tests/codegen-llvm/naked-fn/generics.rs +++ b/tests/codegen-llvm/naked-fn/generics.rs @@ -53,12 +53,11 @@ impl Invert for i64 { } // CHECK: .balign -// CHECK-LABEL: generic_function: +// CHECK-LABEL: generic_functionxEB2_: // CHECK: call // CHECK: ret #[unsafe(naked)] -#[no_mangle] pub extern "C" fn generic_function(x: i64) -> i64 { naked_asm!( "call {}", diff --git a/tests/run-make/fat-lto-module-summary/foo.rs b/tests/run-make/fat-lto-module-summary/foo.rs new file mode 100644 index 0000000000000..324478fd587c3 --- /dev/null +++ b/tests/run-make/fat-lto-module-summary/foo.rs @@ -0,0 +1,3 @@ +#![no_std] + +pub fn foo() {} diff --git a/tests/run-make/fat-lto-module-summary/rmake.rs b/tests/run-make/fat-lto-module-summary/rmake.rs new file mode 100644 index 0000000000000..f04416c68fd96 --- /dev/null +++ b/tests/run-make/fat-lto-module-summary/rmake.rs @@ -0,0 +1,10 @@ +use run_make_support::{llvm_bcanalyzer, rustc}; + +fn main() { + rustc().input("foo.rs").crate_type("lib").arg("-Clto=fat").arg("--emit=llvm-bc").run(); + + llvm_bcanalyzer() + .input("foo.bc") + .run() + .assert_stdout_contains("FULL_LTO_GLOBALVAL_SUMMARY_BLOCK"); +} diff --git a/tests/run-make/rustdoc-filter-doc_cfg-doctest/foo.rs b/tests/run-make/rustdoc-filter-doc_cfg-doctest/foo.rs new file mode 100644 index 0000000000000..76f9f463f4f4d --- /dev/null +++ b/tests/run-make/rustdoc-filter-doc_cfg-doctest/foo.rs @@ -0,0 +1,15 @@ +#![feature(doc_cfg)] + +/// ``` +/// assert!(true); +/// ``` +#[doc(cfg(spec))] +fn f() {} + +#[doc(cfg(false))] +mod dummy { + /// ``` + /// assert!(true); + /// ``` + fn f2() {} +} diff --git a/tests/run-make/rustdoc-filter-doc_cfg-doctest/rmake.rs b/tests/run-make/rustdoc-filter-doc_cfg-doctest/rmake.rs new file mode 100644 index 0000000000000..942f23964f4d3 --- /dev/null +++ b/tests/run-make/rustdoc-filter-doc_cfg-doctest/rmake.rs @@ -0,0 +1,30 @@ +//! Regression test to ensure that `doc(cfg())` has no impact on the filtered-out doctests. +//! +//! Regression test for . + +//@ ignore-cross-compile + +use run_make_support::rustdoc; + +fn check_rustdoc_test_output(edition: &str) { + let out = rustdoc().input("foo.rs").edition(edition).arg("--test").run().stdout_utf8(); + + // There should be two tests run. + assert!(out.contains("running 2 test"), "Failed with edition {edition}"); + // They should be in `foo.rs`. + assert!(out.contains("test foo.rs - f (line 3) ... ok"), "Failed with edition {edition}"); + assert!( + out.contains("test foo.rs - dummy::f2 (line 11) ... ok"), + "Failed with edition {edition}" + ); + // We double-check that the test was run (successfully). + assert!( + out.contains("test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;"), + "Failed with edition {edition}", + ); +} + +fn main() { + check_rustdoc_test_output("2015"); + check_rustdoc_test_output("2024"); +} diff --git a/tests/run-make/rustdoc/markdown-without-title/rmake.rs b/tests/run-make/rustdoc/markdown-without-title/rmake.rs new file mode 100644 index 0000000000000..5bac98c348110 --- /dev/null +++ b/tests/run-make/rustdoc/markdown-without-title/rmake.rs @@ -0,0 +1,45 @@ +// When rustdoc gets a markdown file as input, we want to ensure that if the markdown is invalid, +// the output file won't be truncated in case this markdown is invalid. + +//@ needs-target-std + +use run_make_support::{path, rfs, rustdoc}; + +fn main() { + let output_content = "output"; + let base_file_name = "input"; + + let out_dir = path("out"); + rfs::create_dir(&out_dir); + + // We create the file that should be created by rustdoc and add some content + // into it that we will check is still there once rustdoc failed. + let output = out_dir.join(format!("{base_file_name}.html")); + rfs::write(&output, output_content); + + // We create an "invalid" markdown file (ie no title). + let md_file = format!("{base_file_name}.md"); + rfs::write(&md_file, "Markdown without a title"); + + // We run the failing rustdoc. + rustdoc() + .input(&md_file) + .out_dir(&out_dir) + .run_fail() + .assert_exit_code(1) + .assert_stderr_contains( + "error: invalid markdown file: no initial lines starting with `# ` or `%`", + ); + + // Shouldn't have changed. + assert_eq!(rfs::read_to_string(&output), output_content); + + // We update the input markdown to make it valid for rustdoc. + rfs::write(&md_file, "# a title\n\nMarkdown with a title"); + + // We run rustdoc successfully. + rustdoc().input(&md_file).out_dir(&out_dir).run(); + + // Should have changed. + assert_ne!(rfs::read_to_string(output), output_content); +} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/rmake.rs new file mode 100644 index 0000000000000..6cfc6ed9230ec --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/rmake.rs @@ -0,0 +1,56 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let parts_out_dir = path("parts"); + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("quebec.json").exists()); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("tango.json").exists()); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("sierra.json").exists()); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("tango.rs").run(); + htmldocck().arg(&out_dir).arg("quebec.rs").run(); + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs similarity index 88% rename from tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs index 10f12ad8d1184..cdca794601216 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs @@ -1,13 +1,10 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html //@ has index.html '//h1' 'List of all crates' //@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' //@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' //@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has help.html +//@ has settings.html //@ has quebec/struct.Quebec.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs similarity index 73% rename from tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs index 986c58deb5d6b..b512f4f7677c8 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs @@ -1,15 +1,3 @@ -//@ aux-build:tango.rs -//@ aux-build:romeo.rs -//@ aux-build:quebec.rs -//@ aux-build:sierra.rs -//@ build-aux-docs -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/romeo -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/sierra -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html '//h1' 'List of all crates' //@ has index.html //@ has index.html '//ul[@class="all-items"]//a[@href="indigo/index.html"]' 'indigo' @@ -17,6 +5,8 @@ //@ has index.html '//ul[@class="all-items"]//a[@href="romeo/index.html"]' 'romeo' //@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' //@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has help.html +//@ has settings.html //@ !has quebec/struct.Quebec.html //@ !has romeo/type.Romeo.html //@ !has sierra/struct.Sierra.html diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/rmake.rs new file mode 100644 index 0000000000000..0191e659c5eef --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/rmake.rs @@ -0,0 +1,91 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir("quebec-out") + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/quebec")) + .arg("--enable-index-page") + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir("tango-out") + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/tango")) + .arg("--enable-index-page") + .run(); + + rustc() + .input("sierra.rs") + .crate_name("sierra") + .crate_type("rlib") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .run(); + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir("sierra-out") + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/sierra")) + .arg("--enable-index-page") + .run(); + + rustc() + .input("romeo.rs") + .crate_name("romeo") + .crate_type("rlib") + .extern_("sierra", rust_lib_name("sierra")) + .library_search_path(cwd()) + .run(); + rustdoc() + .input("romeo.rs") + .crate_name("romeo") + .extern_("sierra", rust_lib_name("sierra")) + .library_search_path(cwd()) + .out_dir("romeo-out") + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/romeo")) + .arg("--enable-index-page") + .run(); + + rustdoc() + .input("indigo.rs") + .crate_name("indigo") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/indigo")) + .arg("--enable-index-page") + .run(); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg("--read-doc-meta-dir=info/doc.parts/tango") + .arg("--read-doc-meta-dir=info/doc.parts/romeo") + .arg("--read-doc-meta-dir=info/doc.parts/quebec") + .arg("--read-doc-meta-dir=info/doc.parts/sierra") + .arg("--read-doc-meta-dir=info/doc.parts/indigo") + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("indigo.rs").run(); +} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/romeo.rs b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/romeo.rs new file mode 100644 index 0000000000000..772119ef133c2 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/romeo.rs @@ -0,0 +1,2 @@ +extern crate sierra; +pub type Romeo = sierra::Sierra; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/sierra.rs new file mode 100644 index 0000000000000..796f5118d28b9 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/sierra.rs @@ -0,0 +1,3 @@ +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/rmake.rs new file mode 100644 index 0000000000000..1d6e004b078f0 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/rmake.rs @@ -0,0 +1,47 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let parts_out_dir = path("parts"); + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("quebec.json").exists()); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("tango.json").exists()); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("sierra.json").exists()); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs similarity index 67% rename from tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs index 9a6ca3c6dd41c..21639dc019d70 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs @@ -1,10 +1,6 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ !has index.html +//@ !has help.html +//@ !has settings.html //@ has sierra/struct.Sierra.html //@ hasraw sierra/struct.Sierra.html 'Tango' //@ !has trait.impl/tango/trait.Tango.js diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-separate/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/rmake.rs new file mode 100644 index 0000000000000..84dfda3b040c0 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/rmake.rs @@ -0,0 +1,45 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rfs, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + // all these invocations of rustdoc write the parts, + // but none of them ever reads them + .arg("--write-doc-meta-dir=parts-unused") + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=parts-unused") + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=parts-unused") + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs similarity index 66% rename from tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs index 9d5a1a3c17bfa..e5d3f99568df7 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs @@ -1,10 +1,6 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ !has index.html +//@ !has help.html +//@ !has settings.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html //@ hasraw sierra/struct.Sierra.html 'Tango' diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/no-merge-write-anyway/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/rmake.rs new file mode 100644 index 0000000000000..8b650055953fe --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/rmake.rs @@ -0,0 +1,51 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/quebec")) + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/tango")) + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/sierra")) + .run(); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg(format!("--read-doc-meta-dir=info/doc.parts/tango")) + .arg(format!("--read-doc-meta-dir=info/doc.parts/sierra")) + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs similarity index 77% rename from tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs index 2d94321ed7465..9a485b13e09b9 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs @@ -1,9 +1,3 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has quebec/struct.Quebec.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-include/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/rmake.rs new file mode 100644 index 0000000000000..537058d09f66a --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/rmake.rs @@ -0,0 +1,52 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/quebec")) + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/tango")) + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/sierra")) + .run(); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg(format!("--read-doc-meta-dir=info/doc.parts/tango")) + .arg(format!("--read-doc-meta-dir=info/doc.parts/quebec")) + .arg(format!("--read-doc-meta-dir=info/doc.parts/sierra")) + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs similarity index 78% rename from tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs index 6a2dbb1c31ccc..b6862f4e3c2b0 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs @@ -1,15 +1,10 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html //@ has index.html '//h1' 'List of all crates' //@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' //@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' //@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has help.html +//@ has settings.html //@ has sierra/struct.Sierra.html //@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' //@ hasraw search.index/name/*.js 'Tango' diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite-but-separate/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/rmake.rs new file mode 100644 index 0000000000000..ced70ac3f526f --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/rmake.rs @@ -0,0 +1,48 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts/quebec.d")) + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir=info/doc.parts")) + .run(); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg(format!("--read-doc-meta-dir=info/doc.parts")) + .arg("--enable-index-page") + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/sierra.rs similarity index 82% rename from tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/overwrite/sierra.rs index 57c9732ba8dd7..d95d1495a3210 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/sierra.rs @@ -1,8 +1,3 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has quebec/struct.Quebec.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/overwrite/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs similarity index 82% rename from tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs index c157380edf1f9..4541fe7a3104b 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs @@ -1,9 +1,8 @@ -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html //@ has index.html '//h1' 'List of all crates' //@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has help.html +//@ has settings.html //@ has quebec/struct.Quebec.html //@ hasraw search.index/name/*.js 'Quebec' diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-finalize/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-finalize/rmake.rs new file mode 100644 index 0000000000000..79f05c37e3104 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-finalize/rmake.rs @@ -0,0 +1,26 @@ +//@ needs-target-std + +use run_make_support::{htmldocck, path, rustc, rustdoc}; + +fn main() { + let parts_out_dir = path("parts"); + let out_dir = path("out"); + + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) + .run(); + assert!(parts_out_dir.join("quebec.json").exists()); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("quebec.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs similarity index 82% rename from tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs index 4fd510e31227c..ff955c6efe053 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs @@ -1,9 +1,8 @@ -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html //@ has index.html '//h1' 'List of all crates' //@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has help.html +//@ has settings.html //@ has quebec/struct.Quebec.html //@ hasraw search.index/name/*.js 'Quebec' diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-read-write/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-read-write/rmake.rs new file mode 100644 index 0000000000000..f1f3fb4ae3e3d --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/single-crate-read-write/rmake.rs @@ -0,0 +1,17 @@ +//@ needs-target-std + +use run_make_support::{htmldocck, path, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("quebec.rs").run(); +} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/rmake.rs new file mode 100644 index 0000000000000..28bbbc8fda039 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/rmake.rs @@ -0,0 +1,52 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/quebec") + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/tango") + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/sierra") + .run(); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg("--read-doc-meta-dir=info/doc.parts/tango") + .arg("--read-doc-meta-dir=info/doc.parts/quebec") + .arg("--read-doc-meta-dir=info/doc.parts/sierra") + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs similarity index 78% rename from tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs index 945e8cf84dc7d..980632473a405 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs @@ -1,15 +1,10 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html //@ has index.html '//h1' 'List of all crates' //@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' //@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' //@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has help.html +//@ has settings.html //@ has quebec/struct.Quebec.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-none/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/rmake.rs new file mode 100644 index 0000000000000..f43d940a32af1 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/rmake.rs @@ -0,0 +1,43 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--enable-index-page") + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--enable-index-page") + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs similarity index 88% rename from tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs index 67ce91d1e225a..31b5270b68e1b 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs @@ -1,13 +1,10 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ has index.html //@ has index.html '//h1' 'List of all crates' //@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' //@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' //@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has help.html +//@ has settings.html //@ has quebec/struct.Quebec.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-merge-read-write/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/quebec.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/quebec.rs new file mode 100644 index 0000000000000..3ef377298cc6e --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/quebec.rs @@ -0,0 +1 @@ +pub struct Quebec; diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/rmake.rs new file mode 100644 index 0000000000000..bd8fd59ed1c2a --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/rmake.rs @@ -0,0 +1,43 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + + rustc().input("quebec.rs").crate_name("quebec").crate_type("rlib").run(); + rustdoc() + .input("quebec.rs") + .crate_name("quebec") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/quebec") + .run(); + + rustc() + .input("tango.rs") + .crate_name("tango") + .crate_type("rlib") + .extern_("quebec", rust_lib_name("quebec")) + .run(); + rustdoc() + .input("tango.rs") + .crate_name("tango") + .extern_("quebec", rust_lib_name("quebec")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/tango") + .run(); + + rustdoc() + .input("sierra.rs") + .crate_name("sierra") + .extern_("tango", rust_lib_name("tango")) + .library_search_path(cwd()) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/sierra") + .run(); + + htmldocck().arg(&out_dir).arg("sierra.rs").run(); +} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs similarity index 69% rename from tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs index 61c60cf7c9e15..d8b8bc1271d51 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs @@ -1,10 +1,6 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - //@ !has index.html +//@ !has help.html +//@ !has settings.html //@ has sierra/struct.Sierra.html //@ has tango/trait.Tango.html //@ hasraw sierra/struct.Sierra.html 'Tango' diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/tango.rs b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/tango.rs new file mode 100644 index 0000000000000..a9a44e06c7797 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/transitive-no-info/tango.rs @@ -0,0 +1,2 @@ +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs b/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs similarity index 74% rename from tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs rename to tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs index 998bb559df8c1..50fd79fa1b818 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs +++ b/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs @@ -1,8 +1,3 @@ -//@ aux-build:foxtrot.rs -//@ build-aux-docs -//@ doc-flags:--read-doc-meta-dir=info/doc.parts/foxtrot -//@ doc-flags:-Zunstable-options - //@ has echo/enum.Echo.html //@ hasraw echo/enum.Echo.html 'Foxtrot' //@ hasraw trait.impl/foxtrot/trait.Foxtrot.js 'enum.Echo.html' diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/foxtrot.rs b/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/foxtrot.rs new file mode 100644 index 0000000000000..390cef74d4730 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/foxtrot.rs @@ -0,0 +1 @@ +pub trait Foxtrot {} diff --git a/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/rmake.rs b/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/rmake.rs new file mode 100644 index 0000000000000..69275a28ca8f9 --- /dev/null +++ b/tests/run-make/rustdoc/merge-cross-crate-info/two-separate-out-dir/rmake.rs @@ -0,0 +1,36 @@ +//@ needs-target-std + +use run_make_support::{cwd, htmldocck, path, rust_lib_name, rustc, rustdoc}; + +fn main() { + let out_dir = path("out"); + let alt_out_dir = path("alt-out"); + + rustc().input("foxtrot.rs").crate_name("foxtrot").crate_type("rlib").run(); + rustdoc() + .input("foxtrot.rs") + .crate_name("foxtrot") + .out_dir(&alt_out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/foxtrot") + .run(); + + rustdoc() + .input("echo.rs") + .crate_name("echo") + .extern_("foxtrot", rust_lib_name("foxtrot")) + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg("--write-doc-meta-dir=info/doc.parts/echo") + .run(); + + rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg("--read-doc-meta-dir=info/doc.parts/echo") + .arg("--read-doc-meta-dir=info/doc.parts/foxtrot") + .arg("--enable-index-page") + .run(); + + htmldocck().arg(&out_dir).arg("echo.rs").run(); +} diff --git a/tests/run-make/rustdoc/merge-dir-alias/rmake.rs b/tests/run-make/rustdoc/merge-dir-alias/rmake.rs index 8a5c1aa2af723..3e4941c7a8769 100644 --- a/tests/run-make/rustdoc/merge-dir-alias/rmake.rs +++ b/tests/run-make/rustdoc/merge-dir-alias/rmake.rs @@ -18,12 +18,11 @@ fn main() { .run(); assert!(parts_out_dir.join("dep1.json").exists()); - let output = rustdoc() + rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); - output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); rustdoc() .input("dep2.rs") @@ -33,12 +32,11 @@ fn main() { .run(); assert!(parts_out_dir.join("dep2.json").exists()); - let output2 = rustdoc() + rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); - output2.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); rustdoc() .input("dep1.rs") @@ -48,12 +46,11 @@ fn main() { .run(); assert!(parts_out_dir.join("dep1.json").exists()); - let output3 = rustdoc() + rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); - output3.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); // dep_missing is different, because --write-doc-meta-dir is not supplied rustdoc().input("dep_missing.rs").out_dir(&out_dir).run(); @@ -67,12 +64,11 @@ fn main() { .run(); assert!(parts_out_dir.join("dep1.json").exists()); - let output4 = rustdoc() + rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); - output4.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); htmldocck().arg(&out_dir).arg("dep1.rs").run(); htmldocck().arg(&out_dir).arg("dep2.rs").run(); diff --git a/tests/run-make/rustdoc/merge-dir/rmake.rs b/tests/run-make/rustdoc/merge-dir/rmake.rs index d2d31138bf3c6..e0f144f6234f4 100644 --- a/tests/run-make/rustdoc/merge-dir/rmake.rs +++ b/tests/run-make/rustdoc/merge-dir/rmake.rs @@ -30,12 +30,11 @@ fn main() { rustdoc().input("dep_missing.rs").out_dir(&out_dir).run(); assert!(parts_out_dir.join("dep2.json").exists()); - let output = rustdoc() + rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); - output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); htmldocck().arg(&out_dir).arg("dep1.rs").run(); htmldocck().arg(&out_dir).arg("dep2.rs").run(); diff --git a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs deleted file mode 100644 index c4b3ce498576c..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs deleted file mode 100644 index 299a673418713..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs deleted file mode 100644 index d2af9af496bc3..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs deleted file mode 100644 index bcccc05299a79..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ aux-build:sierra.rs -//@ build-aux-docs -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/romeo -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate sierra; -pub type Romeo = sierra::Sierra; diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs deleted file mode 100644 index 9d5e564720169..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate tango; -pub struct Sierra; -impl tango::Tango for Sierra {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs deleted file mode 100644 index 577c486a3adfb..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs deleted file mode 100644 index d2af9af496bc3..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs deleted file mode 100644 index 577c486a3adfb..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs deleted file mode 100644 index 442eacb91f480..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs deleted file mode 100644 index e10bab806ea0c..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs deleted file mode 100644 index 442eacb91f480..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs deleted file mode 100644 index e10bab806ea0c..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs deleted file mode 100644 index d2af9af496bc3..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs deleted file mode 100644 index 577c486a3adfb..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs deleted file mode 100644 index 35098e62cede9..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec.d -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs deleted file mode 100644 index dcb7965dde86e..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--read-doc-meta-dir=info/doc.parts -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs deleted file mode 100644 index fde3635e62250..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ doc-flags:--read-doc-meta-dir=. -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -//@ has index.html -//@ has index.html '//h1' 'List of all crates' -//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' -//@ has quebec/struct.Quebec.html -//@ hasraw search.index/name/*.js 'Quebec' - -// we can --write-doc-meta-dir, but that doesn't do anything other than create -// the file -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs deleted file mode 100644 index 442eacb91f480..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs deleted file mode 100644 index e10bab806ea0c..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs deleted file mode 100644 index c4b3ce498576c..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs deleted file mode 100644 index 299a673418713..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs deleted file mode 100644 index 442eacb91f480..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs deleted file mode 100644 index e10bab806ea0c..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs b/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs deleted file mode 100644 index 713f8812a55a6..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ unique-doc-out-dir -//@ doc-flags:--write-doc-meta-dir=info/doc.parts/foxtrot -//@ doc-flags:-Zunstable-options - -pub trait Foxtrot {} diff --git a/tests/rustdoc-ui/doc-meta-read-write-err.rs b/tests/rustdoc-ui/doc-meta-read-write-err.rs new file mode 100644 index 0000000000000..64a8ce4185b35 --- /dev/null +++ b/tests/rustdoc-ui/doc-meta-read-write-err.rs @@ -0,0 +1,2 @@ +//@ compile-flags:-Z unstable-options --read-doc-meta-dir . --write-doc-meta-dir . +//~? ERROR cannot pass both --read-doc-meta-dir and --write-doc-meta-dir diff --git a/tests/rustdoc-ui/doc-meta-read-write-err.stderr b/tests/rustdoc-ui/doc-meta-read-write-err.stderr new file mode 100644 index 0000000000000..818deb34300cd --- /dev/null +++ b/tests/rustdoc-ui/doc-meta-read-write-err.stderr @@ -0,0 +1,2 @@ +error: cannot pass both --read-doc-meta-dir and --write-doc-meta-dir + diff --git a/tests/ui/backtrace/auxiliary/line-tables-only-helper.rs b/tests/ui/backtrace/auxiliary/line-tables-only-helper.rs index a9d555feb86b3..993632ea1a112 100644 --- a/tests/ui/backtrace/auxiliary/line-tables-only-helper.rs +++ b/tests/ui/backtrace/auxiliary/line-tables-only-helper.rs @@ -1,16 +1,13 @@ //@ compile-flags: -Cstrip=none -Cdebuginfo=line-tables-only -#[no_mangle] pub fn backtrace_with_baz_in_it(mut cb: F, data: u32) where F: FnMut(u32) { cb(data); } -#[no_mangle] pub fn backtrace_with_bar_in_it(cb: F, data: u32) where F: FnMut(u32) { backtrace_with_baz_in_it(cb, data); } -#[no_mangle] pub fn backtrace_with_foo_in_it(cb: F, data: u32) where F: FnMut(u32) { backtrace_with_bar_in_it(cb, data); } diff --git a/tests/ui/backtrace/line-tables-only.rs b/tests/ui/backtrace/line-tables-only.rs index 320ad93393c71..33d5774079d94 100644 --- a/tests/ui/backtrace/line-tables-only.rs +++ b/tests/ui/backtrace/line-tables-only.rs @@ -32,9 +32,7 @@ fn assert_contains( expected_line: u32, ) { // The formatted frames look like this: - // `{ fn: "backtrace_with_baz_in_it", file: ".../tests/ui/backtrace/auxiliary/line-tables-only-helper.rs", line: 5 }` - // or this: - // `{ fn: "line_tables_only_helper::backtrace_with_baz_in_it", file: "...\tests\ui\backtrace\auxiliary\line-tables-only-helper.rs", line: 5 },` + // `{ fn: "line_tables_only_helper::backtrace_with_baz_in_it::", file: ".../tests/ui/backtrace/auxiliary/line-tables-only-helper.rs", line: 4 }, // Make sure we match the right part when searching for the function name and line number. let expected_line_str = format!("line: {expected_line} "); eprintln!("{:#?}", backtrace); @@ -63,8 +61,8 @@ fn main() { // And with #143208 we also lost `bar` in the line tables. #[cfg(not(all(target_pointer_width = "32", target_env = "msvc")))] { - assert_contains(&backtrace, "backtrace_with_foo_in_it", "line-tables-only-helper.rs", 15); - assert_contains(&backtrace, "backtrace_with_bar_in_it", "line-tables-only-helper.rs", 10); + assert_contains(&backtrace, "backtrace_with_foo_in_it", "line-tables-only-helper.rs", 12); + assert_contains(&backtrace, "backtrace_with_bar_in_it", "line-tables-only-helper.rs", 8); } - assert_contains(&backtrace, "backtrace_with_baz_in_it", "line-tables-only-helper.rs", 5); + assert_contains(&backtrace, "backtrace_with_baz_in_it", "line-tables-only-helper.rs", 4); } diff --git a/tests/ui/generics/export-name-on-generics.fixed b/tests/ui/generics/export-name-on-generics.fixed deleted file mode 100644 index c8a3fd5798f86..0000000000000 --- a/tests/ui/generics/export-name-on-generics.fixed +++ /dev/null @@ -1,157 +0,0 @@ -//@ run-rustfix -#![allow(dead_code, mismatched_lifetime_syntaxes)] -#![deny(no_mangle_generic_items)] - -pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled - -pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - -#[export_name = "baz"] -pub fn baz(x: &i32) -> &i32 { x } - -#[export_name = "qux"] -pub fn qux<'a>(x: &'a i32) -> &i32 { x } - -pub struct Foo; - -impl Foo { - - pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - #[export_name = "baz"] - pub fn baz(x: &i32) -> &i32 { x } - - #[export_name = "qux"] - pub fn qux<'a>(x: &'a i32) -> &i32 { x } -} - -trait Trait1 { - fn foo(); - extern "C" fn bar(); - fn baz(x: &i32) -> &i32; - fn qux<'a>(x: &'a i32) -> &i32; -} - -impl Trait1 for Foo { - - fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - #[export_name = "baz"] - fn baz(x: &i32) -> &i32 { x } - - #[export_name = "qux"] - fn qux<'a>(x: &'a i32) -> &i32 { x } -} - -trait Trait2 { - fn foo(); - fn foo2(); - extern "C" fn bar(); - fn baz(x: &i32) -> &i32; - fn qux<'a>(x: &'a i32) -> &i32; -} - -impl Trait2 for Foo { - - fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - fn foo2() {} //~ ERROR functions generic over types or consts must be mangled - - - extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - - fn baz(x: &i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled - - - fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled -} - -pub struct Bar(#[allow(dead_code)] T); - -impl Bar { - - pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - - pub fn baz() {} //~ ERROR functions generic over types or consts must be mangled -} - -impl Bar { - #[export_name = "qux"] - pub fn qux() {} -} - -trait Trait3 { - fn foo(); - extern "C" fn bar(); - fn baz(); -} - -impl Trait3 for Bar { - - fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - - fn baz() {} //~ ERROR functions generic over types or consts must be mangled -} - -pub struct Baz<'a>(#[allow(dead_code)] &'a i32); - -impl<'a> Baz<'a> { - #[export_name = "foo"] - pub fn foo() {} - - #[export_name = "bar"] - pub fn bar<'b>(x: &'b i32) -> &i32 { x } -} - -trait Trait4 { - fn foo(); - fn bar<'a>(x: &'a i32) -> &i32; -} - -impl Trait4 for Bar { - #[export_name = "foo"] - fn foo() {} - - #[export_name = "bar"] - fn bar<'b>(x: &'b i32) -> &i32 { x } -} - -impl<'a> Trait4 for Baz<'a> { - #[export_name = "foo"] - fn foo() {} - - #[export_name = "bar"] - fn bar<'b>(x: &'b i32) -> &i32 { x } -} - -trait Trait5 { - fn foo(); -} - -impl Trait5 for Foo { - #[export_name = "foo"] - fn foo() {} -} - -impl Trait5 for Bar { - #[export_name = "foo"] - fn foo() {} -} - -fn main() {} diff --git a/tests/ui/generics/export-name-on-generics.rs b/tests/ui/generics/export-name-on-generics.rs index 8b38037fe12fb..8178fee78a30c 100644 --- a/tests/ui/generics/export-name-on-generics.rs +++ b/tests/ui/generics/export-name-on-generics.rs @@ -1,6 +1,4 @@ -//@ run-rustfix #![allow(dead_code, mismatched_lifetime_syntaxes)] -#![deny(no_mangle_generic_items)] #[export_name = "foo"] pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled diff --git a/tests/ui/generics/export-name-on-generics.stderr b/tests/ui/generics/export-name-on-generics.stderr index e08b2b1c8f319..d680430ca867d 100644 --- a/tests/ui/generics/export-name-on-generics.stderr +++ b/tests/ui/generics/export-name-on-generics.stderr @@ -1,19 +1,13 @@ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:6:1 + --> $DIR/export-name-on-generics.rs:4:1 | LL | #[export_name = "foo"] | ---------------------- help: remove this attribute LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/export-name-on-generics.rs:3:9 - | -LL | #![deny(no_mangle_generic_items)] - | ^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:9:1 + --> $DIR/export-name-on-generics.rs:7:1 | LL | #[export_name = "bar"] | ---------------------- help: remove this attribute @@ -21,7 +15,7 @@ LL | pub extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:21:5 + --> $DIR/export-name-on-generics.rs:19:5 | LL | #[export_name = "foo"] | ---------------------- help: remove this attribute @@ -29,7 +23,7 @@ LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:24:5 + --> $DIR/export-name-on-generics.rs:22:5 | LL | #[export_name = "bar"] | ---------------------- help: remove this attribute @@ -37,7 +31,7 @@ LL | pub extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:42:5 + --> $DIR/export-name-on-generics.rs:40:5 | LL | #[export_name = "foo"] | ---------------------- help: remove this attribute @@ -45,7 +39,7 @@ LL | fn foo() {} | ^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:45:5 + --> $DIR/export-name-on-generics.rs:43:5 | LL | #[export_name = "bar"] | ---------------------- help: remove this attribute @@ -53,7 +47,7 @@ LL | extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:64:5 + --> $DIR/export-name-on-generics.rs:62:5 | LL | #[export_name = "foo"] | ---------------------- help: remove this attribute @@ -61,7 +55,7 @@ LL | fn foo() {} | ^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:67:5 + --> $DIR/export-name-on-generics.rs:65:5 | LL | #[export_name = "foo2"] | ----------------------- help: remove this attribute @@ -69,7 +63,7 @@ LL | fn foo2() {} | ^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:70:5 + --> $DIR/export-name-on-generics.rs:68:5 | LL | #[export_name = "baz"] | ---------------------- help: remove this attribute @@ -77,7 +71,7 @@ LL | extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:73:5 + --> $DIR/export-name-on-generics.rs:71:5 | LL | #[export_name = "baz"] | ---------------------- help: remove this attribute @@ -85,7 +79,7 @@ LL | fn baz(x: &i32) -> &i32 { x } | ^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:76:5 + --> $DIR/export-name-on-generics.rs:74:5 | LL | #[export_name = "qux"] | ---------------------- help: remove this attribute @@ -93,7 +87,7 @@ LL | fn qux<'a>(x: &'a i32) -> &i32 { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:83:5 + --> $DIR/export-name-on-generics.rs:81:5 | LL | #[export_name = "foo"] | ---------------------- help: remove this attribute @@ -101,7 +95,7 @@ LL | pub fn foo() {} | ^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:86:5 + --> $DIR/export-name-on-generics.rs:84:5 | LL | #[export_name = "bar"] | ---------------------- help: remove this attribute @@ -109,7 +103,7 @@ LL | pub extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:89:5 + --> $DIR/export-name-on-generics.rs:87:5 | LL | #[export_name = "baz"] | ---------------------- help: remove this attribute @@ -117,7 +111,7 @@ LL | pub fn baz() {} | ^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:105:5 + --> $DIR/export-name-on-generics.rs:103:5 | LL | #[export_name = "foo"] | ---------------------- help: remove this attribute @@ -125,7 +119,7 @@ LL | fn foo() {} | ^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:108:5 + --> $DIR/export-name-on-generics.rs:106:5 | LL | #[export_name = "bar"] | ---------------------- help: remove this attribute @@ -133,7 +127,7 @@ LL | extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/export-name-on-generics.rs:111:5 + --> $DIR/export-name-on-generics.rs:109:5 | LL | #[export_name = "baz"] | ---------------------- help: remove this attribute diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed deleted file mode 100644 index e3e41eb9d0db1..0000000000000 --- a/tests/ui/generics/generic-no-mangle.fixed +++ /dev/null @@ -1,157 +0,0 @@ -//@ run-rustfix -#![allow(dead_code, mismatched_lifetime_syntaxes)] -#![deny(no_mangle_generic_items)] - -pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled - -pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - -#[no_mangle] -pub fn baz(x: &i32) -> &i32 { x } - -#[no_mangle] -pub fn qux<'a>(x: &'a i32) -> &i32 { x } - -pub struct Foo; - -impl Foo { - - pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - #[no_mangle] - pub fn baz(x: &i32) -> &i32 { x } - - #[no_mangle] - pub fn qux<'a>(x: &'a i32) -> &i32 { x } -} - -trait Trait1 { - fn foo(); - extern "C" fn bar(); - fn baz(x: &i32) -> &i32; - fn qux<'a>(x: &'a i32) -> &i32; -} - -impl Trait1 for Foo { - - fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - #[no_mangle] - fn baz(x: &i32) -> &i32 { x } - - #[no_mangle] - fn qux<'a>(x: &'a i32) -> &i32 { x } -} - -trait Trait2 { - fn foo(); - fn foo2(); - extern "C" fn bar(); - fn baz(x: &i32) -> &i32; - fn qux<'a>(x: &'a i32) -> &i32; -} - -impl Trait2 for Foo { - - fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - fn foo2() {} //~ ERROR functions generic over types or consts must be mangled - - - extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - - fn baz(x: &i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled - - - fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled -} - -pub struct Bar(#[allow(dead_code)] T); - -impl Bar { - - pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - - pub fn baz() {} //~ ERROR functions generic over types or consts must be mangled -} - -impl Bar { - #[no_mangle] - pub fn qux() {} -} - -trait Trait3 { - fn foo(); - extern "C" fn bar(); - fn baz(); -} - -impl Trait3 for Bar { - - fn foo() {} //~ ERROR functions generic over types or consts must be mangled - - - extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled - - - fn baz() {} //~ ERROR functions generic over types or consts must be mangled -} - -pub struct Baz<'a>(#[allow(dead_code)] &'a i32); - -impl<'a> Baz<'a> { - #[no_mangle] - pub fn foo() {} - - #[no_mangle] - pub fn bar<'b>(x: &'b i32) -> &i32 { x } -} - -trait Trait4 { - fn foo(); - fn bar<'a>(x: &'a i32) -> &i32; -} - -impl Trait4 for Bar { - #[no_mangle] - fn foo() {} - - #[no_mangle] - fn bar<'b>(x: &'b i32) -> &i32 { x } -} - -impl<'a> Trait4 for Baz<'a> { - #[no_mangle] - fn foo() {} - - #[no_mangle] - fn bar<'b>(x: &'b i32) -> &i32 { x } -} - -trait Trait5 { - fn foo(); -} - -impl Trait5 for Foo { - #[no_mangle] - fn foo() {} -} - -impl Trait5 for Bar { - #[no_mangle] - fn foo() {} -} - -fn main() {} diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 085f8610a548e..b3313538a9905 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,6 +1,4 @@ -//@ run-rustfix #![allow(dead_code, mismatched_lifetime_syntaxes)] -#![deny(no_mangle_generic_items)] #[no_mangle] pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled @@ -14,6 +12,9 @@ pub fn baz(x: &i32) -> &i32 { x } #[no_mangle] pub fn qux<'a>(x: &'a i32) -> &i32 { x } +#[no_mangle] +pub fn generic_const() {} //~ ERROR functions generic over types or consts must be mangled + pub struct Foo; impl Foo { diff --git a/tests/ui/generics/generic-no-mangle.stderr b/tests/ui/generics/generic-no-mangle.stderr index 39fbe4dd76da1..4b267d0dcc55f 100644 --- a/tests/ui/generics/generic-no-mangle.stderr +++ b/tests/ui/generics/generic-no-mangle.stderr @@ -1,19 +1,13 @@ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:6:1 + --> $DIR/generic-no-mangle.rs:4:1 | LL | #[no_mangle] | ------------ help: remove this attribute LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/generic-no-mangle.rs:3:9 - | -LL | #![deny(no_mangle_generic_items)] - | ^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:9:1 + --> $DIR/generic-no-mangle.rs:7:1 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -21,7 +15,15 @@ LL | pub extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:21:5 + --> $DIR/generic-no-mangle.rs:16:1 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub fn generic_const() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:22:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -29,7 +31,7 @@ LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:24:5 + --> $DIR/generic-no-mangle.rs:25:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -37,7 +39,7 @@ LL | pub extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:42:5 + --> $DIR/generic-no-mangle.rs:43:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -45,7 +47,7 @@ LL | fn foo() {} | ^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:45:5 + --> $DIR/generic-no-mangle.rs:46:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -53,7 +55,7 @@ LL | extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:64:5 + --> $DIR/generic-no-mangle.rs:65:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -61,7 +63,7 @@ LL | fn foo() {} | ^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:67:5 + --> $DIR/generic-no-mangle.rs:68:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -69,7 +71,7 @@ LL | fn foo2() {} | ^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:70:5 + --> $DIR/generic-no-mangle.rs:71:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -77,7 +79,7 @@ LL | extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:73:5 + --> $DIR/generic-no-mangle.rs:74:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -85,7 +87,7 @@ LL | fn baz(x: &i32) -> &i32 { x } | ^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:76:5 + --> $DIR/generic-no-mangle.rs:77:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -93,7 +95,7 @@ LL | fn qux<'a>(x: &'a i32) -> &i32 { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:83:5 + --> $DIR/generic-no-mangle.rs:84:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -101,7 +103,7 @@ LL | pub fn foo() {} | ^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:86:5 + --> $DIR/generic-no-mangle.rs:87:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -109,7 +111,7 @@ LL | pub extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:89:5 + --> $DIR/generic-no-mangle.rs:90:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -117,7 +119,7 @@ LL | pub fn baz() {} | ^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:105:5 + --> $DIR/generic-no-mangle.rs:106:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -125,7 +127,7 @@ LL | fn foo() {} | ^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:108:5 + --> $DIR/generic-no-mangle.rs:109:5 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -133,12 +135,12 @@ LL | extern "C" fn bar() {} | ^^^^^^^^^^^^^^^^^^^ error: functions generic over types or consts must be mangled - --> $DIR/generic-no-mangle.rs:111:5 + --> $DIR/generic-no-mangle.rs:112:5 | LL | #[no_mangle] | ------------ help: remove this attribute LL | fn baz() {} | ^^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/lint/suggestions.fixed b/tests/ui/lint/suggestions.fixed index 698cc3f34499f..6fd991e60d4c4 100644 --- a/tests/ui/lint/suggestions.fixed +++ b/tests/ui/lint/suggestions.fixed @@ -9,7 +9,7 @@ //~^ HELP remove this attribute pub fn defiant(_t: T) {} -//~^ WARN functions generic over types or consts must be mangled +//~^ ERROR functions generic over types or consts must be mangled #[no_mangle] fn rio_grande() {} @@ -23,7 +23,7 @@ mod badlands { //~| HELP try a static value #[allow(dead_code)] // for rustfix pub fn val_jean() {} - //~^ WARN functions generic over types or consts must be mangled + //~^ ERROR functions generic over types or consts must be mangled //~| HELP remove this attribute // ... but we can suggest just-`pub` instead of restricted @@ -32,7 +32,7 @@ mod badlands { //~| HELP try a static value #[allow(dead_code)] // for rustfix pub(crate) fn crossfield() {} - //~^ WARN functions generic over types or consts must be mangled + //~^ ERROR functions generic over types or consts must be mangled //~| HELP remove this attribute } diff --git a/tests/ui/lint/suggestions.rs b/tests/ui/lint/suggestions.rs index 6e4c389a9c8c2..c2d422828649a 100644 --- a/tests/ui/lint/suggestions.rs +++ b/tests/ui/lint/suggestions.rs @@ -10,7 +10,7 @@ #[no_mangle] //~^ HELP remove this attribute pub fn defiant(_t: T) {} -//~^ WARN functions generic over types or consts must be mangled +//~^ ERROR functions generic over types or consts must be mangled #[no_mangle] fn rio_grande() {} @@ -24,7 +24,7 @@ mod badlands { //~| HELP try a static value #[allow(dead_code)] // for rustfix #[no_mangle] pub fn val_jean() {} - //~^ WARN functions generic over types or consts must be mangled + //~^ ERROR functions generic over types or consts must be mangled //~| HELP remove this attribute // ... but we can suggest just-`pub` instead of restricted @@ -33,7 +33,7 @@ mod badlands { //~| HELP try a static value #[allow(dead_code)] // for rustfix #[no_mangle] pub(crate) fn crossfield() {} - //~^ WARN functions generic over types or consts must be mangled + //~^ ERROR functions generic over types or consts must be mangled //~| HELP remove this attribute } diff --git a/tests/ui/lint/suggestions.stderr b/tests/ui/lint/suggestions.stderr index c6a7de51da2e6..68bf80e89e1bd 100644 --- a/tests/ui/lint/suggestions.stderr +++ b/tests/ui/lint/suggestions.stderr @@ -58,7 +58,7 @@ LL | #[no_mangle] const DISCOVERY: usize = 1; | = note: `#[deny(no_mangle_const_items)]` on by default -warning: functions generic over types or consts must be mangled +error: functions generic over types or consts must be mangled --> $DIR/suggestions.rs:12:1 | LL | #[no_mangle] @@ -66,8 +66,6 @@ LL | #[no_mangle] LL | LL | pub fn defiant(_t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(no_mangle_generic_items)]` on by default warning: the `warp_factor:` in this pattern is redundant --> $DIR/suggestions.rs:61:23 @@ -85,7 +83,7 @@ LL | #[no_mangle] pub const DAUNTLESS: bool = true; | | | help: try a static value: `pub static` -warning: functions generic over types or consts must be mangled +error: functions generic over types or consts must be mangled --> $DIR/suggestions.rs:26:18 | LL | #[no_mangle] pub fn val_jean() {} @@ -101,7 +99,7 @@ LL | #[no_mangle] pub(crate) const VETAR: bool = true; | | | help: try a static value: `pub static` -warning: functions generic over types or consts must be mangled +error: functions generic over types or consts must be mangled --> $DIR/suggestions.rs:35:18 | LL | #[no_mangle] pub(crate) fn crossfield() {} @@ -109,5 +107,5 @@ LL | #[no_mangle] pub(crate) fn crossfield() {} | | | help: remove this attribute -error: aborting due to 3 previous errors; 8 warnings emitted +error: aborting due to 6 previous errors; 5 warnings emitted diff --git a/tests/ui/reborrow/coerce-shared-associated-type-field.stderr b/tests/ui/reborrow/coerce-shared-associated-type-field.stderr index d533fa2eb8748..31b54e7ed6c9e 100644 --- a/tests/ui/reborrow/coerce-shared-associated-type-field.stderr +++ b/tests/ui/reborrow/coerce-shared-associated-type-field.stderr @@ -1,8 +1,14 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-associated-type-field.rs:27:10 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-associated-type-field.rs:27:1 | LL | impl<'a> CoerceShared> for MyMut<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^---------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 2 non-ZST reborrow data fields + | in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr b/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr index 0b0b7bf048591..62a73361b5cd9 100644 --- a/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr +++ b/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr @@ -1,12 +1,17 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-decl-macro-hygiene.rs:20:14 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-decl-macro-hygiene.rs:20:5 | LL | impl<'a> CoerceShared> for MyMut<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^---------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 2 non-ZST reborrow data fields + | in this `CoerceShared` implementation ... LL | my_macro!(field); | ---------------- in this macro invocation | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts = note: this error originates in the macro `my_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-field-lifetime-swap.rs b/tests/ui/reborrow/coerce-shared-field-lifetime-swap.rs index d4558dd35d775..9d102238467e6 100644 --- a/tests/ui/reborrow/coerce-shared-field-lifetime-swap.rs +++ b/tests/ui/reborrow/coerce-shared-field-lifetime-swap.rs @@ -12,10 +12,10 @@ impl Reborrow for MyMut<'_> {} #[derive(Copy, Clone)] struct MyRef<'a> { x: &'a (), + //~^ ERROR y: &'static (), } impl<'a> CoerceShared> for MyMut<'a> {} -//~^ ERROR fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-field-lifetime-swap.stderr b/tests/ui/reborrow/coerce-shared-field-lifetime-swap.stderr index bce87c68eb912..b6160ad40bcce 100644 --- a/tests/ui/reborrow/coerce-shared-field-lifetime-swap.stderr +++ b/tests/ui/reborrow/coerce-shared-field-lifetime-swap.stderr @@ -1,8 +1,14 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-field-lifetime-swap.rs:18:10 +error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field + --> $DIR/coerce-shared-field-lifetime-swap.rs:14:5 | +LL | x: &'static (), + | -------------- source field `x` has type `&'static ()` +... +LL | x: &'a (), + | ^^^^^^^^^ target field `x` has type `&'a ()` +... LL | impl<'a> CoerceShared> for MyMut<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------------------- required by this `CoerceShared` implementation error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-field-region-obligation.rs b/tests/ui/reborrow/coerce-shared-field-region-obligation.rs new file mode 100644 index 0000000000000..4a39301d6cd18 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-field-region-obligation.rs @@ -0,0 +1,32 @@ +#![feature(reborrow)] + +use std::marker::{CoerceShared, Reborrow}; + +struct FieldMut<'a, T> { + value: &'a mut T, +} + +impl<'a, T> Reborrow for FieldMut<'a, T> {} + +#[derive(Clone, Copy)] +struct FieldRef<'a, T> { + value: &'a T, +} + +impl<'a, T> CoerceShared> for FieldMut<'a, T> {} + +struct Source<'a> { + field: FieldMut<'a, &'a ()>, +} + +impl Reborrow for Source<'_> {} + +#[derive(Clone, Copy)] +struct Target<'a> { + field: FieldRef<'a, &'static ()>, +} + +impl<'a> CoerceShared> for Source<'a> {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-field-region-obligation.stderr b/tests/ui/reborrow/coerce-shared-field-region-obligation.stderr new file mode 100644 index 0000000000000..06b89073f49e1 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-field-region-obligation.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/coerce-shared-field-region-obligation.rs:29:1 + | +LL | impl<'a> CoerceShared> for Source<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `CoerceShared>` + found trait `CoerceShared>` +note: the lifetime `'a` as defined here... + --> $DIR/coerce-shared-field-region-obligation.rs:29:6 + | +LL | impl<'a> CoerceShared> for Source<'a> {} + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/reborrow/coerce-shared-field-relations.rs b/tests/ui/reborrow/coerce-shared-field-relations.rs index b2104efb6028d..3920f3eba7cb5 100644 --- a/tests/ui/reborrow/coerce-shared-field-relations.rs +++ b/tests/ui/reborrow/coerce-shared-field-relations.rs @@ -24,6 +24,7 @@ impl<'a, T> Reborrow for RenamedMut<'a, T> {} #[derive(Clone, Copy)] struct RenamedRef<'a, T> { target: &'a T, + //~^ ERROR } impl<'a, T> CoerceShared> for RenamedMut<'a, T> {} @@ -37,11 +38,11 @@ impl<'a, T> Reborrow for BadMut<'a, T> {} #[derive(Clone, Copy)] struct BadRef<'a, T> { value: &'a u32, + //~^ ERROR _marker: std::marker::PhantomData, } impl<'a, T> CoerceShared> for BadMut<'a, T> {} -//~^ ERROR fn good(_value: CustomRef<'_, u32>) {} diff --git a/tests/ui/reborrow/coerce-shared-field-relations.stderr b/tests/ui/reborrow/coerce-shared-field-relations.stderr index 033a29e1e554e..2a723f954490b 100644 --- a/tests/ui/reborrow/coerce-shared-field-relations.stderr +++ b/tests/ui/reborrow/coerce-shared-field-relations.stderr @@ -1,9 +1,23 @@ -error[E0277]: the trait bound `&'a mut T: CoerceShared<&'a u32>` is not satisfied - --> $DIR/coerce-shared-field-relations.rs:43:1 +error: implementing `CoerceShared` requires every target field to have a corresponding source field + --> $DIR/coerce-shared-field-relations.rs:26:5 | +LL | target: &'a T, + | ^^^^^^^^^^^^^ target field `target` has no corresponding source field +... +LL | impl<'a, T> CoerceShared> for RenamedMut<'a, T> {} + | ----------------- source type `RenamedMut` does not contain field `target` + +error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field + --> $DIR/coerce-shared-field-relations.rs:40:5 + | +LL | value: &'a mut T, + | ---------------- source field `value` has type `&'a mut T` +... +LL | value: &'a u32, + | ^^^^^^^^^^^^^^ target field `value` has type `&'a u32` +... LL | impl<'a, T> CoerceShared> for BadMut<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `CoerceShared<&'a u32>` is not implemented for `&'a mut T` + | ------------------------------------------------------------ required by this `CoerceShared` implementation -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/reborrow/coerce-shared-foreign-private-field.rs b/tests/ui/reborrow/coerce-shared-foreign-private-field.rs index 3adda6733e16f..66c8ece3bd43e 100644 --- a/tests/ui/reborrow/coerce-shared-foreign-private-field.rs +++ b/tests/ui/reborrow/coerce-shared-foreign-private-field.rs @@ -1,5 +1,3 @@ -//@ check-pass - //@ aux-build: reborrow_foreign_private.rs #![feature(reborrow)] @@ -16,5 +14,6 @@ struct LocalMut<'a> { impl<'a> Reborrow for LocalMut<'a> {} impl<'a> CoerceShared> for LocalMut<'a> {} +//~^ ERROR fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-foreign-private-field.stderr b/tests/ui/reborrow/coerce-shared-foreign-private-field.stderr new file mode 100644 index 0000000000000..a328084260d0d --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-foreign-private-field.stderr @@ -0,0 +1,10 @@ +error: implementing `CoerceShared` requires all target type fields to be accessible from the impl + --> $DIR/coerce-shared-foreign-private-field.rs:16:1 + | +LL | impl<'a> CoerceShared> for LocalMut<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^--------------^^^^^^^^^^^^^^^^^^^^^ + | | + | target type `ForeignRef` has inaccessible reborrow data fields + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.rs b/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.rs index 4a70fd49e38ff..a2b88af04eb50 100644 --- a/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.rs +++ b/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.rs @@ -1,5 +1,3 @@ -//@ check-pass - #![feature(reborrow)] use std::marker::{CoerceShared, PhantomData, Reborrow}; @@ -18,5 +16,6 @@ struct LocalPtrMut<'a>(*const i32, PhantomData<&'a ()>); impl<'a> Reborrow for LocalPtrMut<'a> {} impl<'a> CoerceShared> for LocalPtrMut<'a> {} +//~^ ERROR fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.stderr b/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.stderr new file mode 100644 index 0000000000000..b699e1affbc49 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.stderr @@ -0,0 +1,10 @@ +error: implementing `CoerceShared` requires all target type fields to be accessible from the impl + --> $DIR/coerce-shared-foreign-private-tuple-field.rs:18:1 + | +LL | impl<'a> CoerceShared> for LocalPtrMut<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | target type `ForeignPtrRef` has inaccessible reborrow data fields + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-generics.stderr b/tests/ui/reborrow/coerce-shared-generics.stderr index 72efdd475fc10..8e2e4e4485918 100644 --- a/tests/ui/reborrow/coerce-shared-generics.stderr +++ b/tests/ui/reborrow/coerce-shared-generics.stderr @@ -1,8 +1,18 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-generics.rs:26:38 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-generics.rs:26:1 | -LL | impl<'a, T, U: Copy, const N: usize> CoerceShared> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a, T, U: Copy, const N: usize> CoerceShared> + | ^ ---------------------- target type has 2 non-ZST reborrow data fields + | _| + | | +LL | | +LL | | for BufferMut<'a, T, U, N> + | | ---------------------- source type has 2 non-ZST reborrow data fields +LL | | { +LL | | } + | |_^ in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-lifetime-mismatch.rs b/tests/ui/reborrow/coerce-shared-lifetime-mismatch.rs index 90bb4be4c1894..b6b5471adb0fc 100644 --- a/tests/ui/reborrow/coerce-shared-lifetime-mismatch.rs +++ b/tests/ui/reborrow/coerce-shared-lifetime-mismatch.rs @@ -13,6 +13,7 @@ impl<'a> Reborrow for CustomMarker<'a> {} struct StaticMarkerRef<'a>(PhantomData<&'a ()>); impl<'a> CoerceShared> for CustomMarker<'a> {} +//~^ ERROR fn method(_a: StaticMarkerRef<'static>) {} diff --git a/tests/ui/reborrow/coerce-shared-lifetime-mismatch.stderr b/tests/ui/reborrow/coerce-shared-lifetime-mismatch.stderr index 337e4b6938944..7c2e3e22b0b51 100644 --- a/tests/ui/reborrow/coerce-shared-lifetime-mismatch.stderr +++ b/tests/ui/reborrow/coerce-shared-lifetime-mismatch.stderr @@ -1,5 +1,13 @@ +error: implementing `CoerceShared` requires source and target to use the same reborrow lifetime argument + --> $DIR/coerce-shared-lifetime-mismatch.rs:15:10 + | +LL | impl<'a> CoerceShared> for CustomMarker<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^ -- source reborrow lifetime + | | + | target reborrow lifetime + error[E0597]: `a` does not live long enough - --> $DIR/coerce-shared-lifetime-mismatch.rs:21:12 + --> $DIR/coerce-shared-lifetime-mismatch.rs:22:12 | LL | let a = CustomMarker(PhantomData); | - binding `a` declared here @@ -12,6 +20,6 @@ LL | LL | } | - `a` dropped here while still borrowed -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/reborrow/coerce-shared-missing-target-field.rs b/tests/ui/reborrow/coerce-shared-missing-target-field.rs index c528fb85340ac..edd843b041fa8 100644 --- a/tests/ui/reborrow/coerce-shared-missing-target-field.rs +++ b/tests/ui/reborrow/coerce-shared-missing-target-field.rs @@ -12,9 +12,9 @@ impl<'a, T> Reborrow for MissingSourceMut<'a, T> {} struct MissingSourceRef<'a, T> { value: &'a T, len: usize, + //~^ ERROR } impl<'a, T> CoerceShared> for MissingSourceMut<'a, T> {} -//~^ ERROR fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-missing-target-field.stderr b/tests/ui/reborrow/coerce-shared-missing-target-field.stderr index 15146341bc56c..148cf8addf0f9 100644 --- a/tests/ui/reborrow/coerce-shared-missing-target-field.stderr +++ b/tests/ui/reborrow/coerce-shared-missing-target-field.stderr @@ -1,8 +1,11 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-missing-target-field.rs:17:13 +error: implementing `CoerceShared` requires every target field to have a corresponding source field + --> $DIR/coerce-shared-missing-target-field.rs:14:5 | +LL | len: usize, + | ^^^^^^^^^^ target field `len` has no corresponding source field +... LL | impl<'a, T> CoerceShared> for MissingSourceMut<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------- source type `MissingSourceMut` does not contain field `len` error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-multi-non-zst.rs b/tests/ui/reborrow/coerce-shared-multi-non-zst.rs new file mode 100644 index 0000000000000..6625593a4b32e --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-multi-non-zst.rs @@ -0,0 +1,22 @@ +#![feature(reborrow)] +#![allow(dead_code)] + +use std::marker::{CoerceShared, Reborrow}; + +struct Source<'a> { + a: &'a mut u8, + b: u8, +} + +#[derive(Copy, Clone)] +struct Target<'a> { + a: &'a u8, + b: u8, +} + +impl Reborrow for Source<'_> {} + +impl<'a> CoerceShared> for Source<'a> {} +//~^ ERROR + +fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-multi-non-zst.stderr b/tests/ui/reborrow/coerce-shared-multi-non-zst.stderr new file mode 100644 index 0000000000000..231e33f259c63 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-multi-non-zst.stderr @@ -0,0 +1,14 @@ +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-multi-non-zst.rs:19:1 + | +LL | impl<'a> CoerceShared> for Source<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^----------^^^^^^----------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 2 non-ZST reborrow data fields + | in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.rs b/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.rs index a425ab5fd1ced..2a18d0dda06f0 100644 --- a/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.rs +++ b/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.rs @@ -1,5 +1,3 @@ -//@ check-pass - #![feature(reborrow)] use std::marker::{CoerceShared, Reborrow}; @@ -41,4 +39,18 @@ struct InnerLifetimeRef<'a> { impl<'a> CoerceShared> for InnerLifetimeMut<'a> {} +struct RejectedInnerLifetimeMut<'a> { + value: &'a mut &'a (), +} + +impl Reborrow for RejectedInnerLifetimeMut<'_> {} + +#[derive(Copy, Clone)] +struct RejectedInnerLifetimeRef<'a> { + value: &'a &'static (), + //~^ ERROR +} + +impl<'a> CoerceShared> for RejectedInnerLifetimeMut<'a> {} + fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.stderr b/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.stderr new file mode 100644 index 0000000000000..98ab275b31e48 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-mut-ref-field-validation.stderr @@ -0,0 +1,14 @@ +error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field + --> $DIR/coerce-shared-mut-ref-field-validation.rs:50:5 + | +LL | value: &'a mut &'a (), + | --------------------- source field `value` has type `&'a mut &'a ()` +... +LL | value: &'a &'static (), + | ^^^^^^^^^^^^^^^^^^^^^^ target field `value` has type `&'a &'static ()` +... +LL | impl<'a> CoerceShared> for RejectedInnerLifetimeMut<'a> {} + | --------------------------------------------------------------------------------------- required by this `CoerceShared` implementation + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-after-dead.stderr b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-after-dead.stderr index 70a0db88319a7..d0f2540ccbcff 100644 --- a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-after-dead.stderr +++ b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-after-dead.stderr @@ -1,8 +1,14 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-omitted-reborrow-field-after-dead.rs:31:13 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-omitted-reborrow-field-after-dead.rs:31:1 | LL | impl<'a, T> CoerceShared> for OmitMut<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^^^^--------------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 1 non-ZST reborrow data fields + | in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr index d718103c80e7f..ccc3054a1b0c8 100644 --- a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr +++ b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr @@ -1,8 +1,14 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-omitted-reborrow-field-locked.rs:30:13 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-omitted-reborrow-field-locked.rs:30:1 | LL | impl<'a, T> CoerceShared> for OmitMut<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^^^^--------------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 1 non-ZST reborrow data fields + | in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts error[E0506]: cannot assign to `*wrapped.extra.value` because it is borrowed --> $DIR/coerce-shared-omitted-reborrow-field-locked.rs:49:5 diff --git a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field.stderr b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field.stderr index c663576228f62..08ddea2329405 100644 --- a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field.stderr +++ b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field.stderr @@ -1,8 +1,14 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-omitted-reborrow-field.rs:31:13 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-omitted-reborrow-field.rs:31:1 | LL | impl<'a, T> CoerceShared> for OmitMut<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^^^^--------------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 1 non-ZST reborrow data fields + | in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-omitted-zst-field.rs b/tests/ui/reborrow/coerce-shared-omitted-zst-field.rs new file mode 100644 index 0000000000000..f74c914acd272 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-omitted-zst-field.rs @@ -0,0 +1,59 @@ +#![feature(reborrow)] +#![allow(dead_code)] + +use std::marker::{CoerceShared, PhantomData, Reborrow}; + +struct NonCopyZst; + +#[derive(Clone, Copy)] +struct CopyZst; + +struct ReborrowZst<'a>(PhantomData<&'a mut ()>); + +impl Reborrow for ReborrowZst<'_> {} + +struct Source<'a> { + value: &'a mut i32, + marker: NonCopyZst, + //~^ ERROR the trait bound `NonCopyZst: Copy` is not satisfied + //~| ERROR implementing `CoerceShared` requires source fields omitted from the target +} + +impl Reborrow for Source<'_> {} + +#[derive(Clone, Copy)] +struct Target<'a> { + value: &'a i32, +} + +impl<'a> CoerceShared> for Source<'a> {} + +struct CopyZstSource<'a> { + value: &'a mut i32, + marker: CopyZst, +} + +impl Reborrow for CopyZstSource<'_> {} + +#[derive(Clone, Copy)] +struct CopyZstTarget<'a> { + value: &'a i32, +} + +impl<'a> CoerceShared> for CopyZstSource<'a> {} + +struct ReborrowZstSource<'a> { + value: &'a mut i32, + marker: ReborrowZst<'a>, +} + +impl Reborrow for ReborrowZstSource<'_> {} + +#[derive(Clone, Copy)] +struct ReborrowZstTarget<'a> { + value: &'a i32, +} + +impl<'a> CoerceShared> for ReborrowZstSource<'a> {} + +fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-omitted-zst-field.stderr b/tests/ui/reborrow/coerce-shared-omitted-zst-field.stderr new file mode 100644 index 0000000000000..43a6705ce8688 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-omitted-zst-field.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `NonCopyZst: Copy` is not satisfied + --> $DIR/coerce-shared-omitted-zst-field.rs:17:5 + | +LL | marker: NonCopyZst, + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NonCopyZst` + | +help: consider annotating `NonCopyZst` with `#[derive(Copy)]` + | +LL + #[derive(Copy)] +LL | struct NonCopyZst; + | + +error: implementing `CoerceShared` requires source fields omitted from the target to be `Copy` or `Reborrow` + --> $DIR/coerce-shared-omitted-zst-field.rs:17:5 + | +LL | marker: NonCopyZst, + | ^^^^^^^^^^^^^^^^^^ source field `marker` has type `NonCopyZst` +... +LL | impl<'a> CoerceShared> for Source<'a> {} + | --------------------------------------------------- required by this `CoerceShared` implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/reborrow/coerce-shared-reordered-field.stderr b/tests/ui/reborrow/coerce-shared-reordered-field.stderr index e3cd68547c428..5469e5e3d9f49 100644 --- a/tests/ui/reborrow/coerce-shared-reordered-field.stderr +++ b/tests/ui/reborrow/coerce-shared-reordered-field.stderr @@ -1,8 +1,14 @@ -error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced - --> $DIR/coerce-shared-reordered-field.rs:19:10 +error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field + --> $DIR/coerce-shared-reordered-field.rs:19:1 | LL | impl<'a> CoerceShared> for ReorderMut<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^--------------^^^^^^--------------^^^ + | | | | + | | | source type has 2 non-ZST reborrow data fields + | | target type has 2 non-ZST reborrow data fields + | in this `CoerceShared` implementation + | + = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts error: aborting due to 1 previous error diff --git a/tests/ui/reborrow/coerce-shared-wrong-generic.rs b/tests/ui/reborrow/coerce-shared-wrong-generic.rs index 2dc818a7015b2..bbd9cfebcd9e8 100644 --- a/tests/ui/reborrow/coerce-shared-wrong-generic.rs +++ b/tests/ui/reborrow/coerce-shared-wrong-generic.rs @@ -12,10 +12,10 @@ impl<'a, T, U> Reborrow for GenericMut<'a, T, U> {} #[derive(Clone, Copy)] struct GenericRef<'a, T, U> { value: &'a U, + //~^ ERROR marker: PhantomData, } impl<'a, T, U> CoerceShared> for GenericMut<'a, T, U> {} -//~^ ERROR fn main() {} diff --git a/tests/ui/reborrow/coerce-shared-wrong-generic.stderr b/tests/ui/reborrow/coerce-shared-wrong-generic.stderr index d0031a7c8a99e..b037106ebb619 100644 --- a/tests/ui/reborrow/coerce-shared-wrong-generic.stderr +++ b/tests/ui/reborrow/coerce-shared-wrong-generic.stderr @@ -1,9 +1,14 @@ -error[E0277]: the trait bound `&'a mut T: CoerceShared<&'a U>` is not satisfied - --> $DIR/coerce-shared-wrong-generic.rs:18:1 +error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field + --> $DIR/coerce-shared-wrong-generic.rs:14:5 | +LL | value: &'a mut T, + | ---------------- source field `value` has type `&'a mut T` +... +LL | value: &'a U, + | ^^^^^^^^^^^^ target field `value` has type `&'a U` +... LL | impl<'a, T, U> CoerceShared> for GenericMut<'a, T, U> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `CoerceShared<&'a U>` is not implemented for `&'a mut T` + | ----------------------------------------------------------------------------- required by this `CoerceShared` implementation error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`.