1
Fork 0

Auto merge of #133006 - matthiaskrgr:rollup-dz6oiq5, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #126046 (Implement `mixed_integer_ops_unsigned_sub`)
 - #132302 (rustdoc: Treat declarative macros more like other item kinds)
 - #132842 (ABI checks: add support for tier2 arches)
 - #132995 (compiletest: Add ``exact-llvm-major-version`` directive)
 - #132996 (Trim extra space when suggesting removing bad `let`)
 - #132998 (Unvacation myself)
 - #133000 ([rustdoc] Fix duplicated footnote IDs)
 - #133001 (actually test next solver)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-11-14 01:15:35 +00:00
commit bd0826a452
34 changed files with 414 additions and 184 deletions

View file

@ -1,12 +1,19 @@
monomorphize_abi_error_disabled_vector_type_call =
ABI error: this function call uses a vector type that requires the `{$required_feature}` target feature, which is not enabled in the caller
this function call uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller
.label = function called here
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
monomorphize_abi_error_disabled_vector_type_def =
ABI error: this function definition uses a vector type that requires the `{$required_feature}` target feature, which is not enabled
this function definition uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled
.label = function defined here
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
monomorphize_abi_error_unsupported_vector_type_call =
this function call uses a SIMD vector type that is not currently supported with the chosen ABI
.label = function called here
monomorphize_abi_error_unsupported_vector_type_def =
this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
.label = function defined here
monomorphize_couldnt_dump_mono_stats =
unexpected error occurred while dumping monomorphization stats: {$error}

View file

@ -110,3 +110,17 @@ pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> {
pub span: Span,
pub required_feature: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(monomorphize_abi_error_unsupported_vector_type_def)]
pub(crate) struct AbiErrorUnsupportedVectorTypeDef {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(monomorphize_abi_error_unsupported_vector_type_call)]
pub(crate) struct AbiErrorUnsupportedVectorTypeCall {
#[label]
pub span: Span,
}

View file

@ -10,7 +10,10 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_target::abi::call::{FnAbi, PassMode};
use rustc_target::abi::{BackendRepr, RegKind};
use crate::errors::{AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef};
use crate::errors::{
AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef,
AbiErrorUnsupportedVectorTypeCall, AbiErrorUnsupportedVectorTypeDef,
};
fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
match mode {
@ -23,11 +26,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
}
}
/// Checks whether a certain function ABI is compatible with the target features currently enabled
/// for a certain function.
/// If not, `emit_err` is called, with `Some(feature)` if a certain feature should be enabled and
/// with `None` if no feature is known that would make the ABI compatible.
fn do_check_abi<'tcx>(
tcx: TyCtxt<'tcx>,
abi: &FnAbi<'tcx, Ty<'tcx>>,
target_feature_def: DefId,
mut emit_err: impl FnMut(&'static str),
mut emit_err: impl FnMut(Option<&'static str>),
) {
let Some(feature_def) = tcx.sess.target.features_for_correct_vector_abi() else {
return;
@ -40,7 +47,7 @@ fn do_check_abi<'tcx>(
let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
Some((_, feature)) => feature,
None => {
emit_err("<no available feature for this size>");
emit_err(None);
continue;
}
};
@ -48,7 +55,7 @@ fn do_check_abi<'tcx>(
if !tcx.sess.unstable_target_features.contains(&feature_sym)
&& !codegen_attrs.target_features.iter().any(|x| x.name == feature_sym)
{
emit_err(feature);
emit_err(Some(&feature));
}
}
}
@ -65,12 +72,21 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
};
do_check_abi(tcx, abi, instance.def_id(), |required_feature| {
let span = tcx.def_span(instance.def_id());
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorDisabledVectorTypeDef { span, required_feature },
);
if let Some(required_feature) = required_feature {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorDisabledVectorTypeDef { span, required_feature },
);
} else {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorUnsupportedVectorTypeDef { span },
);
}
})
}
@ -109,12 +125,21 @@ fn check_call_site_abi<'tcx>(
return;
};
do_check_abi(tcx, callee_abi, caller.def_id(), |required_feature| {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorDisabledVectorTypeCall { span, required_feature },
);
if let Some(required_feature) = required_feature {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorDisabledVectorTypeCall { span, required_feature },
);
} else {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorUnsupportedVectorTypeCall { span },
);
}
});
}

View file

@ -683,7 +683,9 @@ impl<'a> Parser<'a> {
})
{
self.bump();
self.dcx().emit_err(RemoveLet { span: lo });
// Trim extra space after the `let`
let span = lo.with_hi(self.token.span.lo());
self.dcx().emit_err(RemoveLet { span });
lo = self.token.span;
}

View file

@ -586,9 +586,20 @@ pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
// certain size to have their "proper" ABI on each architecture.
// Note that they must be kept sorted by vector size.
const X86_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
&[(128, "sse"), (256, "avx"), (512, "avx512f")];
&[(128, "sse"), (256, "avx"), (512, "avx512f")]; // FIXME: might need changes for AVX10.
const AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")];
// We might want to add "helium" too.
const ARM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")];
const POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "altivec")];
const WASM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "simd128")];
const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vector")];
const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
&[/*(64, "zvl64b"), */ (128, "v")];
// Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(128, "vis")*/];
impl super::spec::Target {
pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
match &*self.arch {
@ -613,8 +624,15 @@ impl super::spec::Target {
pub fn features_for_correct_vector_abi(&self) -> Option<&'static [(u64, &'static str)]> {
match &*self.arch {
"x86" | "x86_64" => Some(X86_FEATURES_FOR_CORRECT_VECTOR_ABI),
"aarch64" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI),
// FIXME: add support for non-tier1 architectures
"aarch64" | "arm64ec" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI),
"arm" => Some(ARM_FEATURES_FOR_CORRECT_VECTOR_ABI),
"powerpc" | "powerpc64" => Some(POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI),
"loongarch64" => Some(&[]), // on-stack ABI, so we complain about all by-val vectors
"riscv32" | "riscv64" => Some(RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI),
"wasm32" | "wasm64" => Some(WASM_FEATURES_FOR_CORRECT_VECTOR_ABI),
"s390x" => Some(S390X_FEATURES_FOR_CORRECT_VECTOR_ABI),
"sparc" | "sparc64" => Some(SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI),
// FIXME: add support for non-tier2 architectures
_ => None,
}
}

View file

@ -763,6 +763,33 @@ macro_rules! uint_impl {
}
}
/// Checked subtraction with a signed integer. Computes `self - rhs`,
/// returning `None` if overflow occurred.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(mixed_integer_ops_unsigned_sub)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(2), None);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(-2), Some(3));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_sub_signed(-4), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn checked_sub_signed(self, rhs: $SignedT) -> Option<Self> {
let (res, overflow) = self.overflowing_sub_signed(rhs);
if !overflow {
Some(res)
} else {
None
}
}
#[doc = concat!(
"Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
stringify!($SignedT), "`], returning `None` if overflow occurred."
@ -1793,6 +1820,35 @@ macro_rules! uint_impl {
intrinsics::saturating_sub(self, rhs)
}
/// Saturating integer subtraction. Computes `self` - `rhs`, saturating at
/// the numeric bounds instead of overflowing.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(mixed_integer_ops_unsigned_sub)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(2), 0);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(-2), 3);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_sub_signed(-4), ", stringify!($SelfT), "::MAX);")]
/// ```
#[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn saturating_sub_signed(self, rhs: $SignedT) -> Self {
let (res, overflow) = self.overflowing_sub_signed(rhs);
if !overflow {
res
} else if rhs < 0 {
Self::MAX
} else {
0
}
}
/// Saturating integer multiplication. Computes `self * rhs`,
/// saturating at the numeric bounds instead of overflowing.
///
@ -1926,6 +1982,27 @@ macro_rules! uint_impl {
intrinsics::wrapping_sub(self, rhs)
}
/// Wrapping (modular) subtraction with a signed integer. Computes
/// `self - rhs`, wrapping around at the boundary of the type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(mixed_integer_ops_unsigned_sub)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(2), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(-2), 3);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_sub_signed(-4), 1);")]
/// ```
#[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn wrapping_sub_signed(self, rhs: $SignedT) -> Self {
self.wrapping_sub(rhs as Self)
}
/// Wrapping (modular) multiplication. Computes `self *
/// rhs`, wrapping around at the boundary of the type.
///
@ -2378,6 +2455,32 @@ macro_rules! uint_impl {
(c, b || d)
}
/// Calculates `self` - `rhs` with a signed `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(mixed_integer_ops_unsigned_sub)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(2), (", stringify!($SelfT), "::MAX, true));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(-2), (3, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_sub_signed(-4), (1, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn overflowing_sub_signed(self, rhs: $SignedT) -> (Self, bool) {
let (res, overflow) = self.overflowing_sub(rhs as Self);
(res, overflow ^ (rhs < 0))
}
/// Computes the absolute difference between `self` and `other`.
///
/// # Examples

View file

@ -134,11 +134,7 @@ pub(crate) fn try_inline(
})
}
Res::Def(DefKind::Macro(kind), did) => {
let is_doc_hidden = cx.tcx.is_doc_hidden(did)
|| attrs_without_docs
.map(|(attrs, _)| attrs)
.is_some_and(|attrs| utils::attrs_have_doc_flag(attrs.iter(), sym::hidden));
let mac = build_macro(cx, did, name, import_def_id, kind, is_doc_hidden);
let mac = build_macro(cx, did, name, kind);
let type_kind = match kind {
MacroKind::Bang => ItemType::Macro,
@ -740,18 +736,14 @@ fn build_macro(
cx: &mut DocContext<'_>,
def_id: DefId,
name: Symbol,
import_def_id: Option<LocalDefId>,
macro_kind: MacroKind,
is_doc_hidden: bool,
) -> clean::ItemKind {
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
LoadedMacro::MacroDef { def, .. } => match macro_kind {
MacroKind::Bang => {
let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
clean::MacroItem(clean::Macro {
source: utils::display_macro_source(cx, name, &def, def_id, vis, is_doc_hidden),
})
}
MacroKind::Bang => clean::MacroItem(clean::Macro {
source: utils::display_macro_source(cx, name, &def),
macro_rules: def.macro_rules,
}),
MacroKind::Derive | MacroKind::Attr => {
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
}

View file

@ -2787,13 +2787,10 @@ fn clean_maybe_renamed_item<'tcx>(
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
ItemKind::Macro(macro_def, MacroKind::Bang) => {
let ty_vis = cx.tcx.visibility(def_id);
MacroItem(Macro {
// FIXME this shouldn't be false
source: display_macro_source(cx, name, macro_def, def_id, ty_vis, false),
})
}
ItemKind::Macro(macro_def, MacroKind::Bang) => MacroItem(Macro {
source: display_macro_source(cx, name, macro_def),
macro_rules: macro_def.macro_rules,
}),
ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
// proc macros can have a name set by attributes
ItemKind::Fn(ref sig, generics, body_id) => {

View file

@ -2543,6 +2543,8 @@ pub(crate) struct ImportSource {
#[derive(Clone, Debug)]
pub(crate) struct Macro {
pub(crate) source: String,
/// Whether the macro was defined via `macro_rules!` as opposed to `macro`.
pub(crate) macro_rules: bool,
}
#[derive(Clone, Debug)]

View file

@ -24,7 +24,6 @@ use crate::clean::{
clean_middle_ty, inline,
};
use crate::core::DocContext;
use crate::html::format::visibility_to_src_with_space;
#[cfg(test)]
mod tests;
@ -593,7 +592,7 @@ pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
/// Render a sequence of macro arms in a format suitable for displaying to the user
/// as part of an item declaration.
pub(super) fn render_macro_arms<'a>(
fn render_macro_arms<'a>(
tcx: TyCtxt<'_>,
matchers: impl Iterator<Item = &'a TokenTree>,
arm_delim: &str,
@ -614,9 +613,6 @@ pub(super) fn display_macro_source(
cx: &mut DocContext<'_>,
name: Symbol,
def: &ast::MacroDef,
def_id: DefId,
vis: ty::Visibility<DefId>,
is_doc_hidden: bool,
) -> String {
// Extract the spans of all matchers. They represent the "interface" of the macro.
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
@ -626,18 +622,13 @@ pub(super) fn display_macro_source(
} else {
if matchers.len() <= 1 {
format!(
"{vis}macro {name}{matchers} {{\n ...\n}}",
vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
"macro {name}{matchers} {{\n ...\n}}",
matchers = matchers
.map(|matcher| render_macro_matcher(cx.tcx, matcher))
.collect::<String>(),
)
} else {
format!(
"{vis}macro {name} {{\n{arms}}}",
vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
arms = render_macro_arms(cx.tcx, matchers, ","),
)
format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ","))
}
}
}

View file

@ -1615,47 +1615,6 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
})
}
/// This function is the same as print_with_space, except that it renders no links.
/// It's used for macros' rendered source view, which is syntax highlighted and cannot have
/// any HTML in it.
pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
visibility: Option<ty::Visibility<DefId>>,
tcx: TyCtxt<'tcx>,
item_did: DefId,
is_doc_hidden: bool,
) -> impl Display + 'a + Captures<'tcx> {
let vis: Cow<'static, str> = match visibility {
None => "".into(),
Some(ty::Visibility::Public) => "pub ".into(),
Some(ty::Visibility::Restricted(vis_did)) => {
// FIXME(camelid): This may not work correctly if `item_did` is a module.
// However, rustdoc currently never displays a module's
// visibility, so it shouldn't matter.
let parent_module = find_nearest_parent_module(tcx, item_did);
if vis_did.is_crate_root() {
"pub(crate) ".into()
} else if parent_module == Some(vis_did) {
// `pub(in foo)` where `foo` is the parent module
// is the same as no visibility modifier
"".into()
} else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent))
== Some(vis_did)
{
"pub(super) ".into()
} else {
format!("pub(in {}) ", tcx.def_path_str(vis_did)).into()
}
}
};
display_fn(move |f| {
if is_doc_hidden {
f.write_str("#[doc(hidden)] ")?;
}
f.write_str(&vis)
})
}
pub(crate) trait PrintWithSpace {
fn print_with_space(&self) -> &str;
}

View file

@ -58,13 +58,6 @@ pub(crate) fn render_example_with_highlighting(
write_footer(out, playground_button);
}
/// Highlights `src` as an item-decl, returning the HTML output.
pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) {
write!(out, "<pre class=\"rust item-decl\">");
write_code(out, src, None, None);
write!(out, "</pre>");
}
fn write_header(
out: &mut Buffer,
class: &str,

View file

@ -1333,12 +1333,14 @@ impl Markdown<'_> {
let mut s = String::with_capacity(md.len() * 3 / 2);
let p = HeadingLinks::new(p, None, ids, heading_offset);
let p = footnotes::Footnotes::new(p);
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
let p = TableWrapper::new(p);
let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
ids.handle_footnotes(|ids, existing_footnotes| {
let p = HeadingLinks::new(p, None, ids, heading_offset);
let p = footnotes::Footnotes::new(p, existing_footnotes);
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
let p = TableWrapper::new(p);
let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
});
s
}
@ -1367,13 +1369,13 @@ impl MarkdownWithToc<'_> {
let mut toc = TocBuilder::new();
{
ids.handle_footnotes(|ids, existing_footnotes| {
let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1);
let p = footnotes::Footnotes::new(p);
let p = footnotes::Footnotes::new(p, existing_footnotes);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
}
});
(toc.into_toc(), s)
}
@ -1401,13 +1403,15 @@ impl MarkdownItemInfo<'_> {
let mut s = String::with_capacity(md.len() * 3 / 2);
let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
let p = footnotes::Footnotes::new(p);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
let p = p.filter(|event| {
!matches!(event, Event::Start(Tag::Paragraph) | Event::End(TagEnd::Paragraph))
ids.handle_footnotes(|ids, existing_footnotes| {
let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
let p = footnotes::Footnotes::new(p, existing_footnotes);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
let p = p.filter(|event| {
!matches!(event, Event::Start(Tag::Paragraph) | Event::End(TagEnd::Paragraph))
});
html::push_html(&mut s, p);
});
html::push_html(&mut s, p);
s
}
@ -1882,6 +1886,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
#[derive(Clone, Default, Debug)]
pub struct IdMap {
map: FxHashMap<Cow<'static, str>, usize>,
existing_footnotes: usize,
}
// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
@ -1943,7 +1948,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
impl IdMap {
pub fn new() -> Self {
IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone() }
IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 }
}
pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
@ -1959,4 +1964,13 @@ impl IdMap {
self.map.insert(id.clone().into(), 1);
id
}
/// Method to handle `existing_footnotes` increment automatically (to prevent forgetting
/// about it).
pub(crate) fn handle_footnotes<F: FnOnce(&mut Self, &mut usize)>(&mut self, closure: F) {
let mut existing_footnotes = self.existing_footnotes;
closure(self, &mut existing_footnotes);
self.existing_footnotes = existing_footnotes;
}
}

View file

@ -8,36 +8,35 @@ use super::SpannedEvent;
/// Moves all footnote definitions to the end and add back links to the
/// references.
pub(super) struct Footnotes<'a, I> {
pub(super) struct Footnotes<'a, 'b, I> {
inner: I,
footnotes: FxIndexMap<String, FootnoteDef<'a>>,
existing_footnotes: &'b mut usize,
}
/// The definition of a single footnote.
struct FootnoteDef<'a> {
content: Vec<Event<'a>>,
/// The number that appears in the footnote reference and list.
id: u16,
id: usize,
}
impl<'a, I> Footnotes<'a, I> {
pub(super) fn new(iter: I) -> Self {
Footnotes { inner: iter, footnotes: FxIndexMap::default() }
impl<'a, 'b, I> Footnotes<'a, 'b, I> {
pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self {
Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes }
}
fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, u16) {
let new_id = self.footnotes.len() + 1;
fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) {
let new_id = self.footnotes.len() + 1 + *self.existing_footnotes;
let key = key.to_owned();
let FootnoteDef { content, id } = self
.footnotes
.entry(key)
.or_insert(FootnoteDef { content: Vec::new(), id: new_id as u16 });
let FootnoteDef { content, id } =
self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id });
// Don't allow changing the ID of existing entrys, but allow changing the contents.
(content, *id)
}
}
impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b, I> {
type Item = SpannedEvent<'a>;
fn next(&mut self) -> Option<Self::Item> {
@ -47,8 +46,13 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
// When we see a reference (to a footnote we may not know) the definition of,
// reserve a number for it, and emit a link to that number.
let (_, id) = self.get_entry(reference);
let reference =
format!("<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>", id);
let reference = format!(
"<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{1}</a></sup>",
id,
// Although the ID count is for the whole page, the footnote reference
// are local to the item so we make this ID "local" when displayed.
id - *self.existing_footnotes
);
return Some((Event::Html(reference.into()), range));
}
Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => {
@ -64,6 +68,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
// After all the markdown is emmited, emit an <hr> then all the footnotes
// in a list.
let defs: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect();
*self.existing_footnotes += defs.len();
let defs_html = render_footnotes_defs(defs);
return Some((Event::Html(defs_html.into()), 0..0));
} else {

View file

@ -76,9 +76,9 @@ pub(crate) struct Context<'tcx> {
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(not(windows), target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 184);
#[cfg(all(windows, target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 192);
#[cfg(all(windows, target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 200);
/// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> {

View file

@ -35,7 +35,6 @@ use crate::html::format::{
Buffer, Ending, PrintWithSpace, display_fn, join_with_double_colon, print_abi_with_space,
print_constness_with_space, print_where_clause, visibility_print_with_space,
};
use crate::html::highlight;
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
use crate::html::render::{document_full, document_item_info};
use crate::html::url_parts_builder::UrlPartsBuilder;
@ -1745,7 +1744,13 @@ fn item_variants(
}
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
highlight::render_item_decl_with_highlighting(&t.source, w);
wrap_item(w, |w| {
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
if !t.macro_rules {
write!(w, "{}", visibility_print_with_space(it, cx));
}
write!(w, "{}", Escape(&t.source));
});
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
}

View file

@ -25,6 +25,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"dont-check-failure-status",
"edition",
"error-pattern",
"exact-llvm-major-version",
"exec-env",
"failure-status",
"filecheck-flags",

View file

@ -1585,6 +1585,19 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
};
}
}
} else if let Some(version_string) =
config.parse_name_value_directive(line, "exact-llvm-major-version")
{
// Syntax is "exact-llvm-major-version: <version>"
let version = extract_llvm_version(&version_string);
if actual_version.major != version.major {
return IgnoreDecision::Ignore {
reason: format!(
"ignored when the actual LLVM major version is {}, but the test only targets major version {}",
actual_version.major, version.major
),
};
}
}
}
IgnoreDecision::Continue

View file

@ -284,6 +284,21 @@ fn llvm_version() {
let config: Config = cfg().llvm_version("10.0.0").build();
assert!(!check_ignore(&config, "//@ min-llvm-version: 9.0"));
let config: Config = cfg().llvm_version("10.0.0").build();
assert!(check_ignore(&config, "//@ exact-llvm-major-version: 9.0"));
let config: Config = cfg().llvm_version("9.0.0").build();
assert!(check_ignore(&config, "//@ exact-llvm-major-version: 10.0"));
let config: Config = cfg().llvm_version("10.0.0").build();
assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10.0"));
let config: Config = cfg().llvm_version("10.0.0").build();
assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10"));
let config: Config = cfg().llvm_version("10.6.2").build();
assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10"));
}
#[test]

View file

@ -2,8 +2,7 @@
//@ only-x86_64
// FIXME: Remove the `min-llvm-version`.
//@ revisions: NINETEEN TWENTY
//@[NINETEEN] min-llvm-version: 19
//@[NINETEEN] ignore-llvm-version: 20-99
//@[NINETEEN] exact-llvm-major-version: 19
//@[TWENTY] min-llvm-version: 20
//@ min-llvm-version: 19

View file

@ -48,6 +48,8 @@ mod a {
}
mod c {
//@ has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
// Regression test for <https://github.com/rust-lang/rust/issues/83000>:
//@ has - '//pre[@class="rust item-decl"]//a[@class="mod"]/@href' '../../index.html'
pub(in a) macro by_example_vis_named {
($foo:expr) => {}
}

View file

@ -0,0 +1,41 @@
// This test ensures that footnotes ID are not duplicated across an item page.
// This is a regression test for <https://github.com/rust-lang/rust/issues/131901>.
#![crate_name = "foo"]
//@ has 'foo/struct.Foo.html'
pub struct Foo;
impl Foo {
//@ has - '//a[@href="#fn1"]' '1'
//@ has - '//li[@id="fn1"]' 'Hiya'
//@ has - '//a[@href="#fn2"]' '2'
//@ has - '//li[@id="fn2"]' 'Tiya'
/// Link 1 [^1]
/// Link 1.1 [^2]
///
/// [^1]: Hiya
/// [^2]: Tiya
pub fn l1(){}
//@ has - '//a[@href="#fn3"]' '1'
//@ has - '//li[@id="fn3"]' 'Yiya'
//@ has - '//a[@href="#fn4"]' '2'
//@ has - '//li[@id="fn4"]' 'Biya'
/// Link 2 [^1]
/// Link 3 [^2]
///
/// [^1]: Yiya
/// [^2]: Biya
pub fn l2() {}
}
impl Foo {
//@ has - '//a[@href="#fn5"]' '1'
//@ has - '//li[@id="fn5"]' 'Ciya'
/// Link 3 [^1]
///
/// [^1]: Ciya
pub fn l3(){}
}

View file

@ -3,29 +3,17 @@
#![crate_name = "foo"]
//@ has 'foo/macro.todo.html'
//@ has - '//span[@class="macro"]' 'macro_rules!'
//@ hasraw - ' todo {'
//@ hasraw - '{ () =&gt; { ... }; ($('
//@ has - '//span[@class="macro-nonterminal"]' '$'
//@ has - '//span[@class="macro-nonterminal"]' 'arg'
//@ hasraw - ':tt)+'
//@ hasraw - ') =&gt; { ... }; }'
//@ has 'foo/macro.todo.html' '//pre' 'macro_rules! todo { \
// () => { ... }; \
// ($($arg:tt)+) => { ... }; \
// }'
pub use std::todo;
mod mod1 {
//@ has 'foo/macro.macro1.html'
//@ hasraw - 'macro_rules!'
//@ hasraw - 'macro1'
//@ hasraw - '{ () =&gt; { ... }; ($('
//@ has - '//span[@class="macro-nonterminal"]' '$'
//@ has - '//span[@class="macro-nonterminal"]' 'arg'
//@ hasraw - ':'
//@ hasraw - 'expr'
//@ hasraw - '),'
//@ hasraw - '+'
//@ hasraw - ') =&gt; { ... }; }'
//@ has 'foo/macro.macro1.html' '//pre' 'macro_rules! macro1 { \
// () => { ... }; \
// ($($arg:expr),+) => { ... }; \
// }'
#[macro_export]
macro_rules! macro1 {
() => {};

View file

@ -2,12 +2,12 @@ error: expected pattern, found `let`
--> $DIR/unnecessary-let.rs:2:9
|
LL | for let x of [1, 2, 3] {}
| ^^^
| ^^^^
|
help: remove the unnecessary `let` keyword
|
LL - for let x of [1, 2, 3] {}
LL + for x of [1, 2, 3] {}
LL + for x of [1, 2, 3] {}
|
error: missing `in` in `for` loop
@ -25,12 +25,12 @@ error: expected pattern, found `let`
--> $DIR/unnecessary-let.rs:7:9
|
LL | let 1 => {}
| ^^^
| ^^^^
|
help: remove the unnecessary `let` keyword
|
LL - let 1 => {}
LL + 1 => {}
LL + 1 => {}
|
error: aborting due to 3 previous errors

View file

@ -0,0 +1,19 @@
//@ needs-llvm-components: sparc
//@ compile-flags: --target=sparc-unknown-none-elf --crate-type=rlib
//@ build-pass
//@ ignore-pass (test emits codegen-time warnings)
#![no_core]
#![feature(no_core, lang_items, repr_simd)]
#![allow(improper_ctypes_definitions)]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
#[repr(simd)]
pub struct SimdVec([i32; 4]);
pub extern "C" fn pass_by_vec(_: SimdVec) {}
//~^ this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
//~| WARNING this was previously accepted by the compiler

View file

@ -0,0 +1,12 @@
warning: this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
--> $DIR/simd-abi-checks-empty-list.rs:17:1
|
LL | pub extern "C" fn pass_by_vec(_: SimdVec) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= note: `#[warn(abi_unsupported_vector_types)]` on by default
warning: 1 warning emitted

View file

@ -12,19 +12,19 @@ use std::arch::x86_64::*;
struct Wrapper(__m256);
unsafe extern "C" fn w(_: Wrapper) {
//~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
//~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
todo!()
}
unsafe extern "C" fn f(_: __m256) {
//~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
//~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
todo!()
}
unsafe extern "C" fn g() -> __m256 {
//~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
//~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
todo!()
}
@ -53,16 +53,16 @@ unsafe fn test() {
fn main() {
unsafe {
f(g());
//~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
//~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
//~^ WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
}
unsafe {
gavx(favx());
//~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
//~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
//~^ WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
}
@ -73,8 +73,8 @@ fn main() {
unsafe {
w(Wrapper(g()));
//~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
//~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
//~^ WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
}

View file

@ -1,4 +1,4 @@
warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:55:11
|
LL | f(g());
@ -9,7 +9,7 @@ LL | f(g());
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
= note: `#[warn(abi_unsupported_vector_types)]` on by default
warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:55:9
|
LL | f(g());
@ -19,7 +19,7 @@ LL | f(g());
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:63:14
|
LL | gavx(favx());
@ -29,7 +29,7 @@ LL | gavx(favx());
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:63:9
|
LL | gavx(favx());
@ -39,7 +39,7 @@ LL | gavx(favx());
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:75:19
|
LL | w(Wrapper(g()));
@ -49,7 +49,7 @@ LL | w(Wrapper(g()));
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:75:9
|
LL | w(Wrapper(g()));
@ -59,7 +59,7 @@ LL | w(Wrapper(g()));
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
--> $DIR/simd-abi-checks.rs:26:1
|
LL | unsafe extern "C" fn g() -> __m256 {
@ -69,7 +69,7 @@ LL | unsafe extern "C" fn g() -> __m256 {
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
--> $DIR/simd-abi-checks.rs:20:1
|
LL | unsafe extern "C" fn f(_: __m256) {
@ -79,7 +79,7 @@ LL | unsafe extern "C" fn f(_: __m256) {
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
--> $DIR/simd-abi-checks.rs:14:1
|
LL | unsafe extern "C" fn w(_: Wrapper) {

View file

@ -19,6 +19,6 @@ pub struct SseVector([i64; 2]);
#[no_mangle]
pub unsafe extern "C" fn f(_: SseVector) {
//~^ ABI error: this function definition uses a vector type that requires the `sse` target feature, which is not enabled
//~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `sse` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
}

View file

@ -1,4 +1,4 @@
warning: ABI error: this function definition uses a vector type that requires the `sse` target feature, which is not enabled
warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `sse` target feature, which is not enabled
--> $DIR/sse-abi-checks.rs:21:1
|
LL | pub unsafe extern "C" fn f(_: SseVector) {

View file

@ -1,5 +1,5 @@
warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/normalize-self-type-constrains-trait-args.rs:5:12
--> $DIR/normalize-self-type-constrains-trait-args.rs:8:12
|
LL | #![feature(lazy_type_alias)]
| ^^^^^^^^^^^^^^^

View file

@ -0,0 +1,11 @@
warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/normalize-self-type-constrains-trait-args.rs:8:12
|
LL | #![feature(lazy_type_alias)]
| ^^^^^^^^^^^^^^^
|
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,3 +1,6 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass
// This goal is also possible w/ a GAT, but lazy_type_alias

View file

@ -975,7 +975,6 @@ cc = ["@kobzol"]
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
"jieyouxu",
"jyn514",
"oli-obk",
]