mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #135715 - matthiaskrgr:rollup-9a18sxj, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #135641 ([rustdoc] Replace module list items `ul`/`li` with `dl`/`dd`/`dt` elements) - #135703 (Disallow `A { .. }` if `A` has no fields) - #135705 (Consolidate ad-hoc MIR lints into real pass-manager-based MIR lints) - #135708 (Some random compiler nits) Failed merges: - #135685 (Remove unused `item-row` CSS class) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
98572840b6
@ -1991,18 +1991,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
adt_ty: Ty<'tcx>,
|
||||
expected: Expectation<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
path_span: Span,
|
||||
variant: &'tcx ty::VariantDef,
|
||||
hir_fields: &'tcx [hir::ExprField<'tcx>],
|
||||
base_expr: &'tcx hir::StructTailExpr<'tcx>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let adt_ty = self.try_structurally_resolve_type(span, adt_ty);
|
||||
let adt_ty = self.try_structurally_resolve_type(path_span, adt_ty);
|
||||
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
|
||||
self.fudge_inference_if_ok(|| {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?;
|
||||
ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?;
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
return Err(TypeError::Mismatch);
|
||||
}
|
||||
@ -2012,11 +2012,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
});
|
||||
if let Some(adt_ty_hint) = adt_ty_hint {
|
||||
// re-link the variables that the fudging above can create.
|
||||
self.demand_eqtype(span, adt_ty_hint, adt_ty);
|
||||
self.demand_eqtype(path_span, adt_ty_hint, adt_ty);
|
||||
}
|
||||
|
||||
let ty::Adt(adt, args) = adt_ty.kind() else {
|
||||
span_bug!(span, "non-ADT passed to check_expr_struct_fields");
|
||||
span_bug!(path_span, "non-ADT passed to check_expr_struct_fields");
|
||||
};
|
||||
let adt_kind = adt.adt_kind();
|
||||
|
||||
@ -2107,7 +2107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if adt_kind == AdtKind::Union && hir_fields.len() != 1 {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
path_span,
|
||||
E0784,
|
||||
"union expressions should have exactly one field",
|
||||
)
|
||||
@ -2167,6 +2167,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if variant.fields.is_empty() {
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
span,
|
||||
format!(
|
||||
"`{adt_ty}` has no fields, `..` needs at least one default field in the \
|
||||
struct definition",
|
||||
),
|
||||
);
|
||||
err.span_label(path_span, "this type has no fields");
|
||||
err.emit();
|
||||
}
|
||||
if !missing_mandatory_fields.is_empty() {
|
||||
let s = pluralize!(missing_mandatory_fields.len());
|
||||
let fields: Vec<_> =
|
||||
@ -2316,11 +2327,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.collect();
|
||||
|
||||
if !private_fields.is_empty() {
|
||||
self.report_private_fields(adt_ty, span, expr.span, private_fields, hir_fields);
|
||||
self.report_private_fields(
|
||||
adt_ty,
|
||||
path_span,
|
||||
expr.span,
|
||||
private_fields,
|
||||
hir_fields,
|
||||
);
|
||||
} else {
|
||||
self.report_missing_fields(
|
||||
adt_ty,
|
||||
span,
|
||||
path_span,
|
||||
remaining_fields,
|
||||
variant,
|
||||
hir_fields,
|
||||
|
@ -87,7 +87,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
|
||||
}
|
||||
|
||||
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
|
||||
typeck_with_fallback(tcx, def_id, None)
|
||||
typeck_with_inspect(tcx, def_id, None)
|
||||
}
|
||||
|
||||
/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation.
|
||||
@ -99,11 +99,11 @@ pub fn inspect_typeck<'tcx>(
|
||||
def_id: LocalDefId,
|
||||
inspect: ObligationInspector<'tcx>,
|
||||
) -> &'tcx ty::TypeckResults<'tcx> {
|
||||
typeck_with_fallback(tcx, def_id, Some(inspect))
|
||||
typeck_with_inspect(tcx, def_id, Some(inspect))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, inspector), ret)]
|
||||
fn typeck_with_fallback<'tcx>(
|
||||
fn typeck_with_inspect<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
inspector: Option<ObligationInspector<'tcx>>,
|
||||
|
@ -875,6 +875,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
});
|
||||
// Freeze definitions as we don't add new ones at this point.
|
||||
// We need to wait until now since we synthesize a by-move body
|
||||
// for all coroutine-closures.
|
||||
//
|
||||
// This improves performance by allowing lock-free access to them.
|
||||
tcx.untracked().definitions.freeze();
|
||||
|
||||
@ -887,7 +889,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
});
|
||||
});
|
||||
sess.time("MIR_effect_checking", || {
|
||||
for def_id in tcx.hir().body_owners() {
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
tcx.ensure().has_ffi_unwind_calls(def_id);
|
||||
|
||||
// If we need to codegen, ensure that we emit all errors from
|
||||
@ -898,15 +900,17 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
{
|
||||
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
if tcx.is_coroutine(def_id.to_def_id()) {
|
||||
tcx.ensure().mir_coroutine_witnesses(def_id);
|
||||
tcx.ensure().check_coroutine_obligations(
|
||||
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
|
||||
);
|
||||
}
|
||||
sess.time("coroutine_obligations", || {
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
if tcx.is_coroutine(def_id.to_def_id()) {
|
||||
tcx.ensure().mir_coroutine_witnesses(def_id);
|
||||
tcx.ensure().check_coroutine_obligations(
|
||||
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
sess.time("layout_testing", || layout_test::test_layout(tcx));
|
||||
|
@ -1164,8 +1164,7 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
/// Check whether the function has any recursion that could cause the inliner to trigger
|
||||
/// a cycle. Returns the call stack causing the cycle. The call stack does not contain the
|
||||
/// current function, just all intermediate functions.
|
||||
/// a cycle.
|
||||
query mir_callgraph_reachable(key: (ty::Instance<'tcx>, LocalDefId)) -> bool {
|
||||
fatal_cycle
|
||||
desc { |tcx|
|
||||
|
@ -118,12 +118,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
|
||||
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||
.label = use of extern static
|
||||
|
||||
mir_build_force_inline =
|
||||
`{$callee}` is incompatible with `#[rustc_force_inline]`
|
||||
.attr = annotation here
|
||||
.callee = `{$callee}` defined here
|
||||
.note = incompatible due to: {$reason}
|
||||
|
||||
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
|
||||
mir_build_initializing_type_with_requires_unsafe =
|
||||
@ -330,12 +324,6 @@ mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/s
|
||||
mir_build_type_not_structural_tip =
|
||||
the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
|
||||
mir_build_unconditional_recursion = function cannot return without recursing
|
||||
.label = cannot return without recursing
|
||||
.help = a `loop` may express intention better if this is on purpose
|
||||
|
||||
mir_build_unconditional_recursion_call_site_label = recursive call site
|
||||
|
||||
mir_build_union_field_requires_unsafe =
|
||||
access to union field is unsafe and requires unsafe block
|
||||
.note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
||||
|
@ -26,10 +26,8 @@ use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::lints;
|
||||
use crate::builder::expr::as_place::PlaceBuilder;
|
||||
use crate::builder::scope::DropKind;
|
||||
use crate::check_inline;
|
||||
|
||||
pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -48,7 +46,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
|
||||
}
|
||||
|
||||
/// Construct the MIR for a given `DefId`.
|
||||
pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
|
||||
pub(crate) fn build_mir<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
|
||||
let tcx = tcx.tcx;
|
||||
tcx.ensure_with_value().thir_abstract_const(def);
|
||||
if let Err(e) = tcx.check_match(def) {
|
||||
@ -80,9 +78,6 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx
|
||||
}
|
||||
};
|
||||
|
||||
lints::check(tcx, &body);
|
||||
check_inline::check_force_inline(tcx, &body);
|
||||
|
||||
// The borrow checker will replace all the regions here with its own
|
||||
// inference variables. There's no point having non-erased regions here.
|
||||
// The exception is `body.user_type_annotations`, which is used unmodified
|
||||
|
@ -11,16 +11,6 @@ use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_unconditional_recursion)]
|
||||
#[help]
|
||||
pub(crate) struct UnconditionalRecursion {
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
#[label(mir_build_unconditional_recursion_call_site_label)]
|
||||
pub(crate) call_sites: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)]
|
||||
pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
|
||||
@ -1107,15 +1097,3 @@ impl<'a> Subdiagnostic for Rust2024IncompatiblePatSugg<'a> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_force_inline)]
|
||||
#[note]
|
||||
pub(crate) struct InvalidForceInline {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label(mir_build_callee)]
|
||||
pub callee_span: Span,
|
||||
pub callee: String,
|
||||
pub reason: &'static str,
|
||||
}
|
||||
|
@ -15,11 +15,9 @@
|
||||
// "Go to file" feature to silently ignore all files in the module, probably
|
||||
// because it assumes that "build" is a build-output directory. See #134365.
|
||||
mod builder;
|
||||
pub mod check_inline;
|
||||
mod check_tail_calls;
|
||||
mod check_unsafety;
|
||||
mod errors;
|
||||
pub mod lints;
|
||||
mod thir;
|
||||
|
||||
use rustc_middle::util::Providers;
|
||||
@ -29,7 +27,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.check_match = thir::pattern::check_match;
|
||||
providers.lit_to_const = thir::constant::lit_to_const;
|
||||
providers.hooks.build_mir = builder::mir_build;
|
||||
providers.hooks.build_mir = builder::build_mir;
|
||||
providers.closure_saved_names_of_captured_variables =
|
||||
builder::closure_saved_names_of_captured_variables;
|
||||
providers.check_unsafety = check_unsafety::check_unsafety;
|
||||
|
@ -27,6 +27,12 @@ mir_transform_force_inline =
|
||||
.callee = `{$callee}` defined here
|
||||
.note = could not be inlined due to: {$reason}
|
||||
|
||||
mir_transform_force_inline_attr =
|
||||
`{$callee}` is incompatible with `#[rustc_force_inline]`
|
||||
.attr = annotation here
|
||||
.callee = `{$callee}` defined here
|
||||
.note = incompatible due to: {$reason}
|
||||
|
||||
mir_transform_force_inline_justification =
|
||||
`{$callee}` is required to be inlined to: {$sym}
|
||||
|
||||
@ -66,6 +72,12 @@ mir_transform_unaligned_packed_ref = reference to packed field is unaligned
|
||||
.note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
|
||||
.help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
|
||||
|
||||
mir_transform_unconditional_recursion = function cannot return without recursing
|
||||
.label = cannot return without recursing
|
||||
.help = a `loop` may express intention better if this is on purpose
|
||||
|
||||
mir_transform_unconditional_recursion_call_site_label = recursive call site
|
||||
|
||||
mir_transform_undefined_transmute = pointers cannot be transmuted to integers during const eval
|
||||
.note = at compile-time, pointers do not have an integer value
|
||||
.note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
|
||||
|
@ -10,25 +10,54 @@ use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::errors::UnconditionalRecursion;
|
||||
use crate::pass_manager::MirLint;
|
||||
|
||||
pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
check_call_recursion(tcx, body);
|
||||
pub(super) struct CheckCallRecursion;
|
||||
|
||||
impl<'tcx> MirLint<'tcx> for CheckCallRecursion {
|
||||
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let def_id = body.source.def_id().expect_local();
|
||||
|
||||
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
|
||||
// If this is trait/impl method, extract the trait's args.
|
||||
let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
|
||||
Some(trait_def_id) => {
|
||||
let trait_args_count = tcx.generics_of(trait_def_id).count();
|
||||
&GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
|
||||
}
|
||||
_ => &[],
|
||||
};
|
||||
|
||||
check_recursion(tcx, body, CallRecursion { trait_args })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_call_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let def_id = body.source.def_id().expect_local();
|
||||
/// Requires drop elaboration to have been performed.
|
||||
pub(super) struct CheckDropRecursion;
|
||||
|
||||
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
|
||||
// If this is trait/impl method, extract the trait's args.
|
||||
let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
|
||||
Some(trait_def_id) => {
|
||||
let trait_args_count = tcx.generics_of(trait_def_id).count();
|
||||
&GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
|
||||
impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
|
||||
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let def_id = body.source.def_id().expect_local();
|
||||
|
||||
// First check if `body` is an `fn drop()` of `Drop`
|
||||
if let DefKind::AssocFn = tcx.def_kind(def_id)
|
||||
&& let Some(trait_ref) =
|
||||
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
|
||||
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
|
||||
&& drop_trait == trait_ref.instantiate_identity().def_id
|
||||
// avoid erroneous `Drop` impls from causing ICEs below
|
||||
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
|
||||
&& sig.inputs().skip_binder().len() == 1
|
||||
{
|
||||
// It was. Now figure out for what type `Drop` is implemented and then
|
||||
// check for recursion.
|
||||
if let ty::Ref(_, dropped_ty, _) =
|
||||
tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
|
||||
{
|
||||
check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
|
||||
}
|
||||
_ => &[],
|
||||
};
|
||||
|
||||
check_recursion(tcx, body, CallRecursion { trait_args })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,30 +90,6 @@ fn check_recursion<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires drop elaboration to have been performed first.
|
||||
pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let def_id = body.source.def_id().expect_local();
|
||||
|
||||
// First check if `body` is an `fn drop()` of `Drop`
|
||||
if let DefKind::AssocFn = tcx.def_kind(def_id)
|
||||
&& let Some(trait_ref) =
|
||||
tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
|
||||
&& let Some(drop_trait) = tcx.lang_items().drop_trait()
|
||||
&& drop_trait == trait_ref.instantiate_identity().def_id
|
||||
// avoid erroneous `Drop` impls from causing ICEs below
|
||||
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
|
||||
&& sig.inputs().skip_binder().len() == 1
|
||||
{
|
||||
// It was. Now figure out for what type `Drop` is implemented and then
|
||||
// check for recursion.
|
||||
if let ty::Ref(_, dropped_ty, _) =
|
||||
tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
|
||||
{
|
||||
check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait TerminatorClassifier<'tcx> {
|
||||
fn is_recursive_terminator(
|
||||
&self,
|
@ -1,3 +1,6 @@
|
||||
//! Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its
|
||||
//! definition alone (irrespective of any specific caller).
|
||||
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
@ -6,30 +9,37 @@ use rustc_middle::ty;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::sym;
|
||||
|
||||
/// Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its
|
||||
/// definition alone (irrespective of any specific caller).
|
||||
pub(crate) fn check_force_inline<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let def_id = body.source.def_id();
|
||||
if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() {
|
||||
return;
|
||||
}
|
||||
let InlineAttr::Force { attr_span, .. } = tcx.codegen_fn_attrs(def_id).inline else {
|
||||
return;
|
||||
};
|
||||
use crate::pass_manager::MirLint;
|
||||
|
||||
if let Err(reason) =
|
||||
is_inline_valid_on_fn(tcx, def_id).and_then(|_| is_inline_valid_on_body(tcx, body))
|
||||
{
|
||||
tcx.dcx().emit_err(crate::errors::InvalidForceInline {
|
||||
attr_span,
|
||||
callee_span: tcx.def_span(def_id),
|
||||
callee: tcx.def_path_str(def_id),
|
||||
reason,
|
||||
});
|
||||
pub(super) struct CheckForceInline;
|
||||
|
||||
impl<'tcx> MirLint<'tcx> for CheckForceInline {
|
||||
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
||||
let def_id = body.source.def_id();
|
||||
if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() {
|
||||
return;
|
||||
}
|
||||
let InlineAttr::Force { attr_span, .. } = tcx.codegen_fn_attrs(def_id).inline else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Err(reason) =
|
||||
is_inline_valid_on_fn(tcx, def_id).and_then(|_| is_inline_valid_on_body(tcx, body))
|
||||
{
|
||||
tcx.dcx().emit_err(crate::errors::InvalidForceInline {
|
||||
attr_span,
|
||||
callee_span: tcx.def_span(def_id),
|
||||
callee: tcx.def_path_str(def_id),
|
||||
reason,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_inline_valid_on_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Result<(), &'static str> {
|
||||
pub(super) fn is_inline_valid_on_fn<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
) -> Result<(), &'static str> {
|
||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
if tcx.has_attr(def_id, sym::rustc_no_mir_inline) {
|
||||
return Err("#[rustc_no_mir_inline]");
|
||||
@ -65,7 +75,7 @@ pub fn is_inline_valid_on_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Result<(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_inline_valid_on_body<'tcx>(
|
||||
pub(super) fn is_inline_valid_on_body<'tcx>(
|
||||
_: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
) -> Result<(), &'static str> {
|
@ -9,6 +9,28 @@ use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_transform_unconditional_recursion)]
|
||||
#[help]
|
||||
pub(crate) struct UnconditionalRecursion {
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
#[label(mir_transform_unconditional_recursion_call_site_label)]
|
||||
pub(crate) call_sites: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_transform_force_inline_attr)]
|
||||
#[note]
|
||||
pub(crate) struct InvalidForceInline {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label(mir_transform_callee)]
|
||||
pub callee_span: Span,
|
||||
pub callee: String,
|
||||
pub reason: &'static str,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
pub(crate) enum ConstMutate {
|
||||
#[diag(mir_transform_const_modify)]
|
||||
|
@ -21,8 +21,8 @@ use tracing::{debug, instrument, trace, trace_span};
|
||||
use crate::cost_checker::CostChecker;
|
||||
use crate::deref_separator::deref_finder;
|
||||
use crate::simplify::simplify_cfg;
|
||||
use crate::util;
|
||||
use crate::validate::validate_types;
|
||||
use crate::{check_inline, util};
|
||||
|
||||
pub(crate) mod cycle;
|
||||
|
||||
@ -575,7 +575,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
|
||||
check_mir_is_available(inliner, caller_body, callsite.callee)?;
|
||||
|
||||
let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
|
||||
rustc_mir_build::check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?;
|
||||
check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?;
|
||||
check_codegen_attributes(inliner, callsite, callee_attrs)?;
|
||||
|
||||
let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
|
||||
@ -590,7 +590,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
|
||||
}
|
||||
|
||||
let callee_body = try_instance_mir(tcx, callsite.callee.def)?;
|
||||
rustc_mir_build::check_inline::is_inline_valid_on_body(tcx, callee_body)?;
|
||||
check_inline::is_inline_valid_on_body(tcx, callee_body)?;
|
||||
inliner.check_callee_mir_body(callsite, callee_body, callee_attrs)?;
|
||||
|
||||
let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(
|
||||
|
@ -114,6 +114,8 @@ declare_passes! {
|
||||
mod add_moves_for_packed_drops : AddMovesForPackedDrops;
|
||||
mod add_retag : AddRetag;
|
||||
mod add_subtyping_projections : Subtyper;
|
||||
mod check_inline : CheckForceInline;
|
||||
mod check_call_recursion : CheckCallRecursion, CheckDropRecursion;
|
||||
mod check_alignment : CheckAlignment;
|
||||
mod check_const_item_mutation : CheckConstItemMutation;
|
||||
mod check_packed_ref : CheckPackedRef;
|
||||
@ -375,6 +377,8 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
|
||||
&mut body,
|
||||
&[
|
||||
// MIR-level lints.
|
||||
&Lint(check_inline::CheckForceInline),
|
||||
&Lint(check_call_recursion::CheckCallRecursion),
|
||||
&Lint(check_packed_ref::CheckPackedRef),
|
||||
&Lint(check_const_item_mutation::CheckConstItemMutation),
|
||||
&Lint(function_item_references::FunctionItemReferences),
|
||||
@ -505,10 +509,6 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
|
||||
|
||||
run_analysis_to_runtime_passes(tcx, &mut body);
|
||||
|
||||
// Now that drop elaboration has been performed, we can check for
|
||||
// unconditional drop recursion.
|
||||
rustc_mir_build::lints::check_drop_recursion(tcx, &body);
|
||||
|
||||
tcx.alloc_steal_mir(body)
|
||||
}
|
||||
|
||||
@ -570,6 +570,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
// Calling this after `PostAnalysisNormalize` ensures that we don't deal with opaque types.
|
||||
&add_subtyping_projections::Subtyper,
|
||||
&elaborate_drops::ElaborateDrops,
|
||||
// Needs to happen after drop elaboration.
|
||||
&Lint(check_call_recursion::CheckDropRecursion),
|
||||
// This will remove extraneous landing pads which are no longer
|
||||
// necessary as well as forcing any call in a non-unwinding
|
||||
// function calling a possibly-unwinding function to abort the process.
|
||||
|
@ -140,10 +140,9 @@ macro_rules! item_template_methods {
|
||||
};
|
||||
}
|
||||
|
||||
const ITEM_TABLE_OPEN: &str = "<ul class=\"item-table\">";
|
||||
const ITEM_TABLE_CLOSE: &str = "</ul>";
|
||||
const ITEM_TABLE_ROW_OPEN: &str = "<li>";
|
||||
const ITEM_TABLE_ROW_CLOSE: &str = "</li>";
|
||||
const ITEM_TABLE_OPEN: &str = "<dl class=\"item-table\">";
|
||||
const REEXPORTS_TABLE_OPEN: &str = "<dl class=\"item-table reexports\">";
|
||||
const ITEM_TABLE_CLOSE: &str = "</dl>";
|
||||
|
||||
// A component in a `use` path, like `string` in std::string::ToString
|
||||
struct PathComponent {
|
||||
@ -400,37 +399,32 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
w.write_str(ITEM_TABLE_CLOSE);
|
||||
}
|
||||
last_section = Some(my_section);
|
||||
write_section_heading(
|
||||
w,
|
||||
my_section.name(),
|
||||
&cx.derive_id(my_section.id()),
|
||||
None,
|
||||
ITEM_TABLE_OPEN,
|
||||
);
|
||||
let section_id = my_section.id();
|
||||
let tag =
|
||||
if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN };
|
||||
write_section_heading(w, my_section.name(), &cx.derive_id(section_id), None, tag);
|
||||
}
|
||||
|
||||
match myitem.kind {
|
||||
clean::ExternCrateItem { ref src } => {
|
||||
use crate::html::format::anchor;
|
||||
|
||||
w.write_str(ITEM_TABLE_ROW_OPEN);
|
||||
match *src {
|
||||
Some(src) => write!(
|
||||
w,
|
||||
"<div class=\"item-name\"><code>{}extern crate {} as {};",
|
||||
"<dt><code>{}extern crate {} as {};",
|
||||
visibility_print_with_space(myitem, cx),
|
||||
anchor(myitem.item_id.expect_def_id(), src, cx),
|
||||
EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
|
||||
),
|
||||
None => write!(
|
||||
w,
|
||||
"<div class=\"item-name\"><code>{}extern crate {};",
|
||||
"<dt><code>{}extern crate {};",
|
||||
visibility_print_with_space(myitem, cx),
|
||||
anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
|
||||
),
|
||||
}
|
||||
w.write_str("</code></div>");
|
||||
w.write_str(ITEM_TABLE_ROW_CLOSE);
|
||||
w.write_str("</code></dt>");
|
||||
}
|
||||
|
||||
clean::ImportItem(ref import) => {
|
||||
@ -438,28 +432,20 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
|
||||
});
|
||||
|
||||
w.write_str(ITEM_TABLE_ROW_OPEN);
|
||||
let id = match import.kind {
|
||||
clean::ImportKind::Simple(s) => {
|
||||
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
|
||||
}
|
||||
clean::ImportKind::Glob => String::new(),
|
||||
};
|
||||
let (stab_tags_before, stab_tags_after) = if stab_tags.is_empty() {
|
||||
("", "")
|
||||
} else {
|
||||
("<div class=\"desc docblock-short\">", "</div>")
|
||||
};
|
||||
write!(
|
||||
w,
|
||||
"<div class=\"item-name\"{id}>\
|
||||
<code>{vis}{imp}</code>\
|
||||
</div>\
|
||||
{stab_tags_before}{stab_tags}{stab_tags_after}",
|
||||
"<dt{id}>\
|
||||
<code>{vis}{imp}</code>{stab_tags}\
|
||||
</dt>",
|
||||
vis = visibility_print_with_space(myitem, cx),
|
||||
imp = import.print(cx),
|
||||
);
|
||||
w.write_str(ITEM_TABLE_ROW_CLOSE);
|
||||
}
|
||||
|
||||
_ => {
|
||||
@ -492,22 +478,18 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
_ => "",
|
||||
};
|
||||
|
||||
w.write_str(ITEM_TABLE_ROW_OPEN);
|
||||
let docs =
|
||||
MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
|
||||
let (docs_before, docs_after) = if docs.is_empty() {
|
||||
("", "")
|
||||
} else {
|
||||
("<div class=\"desc docblock-short\">", "</div>")
|
||||
};
|
||||
let (docs_before, docs_after) =
|
||||
if docs.is_empty() { ("", "") } else { ("<dd>", "</dd>") };
|
||||
write!(
|
||||
w,
|
||||
"<div class=\"item-name\">\
|
||||
"<dt>\
|
||||
<a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
|
||||
{visibility_and_hidden}\
|
||||
{unsafety_flag}\
|
||||
{stab_tags}\
|
||||
</div>\
|
||||
</dt>\
|
||||
{docs_before}{docs}{docs_after}",
|
||||
name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
|
||||
visibility_and_hidden = visibility_and_hidden,
|
||||
@ -521,7 +503,6 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
);
|
||||
w.write_str(ITEM_TABLE_ROW_CLOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ h1, h2, h3, h4, h5, h6,
|
||||
.mobile-topbar,
|
||||
.search-input,
|
||||
.search-results .result-name,
|
||||
.item-name > a,
|
||||
.item-table dt > a,
|
||||
.out-of-band,
|
||||
.sub-heading,
|
||||
span.since,
|
||||
@ -385,11 +385,11 @@ details:not(.toggle) summary {
|
||||
code, pre, .code-header, .type-signature {
|
||||
font-family: "Source Code Pro", monospace;
|
||||
}
|
||||
.docblock code, .docblock-short code {
|
||||
.docblock code, .item-table dd code {
|
||||
border-radius: 3px;
|
||||
padding: 0 0.125em;
|
||||
}
|
||||
.docblock pre code, .docblock-short pre code {
|
||||
.docblock pre code, .item-table dd pre code {
|
||||
padding: 0;
|
||||
}
|
||||
pre {
|
||||
@ -887,13 +887,13 @@ both the code example and the line numbers, so we need to remove the radius in t
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.docblock-short {
|
||||
.item-table dd {
|
||||
overflow-wrap: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
/* Wrap non-pre code blocks (`text`) but not (```text```). */
|
||||
.docblock :not(pre) > code,
|
||||
.docblock-short code {
|
||||
.item-table dd code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
@ -938,7 +938,7 @@ rustdoc-toolbar {
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.docblock code, .docblock-short code,
|
||||
.docblock code, .item-table dd code,
|
||||
pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers {
|
||||
background-color: var(--code-block-background-color);
|
||||
border-radius: var(--code-block-border-radius);
|
||||
@ -964,7 +964,7 @@ pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers {
|
||||
background: var(--table-alt-row-background-color);
|
||||
}
|
||||
|
||||
.docblock .stab, .docblock-short .stab, .docblock p code {
|
||||
.docblock .stab, .item-table dd .stab, .docblock p code {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@ -1069,7 +1069,7 @@ because of the `[-]` element which would overlap with it. */
|
||||
.example-wrap .rust a:hover,
|
||||
.all-items a:hover,
|
||||
.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),
|
||||
.docblock-short a:not(.scrape-help):not(.tooltip):hover,
|
||||
.item-table dd a:not(.scrape-help):not(.tooltip):hover,
|
||||
.item-info a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@ -1102,20 +1102,17 @@ table,
|
||||
}
|
||||
|
||||
.item-table {
|
||||
display: table;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.item-table > li {
|
||||
display: table-row;
|
||||
}
|
||||
.item-table > li > div {
|
||||
display: table-cell;
|
||||
}
|
||||
.item-table > li > .item-name {
|
||||
.item-table > dt {
|
||||
padding-right: 1.25rem;
|
||||
}
|
||||
.item-table > dd {
|
||||
margin-inline-start: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.search-results-title {
|
||||
margin-top: 0;
|
||||
@ -1415,7 +1412,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
padding: 3px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.item-name .stab {
|
||||
.item-table dt .stab {
|
||||
margin-left: 0.3125em;
|
||||
}
|
||||
.stab {
|
||||
@ -2476,8 +2473,7 @@ in src-script.js and main.js
|
||||
}
|
||||
|
||||
/* Display an alternating layout on tablets and phones */
|
||||
.item-table, .item-row, .item-table > li, .item-table > li > div,
|
||||
.search-results > a, .search-results > a > div {
|
||||
.item-row, .search-results > a, .search-results > a > div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@ -2485,7 +2481,7 @@ in src-script.js and main.js
|
||||
.search-results > a {
|
||||
padding: 5px 0px;
|
||||
}
|
||||
.search-results > a > div.desc, .item-table > li > div.desc {
|
||||
.search-results > a > div.desc, .item-table dd {
|
||||
padding-left: 2em;
|
||||
}
|
||||
.search-results .result-name {
|
||||
@ -2546,12 +2542,20 @@ in src-script.js and main.js
|
||||
box-shadow: 0 0 4px var(--main-background-color);
|
||||
}
|
||||
|
||||
.item-table > li > .item-name {
|
||||
width: 33%;
|
||||
/* Since the screen is wide enough, we show items on their description on the same line. */
|
||||
.item-table:not(.reexports) {
|
||||
display: grid;
|
||||
grid-template-columns: 33% 67%;
|
||||
}
|
||||
.item-table > li > div {
|
||||
.item-table > dt, .item-table > dd {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.item-table > dt {
|
||||
grid-column-start: 1;
|
||||
}
|
||||
.item-table > dd {
|
||||
grid-column-start: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
@ -3,7 +3,7 @@
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/huge_amount_of_consts/index.html"
|
||||
|
||||
compare-elements-position-near-false: (
|
||||
"//ul[@class='item-table']/li[last()-1]",
|
||||
"//ul[@class='item-table']/li[last()-3]",
|
||||
"//dl[@class='item-table']/dt[last()-1]",
|
||||
"//dl[@class='item-table']/dt[last()-3]",
|
||||
{"y": 12},
|
||||
)
|
||||
|
@ -3,21 +3,21 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/short_docs/index.html"
|
||||
set-window-size: (1000, 600)
|
||||
|
||||
// First we ensure that there is only one `item-table`...
|
||||
assert-count: ("ul.item-table", 1)
|
||||
assert-count: ("dl.item-table", 1)
|
||||
// And only two items in it.
|
||||
assert-count: ("ul.item-table li", 2)
|
||||
assert-count: ("dl.item-table dt", 2)
|
||||
|
||||
// If they don't have the same height, then it means one of the two is on two lines whereas it
|
||||
// shouldn't!
|
||||
compare-elements-size: (
|
||||
".item-table .item-name a[href='fn.mult_vec_num.html']",
|
||||
".item-table .item-name a[href='fn.subt_vec_num.html']",
|
||||
".item-table dt a[href='fn.mult_vec_num.html']",
|
||||
".item-table dt a[href='fn.subt_vec_num.html']",
|
||||
["height"],
|
||||
)
|
||||
|
||||
// We also check that the `item-table` is taking the full width.
|
||||
compare-elements-size: (
|
||||
"#functions",
|
||||
"ul.item-table",
|
||||
"dl.item-table",
|
||||
["width"],
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
// This test ensures that <table> elements aren't display in items summary.
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/summary_table/index.html"
|
||||
// We check that we picked the right item first.
|
||||
assert-text: (".item-table .item-name", "Foo")
|
||||
assert-text: (".item-table dt", "Foo")
|
||||
// Then we check that its summary is empty.
|
||||
assert-false: ".item-table .desc"
|
||||
assert-false: ".item-table dd"
|
||||
|
@ -12,59 +12,59 @@ assert: (".stab.portability")
|
||||
|
||||
// make sure that deprecated and portability have the right colors
|
||||
assert-css: (
|
||||
".item-table .item-name .stab.deprecated",
|
||||
".item-table dt .stab.deprecated",
|
||||
{ "background-color": "#fff5d6" },
|
||||
)
|
||||
assert-css: (
|
||||
".item-table .item-name .stab.portability",
|
||||
".item-table dt .stab.portability",
|
||||
{ "background-color": "#fff5d6" },
|
||||
)
|
||||
|
||||
// table like view
|
||||
assert-css: (".desc.docblock-short", { "padding-left": "0px" })
|
||||
assert-css: ("dd", { "padding-left": "0px" })
|
||||
compare-elements-position-near: (
|
||||
"//*[@class='item-name']//a[normalize-space()='replaced_function']",
|
||||
".item-name .stab.deprecated",
|
||||
"//dt//a[normalize-space()='replaced_function']",
|
||||
"dt .stab.deprecated",
|
||||
{"y": 2},
|
||||
)
|
||||
// "Unix" part is on second line
|
||||
compare-elements-position-false: (
|
||||
".item-name .stab.deprecated",
|
||||
".item-name .stab.portability",
|
||||
"dt .stab.deprecated",
|
||||
"dt .stab.portability",
|
||||
["y"],
|
||||
)
|
||||
|
||||
// Ensure no wrap
|
||||
compare-elements-position: (
|
||||
"//*[@class='item-name']//a[normalize-space()='replaced_function']/..",
|
||||
"//*[@class='desc docblock-short'][normalize-space()='a thing with a label']",
|
||||
"//dt//a[normalize-space()='replaced_function']/..",
|
||||
"//dd[normalize-space()='a thing with a label']",
|
||||
["y"],
|
||||
)
|
||||
|
||||
// Mobile view
|
||||
set-window-size: (600, 600)
|
||||
// staggered layout with 2em spacing
|
||||
assert-css: (".desc.docblock-short", { "padding-left": "32px" })
|
||||
assert-css: ("dd", { "padding-left": "32px" })
|
||||
compare-elements-position-near: (
|
||||
"//*[@class='item-name']//a[normalize-space()='replaced_function']",
|
||||
".item-name .stab.deprecated",
|
||||
"//dt//a[normalize-space()='replaced_function']",
|
||||
"dt .stab.deprecated",
|
||||
{"y": 2},
|
||||
)
|
||||
compare-elements-position: (
|
||||
".item-name .stab.deprecated",
|
||||
".item-name .stab.portability",
|
||||
"dt .stab.deprecated",
|
||||
"dt .stab.portability",
|
||||
["y"],
|
||||
)
|
||||
|
||||
// Ensure wrap
|
||||
compare-elements-position-false: (
|
||||
"//*[@class='item-name']//a[normalize-space()='replaced_function']/..",
|
||||
"//*[@class='desc docblock-short'][normalize-space()='a thing with a label']",
|
||||
"//dt//a[normalize-space()='replaced_function']/..",
|
||||
"//dd[normalize-space()='a thing with a label']",
|
||||
["y"],
|
||||
)
|
||||
compare-elements-position-false: (
|
||||
".item-name .stab.deprecated",
|
||||
"//*[@class='desc docblock-short'][normalize-space()='a thing with a label']",
|
||||
"dt .stab.deprecated",
|
||||
"//dd[normalize-space()='a thing with a label']",
|
||||
["y"],
|
||||
)
|
||||
|
||||
|
@ -37,9 +37,9 @@ define-function: (
|
||||
},
|
||||
ALL,
|
||||
)
|
||||
move-cursor-to: ".desc a[href='long_code_block_link/index.html']"
|
||||
move-cursor-to: "dd a[href='long_code_block_link/index.html']"
|
||||
assert-css: (
|
||||
".desc a[href='long_code_block_link/index.html']",
|
||||
"dd a[href='long_code_block_link/index.html']",
|
||||
{"text-decoration": "underline solid " + |mod|},
|
||||
)
|
||||
},
|
||||
|
@ -1,67 +1,67 @@
|
||||
// This test checks that the correct font is used on module items (in index.html pages).
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-css: (
|
||||
".item-table .item-name > a",
|
||||
".item-table dt > a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
ALL,
|
||||
)
|
||||
assert-css: (
|
||||
".item-table .docblock-short",
|
||||
".item-table dd",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
ALL,
|
||||
)
|
||||
|
||||
// modules
|
||||
assert-css: (
|
||||
"#modules + .item-table .item-name a",
|
||||
"#modules + .item-table dt a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
)
|
||||
assert-css: (
|
||||
"#modules + .item-table .desc.docblock-short",
|
||||
"#modules + .item-table ",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
)
|
||||
// structs
|
||||
assert-css: (
|
||||
"#structs + .item-table .item-name a",
|
||||
"#structs + .item-table dt a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
)
|
||||
assert-css: (
|
||||
"#structs + .item-table .desc.docblock-short",
|
||||
"#structs + .item-table dd",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
)
|
||||
// enums
|
||||
assert-css: (
|
||||
"#enums + .item-table .item-name a",
|
||||
"#enums + .item-table dt a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
)
|
||||
assert-css: (
|
||||
"#enums + .item-table .desc.docblock-short",
|
||||
"#enums + .item-table dd",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
)
|
||||
// traits
|
||||
assert-css: (
|
||||
"#traits + .item-table .item-name a",
|
||||
"#traits + .item-table dt a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
)
|
||||
assert-css: (
|
||||
"#traits + .item-table .desc.docblock-short",
|
||||
"#traits + .item-table dd",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
)
|
||||
// functions
|
||||
assert-css: (
|
||||
"#functions + .item-table .item-name a",
|
||||
"#functions + .item-table dt a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
)
|
||||
assert-css: (
|
||||
"#functions + .item-table .desc.docblock-short",
|
||||
"#functions + .item-table dd",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
)
|
||||
// keywords
|
||||
assert-css: (
|
||||
"#keywords + .item-table .item-name a",
|
||||
"#keywords + .item-table dt a",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
)
|
||||
assert-css: (
|
||||
"#keywords + .item-table .desc.docblock-short",
|
||||
"#keywords + .item-table dd",
|
||||
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
|
||||
)
|
||||
|
@ -65,8 +65,8 @@ assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Functions")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Type Aliases")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(10)", "Unions")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(11)", "Keywords")
|
||||
assert-text: ("#structs + .item-table .item-name > a", "Foo")
|
||||
click: "#structs + .item-table .item-name > a"
|
||||
assert-text: ("#structs + .item-table dt > a", "Foo")
|
||||
click: "#structs + .item-table dt > a"
|
||||
|
||||
// PAGE: struct.Foo.html
|
||||
assert-count: (".sidebar .sidebar-crate", 1)
|
||||
@ -101,8 +101,8 @@ assert-text: (".sidebar-elems > section ul.block > li:nth-child(2)", "Structs")
|
||||
assert-text: (".sidebar-elems > section ul.block > li:nth-child(3)", "Traits")
|
||||
assert-text: (".sidebar-elems > section ul.block > li:nth-child(4)", "Functions")
|
||||
assert-text: (".sidebar-elems > section ul.block > li:nth-child(5)", "Type Aliases")
|
||||
assert-text: ("#functions + .item-table .item-name > a", "foobar")
|
||||
click: "#functions + .item-table .item-name > a"
|
||||
assert-text: ("#functions + .item-table dt > a", "foobar")
|
||||
click: "#functions + .item-table dt > a"
|
||||
|
||||
// PAGE: fn.foobar.html
|
||||
// In items containing no items (like functions or constants) and in modules, we have no
|
||||
@ -145,7 +145,7 @@ assert-text: (".sidebar-elems ul.block > li.current > a", "sub_sub_module")
|
||||
// We check that we don't have the crate list.
|
||||
assert-false: ".sidebar-elems .crate"
|
||||
assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
|
||||
assert-text: ("#functions + .item-table .item-name > a", "foo")
|
||||
assert-text: ("#functions + .item-table dt > a", "foo")
|
||||
|
||||
// Links to trait implementations in the sidebar should not wrap even if they are long.
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/struct.HasALongTraitWithParams.html"
|
||||
|
@ -17,7 +17,7 @@ define-function: (
|
||||
[theme, color],
|
||||
block {
|
||||
call-function: ("switch-theme", {"theme": |theme|})
|
||||
assert-css: (".item-name sup", {"color": |color|})
|
||||
assert-css: ("dt sup", {"color": |color|})
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -16,7 +16,7 @@ mod bar {
|
||||
//@ count - '//*[@id="main-content"]/h2' 2
|
||||
//@ has - '//*[@id="main-content"]/h2' 'Re-exports'
|
||||
//@ has - '//*[@id="main-content"]/h2' 'Modules'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="item-table"]//li//code' 'pub use foo::Foo as _;'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="item-table"]//li//code' 'pub use bar::Bar as _;'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="item-table reexports"]/dt//code' 'pub use foo::Foo as _;'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="item-table reexports"]/dt//code' 'pub use bar::Bar as _;'
|
||||
pub use foo::Foo as _;
|
||||
pub use bar::Bar as _;
|
||||
|
@ -9,7 +9,7 @@
|
||||
//@ has - '//*[@id="main-content"]/h2' 'Structs'
|
||||
//@ has - '//*[@id="main-content"]/h2' 'Re-exports'
|
||||
// The 3 re-exports.
|
||||
//@ count - '//*[@id="main-content"]//*[@class="item-table"]//li//code' 3
|
||||
//@ count - '//*[@id="main-content"]//*[@class="item-table reexports"]/dt//code' 3
|
||||
// The public struct.
|
||||
//@ count - '//*[@id="main-content"]//a[@class="struct"]' 1
|
||||
|
||||
|
@ -11,15 +11,15 @@ mod sub {
|
||||
pub fn public() {}
|
||||
}
|
||||
|
||||
//@ matches - '//*[@class="desc docblock-short"]' '^Displayed$'
|
||||
//@ matches - '//dd' '^Displayed$'
|
||||
/// Displayed
|
||||
#[doc(inline)]
|
||||
pub use crate::bar as Bar;
|
||||
//@ matches - '//*[@class="desc docblock-short"]' '^Hello\sDisplayed$'
|
||||
//@ matches - '//dd' '^Hello\sDisplayed$'
|
||||
#[doc(inline)]
|
||||
/// Hello
|
||||
pub use crate::Bar as Bar2;
|
||||
|
||||
//@ matches - '//*[@class="desc docblock-short"]' '^Public$'
|
||||
//@ matches - '//dd' '^Public$'
|
||||
/// Public
|
||||
pub use crate::sub::public as Public;
|
||||
|
@ -5,8 +5,8 @@
|
||||
#![no_core]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@class="item-name"]/*[@class="stab portability"]' 'foobar'
|
||||
//@ has - '//*[@class="item-name"]/*[@class="stab portability"]' 'bar'
|
||||
//@ has - '//dt/*[@class="stab portability"]' 'foobar'
|
||||
//@ has - '//dt/*[@class="stab portability"]' 'bar'
|
||||
|
||||
#[doc(cfg(feature = "foobar"))]
|
||||
mod imp_priv {
|
||||
|
@ -1,6 +1,5 @@
|
||||
//@ has deprecated/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \
|
||||
// 'Deprecated'
|
||||
//@ has - '//*[@class="desc docblock-short"]' 'Deprecated docs'
|
||||
//@ has deprecated/index.html '//dt/span[@class="stab deprecated"]' 'Deprecated'
|
||||
//@ has - '//dd' 'Deprecated docs'
|
||||
|
||||
//@ has deprecated/struct.S.html '//*[@class="stab deprecated"]' \
|
||||
// 'Deprecated since 1.0.0: text'
|
||||
@ -8,7 +7,7 @@
|
||||
#[deprecated(since = "1.0.0", note = "text")]
|
||||
pub struct S;
|
||||
|
||||
//@ matches deprecated/index.html '//*[@class="desc docblock-short"]' '^Docs'
|
||||
//@ matches deprecated/index.html '//dd' '^Docs'
|
||||
/// Docs
|
||||
pub struct T;
|
||||
|
||||
|
@ -5,19 +5,19 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@class="item-name"]/span[@title="Hidden item"]' '👻'
|
||||
//@ has - '//dt/span[@title="Hidden item"]' '👻'
|
||||
|
||||
//@ has - '//*[@id="reexport.hidden_reexport"]/code' '#[doc(hidden)] pub use hidden::inside_hidden as hidden_reexport;'
|
||||
#[doc(hidden)]
|
||||
pub use hidden::inside_hidden as hidden_reexport;
|
||||
|
||||
//@ has - '//*[@class="item-name"]/a[@class="trait"]' 'TraitHidden'
|
||||
//@ has - '//dt/a[@class="trait"]' 'TraitHidden'
|
||||
//@ has 'foo/trait.TraitHidden.html'
|
||||
//@ has - '//code' '#[doc(hidden)] pub trait TraitHidden'
|
||||
#[doc(hidden)]
|
||||
pub trait TraitHidden {}
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="item-name"]/a[@class="trait"]' 'Trait'
|
||||
//@ has 'foo/index.html' '//dt/a[@class="trait"]' 'Trait'
|
||||
pub trait Trait {
|
||||
//@ has 'foo/trait.Trait.html'
|
||||
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0u32'
|
||||
@ -29,7 +29,7 @@ pub trait Trait {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="item-name"]/a[@class="struct"]' 'Struct'
|
||||
//@ has 'foo/index.html' '//dt/a[@class="struct"]' 'Struct'
|
||||
//@ has 'foo/struct.Struct.html'
|
||||
pub struct Struct {
|
||||
//@ has - '//*[@id="structfield.a"]/code' 'a: u32'
|
||||
@ -50,7 +50,7 @@ impl Trait for Struct {
|
||||
//@ has - '//*[@id="impl-TraitHidden-for-Struct"]/*[@class="code-header"]' 'impl TraitHidden for Struct'
|
||||
impl TraitHidden for Struct {}
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="item-name"]/a[@class="enum"]' 'HiddenEnum'
|
||||
//@ has 'foo/index.html' '//dt/a[@class="enum"]' 'HiddenEnum'
|
||||
//@ has 'foo/enum.HiddenEnum.html'
|
||||
//@ has - '//code' '#[doc(hidden)] pub enum HiddenEnum'
|
||||
#[doc(hidden)]
|
||||
@ -58,18 +58,18 @@ pub enum HiddenEnum {
|
||||
A,
|
||||
}
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="item-name"]/a[@class="enum"]' 'Enum'
|
||||
//@ has 'foo/index.html' '//dt/a[@class="enum"]' 'Enum'
|
||||
pub enum Enum {
|
||||
//@ has 'foo/enum.Enum.html' '//*[@id="variant.A"]/*[@class="code-header"]' 'A'
|
||||
#[doc(hidden)]
|
||||
A,
|
||||
}
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="item-name"]/a[@class="mod"]' 'hidden'
|
||||
//@ has 'foo/index.html' '//dt/a[@class="mod"]' 'hidden'
|
||||
#[doc(hidden)]
|
||||
pub mod hidden {
|
||||
//@ has 'foo/hidden/index.html'
|
||||
//@ has - '//*[@class="item-name"]/a[@class="fn"]' 'inside_hidden'
|
||||
//@ has - '//dt/a[@class="fn"]' 'inside_hidden'
|
||||
//@ has 'foo/hidden/fn.inside_hidden.html'
|
||||
pub fn inside_hidden() {}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub struct Portable;
|
||||
//@ has doc_cfg/unix_only/index.html \
|
||||
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
|
||||
// 'Available on Unix only.'
|
||||
//@ matches - '//*[@class="item-name"]//*[@class="stab portability"]' '\AARM\Z'
|
||||
//@ matches - '//dt//*[@class="stab portability"]' '\AARM\Z'
|
||||
//@ count - '//*[@class="stab portability"]' 2
|
||||
#[doc(cfg(unix))]
|
||||
pub mod unix_only {
|
||||
@ -42,7 +42,7 @@ pub mod unix_only {
|
||||
//@ has doc_cfg/wasi_only/index.html \
|
||||
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
|
||||
// 'Available on WASI only.'
|
||||
//@ matches - '//*[@class="item-name"]//*[@class="stab portability"]' '\AWebAssembly\Z'
|
||||
//@ matches - '//dt//*[@class="stab portability"]' '\AWebAssembly\Z'
|
||||
//@ count - '//*[@class="stab portability"]' 2
|
||||
#[doc(cfg(target_os = "wasi"))]
|
||||
pub mod wasi_only {
|
||||
@ -74,7 +74,7 @@ pub mod wasi_only {
|
||||
|
||||
// the portability header is different on the module view versus the full view
|
||||
//@ has doc_cfg/index.html
|
||||
//@ matches - '//*[@class="item-name"]//*[@class="stab portability"]' '\Aavx\Z'
|
||||
//@ matches - '//dt//*[@class="stab portability"]' '\Aavx\Z'
|
||||
|
||||
//@ has doc_cfg/fn.uses_target_feature.html
|
||||
//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
|
||||
|
@ -26,7 +26,7 @@ pub mod single_reexport {
|
||||
//@ has 'foo/single_reexport/index.html'
|
||||
|
||||
// First we check that we have 4 type aliases.
|
||||
//@ count - '//*[@id="main-content"]/*[@class="item-table"]//code' 4
|
||||
//@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 4
|
||||
|
||||
// Then we check that we have the correct link for each re-export.
|
||||
|
||||
@ -131,10 +131,10 @@ mod private {
|
||||
pub mod doc_hidden_reexport {
|
||||
//@ has 'foo/doc_hidden_reexport/index.html'
|
||||
// Ensure there is only one item in this page and that it's a struct.
|
||||
//@ count - '//*[@class="item-name"]' 1
|
||||
//@ count - '//dt' 1
|
||||
//@ has - '//a[@class="struct"]' 'Reexport'
|
||||
// Check that the `#[doc(hidden)]` re-export's attributes are not taken into account.
|
||||
//@ has - '//*[@class="desc docblock-short"]' 'Visible. Original.'
|
||||
//@ has - '//dd' 'Visible. Original.'
|
||||
/// Visible.
|
||||
pub use self::Bar3 as Reexport;
|
||||
/// Hidden.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="desc docblock-short"]' '–'
|
||||
//@ has 'foo/index.html' '//dd' '–'
|
||||
//@ has 'foo/struct.Bar.html' '//*[@class="docblock"]' '–'
|
||||
|
||||
/// --
|
||||
|
@ -2,8 +2,8 @@
|
||||
#![feature(doc_cfg)]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ matches '-' '//*[@class="item-name"]//*[@class="stab portability"]' '^sync$'
|
||||
//@ has '-' '//*[@class="item-name"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
|
||||
//@ matches '-' '//dt//*[@class="stab portability"]' '^sync$'
|
||||
//@ has '-' '//dt//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
|
||||
|
||||
//@ has 'foo/struct.Foo.html'
|
||||
//@ has '-' '//*[@class="stab portability"]' 'sync'
|
||||
|
@ -4,8 +4,8 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@class="desc docblock-short"]' 'hello bla'
|
||||
//@ !has - '//*[@class="desc docblock-short"]/sup' '1'
|
||||
//@ has - '//dd' 'hello bla'
|
||||
//@ !has - '//dd/sup' '1'
|
||||
|
||||
//@ has 'foo/struct.S.html'
|
||||
//@ has - '//*[@class="docblock"]//sup' '1'
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
// There are two items.
|
||||
//@ count - '//*[@class="item-table"]//div[@class="item-name"]' 2
|
||||
//@ count - '//*[@class="item-table"]/dt' 2
|
||||
// Only one of them should have an attribute.
|
||||
//@ count - '//*[@class="item-table"]//div[@class="item-name"]/*[@class="stab portability"]' 1
|
||||
//@ count - '//*[@class="item-table"]/dt/*[@class="stab portability"]' 1
|
||||
|
||||
mod a {
|
||||
#[doc(cfg(not(feature = "a")))]
|
||||
|
@ -6,9 +6,9 @@
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
// There are two items.
|
||||
//@ count - '//*[@class="item-table"]//div[@class="item-name"]' 2
|
||||
//@ count - '//*[@class="item-table"]/dt' 2
|
||||
// Only one of them should have an attribute.
|
||||
//@ count - '//*[@class="item-table"]//div[@class="item-name"]/*[@class="stab portability"]' 1
|
||||
//@ count - '//*[@class="item-table"]/dt/*[@class="stab portability"]' 1
|
||||
|
||||
mod a {
|
||||
#[cfg(not(feature = "a"))]
|
||||
|
@ -15,6 +15,6 @@ mod sub4 {
|
||||
pub use sub4::inner::*;
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//div[@class="desc docblock-short"]' '1'
|
||||
//@ !has - '//div[@class="desc docblock-short"]' '0'
|
||||
//@ has - '//dd' '1'
|
||||
//@ !has - '//dd' '0'
|
||||
fn main() { assert_eq!(X, 1); }
|
||||
|
@ -1,17 +1,17 @@
|
||||
//@ has 'glob_shadowing/index.html'
|
||||
//@ count - '//div[@class="item-name"]' 6
|
||||
//@ !has - '//div[@class="desc docblock-short"]' 'sub1::describe'
|
||||
//@ has - '//div[@class="desc docblock-short"]' 'sub2::describe'
|
||||
//@ count - '//dt' 6
|
||||
//@ !has - '//dd' 'sub1::describe'
|
||||
//@ has - '//dd' 'sub2::describe'
|
||||
|
||||
//@ !has - '//div[@class="desc docblock-short"]' 'sub1::describe2'
|
||||
//@ !has - '//dd' 'sub1::describe2'
|
||||
|
||||
//@ !has - '//div[@class="desc docblock-short"]' 'sub1::prelude'
|
||||
//@ has - '//div[@class="desc docblock-short"]' 'mod::prelude'
|
||||
//@ !has - '//dd' 'sub1::prelude'
|
||||
//@ has - '//dd' 'mod::prelude'
|
||||
|
||||
//@ has - '//div[@class="desc docblock-short"]' 'sub1::Foo (struct)'
|
||||
//@ has - '//div[@class="desc docblock-short"]' 'mod::Foo (function)'
|
||||
//@ has - '//dd' 'sub1::Foo (struct)'
|
||||
//@ has - '//dd' 'mod::Foo (function)'
|
||||
|
||||
//@ has - '//div[@class="desc docblock-short"]' 'sub4::inner::X'
|
||||
//@ has - '//dd' 'sub4::inner::X'
|
||||
|
||||
//@ has 'glob_shadowing/fn.describe.html'
|
||||
//@ has - '//div[@class="docblock"]' 'sub2::describe'
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
// There should be only `type A`.
|
||||
//@ count - '//*[@class="item-table"]//*[@class="item-name"]' 1
|
||||
//@ has - '//*[@class="item-name"]/a[@href="type.A.html"]' 'A'
|
||||
//@ count - '//*[@class="item-table"]//dt' 1
|
||||
//@ has - '//dt/a[@href="type.A.html"]' 'A'
|
||||
|
||||
mod foo {
|
||||
pub struct S;
|
||||
|
@ -9,7 +9,7 @@
|
||||
//@ count - '//*[@id="main-content"]/*[@class="section-header"]' 1
|
||||
//@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs'
|
||||
//@ has - '//*[@id="main-content"]//a[@href="struct.Reexport.html"]' 'Reexport'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="desc docblock-short"]' 'Visible. Original.'
|
||||
//@ has - '//*[@id="main-content"]//dd' 'Visible. Original.'
|
||||
|
||||
mod private {
|
||||
/// Original.
|
||||
|
@ -11,14 +11,14 @@ extern crate rustdoc_hidden;
|
||||
pub use rustdoc_hidden::Foo;
|
||||
|
||||
// Even if the foreign item has `doc(hidden)`, we should be able to inline it.
|
||||
//@ has - '//*[@class="item-name"]/a[@class="struct"]' 'Inlined'
|
||||
//@ has - '//dt/a[@class="struct"]' 'Inlined'
|
||||
#[doc(inline)]
|
||||
pub use rustdoc_hidden::Foo as Inlined;
|
||||
|
||||
// Even with this import, we should not see `Foo`.
|
||||
//@ count - '//*[@class="item-name"]' 4
|
||||
//@ has - '//*[@class="item-name"]/a[@class="struct"]' 'Bar'
|
||||
//@ has - '//*[@class="item-name"]/a[@class="fn"]' 'foo'
|
||||
//@ count - '//dt' 4
|
||||
//@ has - '//dt/a[@class="struct"]' 'Bar'
|
||||
//@ has - '//dt/a[@class="fn"]' 'foo'
|
||||
pub use rustdoc_hidden::*;
|
||||
|
||||
//@ has inline_hidden/fn.foo.html
|
||||
|
@ -6,10 +6,8 @@
|
||||
|
||||
extern crate macros;
|
||||
|
||||
//@ has foo/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \
|
||||
// Deprecated
|
||||
//@ has - '//*[@class="item-name"]/span[@class="stab unstable"]' \
|
||||
// Experimental
|
||||
//@ has foo/index.html '//dt/span[@class="stab deprecated"]' Deprecated
|
||||
//@ has - '//dt/span[@class="stab unstable"]' Experimental
|
||||
|
||||
//@ has foo/macro.my_macro.html
|
||||
//@ has - '//*[@class="docblock"]' 'docs for my_macro'
|
||||
|
@ -8,7 +8,7 @@
|
||||
//@ !matches internal/index.html \
|
||||
// '//*[@class="desc docblock-short"]/span[@class="stab internal"]' \
|
||||
// ''
|
||||
//@ matches - '//*[@class="desc docblock-short"]' 'Docs'
|
||||
//@ matches - '//dd' 'Docs'
|
||||
|
||||
//@ !has internal/struct.S.html '//*[@class="stab unstable"]' ''
|
||||
//@ !has internal/struct.S.html '//*[@class="stab internal"]' ''
|
||||
|
@ -32,8 +32,8 @@ pub mod subone {
|
||||
//@ has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo'
|
||||
//@ has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar'
|
||||
// Though there should be such links later
|
||||
//@ has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.foo.html"]' 'foo'
|
||||
//@ has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.bar.html"]' 'bar'
|
||||
//@ has - '//section[@id="main-content"]/dl[@class="item-table"]/dt/a[@class="fn"][@href="fn.foo.html"]' 'foo'
|
||||
//@ has - '//section[@id="main-content"]/dl[@class="item-table"]/dt/a[@class="fn"][@href="fn.bar.html"]' 'bar'
|
||||
/// See either [foo] or [bar].
|
||||
pub mod subtwo {
|
||||
|
||||
@ -71,8 +71,8 @@ pub mod subthree {
|
||||
// Next we go *deeper* - In order to ensure it's not just "this or parent"
|
||||
// we test `crate::` and a `super::super::...` chain
|
||||
//@ has foo/subfour/subfive/subsix/subseven/subeight/index.html
|
||||
//@ has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
|
||||
//@ has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
|
||||
//@ has - '//section[@id="main-content"]/dl[@class="item-table"]/dd//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
|
||||
//@ has - '//section[@id="main-content"]/dl[@class="item-table"]/dd//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
|
||||
pub mod subfour {
|
||||
pub mod subfive {
|
||||
pub mod subsix {
|
||||
|
@ -1 +1 @@
|
||||
<ul class="item-table"><li><div class="item-name"><a class="constant" href="constant.MY_CONSTANT.html" title="constant item_desc_list_at_start::MY_CONSTANT">MY_<wbr />CONSTANT</a></div><div class="desc docblock-short">Groups: <code>SamplePatternSGIS</code>, <code>SamplePatternEXT</code></div></li></ul>
|
||||
<dl class="item-table"><dt><a class="constant" href="constant.MY_CONSTANT.html" title="constant item_desc_list_at_start::MY_CONSTANT">MY_<wbr />CONSTANT</a></dt><dd>Groups: <code>SamplePatternSGIS</code>, <code>SamplePatternEXT</code></dd></dl>
|
@ -1,7 +1,8 @@
|
||||
//@ has item_desc_list_at_start/index.html
|
||||
//@ count - '//ul[@class="item-table"]/li/div/li' 0
|
||||
//@ count - '//ul[@class="item-table"]/li' 1
|
||||
//@ snapshot item-table - '//ul[@class="item-table"]'
|
||||
//@ count - '//dl[@class="item-table"]/dd//ul' 0
|
||||
//@ count - '//dl[@class="item-table"]/dd//li' 0
|
||||
//@ count - '//dl[@class="item-table"]/dd' 1
|
||||
//@ snapshot item-table - '//dl[@class="item-table"]'
|
||||
|
||||
// based on https://docs.rs/gl_constants/0.1.1/src/gl_constants/lib.rs.html#16
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
// https://github.com/rust-lang/rust/issues/106142
|
||||
#![crate_name="foo"]
|
||||
|
||||
//@ has 'foo/a/index.html'
|
||||
//@ count 'foo/a/index.html' '//ul[@class="item-table"]//li//a' 1
|
||||
|
||||
#![allow(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
pub mod a {
|
||||
/// [`m`]
|
||||
pub fn f() {}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! m {
|
||||
() => {};
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
//@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Functions'
|
||||
//@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Traits'
|
||||
// Checking that there are only three items.
|
||||
//@ count - '//*[@id="main-content"]//*[@class="item-name"]' 3
|
||||
//@ count - '//*[@id="main-content"]//dt' 3
|
||||
//@ has - '//*[@id="main-content"]//a[@href="struct.Bar.html"]' 'Bar'
|
||||
//@ has - '//*[@id="main-content"]//a[@href="fn.foo.html"]' 'foo'
|
||||
//@ has - '//*[@id="main-content"]//a[@href="trait.Foo.html"]' 'Foo'
|
||||
|
@ -5,8 +5,8 @@
|
||||
#![no_std]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@class="item-name"]/a[@class="type"]' 'AtomicU8'
|
||||
//@ has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8'
|
||||
//@ has - '//dt/a[@class="type"]' 'AtomicU8'
|
||||
//@ has - '//dt/a[@class="constant"]' 'AtomicU8'
|
||||
// We also ensure we don't have another item displayed.
|
||||
//@ count - '//*[@id="main-content"]/*[@class="section-header"]' 2
|
||||
//@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Type Aliases'
|
||||
|
@ -5,8 +5,8 @@
|
||||
#![no_std]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@class="item-name"]/a[@class="struct"]' 'AtomicU8'
|
||||
//@ has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8'
|
||||
//@ has - '//dt/a[@class="struct"]' 'AtomicU8'
|
||||
//@ has - '//dt/a[@class="constant"]' 'AtomicU8'
|
||||
// We also ensure we don't have another item displayed.
|
||||
//@ count - '//*[@id="main-content"]/*[@class="section-header"]' 2
|
||||
//@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs'
|
||||
|
@ -1,5 +1,5 @@
|
||||
// https://github.com/rust-lang/rust/issues/95873
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has foo/index.html "//*[@class='item-name']" "pub use ::std as x;"
|
||||
//@ has foo/index.html "//dt" "pub use ::std as x;"
|
||||
pub use ::std as x;
|
||||
|
@ -13,18 +13,18 @@ mod foo {
|
||||
}
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@class="item-name"]' 'BabarNon-lie'
|
||||
//@ has - '//dt' 'BabarNon-lie'
|
||||
#[cfg(not(feature = "lie"))]
|
||||
pub use crate::foo::Bar as Babar;
|
||||
|
||||
//@ has - '//*[@class="item-name"]' 'Babar2Non-cake'
|
||||
//@ has - '//dt' 'Babar2Non-cake'
|
||||
#[doc(cfg(not(feature = "cake")))]
|
||||
pub use crate::foo::Bar2 as Babar2;
|
||||
|
||||
//@ has - '//*[@class="item-table"]/li' 'pub use crate::Babar as Elephant;Non-robot'
|
||||
//@ has - '//*[@class="item-table reexports"]/dt' 'pub use crate::Babar as Elephant;Non-robot'
|
||||
#[cfg(not(feature = "robot"))]
|
||||
pub use crate::Babar as Elephant;
|
||||
|
||||
//@ has - '//*[@class="item-table"]/li' 'pub use crate::Babar2 as Elephant2;Non-cat'
|
||||
//@ has - '//*[@class="item-table reexports"]/dt' 'pub use crate::Babar2 as Elephant2;Non-cat'
|
||||
#[doc(cfg(not(feature = "cat")))]
|
||||
pub use crate::Babar2 as Elephant2;
|
||||
|
@ -8,13 +8,13 @@ extern crate reexport_check;
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use std::i32;
|
||||
//@ !has 'foo/index.html' '//code' 'pub use self::string::String;'
|
||||
//@ has 'foo/index.html' '//div[@class="item-name"]' 'String'
|
||||
//@ has 'foo/index.html' '//dt' 'String'
|
||||
pub use std::string::String;
|
||||
|
||||
// i32 is deprecated, String is not
|
||||
//@ count 'foo/index.html' '//span[@class="stab deprecated"]' 1
|
||||
|
||||
//@ has 'foo/index.html' '//div[@class="desc docblock-short"]' 'Docs in original'
|
||||
//@ has 'foo/index.html' '//dd' 'Docs in original'
|
||||
// this is a no-op, but shows what happens if there's an attribute that isn't a doc-comment
|
||||
#[doc(inline)]
|
||||
pub use reexport_check::S;
|
||||
|
@ -12,5 +12,5 @@ mod private_module {
|
||||
//@ has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
|
||||
pub use crate::private_module::Public as Foo;
|
||||
// Glob re-exports with no visible items should not be displayed.
|
||||
//@ count - '//*[@class="item-table"]/li' 1
|
||||
//@ count - '//*[@class="item-table reexports"]/dt' 1
|
||||
pub use crate::private_module::*;
|
||||
|
@ -25,5 +25,6 @@ pub mod a {
|
||||
//@ has - '//*[@id="main-content"]//*[@id="reexport.A"]' 'pub use self::a::A;'
|
||||
//@ has - '//*[@id="main-content"]//*[@id="reexport.B"]' 'pub use self::a::B;'
|
||||
// Should only contain "Modules" and "Re-exports".
|
||||
//@ count - '//*[@id="main-content"]//*[@class="item-table"]' 2
|
||||
//@ count - '//*[@id="main-content"]//*[@class="item-table"]' 1
|
||||
//@ count - '//*[@id="main-content"]//*[@class="item-table reexports"]' 1
|
||||
pub use self::a::{A, B};
|
||||
|
@ -5,7 +5,7 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has 'foo/index.html'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="item-name"]/a[@href="trait.Foo.html"]' 'Foo'
|
||||
//@ has - '//*[@id="main-content"]//dt/a[@href="trait.Foo.html"]' 'Foo'
|
||||
|
||||
//@ has 'foo/trait.Foo.html'
|
||||
//@ has - '//*[@id="main-content"]//*[@class="code-header"]' 'fn test()'
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has foo/index.html '//*[@class="desc docblock-short"]' 'fooo'
|
||||
//@ !has foo/index.html '//*[@class="desc docblock-short"]/h1' 'fooo'
|
||||
//@ has foo/index.html '//dd' 'fooo'
|
||||
//@ !has foo/index.html '//dd//h1' 'fooo'
|
||||
|
||||
//@ has foo/fn.foo.html '//h2[@id="fooo"]' 'fooo'
|
||||
//@ has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' '§'
|
||||
@ -10,8 +10,8 @@
|
||||
/// foo
|
||||
pub fn foo() {}
|
||||
|
||||
//@ has foo/index.html '//*[@class="desc docblock-short"]' 'mooood'
|
||||
//@ !has foo/index.html '//*[@class="desc docblock-short"]/h2' 'mooood'
|
||||
//@ has foo/index.html '//dd' 'mooood'
|
||||
//@ !has foo/index.html '//dd//h2' 'mooood'
|
||||
|
||||
//@ has foo/foo/index.html '//h3[@id="mooood"]' 'mooood'
|
||||
//@ has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' '§'
|
||||
@ -20,8 +20,7 @@ pub fn foo() {}
|
||||
/// foo mod
|
||||
pub mod foo {}
|
||||
|
||||
//@ has foo/index.html '//*[@class="desc docblock-short"]/a[@href=\
|
||||
// "https://nougat.world"]/code' 'nougat'
|
||||
//@ has foo/index.html '//dd/a[@href="https://nougat.world"]/code' 'nougat'
|
||||
|
||||
/// [`nougat`](https://nougat.world)
|
||||
pub struct Bar;
|
||||
|
@ -5,9 +5,9 @@
|
||||
#![stable(feature = "core", since = "1.6.0")]
|
||||
|
||||
//@ has stability/index.html
|
||||
//@ has - '//ul[@class="item-table"]/li[1]//a' AaStable
|
||||
//@ has - '//ul[@class="item-table"]/li[2]//a' ZzStable
|
||||
//@ has - '//ul[@class="item-table"]/li[3]//a' Unstable
|
||||
//@ has - '//dl[@class="item-table"]/dt[1]//a' AaStable
|
||||
//@ has - '//dl[@class="item-table"]/dt[2]//a' ZzStable
|
||||
//@ has - '//dl[@class="item-table"]/dt[3]//a' Unstable
|
||||
|
||||
#[stable(feature = "rust2", since = "2.2.2")]
|
||||
pub struct AaStable;
|
||||
|
@ -4,11 +4,9 @@
|
||||
#![unstable(feature = "test", issue = "32374")]
|
||||
#![crate_name="issue_32374"]
|
||||
|
||||
//@ matches issue_32374/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \
|
||||
// 'Deprecated'
|
||||
//@ matches issue_32374/index.html '//*[@class="item-name"]/span[@class="stab unstable"]' \
|
||||
// 'Experimental'
|
||||
//@ matches issue_32374/index.html '//*[@class="desc docblock-short"]/text()' 'Docs'
|
||||
//@ matches issue_32374/index.html '//dt/span[@class="stab deprecated"]' 'Deprecated'
|
||||
//@ matches issue_32374/index.html '//dt/span[@class="stab unstable"]' 'Experimental'
|
||||
//@ matches issue_32374/index.html '//dd/text()' 'Docs'
|
||||
|
||||
//@ has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' '👎'
|
||||
//@ has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' \
|
||||
|
@ -1,6 +1,6 @@
|
||||
// https://github.com/rust-lang/rust/issues/46377
|
||||
#![crate_name="foo"]
|
||||
|
||||
//@ has 'foo/index.html' '//*[@class="desc docblock-short"]' 'Check out this struct!'
|
||||
//@ has 'foo/index.html' '//dd' 'Check out this struct!'
|
||||
/// # Check out this struct!
|
||||
pub struct SomeStruct;
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH]::multiple_storage)) (after pass CheckPackedRef) at bb0[1]:
|
||||
error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH]::multiple_storage)) (after pass CheckForceInline) at bb0[1]:
|
||||
StorageLive(_1) which already has storage here
|
||||
--> $DIR/storage-live.rs:23:13
|
||||
|
|
||||
|
21
tests/ui/structs/default-field-values/empty-struct.rs
Normal file
21
tests/ui/structs/default-field-values/empty-struct.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![feature(default_field_values)]
|
||||
|
||||
// If an API wants users to always use `..` even if they specify all the fields, they should use a
|
||||
// sentinel field. As of now, that field can't be made private so it is only constructable with this
|
||||
// syntax, but this might change in the future.
|
||||
|
||||
struct A {}
|
||||
struct B();
|
||||
struct C;
|
||||
struct D {
|
||||
x: i32,
|
||||
}
|
||||
struct E(i32);
|
||||
|
||||
fn main() {
|
||||
let _ = A { .. }; //~ ERROR has no fields
|
||||
let _ = B { .. }; //~ ERROR has no fields
|
||||
let _ = C { .. }; //~ ERROR has no fields
|
||||
let _ = D { x: 0, .. };
|
||||
let _ = E { 0: 0, .. };
|
||||
}
|
26
tests/ui/structs/default-field-values/empty-struct.stderr
Normal file
26
tests/ui/structs/default-field-values/empty-struct.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error: `A` has no fields, `..` needs at least one default field in the struct definition
|
||||
--> $DIR/empty-struct.rs:16:17
|
||||
|
|
||||
LL | let _ = A { .. };
|
||||
| - ^^
|
||||
| |
|
||||
| this type has no fields
|
||||
|
||||
error: `B` has no fields, `..` needs at least one default field in the struct definition
|
||||
--> $DIR/empty-struct.rs:17:17
|
||||
|
|
||||
LL | let _ = B { .. };
|
||||
| - ^^
|
||||
| |
|
||||
| this type has no fields
|
||||
|
||||
error: `C` has no fields, `..` needs at least one default field in the struct definition
|
||||
--> $DIR/empty-struct.rs:18:17
|
||||
|
|
||||
LL | let _ = C { .. };
|
||||
| - ^^
|
||||
| |
|
||||
| this type has no fields
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user