Auto merge of #144360 - matthiaskrgr:rollup-b6ej0mm, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang/rust#144173 (Remove tidy checks for `tests/ui/issues/`) - rust-lang/rust#144234 (Fix broken TLS destructors on 32-bit win7) - rust-lang/rust#144239 (Clean `rustc/parse/src/lexer` to improve maintainability) - rust-lang/rust#144256 (Don't ICE on non-TypeId metadata within TypeId) - rust-lang/rust#144290 (update tests/ui/SUMMARY.md) - rust-lang/rust#144292 (mbe: Use concrete type for `get_unused_rule`) - rust-lang/rust#144298 (coverage: Enlarge empty spans during MIR instrumentation, not codegen) - rust-lang/rust#144311 (Add powerpc64le-unknown-linux-musl to CI rustc targets) - rust-lang/rust#144315 (bootstrap: add package.json and package-lock.json to dist tarball) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
29a58723b0
25 changed files with 221 additions and 1428 deletions
|
|
@ -39,7 +39,10 @@ impl Coords {
|
|||
/// or other expansions), and if it does happen then skipping a span or function is
|
||||
/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid.
|
||||
pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> {
|
||||
let span = ensure_non_empty_span(source_map, span)?;
|
||||
if span.is_empty() {
|
||||
debug_assert!(false, "can't make coords from empty span: {span:?}");
|
||||
return None;
|
||||
}
|
||||
|
||||
let lo = span.lo();
|
||||
let hi = span.hi();
|
||||
|
|
@ -70,29 +73,6 @@ pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span)
|
|||
})
|
||||
}
|
||||
|
||||
fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
|
||||
if !span.is_empty() {
|
||||
return Some(span);
|
||||
}
|
||||
|
||||
// The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
|
||||
source_map
|
||||
.span_to_source(span, |src, start, end| try {
|
||||
// Adjusting span endpoints by `BytePos(1)` is normally a bug,
|
||||
// but in this case we have specifically checked that the character
|
||||
// we're skipping over is one of two specific ASCII characters, so
|
||||
// adjusting by exactly 1 byte is correct.
|
||||
if src.as_bytes().get(end).copied() == Some(b'{') {
|
||||
Some(span.with_hi(span.hi() + BytePos(1)))
|
||||
} else if start > 0 && src.as_bytes()[start - 1] == b'}' {
|
||||
Some(span.with_lo(span.lo() - BytePos(1)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
|
||||
/// If `llvm-cov` sees a source region that is improperly ordered (end < start),
|
||||
/// it will immediately exit with a fatal error. To prevent that from happening,
|
||||
/// discard regions that are improperly ordered, or might be interpreted in a
|
||||
|
|
|
|||
|
|
@ -1000,7 +1000,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
ptr: Pointer<Option<M::Provenance>>,
|
||||
) -> InterpResult<'tcx, (Ty<'tcx>, u64)> {
|
||||
let (alloc_id, offset, _meta) = self.ptr_get_alloc_id(ptr, 0)?;
|
||||
let GlobalAlloc::TypeId { ty } = self.tcx.global_alloc(alloc_id) else {
|
||||
let Some(GlobalAlloc::TypeId { ty }) = self.tcx.try_get_global_alloc(alloc_id) else {
|
||||
throw_ub_format!("invalid `TypeId` value: not all bytes carry type id metadata")
|
||||
};
|
||||
interp_ok((ty, offset.bytes()))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::any::Any;
|
||||
use std::default::Default;
|
||||
use std::iter;
|
||||
use std::path::Component::Prefix;
|
||||
|
|
@ -361,17 +362,13 @@ where
|
|||
}
|
||||
|
||||
/// Represents a thing that maps token trees to Macro Results
|
||||
pub trait TTMacroExpander {
|
||||
pub trait TTMacroExpander: Any {
|
||||
fn expand<'cx>(
|
||||
&self,
|
||||
ecx: &'cx mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
input: TokenStream,
|
||||
) -> MacroExpanderResult<'cx>;
|
||||
|
||||
fn get_unused_rule(&self, _rule_i: usize) -> Option<(&Ident, Span)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub type MacroExpanderResult<'cx> = ExpandResult<Box<dyn MacResult + 'cx>, ()>;
|
||||
|
|
@ -379,7 +376,7 @@ pub type MacroExpanderResult<'cx> = ExpandResult<Box<dyn MacResult + 'cx>, ()>;
|
|||
pub type MacroExpanderFn =
|
||||
for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>;
|
||||
|
||||
impl<F> TTMacroExpander for F
|
||||
impl<F: 'static> TTMacroExpander for F
|
||||
where
|
||||
F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ mod placeholders;
|
|||
mod proc_macro_server;
|
||||
mod stats;
|
||||
|
||||
pub use mbe::macro_rules::compile_declarative_macro;
|
||||
pub use mbe::macro_rules::{MacroRulesMacroExpander, compile_declarative_macro};
|
||||
pub mod base;
|
||||
pub mod config;
|
||||
pub mod expand;
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ pub(super) struct MacroRule {
|
|||
rhs: mbe::TokenTree,
|
||||
}
|
||||
|
||||
struct MacroRulesMacroExpander {
|
||||
pub struct MacroRulesMacroExpander {
|
||||
node_id: NodeId,
|
||||
name: Ident,
|
||||
span: Span,
|
||||
|
|
@ -136,6 +136,14 @@ struct MacroRulesMacroExpander {
|
|||
rules: Vec<MacroRule>,
|
||||
}
|
||||
|
||||
impl MacroRulesMacroExpander {
|
||||
pub fn get_unused_rule(&self, rule_i: usize) -> Option<(&Ident, Span)> {
|
||||
// If the rhs contains an invocation like `compile_error!`, don't report it as unused.
|
||||
let rule = &self.rules[rule_i];
|
||||
if has_compile_error_macro(&rule.rhs) { None } else { Some((&self.name, rule.lhs_span)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TTMacroExpander for MacroRulesMacroExpander {
|
||||
fn expand<'cx>(
|
||||
&self,
|
||||
|
|
@ -154,12 +162,6 @@ impl TTMacroExpander for MacroRulesMacroExpander {
|
|||
&self.rules,
|
||||
))
|
||||
}
|
||||
|
||||
fn get_unused_rule(&self, rule_i: usize) -> Option<(&Ident, Span)> {
|
||||
// If the rhs contains an invocation like `compile_error!`, don't report it as unused.
|
||||
let rule = &self.rules[rule_i];
|
||||
if has_compile_error_macro(&rule.rhs) { None } else { Some((&self.name, rule.lhs_span)) }
|
||||
}
|
||||
}
|
||||
|
||||
struct DummyExpander(ErrorGuaranteed);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
|
||||
|
|
@ -83,8 +84,18 @@ pub(super) fn extract_refined_covspans<'tcx>(
|
|||
// Discard any span that overlaps with a hole.
|
||||
discard_spans_overlapping_holes(&mut covspans, &holes);
|
||||
|
||||
// Perform more refinement steps after holes have been dealt with.
|
||||
// Discard spans that overlap in unwanted ways.
|
||||
let mut covspans = remove_unwanted_overlapping_spans(covspans);
|
||||
|
||||
// For all empty spans, either enlarge them to be non-empty, or discard them.
|
||||
let source_map = tcx.sess.source_map();
|
||||
covspans.retain_mut(|covspan| {
|
||||
let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false };
|
||||
covspan.span = span;
|
||||
true
|
||||
});
|
||||
|
||||
// Merge covspans that can be merged.
|
||||
covspans.dedup_by(|b, a| a.merge_if_eligible(b));
|
||||
|
||||
code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
|
||||
|
|
@ -230,3 +241,26 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
|
|||
// - Both have the same start and span A extends further right
|
||||
.then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
|
||||
}
|
||||
|
||||
fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
|
||||
if !span.is_empty() {
|
||||
return Some(span);
|
||||
}
|
||||
|
||||
// The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
|
||||
source_map
|
||||
.span_to_source(span, |src, start, end| try {
|
||||
// Adjusting span endpoints by `BytePos(1)` is normally a bug,
|
||||
// but in this case we have specifically checked that the character
|
||||
// we're skipping over is one of two specific ASCII characters, so
|
||||
// adjusting by exactly 1 byte is correct.
|
||||
if src.as_bytes().get(end).copied() == Some(b'{') {
|
||||
Some(span.with_hi(span.hi() + BytePos(1)))
|
||||
} else if start > 0 && src.as_bytes()[start - 1] == b'}' {
|
||||
Some(span.with_lo(span.lo() - BytePos(1)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,23 +126,29 @@ pub(super) fn report_suspicious_mismatch_block(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn make_unclosed_delims_error(
|
||||
unmatched: UnmatchedDelim,
|
||||
psess: &ParseSess,
|
||||
) -> Option<Diag<'_>> {
|
||||
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
|
||||
// `unmatched_delims` only for error recovery in the `Parser`.
|
||||
let found_delim = unmatched.found_delim?;
|
||||
let mut spans = vec![unmatched.found_span];
|
||||
if let Some(sp) = unmatched.unclosed_span {
|
||||
spans.push(sp);
|
||||
};
|
||||
let err = psess.dcx().create_err(MismatchedClosingDelimiter {
|
||||
spans,
|
||||
delimiter: pprust::token_kind_to_string(&found_delim.as_close_token_kind()).to_string(),
|
||||
unmatched: unmatched.found_span,
|
||||
opening_candidate: unmatched.candidate_span,
|
||||
unclosed: unmatched.unclosed_span,
|
||||
});
|
||||
Some(err)
|
||||
pub(crate) fn make_errors_for_mismatched_closing_delims<'psess>(
|
||||
unmatcheds: &[UnmatchedDelim],
|
||||
psess: &'psess ParseSess,
|
||||
) -> Vec<Diag<'psess>> {
|
||||
unmatcheds
|
||||
.iter()
|
||||
.filter_map(|unmatched| {
|
||||
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
|
||||
// `unmatched_delims` only for error recovery in the `Parser`.
|
||||
let found_delim = unmatched.found_delim?;
|
||||
let mut spans = vec![unmatched.found_span];
|
||||
if let Some(sp) = unmatched.unclosed_span {
|
||||
spans.push(sp);
|
||||
};
|
||||
let err = psess.dcx().create_err(MismatchedClosingDelimiter {
|
||||
spans,
|
||||
delimiter: pprust::token_kind_to_string(&found_delim.as_close_token_kind())
|
||||
.to_string(),
|
||||
unmatched: unmatched.found_span,
|
||||
opening_candidate: unmatched.candidate_span,
|
||||
unclosed: unmatched.unclosed_span,
|
||||
});
|
||||
Some(err)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use diagnostics::make_unclosed_delims_error;
|
||||
use diagnostics::make_errors_for_mismatched_closing_delims;
|
||||
use rustc_ast::ast::{self, AttrStyle};
|
||||
use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
|
|
@ -71,27 +71,23 @@ pub(crate) fn lex_token_trees<'psess, 'src>(
|
|||
};
|
||||
let res = lexer.lex_token_trees(/* is_delimited */ false);
|
||||
|
||||
let mut unmatched_delims: Vec<_> = lexer
|
||||
.diag_info
|
||||
.unmatched_delims
|
||||
.into_iter()
|
||||
.filter_map(|unmatched_delim| make_unclosed_delims_error(unmatched_delim, psess))
|
||||
.collect();
|
||||
let mut unmatched_closing_delims: Vec<_> =
|
||||
make_errors_for_mismatched_closing_delims(&lexer.diag_info.unmatched_delims, psess);
|
||||
|
||||
match res {
|
||||
Ok((_open_spacing, stream)) => {
|
||||
if unmatched_delims.is_empty() {
|
||||
if unmatched_closing_delims.is_empty() {
|
||||
Ok(stream)
|
||||
} else {
|
||||
// Return error if there are unmatched delimiters or unclosed delimiters.
|
||||
Err(unmatched_delims)
|
||||
Err(unmatched_closing_delims)
|
||||
}
|
||||
}
|
||||
Err(errs) => {
|
||||
// We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
|
||||
// because the delimiter mismatch is more likely to be the root cause of error
|
||||
unmatched_delims.extend(errs);
|
||||
Err(unmatched_delims)
|
||||
unmatched_closing_delims.extend(errs);
|
||||
Err(unmatched_closing_delims)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,45 +51,6 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
|
|||
}
|
||||
}
|
||||
|
||||
fn eof_err(&mut self) -> Diag<'psess> {
|
||||
let msg = "this file contains an unclosed delimiter";
|
||||
let mut err = self.dcx().struct_span_err(self.token.span, msg);
|
||||
|
||||
let unclosed_delimiter_show_limit = 5;
|
||||
let len = usize::min(unclosed_delimiter_show_limit, self.diag_info.open_delimiters.len());
|
||||
for &(_, span) in &self.diag_info.open_delimiters[..len] {
|
||||
err.span_label(span, "unclosed delimiter");
|
||||
self.diag_info.unmatched_delims.push(UnmatchedDelim {
|
||||
found_delim: None,
|
||||
found_span: self.token.span,
|
||||
unclosed_span: Some(span),
|
||||
candidate_span: None,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some((_, span)) = self.diag_info.open_delimiters.get(unclosed_delimiter_show_limit)
|
||||
&& self.diag_info.open_delimiters.len() >= unclosed_delimiter_show_limit + 2
|
||||
{
|
||||
err.span_label(
|
||||
*span,
|
||||
format!(
|
||||
"another {} unclosed delimiters begin from here",
|
||||
self.diag_info.open_delimiters.len() - unclosed_delimiter_show_limit
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((delim, _)) = self.diag_info.open_delimiters.last() {
|
||||
report_suspicious_mismatch_block(
|
||||
&mut err,
|
||||
&self.diag_info,
|
||||
self.psess.source_map(),
|
||||
*delim,
|
||||
)
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
fn lex_token_tree_open_delim(
|
||||
&mut self,
|
||||
open_delim: Delimiter,
|
||||
|
|
@ -206,13 +167,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
|
|||
} else if let Some(glued) = self.token.glue(&next_tok) {
|
||||
self.token = glued;
|
||||
} else {
|
||||
let this_spacing = if next_tok.is_punct() {
|
||||
Spacing::Joint
|
||||
} else if next_tok == token::Eof {
|
||||
Spacing::Alone
|
||||
} else {
|
||||
Spacing::JointHidden
|
||||
};
|
||||
let this_spacing = self.calculate_spacing(&next_tok);
|
||||
break (this_spacing, next_tok);
|
||||
}
|
||||
};
|
||||
|
|
@ -223,23 +178,64 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
|
|||
// Cut-down version of `bump` used when the token kind is known in advance.
|
||||
fn bump_minimal(&mut self) -> Spacing {
|
||||
let (next_tok, is_next_tok_preceded_by_whitespace) = self.next_token_from_cursor();
|
||||
|
||||
let this_spacing = if is_next_tok_preceded_by_whitespace {
|
||||
Spacing::Alone
|
||||
} else {
|
||||
if next_tok.is_punct() {
|
||||
Spacing::Joint
|
||||
} else if next_tok == token::Eof {
|
||||
Spacing::Alone
|
||||
} else {
|
||||
Spacing::JointHidden
|
||||
}
|
||||
self.calculate_spacing(&next_tok)
|
||||
};
|
||||
|
||||
self.token = next_tok;
|
||||
this_spacing
|
||||
}
|
||||
|
||||
fn calculate_spacing(&self, next_tok: &Token) -> Spacing {
|
||||
if next_tok.is_punct() {
|
||||
Spacing::Joint
|
||||
} else if *next_tok == token::Eof {
|
||||
Spacing::Alone
|
||||
} else {
|
||||
Spacing::JointHidden
|
||||
}
|
||||
}
|
||||
|
||||
fn eof_err(&mut self) -> Diag<'psess> {
|
||||
const UNCLOSED_DELIMITER_SHOW_LIMIT: usize = 5;
|
||||
let msg = "this file contains an unclosed delimiter";
|
||||
let mut err = self.dcx().struct_span_err(self.token.span, msg);
|
||||
|
||||
let len = usize::min(UNCLOSED_DELIMITER_SHOW_LIMIT, self.diag_info.open_delimiters.len());
|
||||
for &(_, span) in &self.diag_info.open_delimiters[..len] {
|
||||
err.span_label(span, "unclosed delimiter");
|
||||
self.diag_info.unmatched_delims.push(UnmatchedDelim {
|
||||
found_delim: None,
|
||||
found_span: self.token.span,
|
||||
unclosed_span: Some(span),
|
||||
candidate_span: None,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some((_, span)) = self.diag_info.open_delimiters.get(UNCLOSED_DELIMITER_SHOW_LIMIT)
|
||||
&& self.diag_info.open_delimiters.len() >= UNCLOSED_DELIMITER_SHOW_LIMIT + 2
|
||||
{
|
||||
err.span_label(
|
||||
*span,
|
||||
format!(
|
||||
"another {} unclosed delimiters begin from here",
|
||||
self.diag_info.open_delimiters.len() - UNCLOSED_DELIMITER_SHOW_LIMIT
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((delim, _)) = self.diag_info.open_delimiters.last() {
|
||||
report_suspicious_mismatch_block(
|
||||
&mut err,
|
||||
&self.diag_info,
|
||||
self.psess.source_map(),
|
||||
*delim,
|
||||
)
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
fn close_delim_err(&mut self, delim: Delimiter) -> Diag<'psess> {
|
||||
// An unexpected closing delimiter (i.e., there is no matching opening delimiter).
|
||||
let token_str = token_to_string(&self.token);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! A bunch of methods and structures more or less related to resolving macros and
|
||||
//! interface provided by `Resolver` to macro expander.
|
||||
|
||||
use std::any::Any;
|
||||
use std::cell::Cell;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -13,10 +14,10 @@ use rustc_expand::base::{
|
|||
Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension,
|
||||
SyntaxExtensionKind,
|
||||
};
|
||||
use rustc_expand::compile_declarative_macro;
|
||||
use rustc_expand::expand::{
|
||||
AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
|
||||
};
|
||||
use rustc_expand::{MacroRulesMacroExpander, compile_declarative_macro};
|
||||
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||
use rustc_middle::middle::stability;
|
||||
|
|
@ -357,8 +358,12 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||
let SyntaxExtensionKind::LegacyBang(ref ext) = m.ext.kind else {
|
||||
continue;
|
||||
};
|
||||
let ext: &dyn Any = ext.as_ref();
|
||||
let Some(m) = ext.downcast_ref::<MacroRulesMacroExpander>() else {
|
||||
continue;
|
||||
};
|
||||
for arm_i in unused_arms.iter() {
|
||||
if let Some((ident, rule_span)) = ext.get_unused_rule(arm_i) {
|
||||
if let Some((ident, rule_span)) = m.get_unused_rule(arm_i) {
|
||||
self.lint_buffer.buffer_lint(
|
||||
UNUSED_MACRO_RULES,
|
||||
node_id,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
//! We don't actually use the `/INCLUDE` linker flag here like the article
|
||||
//! mentions because the Rust compiler doesn't propagate linker flags, but
|
||||
//! instead we use a shim function which performs a volatile 1-byte load from
|
||||
//! the address of the symbol to ensure it sticks around.
|
||||
//! the address of the _tls_used symbol to ensure it sticks around.
|
||||
//!
|
||||
//! [1]: https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
|
||||
//! [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base/threading/thread_local_storage_win.cc#L42
|
||||
|
|
@ -68,9 +68,20 @@ use core::ffi::c_void;
|
|||
use crate::ptr;
|
||||
use crate::sys::c;
|
||||
|
||||
unsafe extern "C" {
|
||||
#[link_name = "_tls_used"]
|
||||
static TLS_USED: u8;
|
||||
}
|
||||
pub fn enable() {
|
||||
// When destructors are used, we don't want LLVM eliminating CALLBACK for any
|
||||
// reason. Once the symbol makes it to the linker, it will do the rest.
|
||||
// When destructors are used, we need to add a reference to the _tls_used
|
||||
// symbol provided by the CRT, otherwise the TLS support code will get
|
||||
// GC'd by the linker and our callback won't be called.
|
||||
unsafe { ptr::from_ref(&TLS_USED).read_volatile() };
|
||||
// We also need to reference CALLBACK to make sure it does not get GC'd
|
||||
// by the compiler/LLVM. The callback will end up inside the TLS
|
||||
// callback array pointed to by _TLS_USED through linker shenanigans,
|
||||
// but as far as the compiler is concerned, it looks like the data is
|
||||
// unused, so we need this hack to prevent it from disappearing.
|
||||
unsafe { ptr::from_ref(&CALLBACK).read_volatile() };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1068,6 +1068,8 @@ impl Step for PlainSourceTarball {
|
|||
"bootstrap.example.toml",
|
||||
"configure",
|
||||
"license-metadata.json",
|
||||
"package-lock.json",
|
||||
"package.json",
|
||||
"x",
|
||||
"x.ps1",
|
||||
"x.py",
|
||||
|
|
|
|||
|
|
@ -875,6 +875,7 @@ pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: boo
|
|||
"powerpc-unknown-linux-gnu",
|
||||
"powerpc64-unknown-linux-gnu",
|
||||
"powerpc64le-unknown-linux-gnu",
|
||||
"powerpc64le-unknown-linux-musl",
|
||||
"riscv64gc-unknown-linux-gnu",
|
||||
"s390x-unknown-linux-gnu",
|
||||
"x86_64-apple-darwin",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,24 +1,12 @@
|
|||
//! Tidy check to ensure below in UI test directories:
|
||||
//! - the number of entries in each directory must be less than `ENTRY_LIMIT`
|
||||
//! - there are no stray `.stderr` files
|
||||
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::collections::BTreeSet;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use ignore::Walk;
|
||||
|
||||
// FIXME: GitHub's UI truncates file lists that exceed 1000 entries, so these
|
||||
// should all be 1000 or lower. Limits significantly smaller than 1000 are also
|
||||
// desirable, because large numbers of files are unwieldy in general. See issue
|
||||
// #73494.
|
||||
const ENTRY_LIMIT: u32 = 901;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
|
||||
const ISSUES_ENTRY_LIMIT: u32 = 1616;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
"stderr", // expected stderr file, corresponds to a rs file
|
||||
|
|
@ -54,42 +42,6 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
|
|||
"tests/ui/std/windows-bat-args3.bat", // tests escaping arguments through batch files
|
||||
];
|
||||
|
||||
fn check_entries(tests_path: &Path, bad: &mut bool) {
|
||||
let mut directories: HashMap<PathBuf, u32> = HashMap::new();
|
||||
|
||||
for entry in Walk::new(tests_path.join("ui")).flatten() {
|
||||
let parent = entry.path().parent().unwrap().to_path_buf();
|
||||
*directories.entry(parent).or_default() += 1;
|
||||
}
|
||||
|
||||
let (mut max, mut max_issues) = (0, 0);
|
||||
for (dir_path, count) in directories {
|
||||
let is_issues_dir = tests_path.join("ui/issues") == dir_path;
|
||||
let (limit, maxcnt) = if is_issues_dir {
|
||||
(ISSUES_ENTRY_LIMIT, &mut max_issues)
|
||||
} else {
|
||||
(ENTRY_LIMIT, &mut max)
|
||||
};
|
||||
*maxcnt = (*maxcnt).max(count);
|
||||
if count > limit {
|
||||
tidy_error!(
|
||||
bad,
|
||||
"following path contains more than {} entries, \
|
||||
you should move the test to some relevant subdirectory (current: {}): {}",
|
||||
limit,
|
||||
count,
|
||||
dir_path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
if ISSUES_ENTRY_LIMIT > max_issues {
|
||||
tidy_error!(
|
||||
bad,
|
||||
"`ISSUES_ENTRY_LIMIT` is too high (is {ISSUES_ENTRY_LIMIT}, should be {max_issues})"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(root_path: &Path, bless: bool, bad: &mut bool) {
|
||||
let issues_txt_header = r#"============================================================
|
||||
⚠️⚠️⚠️NOTHING SHOULD EVER BE ADDED TO THIS LIST⚠️⚠️⚠️
|
||||
|
|
@ -97,7 +49,6 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) {
|
|||
"#;
|
||||
|
||||
let path = &root_path.join("tests");
|
||||
check_entries(path, bad);
|
||||
|
||||
// the list of files in ui tests that are allowed to start with `issue-XXXX`
|
||||
// BTreeSet because we would like a stable ordering so --bless works
|
||||
|
|
@ -179,7 +130,9 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) {
|
|||
.unwrap()
|
||||
.replace(std::path::MAIN_SEPARATOR_STR, "/");
|
||||
|
||||
if !remaining_issue_names.remove(stripped_path.as_str()) {
|
||||
if !remaining_issue_names.remove(stripped_path.as_str())
|
||||
&& !stripped_path.starts_with("ui/issues/")
|
||||
{
|
||||
tidy_error!(
|
||||
bad,
|
||||
"file `tests/{stripped_path}` must begin with a descriptive name, consider `{{reason}}-issue-{issue_n}.rs`",
|
||||
|
|
|
|||
|
|
@ -37,32 +37,29 @@ Number of file 0 mappings: 8
|
|||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::main::{closure#0}
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
|
||||
Number of files: 1
|
||||
- file 0 => $DIR/async_closure.rs
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
|
||||
- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::main::{closure#0}
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
|
||||
Number of files: 1
|
||||
- file 0 => $DIR/async_closure.rs
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
|
||||
- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
|
||||
Number of files: 1
|
||||
- file 0 => $DIR/async_closure.rs
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
|
||||
- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:18 (#0);
|
||||
+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:23: 19:30 (#0);
|
||||
+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:31: 19:32 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:1: 21:2 (#0);
|
||||
+
|
||||
bb0: {
|
||||
+ Coverage::VirtualCounter(bcb0);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 27:17 (#0);
|
||||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:28:5: 28:9 (#0);
|
||||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:2: 29:2 (#0);
|
||||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 29:2 (#0);
|
||||
+
|
||||
bb0: {
|
||||
+ Coverage::VirtualCounter(bcb0);
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:10 (#0);
|
||||
+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0);
|
||||
+ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0);
|
||||
+ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:9: 17:10 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:1: 19:2 (#0);
|
||||
+
|
||||
bb0: {
|
||||
+ Coverage::VirtualCounter(bcb0);
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
|
||||
coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
|
||||
coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
|
||||
coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
|
||||
coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
|
||||
coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
|
||||
coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
|
||||
coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
|
||||
|
||||
bb0: {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
|
||||
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
|
||||
+ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
|
||||
+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
|
||||
+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
|
||||
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
|
||||
+ coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
|
||||
+
|
||||
bb0: {
|
||||
|
|
|
|||
|
|
@ -1277,9 +1277,9 @@ See [Tracking issue for specialization (RFC 1210) #31844](https://github.com/rus
|
|||
|
||||
Stability attributes used internally by the standard library: `#[stable()]` and `#[unstable()]`.
|
||||
|
||||
## `tests/ui/stable-mir-print/`
|
||||
## `tests/ui/rustc_public-ir-print/`
|
||||
|
||||
Some tests for pretty printing of StableMIR.
|
||||
Some tests for pretty printing of rustc_public's IR.
|
||||
|
||||
## `tests/ui/stack-protector/`: `-Z stack-protector` command line flag
|
||||
|
||||
|
|
|
|||
16
tests/ui/consts/const_transmute_type_id6.rs
Normal file
16
tests/ui/consts/const_transmute_type_id6.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! Test that we do not ICE and that we do report an error
|
||||
//! when placing non-TypeId provenance into a TypeId.
|
||||
|
||||
#![feature(const_trait_impl, const_cmp)]
|
||||
|
||||
use std::any::TypeId;
|
||||
use std::mem::transmute;
|
||||
|
||||
const X: bool = {
|
||||
let a = ();
|
||||
let id: TypeId = unsafe { transmute([&raw const a; 16 / size_of::<*const ()>()]) };
|
||||
id == id
|
||||
//~^ ERROR: invalid `TypeId` value: not all bytes carry type id metadata
|
||||
};
|
||||
|
||||
fn main() {}
|
||||
15
tests/ui/consts/const_transmute_type_id6.stderr
Normal file
15
tests/ui/consts/const_transmute_type_id6.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error[E0080]: invalid `TypeId` value: not all bytes carry type id metadata
|
||||
--> $DIR/const_transmute_type_id6.rs:12:5
|
||||
|
|
||||
LL | id == id
|
||||
| ^^^^^^^^ evaluation of `X` failed inside this call
|
||||
|
|
||||
note: inside `<TypeId as PartialEq>::eq`
|
||||
--> $SRC_DIR/core/src/any.rs:LL:COL
|
||||
note: inside `<TypeId as PartialEq>::eq::compiletime`
|
||||
--> $SRC_DIR/core/src/any.rs:LL:COL
|
||||
= note: this error originates in the macro `$crate::intrinsics::const_eval_select` which comes from the expansion of the macro `crate::intrinsics::const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
|
@ -1147,6 +1147,12 @@ cc = ["@nnethercote"]
|
|||
message = "Changes to the size of AST and/or HIR nodes."
|
||||
cc = ["@nnethercote"]
|
||||
|
||||
[mentions."tests/ui/issues"]
|
||||
message = """
|
||||
This PR modifies `tests/ui/issues/`. If this PR is adding new tests to `tests/ui/issues/`,
|
||||
please refrain from doing so, and instead add it to more descriptive subdirectories.
|
||||
"""
|
||||
|
||||
[mentions."compiler/rustc_sanitizers"]
|
||||
cc = ["@rcvalle"]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue