Auto merge of #149798 - matthiaskrgr:rollup-wjgs9x6, r=matthiaskrgr
Rollup of 11 pull requests Successful merges: - rust-lang/rust#147585 (Suppress the error for private fields with non_exhaustive attribute) - rust-lang/rust#149215 (Emit `check-cfg` lints during attribute parsing rather than evaluation) - rust-lang/rust#149652 (Add release notes for 1.92.0) - rust-lang/rust#149720 (rustdoc book: mention inner doc attribute) - rust-lang/rust#149730 (lint: emit proper diagnostic for unsafe binders in improper_ctypes instead of ICE) - rust-lang/rust#149754 (Retire `opt_str2` from compiletest cli parsing) - rust-lang/rust#149755 (bootstrap: Use a `CompiletestMode` enum instead of bare strings) - rust-lang/rust#149763 (Add inline attribute to generated delegation function if needed) - rust-lang/rust#149772 (test: Add a test for 146133) - rust-lang/rust#149779 (Fix typo "an" → "and") - rust-lang/rust#149782 (Remove `[no-mentions]` handler in the triagebot config) Failed merges: - rust-lang/rust#148491 ( Correctly provide suggestions when encountering `async fn` with a `dyn Trait` return type) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d5525a7300
45 changed files with 771 additions and 217 deletions
85
RELEASES.md
85
RELEASES.md
|
|
@ -1,3 +1,88 @@
|
|||
Version 1.92.0 (2025-12-11)
|
||||
==========================
|
||||
|
||||
<a id="1.92.0-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Document `MaybeUninit` representation and validity](https://github.com/rust-lang/rust/pull/140463)
|
||||
- [Allow `&raw [mut | const]` for union field in safe code](https://github.com/rust-lang/rust/pull/141469)
|
||||
- [Prefer item bounds of associated types over where-bounds for auto-traits and `Sized`](https://github.com/rust-lang/rust/pull/144064)
|
||||
- [Do not materialize `X` in `[X; 0]` when `X` is unsizing a const](https://github.com/rust-lang/rust/pull/145277)
|
||||
- [Support combining `#[track_caller]` and `#[no_mangle]` (requires every declaration specifying `#[track_caller]` as well)](https://github.com/rust-lang/rust/pull/145724)
|
||||
- [Make never type lints `never_type_fallback_flowing_into_unsafe` and `dependency_on_unit_never_type_fallback` deny-by-default](https://github.com/rust-lang/rust/pull/146167)
|
||||
- [Allow specifying multiple bounds for same associated item, except in trait objects](https://github.com/rust-lang/rust/pull/146593)
|
||||
- [Slightly strengthen higher-ranked region handling in coherence](https://github.com/rust-lang/rust/pull/146725)
|
||||
- [The `unused_must_use` lint no longer warns on `Result<(), Uninhabited>` (for instance, `Result<(), !>`), or `ControlFlow<Uninhabited, ()>`](https://github.com/rust-lang/rust/pull/147382). This avoids having to check for an error that can never happen.
|
||||
|
||||
<a id="1.92.0-Compiler"></a>
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [Make `mips64el-unknown-linux-muslabi64` link dynamically](https://github.com/rust-lang/rust/pull/146858)
|
||||
- [Remove current code for embedding command-line args in PDB](https://github.com/rust-lang/rust/pull/147022)
|
||||
Command-line information is typically not needed by debugging tools, and the removed code
|
||||
was causing problems for incremental builds even on targets that don't use PDB debuginfo.
|
||||
|
||||
<a id="1.92.0-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [Specialize `Iterator::eq{_by}` for `TrustedLen` iterators](https://github.com/rust-lang/rust/pull/137122)
|
||||
- [Simplify `Extend` for tuples](https://github.com/rust-lang/rust/pull/138799)
|
||||
- [Added details to `Debug` for `EncodeWide`](https://github.com/rust-lang/rust/pull/140153).
|
||||
- [`iter::Repeat::last`](https://github.com/rust-lang/rust/pull/147258) and [`count`](https://github.com/rust-lang/rust/pull/146410) will now panic, rather than looping infinitely.
|
||||
|
||||
<a id="1.92.0-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`NonZero<u{N}>::div_ceil`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.div_ceil)
|
||||
- [`Location::file_as_c_str`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.file_as_c_str)
|
||||
- [`RwLockWriteGuard::downgrade`](https://doc.rust-lang.org/stable/std/sync/struct.RwLockWriteGuard.html#method.downgrade)
|
||||
- [`Box::new_zeroed`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.new_zeroed)
|
||||
- [`Box::new_zeroed_slice`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.new_zeroed_slice)
|
||||
- [`Rc::new_zeroed`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.new_zeroed)
|
||||
- [`Rc::new_zeroed_slice`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.new_zeroed_slice)
|
||||
- [`Arc::new_zeroed`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.new_zeroed)
|
||||
- [`Arc::new_zeroed_slice`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.new_zeroed_slice)
|
||||
- [`btree_map::Entry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/btree_map/enum.Entry.html#method.insert_entry)
|
||||
- [`btree_map::VacantEntry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/btree_map/struct.VacantEntry.html#method.insert_entry)
|
||||
- [`impl Extend<proc_macro::Group> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CGroup%3E-for-TokenStream)
|
||||
- [`impl Extend<proc_macro::Literal> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CLiteral%3E-for-TokenStream)
|
||||
- [`impl Extend<proc_macro::Punct> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CPunct%3E-for-TokenStream)
|
||||
- [`impl Extend<proc_macro::Ident> for proc_macro::TokenStream`](https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#impl-Extend%3CIdent%3E-for-TokenStream)
|
||||
|
||||
These previously stable APIs are now stable in const contexts:
|
||||
|
||||
- [`<[_]>::rotate_left`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.rotate_left)
|
||||
- [`<[_]>::rotate_right`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.rotate_right)
|
||||
|
||||
<a id="1.92.0-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [Added a new chapter](https://github.com/rust-lang/cargo/issues/16119) to the Cargo book, ["Optimizing Build Performance"](https://doc.rust-lang.org/stable/cargo/guide/build-performance.html).
|
||||
|
||||
<a id="1.92.0-Rustdoc"></a>
|
||||
|
||||
Rustdoc
|
||||
-----
|
||||
- [If a trait item appears in rustdoc search, hide the corresponding impl items](https://github.com/rust-lang/rust/pull/145898). Previously a search for "last" would show both `Iterator::last` as well as impl methods like `std::vec::IntoIter::last`. Now these impl methods will be hidden, freeing up space for inherent methods like `BTreeSet::last`.
|
||||
- [Relax rules for identifiers in search](https://github.com/rust-lang/rust/pull/147860). Previously you could only search for identifiers that were valid in rust code, now searches only need to be valid as part of an identifier. For example, you can now perform a search that starts with a digit.
|
||||
|
||||
<a id="1.92.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
* [Fix backtraces with `-C panic=abort` on Linux by generating unwind tables by default](https://github.com/rust-lang/rust/pull/143613). Build with `-C force-unwind-tables=no` to keep omitting unwind tables.
|
||||
- As part of the larger effort refactoring compiler built-in attributes and their diagnostics, [the future-compatibility lint `invalid_macro_export_arguments` is upgraded to deny-by-default and will be reported in dependencies too.](https://github.com/rust-lang/rust/pull/143857)
|
||||
- [Update the minimum external LLVM to 20](https://github.com/rust-lang/rust/pull/145071)
|
||||
- [Prevent downstream `impl DerefMut for Pin<LocalType>`](https://github.com/rust-lang/rust/pull/145608)
|
||||
- [Don't apply temporary lifetime extension rules to the arguments of non-extended `pin!` and formatting macros](https://github.com/rust-lang/rust/pull/145838)
|
||||
|
||||
|
||||
Version 1.91.1 (2025-11-10)
|
||||
===========================
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ use hir::{BodyId, HirId};
|
|||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::*;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::attrs::{AttributeKind, InlineAttr};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
|
||||
|
|
@ -87,6 +88,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
|
||||
match sig_id {
|
||||
Ok(sig_id) => {
|
||||
self.add_inline_attribute_if_needed(span);
|
||||
|
||||
let is_method = self.is_method(sig_id, span);
|
||||
let (param_count, c_variadic) = self.param_count(sig_id);
|
||||
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
|
||||
|
|
@ -100,6 +103,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_inline_attribute_if_needed(&mut self, span: Span) {
|
||||
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
|
||||
let create_inline_attr_slice =
|
||||
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];
|
||||
|
||||
let new_attributes = match self.attrs.get(&PARENT_ID) {
|
||||
Some(attrs) => {
|
||||
// Check if reuse already specifies any inline attribute, if so, do nothing
|
||||
if attrs
|
||||
.iter()
|
||||
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.arena.alloc_from_iter(
|
||||
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
|
||||
)
|
||||
}
|
||||
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
|
||||
};
|
||||
|
||||
self.attrs.insert(PARENT_ID, new_attributes);
|
||||
}
|
||||
|
||||
fn get_delegation_sig_id(
|
||||
&self,
|
||||
item_id: NodeId,
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ use std::convert::identity;
|
|||
|
||||
use rustc_ast::token::Delimiter;
|
||||
use rustc_ast::tokenstream::DelimSpan;
|
||||
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, NodeId, ast, token};
|
||||
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate, Features, template};
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrPath, RustcVersion};
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::{exp, parse_in};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::parse::{ParseSess, feature_err};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
|
||||
|
|
@ -23,10 +23,7 @@ use crate::session_diagnostics::{
|
|||
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
|
||||
ParsedDescription,
|
||||
};
|
||||
use crate::{
|
||||
AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics,
|
||||
try_gate_cfg,
|
||||
};
|
||||
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics, try_gate_cfg};
|
||||
|
||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["predicate"],
|
||||
|
|
@ -195,43 +192,46 @@ fn parse_name_value<S: Stage>(
|
|||
}
|
||||
};
|
||||
|
||||
Ok(CfgEntry::NameValue { name, name_span, value, span })
|
||||
match cx.sess.psess.check_config.expecteds.get(&name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&value.map(|(v, _)| v)) => cx
|
||||
.emit_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
AttributeLintKind::UnexpectedCfgValue((name, name_span), value),
|
||||
span,
|
||||
),
|
||||
None if cx.sess.psess.check_config.exhaustive_names => cx.emit_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
AttributeLintKind::UnexpectedCfgName((name, name_span), value),
|
||||
span,
|
||||
),
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
|
||||
Ok(CfgEntry::NameValue { name, value: value.map(|(v, _)| v), span })
|
||||
}
|
||||
|
||||
pub fn eval_config_entry(
|
||||
sess: &Session,
|
||||
cfg_entry: &CfgEntry,
|
||||
id: NodeId,
|
||||
emit_lints: ShouldEmit,
|
||||
) -> EvalConfigResult {
|
||||
pub fn eval_config_entry(sess: &Session, cfg_entry: &CfgEntry) -> EvalConfigResult {
|
||||
match cfg_entry {
|
||||
CfgEntry::All(subs, ..) => {
|
||||
let mut all = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
let res = eval_config_entry(sess, sub);
|
||||
if !res.as_bool() {
|
||||
all.get_or_insert(res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
all.unwrap_or_else(|| EvalConfigResult::True)
|
||||
EvalConfigResult::True
|
||||
}
|
||||
CfgEntry::Any(subs, span) => {
|
||||
let mut any = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
let res = eval_config_entry(sess, sub);
|
||||
if res.as_bool() {
|
||||
any.get_or_insert(res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
any.unwrap_or_else(|| EvalConfigResult::False {
|
||||
reason: cfg_entry.clone(),
|
||||
reason_span: *span,
|
||||
})
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
}
|
||||
CfgEntry::Not(sub, span) => {
|
||||
if eval_config_entry(sess, sub, id, emit_lints).as_bool() {
|
||||
if eval_config_entry(sess, sub).as_bool() {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
} else {
|
||||
EvalConfigResult::True
|
||||
|
|
@ -244,32 +244,8 @@ pub fn eval_config_entry(
|
|||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
}
|
||||
}
|
||||
CfgEntry::NameValue { name, name_span, value, span } => {
|
||||
if let ShouldEmit::ErrorsAndLints = emit_lints {
|
||||
match sess.psess.check_config.expecteds.get(name) {
|
||||
Some(ExpectedValues::Some(values))
|
||||
if !values.contains(&value.map(|(v, _)| v)) =>
|
||||
{
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
}
|
||||
|
||||
if sess.psess.config.contains(&(*name, value.map(|(v, _)| v))) {
|
||||
CfgEntry::NameValue { name, value, span } => {
|
||||
if sess.psess.config.contains(&(*name, *value)) {
|
||||
EvalConfigResult::True
|
||||
} else {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, Nod
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
|
||||
use rustc_hir::RustcVersion;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
|
|
@ -51,10 +52,10 @@ pub fn cfg_matches(
|
|||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue(
|
||||
BuiltinLintDiag::AttributeLint(AttributeLintKind::UnexpectedCfgValue(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
|
|
@ -62,10 +63,10 @@ pub fn cfg_matches(
|
|||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
BuiltinLintDiag::UnexpectedCfgName(
|
||||
BuiltinLintDiag::AttributeLint(AttributeLintKind::UnexpectedCfgName(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
|
|
|
|||
|
|
@ -26,13 +26,7 @@ pub(crate) fn expand_cfg(
|
|||
|
||||
ExpandResult::Ready(match parse_cfg(cx, sp, tts) {
|
||||
Ok(cfg) => {
|
||||
let matches_cfg = attr::eval_config_entry(
|
||||
cx.sess,
|
||||
&cfg,
|
||||
cx.current_expansion.lint_node_id,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
)
|
||||
.as_bool();
|
||||
let matches_cfg = attr::eval_config_entry(cx.sess, &cfg).as_bool();
|
||||
|
||||
MacEager::expr(cx.expr_bool(sp, matches_cfg))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_attr_parsing::{
|
||||
CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, ShouldEmit, parse_cfg_select,
|
||||
CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, parse_cfg_select,
|
||||
};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
|
|
@ -10,21 +10,13 @@ use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
|
|||
|
||||
/// Selects the first arm whose predicate evaluates to true.
|
||||
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
|
||||
let mut result = None;
|
||||
for (cfg, tt, arm_span) in branches.reachable {
|
||||
if let EvalConfigResult::True = attr::eval_config_entry(
|
||||
&ecx.sess,
|
||||
&cfg,
|
||||
ecx.current_expansion.lint_node_id,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
) {
|
||||
// FIXME(#149215) Ideally we should short-circuit here, but `eval_config_entry` currently emits lints so we cannot do this yet.
|
||||
result.get_or_insert((tt, arm_span));
|
||||
if let EvalConfigResult::True = attr::eval_config_entry(&ecx.sess, &cfg) {
|
||||
return Some((tt, arm_span));
|
||||
}
|
||||
}
|
||||
|
||||
let wildcard = branches.wildcard.map(|(_, tt, span)| (tt, span));
|
||||
result.or(wildcard)
|
||||
branches.wildcard.map(|(_, tt, span)| (tt, span))
|
||||
}
|
||||
|
||||
pub(super) fn expand_cfg_select<'cx>(
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ use find_msvc_tools;
|
|||
use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_ast::CRATE_NODE_ID;
|
||||
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
|
||||
use rustc_attr_parsing::eval_config_entry;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
|
|
@ -3029,9 +3028,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
|
|||
|
||||
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => {
|
||||
eval_config_entry(sess, cfg, CRATE_NODE_ID, ShouldEmit::ErrorsAndLints).as_bool()
|
||||
}
|
||||
Some(ref cfg) => eval_config_entry(sess, cfg).as_bool(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,10 +163,7 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec
|
|||
.iter()
|
||||
.flat_map(|attr| strip_unconfigured.process_cfg_attr(attr))
|
||||
.take_while(|attr| {
|
||||
!is_cfg(attr)
|
||||
|| strip_unconfigured
|
||||
.cfg_true(attr, strip_unconfigured.lint_node_id, ShouldEmit::Nothing)
|
||||
.as_bool()
|
||||
!is_cfg(attr) || strip_unconfigured.cfg_true(attr, ShouldEmit::Nothing).as_bool()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
@ -309,14 +306,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
if !attr::eval_config_entry(
|
||||
self.sess,
|
||||
&cfg_predicate,
|
||||
ast::CRATE_NODE_ID,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
)
|
||||
.as_bool()
|
||||
{
|
||||
if !attr::eval_config_entry(self.sess, &cfg_predicate).as_bool() {
|
||||
return vec![trace_attr];
|
||||
}
|
||||
|
||||
|
|
@ -400,23 +390,17 @@ impl<'a> StripUnconfigured<'a> {
|
|||
|
||||
/// Determines if a node with the given attributes should be included in this configuration.
|
||||
fn in_cfg(&self, attrs: &[Attribute]) -> bool {
|
||||
attrs.iter().all(|attr| {
|
||||
!is_cfg(attr)
|
||||
|| self.cfg_true(attr, self.lint_node_id, ShouldEmit::ErrorsAndLints).as_bool()
|
||||
})
|
||||
attrs
|
||||
.iter()
|
||||
.all(|attr| !is_cfg(attr) || self.cfg_true(attr, ShouldEmit::ErrorsAndLints).as_bool())
|
||||
}
|
||||
|
||||
pub(crate) fn cfg_true(
|
||||
&self,
|
||||
attr: &Attribute,
|
||||
node: NodeId,
|
||||
emit_errors: ShouldEmit,
|
||||
) -> EvalConfigResult {
|
||||
pub(crate) fn cfg_true(&self, attr: &Attribute, emit_errors: ShouldEmit) -> EvalConfigResult {
|
||||
let Some(cfg) = AttributeParser::parse_single(
|
||||
self.sess,
|
||||
attr,
|
||||
attr.span,
|
||||
node,
|
||||
self.lint_node_id,
|
||||
self.features,
|
||||
emit_errors,
|
||||
parse_cfg,
|
||||
|
|
@ -426,7 +410,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
return EvalConfigResult::True;
|
||||
};
|
||||
|
||||
eval_config_entry(self.sess, &cfg, self.lint_node_id, emit_errors)
|
||||
eval_config_entry(self.sess, &cfg)
|
||||
}
|
||||
|
||||
/// If attributes are not allowed on expressions, emit an error for `attr`
|
||||
|
|
|
|||
|
|
@ -2213,7 +2213,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
attr: ast::Attribute,
|
||||
pos: usize,
|
||||
) -> EvalConfigResult {
|
||||
let res = self.cfg().cfg_true(&attr, node.node_id(), ShouldEmit::ErrorsAndLints);
|
||||
let res = self.cfg().cfg_true(&attr, ShouldEmit::ErrorsAndLints);
|
||||
if res.as_bool() {
|
||||
// A trace attribute left in AST in place of the original `cfg` attribute.
|
||||
// It can later be used by lints or other diagnostics.
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ pub enum CfgEntry {
|
|||
Any(ThinVec<CfgEntry>, Span),
|
||||
Not(Box<CfgEntry>, Span),
|
||||
Bool(bool, Span),
|
||||
NameValue { name: Symbol, name_span: Span, value: Option<(Symbol, Span)>, span: Span },
|
||||
NameValue { name: Symbol, value: Option<Symbol>, span: Span },
|
||||
Version(Option<RustcVersion>, Span),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2191,7 +2191,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys);
|
||||
} else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() {
|
||||
} else if adt_kind != AdtKind::Union
|
||||
&& !remaining_fields.is_empty()
|
||||
//~ non_exhaustive already reported, which will only happen for extern modules
|
||||
&& !variant.field_list_has_applicable_non_exhaustive()
|
||||
{
|
||||
debug!(?remaining_fields);
|
||||
let private_fields: Vec<&ty::FieldDef> = variant
|
||||
.fields
|
||||
|
|
|
|||
|
|
@ -416,6 +416,8 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
|
|||
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
|
||||
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
|
||||
|
||||
lint_improper_ctypes_unsafe_binder = unsafe binders are incompatible with foreign function interfaces
|
||||
|
||||
lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a pointer without provenance
|
||||
.note = this is dangerous because dereferencing the resulting pointer is undefined behavior
|
||||
.note_exposed_provenance = exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
|
||||
|
|
|
|||
|
|
@ -169,12 +169,6 @@ pub fn decorate_builtin_lint(
|
|||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgName(name, value) => {
|
||||
check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
|
||||
check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
|
||||
let suggestion = match sugg {
|
||||
Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd {
|
||||
|
|
@ -310,8 +304,8 @@ pub fn decorate_builtin_lint(
|
|||
}
|
||||
|
||||
pub fn decorate_attribute_lint(
|
||||
_sess: &Session,
|
||||
_tcx: Option<TyCtxt<'_>>,
|
||||
sess: &Session,
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
kind: &AttributeLintKind,
|
||||
diag: &mut Diag<'_, ()>,
|
||||
) {
|
||||
|
|
@ -367,5 +361,11 @@ pub fn decorate_attribute_lint(
|
|||
suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
|
||||
}
|
||||
.decorate_lint(diag),
|
||||
&AttributeLintKind::UnexpectedCfgName(name, value) => {
|
||||
check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag)
|
||||
}
|
||||
&AttributeLintKind::UnexpectedCfgValue(name, value) => {
|
||||
check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -669,7 +669,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
FfiSafe
|
||||
}
|
||||
|
||||
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
|
||||
ty::UnsafeBinder(_) => {
|
||||
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_unsafe_binder, help: None }
|
||||
}
|
||||
|
||||
ty::Param(..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
|
||||
|
|
|
|||
|
|
@ -636,8 +636,6 @@ pub enum BuiltinLintDiag {
|
|||
},
|
||||
BreakWithLabelAndLoop(Span),
|
||||
UnicodeTextFlow(Span, String),
|
||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||
DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
|
||||
SingleUseLifetime {
|
||||
/// Span of the parameter which declares this lifetime.
|
||||
|
|
@ -733,6 +731,8 @@ pub enum AttributeLintKind {
|
|||
attribute_name_span: Span,
|
||||
sugg_spans: (Span, Span),
|
||||
},
|
||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||
}
|
||||
|
||||
pub type RegisteredTools = FxIndexSet<Ident>;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ use std::ops::ControlFlow;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::CRATE_NODE_ID;
|
||||
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
|
||||
use rustc_attr_parsing::eval_config_entry;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::attrs::{AttributeKind, NativeLibKind, PeImportNameType};
|
||||
use rustc_hir::find_attr;
|
||||
|
|
@ -188,9 +187,7 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
|
|||
|
||||
pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => {
|
||||
eval_config_entry(sess, cfg, CRATE_NODE_ID, ShouldEmit::ErrorsAndLints).as_bool()
|
||||
}
|
||||
Some(ref cfg) => eval_config_entry(sess, cfg).as_bool(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3070,7 +3070,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
let item_was = if let CfgEntry::NameValue { value: Some((feature, _)), .. } = cfg.0 {
|
||||
let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
|
||||
errors::ItemWas::BehindFeature { feature, span: cfg.1 }
|
||||
} else {
|
||||
errors::ItemWas::CfgOut { span: cfg.1 }
|
||||
|
|
|
|||
|
|
@ -1324,7 +1324,7 @@ impl Read for &File {
|
|||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// This function currently returns `true` on Unix an `false` on Windows.
|
||||
/// This function currently returns `true` on Unix and `false` on Windows.
|
||||
/// Note that this [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: io#platform-specific-behavior
|
||||
|
|
@ -1385,7 +1385,7 @@ impl Write for &File {
|
|||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// This function currently returns `true` on Unix an `false` on Windows.
|
||||
/// This function currently returns `true` on Unix and `false` on Windows.
|
||||
/// Note that this [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: io#platform-specific-behavior
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
//! `./x.py test` (aka [`Kind::Test`]) is currently allowed to reach build steps in other modules.
|
||||
//! However, this contains ~all test parts we expect people to be able to build and run locally.
|
||||
|
||||
// (This file should be split up, but having tidy block all changes is not helpful.)
|
||||
// ignore-tidy-filelength
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env::split_paths;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
|
@ -17,6 +20,7 @@ use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
|
|||
use crate::core::build_steps::llvm::get_llvm_version;
|
||||
use crate::core::build_steps::run::{get_completion_paths, get_help_path};
|
||||
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
|
||||
use crate::core::build_steps::test::compiletest::CompiletestMode;
|
||||
use crate::core::build_steps::tool::{
|
||||
self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
|
||||
ToolTargetBuildMode, get_tool_target_compiler,
|
||||
|
|
@ -39,6 +43,8 @@ use crate::utils::helpers::{
|
|||
use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
|
||||
use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
|
||||
|
||||
mod compiletest;
|
||||
|
||||
/// Runs `cargo test` on various internal tools used by bootstrap.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct CrateBootstrap {
|
||||
|
|
@ -1085,7 +1091,7 @@ impl Step for RustdocJSNotStd {
|
|||
builder.ensure(Compiletest {
|
||||
test_compiler: self.compiler,
|
||||
target: self.target,
|
||||
mode: "rustdoc-js",
|
||||
mode: CompiletestMode::RustdocJs,
|
||||
suite: "rustdoc-js",
|
||||
path: "tests/rustdoc-js",
|
||||
compare_mode: None,
|
||||
|
|
@ -1478,7 +1484,7 @@ macro_rules! test {
|
|||
builder.ensure(Compiletest {
|
||||
test_compiler: self.test_compiler,
|
||||
target: self.target,
|
||||
mode: $mode,
|
||||
mode: const { $mode },
|
||||
suite: $suite,
|
||||
path: $path,
|
||||
compare_mode: (const {
|
||||
|
|
@ -1493,34 +1499,39 @@ macro_rules! test {
|
|||
};
|
||||
}
|
||||
|
||||
test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
|
||||
test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
|
||||
|
||||
test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
|
||||
test!(Crashes {
|
||||
path: "tests/crashes",
|
||||
mode: CompiletestMode::Crashes,
|
||||
suite: "crashes",
|
||||
default: true,
|
||||
});
|
||||
|
||||
test!(CodegenLlvm {
|
||||
path: "tests/codegen-llvm",
|
||||
mode: "codegen",
|
||||
mode: CompiletestMode::Codegen,
|
||||
suite: "codegen-llvm",
|
||||
default: true
|
||||
});
|
||||
|
||||
test!(CodegenUnits {
|
||||
path: "tests/codegen-units",
|
||||
mode: "codegen-units",
|
||||
mode: CompiletestMode::CodegenUnits,
|
||||
suite: "codegen-units",
|
||||
default: true,
|
||||
});
|
||||
|
||||
test!(Incremental {
|
||||
path: "tests/incremental",
|
||||
mode: "incremental",
|
||||
mode: CompiletestMode::Incremental,
|
||||
suite: "incremental",
|
||||
default: true,
|
||||
});
|
||||
|
||||
test!(Debuginfo {
|
||||
path: "tests/debuginfo",
|
||||
mode: "debuginfo",
|
||||
mode: CompiletestMode::Debuginfo,
|
||||
suite: "debuginfo",
|
||||
default: true,
|
||||
compare_mode: Some("split-dwarf"),
|
||||
|
|
@ -1528,7 +1539,7 @@ test!(Debuginfo {
|
|||
|
||||
test!(UiFullDeps {
|
||||
path: "tests/ui-fulldeps",
|
||||
mode: "ui",
|
||||
mode: CompiletestMode::Ui,
|
||||
suite: "ui-fulldeps",
|
||||
default: true,
|
||||
IS_HOST: true,
|
||||
|
|
@ -1536,14 +1547,14 @@ test!(UiFullDeps {
|
|||
|
||||
test!(Rustdoc {
|
||||
path: "tests/rustdoc",
|
||||
mode: "rustdoc",
|
||||
mode: CompiletestMode::Rustdoc,
|
||||
suite: "rustdoc",
|
||||
default: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
test!(RustdocUi {
|
||||
path: "tests/rustdoc-ui",
|
||||
mode: "ui",
|
||||
mode: CompiletestMode::Ui,
|
||||
suite: "rustdoc-ui",
|
||||
default: true,
|
||||
IS_HOST: true,
|
||||
|
|
@ -1551,7 +1562,7 @@ test!(RustdocUi {
|
|||
|
||||
test!(RustdocJson {
|
||||
path: "tests/rustdoc-json",
|
||||
mode: "rustdoc-json",
|
||||
mode: CompiletestMode::RustdocJson,
|
||||
suite: "rustdoc-json",
|
||||
default: true,
|
||||
IS_HOST: true,
|
||||
|
|
@ -1559,40 +1570,46 @@ test!(RustdocJson {
|
|||
|
||||
test!(Pretty {
|
||||
path: "tests/pretty",
|
||||
mode: "pretty",
|
||||
mode: CompiletestMode::Pretty,
|
||||
suite: "pretty",
|
||||
default: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
|
||||
test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
|
||||
test!(RunMake {
|
||||
path: "tests/run-make",
|
||||
mode: CompiletestMode::RunMake,
|
||||
suite: "run-make",
|
||||
default: true,
|
||||
});
|
||||
test!(RunMakeCargo {
|
||||
path: "tests/run-make-cargo",
|
||||
mode: "run-make",
|
||||
mode: CompiletestMode::RunMake,
|
||||
suite: "run-make-cargo",
|
||||
default: true
|
||||
});
|
||||
|
||||
test!(AssemblyLlvm {
|
||||
path: "tests/assembly-llvm",
|
||||
mode: "assembly",
|
||||
mode: CompiletestMode::Assembly,
|
||||
suite: "assembly-llvm",
|
||||
default: true
|
||||
});
|
||||
|
||||
/// Runs the coverage test suite at `tests/coverage` in some or all of the
|
||||
/// coverage test modes.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Coverage {
|
||||
pub compiler: Compiler,
|
||||
pub target: TargetSelection,
|
||||
pub mode: &'static str,
|
||||
pub(crate) mode: CompiletestMode,
|
||||
}
|
||||
|
||||
impl Coverage {
|
||||
const PATH: &'static str = "tests/coverage";
|
||||
const SUITE: &'static str = "coverage";
|
||||
const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
|
||||
const ALL_MODES: &[CompiletestMode] =
|
||||
&[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
|
||||
}
|
||||
|
||||
impl Step for Coverage {
|
||||
|
|
@ -1608,7 +1625,7 @@ impl Step for Coverage {
|
|||
// - `./x test coverage-run -- tests/coverage/trivial.rs`
|
||||
run = run.suite_path(Self::PATH);
|
||||
for mode in Self::ALL_MODES {
|
||||
run = run.alias(mode);
|
||||
run = run.alias(mode.as_str());
|
||||
}
|
||||
run
|
||||
}
|
||||
|
|
@ -1631,15 +1648,15 @@ impl Step for Coverage {
|
|||
for path in &run.paths {
|
||||
match path {
|
||||
PathSet::Set(_) => {
|
||||
for mode in Self::ALL_MODES {
|
||||
if path.assert_single_path().path == Path::new(mode) {
|
||||
for &mode in Self::ALL_MODES {
|
||||
if path.assert_single_path().path == Path::new(mode.as_str()) {
|
||||
modes.push(mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
PathSet::Suite(_) => {
|
||||
modes.extend(Self::ALL_MODES);
|
||||
modes.extend_from_slice(Self::ALL_MODES);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1647,7 +1664,9 @@ impl Step for Coverage {
|
|||
|
||||
// Skip any modes that were explicitly skipped/excluded on the command-line.
|
||||
// FIXME(Zalathar): Integrate this into central skip handling somehow?
|
||||
modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
|
||||
modes.retain(|mode| {
|
||||
!run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str()))
|
||||
});
|
||||
|
||||
// FIXME(Zalathar): Make these commands skip all coverage tests, as expected:
|
||||
// - `./x test --skip=tests`
|
||||
|
|
@ -1678,7 +1697,7 @@ impl Step for Coverage {
|
|||
|
||||
test!(CoverageRunRustdoc {
|
||||
path: "tests/coverage-run-rustdoc",
|
||||
mode: "coverage-run",
|
||||
mode: CompiletestMode::CoverageRun,
|
||||
suite: "coverage-run-rustdoc",
|
||||
default: true,
|
||||
IS_HOST: true,
|
||||
|
|
@ -1712,7 +1731,7 @@ impl Step for MirOpt {
|
|||
builder.ensure(Compiletest {
|
||||
test_compiler: self.compiler,
|
||||
target,
|
||||
mode: "mir-opt",
|
||||
mode: CompiletestMode::MirOpt,
|
||||
suite: "mir-opt",
|
||||
path: "tests/mir-opt",
|
||||
compare_mode: None,
|
||||
|
|
@ -1755,7 +1774,7 @@ struct Compiletest {
|
|||
/// The compiler that we're testing.
|
||||
test_compiler: Compiler,
|
||||
target: TargetSelection,
|
||||
mode: &'static str,
|
||||
mode: CompiletestMode,
|
||||
suite: &'static str,
|
||||
path: &'static str,
|
||||
compare_mode: Option<&'static str>,
|
||||
|
|
@ -1791,7 +1810,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
let suite_path = self.path;
|
||||
|
||||
// Skip codegen tests if they aren't enabled in configuration.
|
||||
if !builder.config.codegen_tests && mode == "codegen" {
|
||||
if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1829,7 +1848,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
target,
|
||||
});
|
||||
}
|
||||
if mode == "run-make" {
|
||||
if mode == CompiletestMode::RunMake {
|
||||
builder.tool_exe(Tool::RunMakeSupport);
|
||||
}
|
||||
|
||||
|
|
@ -1886,7 +1905,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
// suites, `run-make` and `run-make-cargo`. That way, contributors who do not need to run
|
||||
// the `run-make` tests that need in-tree cargo do not need to spend time building in-tree
|
||||
// cargo.
|
||||
if mode == "run-make" {
|
||||
if mode == CompiletestMode::RunMake {
|
||||
// We need to pass the compiler that was used to compile run-make-support,
|
||||
// because we have to use the same compiler to compile rmake.rs recipes.
|
||||
let stage0_rustc_path = builder.compiler(0, test_compiler.host);
|
||||
|
|
@ -1910,17 +1929,18 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
}
|
||||
|
||||
// Avoid depending on rustdoc when we don't need it.
|
||||
if mode == "rustdoc"
|
||||
|| mode == "run-make"
|
||||
|| (mode == "ui" && is_rustdoc)
|
||||
|| mode == "rustdoc-js"
|
||||
|| mode == "rustdoc-json"
|
||||
|| suite == "coverage-run-rustdoc"
|
||||
if matches!(
|
||||
mode,
|
||||
CompiletestMode::RunMake
|
||||
| CompiletestMode::Rustdoc
|
||||
| CompiletestMode::RustdocJs
|
||||
| CompiletestMode::RustdocJson
|
||||
) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
|
||||
{
|
||||
cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
|
||||
}
|
||||
|
||||
if mode == "rustdoc-json" {
|
||||
if mode == CompiletestMode::RustdocJson {
|
||||
// Use the stage0 compiler for jsondocck
|
||||
let json_compiler = builder.compiler(0, builder.host_target);
|
||||
cmd.arg("--jsondocck-path")
|
||||
|
|
@ -1930,7 +1950,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
);
|
||||
}
|
||||
|
||||
if matches!(mode, "coverage-map" | "coverage-run") {
|
||||
if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
|
||||
let coverage_dump = builder.tool_exe(Tool::CoverageDump);
|
||||
cmd.arg("--coverage-dump-path").arg(coverage_dump);
|
||||
}
|
||||
|
|
@ -1957,7 +1977,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
cmd.arg("--sysroot-base").arg(sysroot);
|
||||
|
||||
cmd.arg("--suite").arg(suite);
|
||||
cmd.arg("--mode").arg(mode);
|
||||
cmd.arg("--mode").arg(mode.as_str());
|
||||
cmd.arg("--target").arg(target.rustc_target_arg());
|
||||
cmd.arg("--host").arg(&*test_compiler.host.triple);
|
||||
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
|
||||
|
|
@ -2036,7 +2056,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
|
||||
if let Some(ref nodejs) = builder.config.nodejs {
|
||||
cmd.arg("--nodejs").arg(nodejs);
|
||||
} else if mode == "rustdoc-js" {
|
||||
} else if mode == CompiletestMode::RustdocJs {
|
||||
panic!("need nodejs to run rustdoc-js suite");
|
||||
}
|
||||
if builder.config.rust_optimize_tests {
|
||||
|
|
@ -2055,7 +2075,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
|
||||
flags.push(format!(
|
||||
"-Cdebuginfo={}",
|
||||
if mode == "codegen" {
|
||||
if mode == CompiletestMode::Codegen {
|
||||
// codegen tests typically check LLVM IR and are sensitive to additional debuginfo.
|
||||
// So do not apply `rust.debuginfo-level-tests` for codegen tests.
|
||||
if builder.config.rust_debuginfo_level_tests
|
||||
|
|
@ -2122,7 +2142,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
cmd.arg("--android-cross-path").arg(android_cross_path);
|
||||
}
|
||||
|
||||
if mode == "debuginfo" {
|
||||
if mode == CompiletestMode::Debuginfo {
|
||||
if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
|
||||
{
|
||||
cmd.arg("--gdb").arg(gdb.as_ref());
|
||||
|
|
@ -2155,7 +2175,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
// in rustdoc-js mode, allow filters to be rs files or js files.
|
||||
// use a late-initialized Vec to avoid cloning for other modes.
|
||||
let mut paths_v;
|
||||
if mode == "rustdoc-js" {
|
||||
if mode == CompiletestMode::RustdocJs {
|
||||
paths_v = paths.to_vec();
|
||||
for p in &mut paths_v {
|
||||
if let Some(ext) = p.extension()
|
||||
|
|
@ -2237,7 +2257,9 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
cmd.arg("--host-rustcflags").arg(link_llvm);
|
||||
}
|
||||
|
||||
if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
|
||||
if !builder.config.dry_run()
|
||||
&& matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
|
||||
{
|
||||
// The llvm/bin directory contains many useful cross-platform
|
||||
// tools. Pass the path to run-make tests so they can use them.
|
||||
// (The coverage-run tests also need these tools to process
|
||||
|
|
@ -2249,7 +2271,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
|
||||
}
|
||||
|
||||
if !builder.config.dry_run() && mode == "run-make" {
|
||||
if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
|
||||
// If LLD is available, add it to the PATH
|
||||
if builder.config.lld_enabled {
|
||||
let lld_install_root =
|
||||
|
|
@ -2269,7 +2291,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
|
||||
// Only pass correct values for these flags for the `run-make` suite as it
|
||||
// requires that a C++ compiler was configured which isn't always the case.
|
||||
if !builder.config.dry_run() && mode == "run-make" {
|
||||
if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
|
||||
let mut cflags = builder.cc_handled_clags(target, CLang::C);
|
||||
cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
|
||||
let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
|
||||
|
|
@ -2385,7 +2407,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
builder.metrics.begin_test_suite(
|
||||
build_helper::metrics::TestSuiteMetadata::Compiletest {
|
||||
suite: suite.into(),
|
||||
mode: mode.into(),
|
||||
mode: mode.to_string(),
|
||||
compare_mode: None,
|
||||
target: self.target.triple.to_string(),
|
||||
host: self.test_compiler.host.triple.to_string(),
|
||||
|
|
@ -2408,7 +2430,7 @@ Please disable assertions with `rust.debug-assertions = false`.
|
|||
builder.metrics.begin_test_suite(
|
||||
build_helper::metrics::TestSuiteMetadata::Compiletest {
|
||||
suite: suite.into(),
|
||||
mode: mode.into(),
|
||||
mode: mode.to_string(),
|
||||
compare_mode: Some(compare_mode.into()),
|
||||
target: self.target.triple.to_string(),
|
||||
host: self.test_compiler.host.triple.to_string(),
|
||||
|
|
|
|||
71
src/bootstrap/src/core/build_steps/test/compiletest.rs
Normal file
71
src/bootstrap/src/core/build_steps/test/compiletest.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
use std::fmt;
|
||||
|
||||
/// Enum of all the "test modes" understood by compiletest.
|
||||
///
|
||||
/// Some of these mode names happen to overlap with the names of test suite
|
||||
/// directories, but the relationship between modes and suites is not 1:1.
|
||||
/// For example:
|
||||
/// - Mode `ui` is used by suites `tests/ui` and `tests/rustdoc-ui`
|
||||
/// - Suite `tests/coverage` uses modes `coverage-map` and `coverage-run`
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum CompiletestMode {
|
||||
// tidy-alphabetical-start
|
||||
Assembly,
|
||||
Codegen,
|
||||
CodegenUnits,
|
||||
CoverageMap,
|
||||
CoverageRun,
|
||||
Crashes,
|
||||
Debuginfo,
|
||||
Incremental,
|
||||
MirOpt,
|
||||
Pretty,
|
||||
RunMake,
|
||||
Rustdoc,
|
||||
RustdocJs,
|
||||
RustdocJson,
|
||||
Ui,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
impl CompiletestMode {
|
||||
/// Returns a string representing this mode, which can be passed to
|
||||
/// compiletest via a command-line argument.
|
||||
///
|
||||
/// These mode names must be kept in sync with the ones understood by
|
||||
/// compiletest's `TestMode`, but they change so rarely that doing so
|
||||
/// manually should not be burdensome.
|
||||
pub(crate) const fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
// tidy-alphabetical-start
|
||||
Self::Assembly => "assembly",
|
||||
Self::Codegen => "codegen",
|
||||
Self::CodegenUnits => "codegen-units",
|
||||
Self::CoverageMap => "coverage-map",
|
||||
Self::CoverageRun => "coverage-run",
|
||||
Self::Crashes => "crashes",
|
||||
Self::Debuginfo => "debuginfo",
|
||||
Self::Incremental => "incremental",
|
||||
Self::MirOpt => "mir-opt",
|
||||
Self::Pretty => "pretty",
|
||||
Self::RunMake => "run-make",
|
||||
Self::Rustdoc => "rustdoc",
|
||||
Self::RustdocJs => "rustdoc-js",
|
||||
Self::RustdocJson => "rustdoc-json",
|
||||
Self::Ui => "ui",
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CompiletestMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CompiletestMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<Self as fmt::Display>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
|
@ -346,7 +346,7 @@ fn test_test_coverage() {
|
|||
let mut cache = run_build(&config.paths.clone(), config);
|
||||
|
||||
let modes =
|
||||
cache.all::<test::Coverage>().iter().map(|(step, ())| step.mode).collect::<Vec<_>>();
|
||||
cache.inspect_all_steps_of_type::<test::Coverage, _>(|step, ()| step.mode.as_str());
|
||||
assert_eq!(modes, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,16 +270,18 @@ impl Cache {
|
|||
|
||||
#[cfg(test)]
|
||||
impl Cache {
|
||||
pub fn all<S: Ord + Step>(&mut self) -> Vec<(S, S::Output)> {
|
||||
let cache = self.cache.get_mut();
|
||||
let type_id = TypeId::of::<S>();
|
||||
let mut v = cache
|
||||
.remove(&type_id)
|
||||
.map(|b| b.downcast::<HashMap<S, S::Output>>().expect("correct type"))
|
||||
.map(|m| m.into_iter().collect::<Vec<_>>())
|
||||
pub(crate) fn inspect_all_steps_of_type<S: Step, T: Ord>(
|
||||
&self,
|
||||
map_fn: impl Fn(&S, &S::Output) -> T,
|
||||
) -> Vec<T> {
|
||||
let cache = self.cache.borrow();
|
||||
let mut values = cache
|
||||
.get(&TypeId::of::<S>())
|
||||
.map(|any| any.downcast_ref::<HashMap<S, S::Output>>().expect("correct type"))
|
||||
.map(|m| m.iter().map(|(step, output)| map_fn(step, output)).collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
v.sort_by_key(|(s, _)| s.clone());
|
||||
v
|
||||
values.sort();
|
||||
values
|
||||
}
|
||||
|
||||
pub fn contains<S: Step>(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ The `#[doc]` attribute lets you control various aspects of how `rustdoc` does
|
|||
its job.
|
||||
|
||||
The most basic function of `#[doc]` is to handle the actual documentation
|
||||
text. That is, `///` is syntax sugar for `#[doc]`. This means that these two
|
||||
are the same:
|
||||
text. That is, `///` is syntax sugar for `#[doc]` (as is `//!` for `#![doc]`).
|
||||
This means that these two are the same:
|
||||
|
||||
```rust,no_run
|
||||
/// This is a doc comment.
|
||||
|
|
|
|||
|
|
@ -255,8 +255,17 @@ fn parse_config(args: Vec<String>) -> Config {
|
|||
}
|
||||
}
|
||||
|
||||
let target = opt_str2(matches.opt_str("target"));
|
||||
let host = matches.opt_str("host").expect("`--host` must be unconditionally specified");
|
||||
let target = matches.opt_str("target").expect("`--target` must be unconditionally specified");
|
||||
|
||||
let android_cross_path = matches.opt_str("android-cross-path").map(Utf8PathBuf::from);
|
||||
|
||||
// FIXME: `adb_path` should be an `Option<Utf8PathBuf>`...
|
||||
let adb_path = matches.opt_str("adb-path").map(Utf8PathBuf::from).unwrap_or_default();
|
||||
// FIXME: `adb_test_dir` should be an `Option<Utf8PathBuf>`...
|
||||
let adb_test_dir = matches.opt_str("adb-test-dir").map(Utf8PathBuf::from).unwrap_or_default();
|
||||
let adb_device_status = target.contains("android") && !adb_test_dir.as_str().is_empty();
|
||||
|
||||
// FIXME: `cdb_version` is *derived* from cdb, but it's *not* technically a config!
|
||||
let cdb = debuggers::discover_cdb(matches.opt_str("cdb"), &target);
|
||||
let cdb_version = cdb.as_deref().and_then(debuggers::query_cdb_version);
|
||||
|
|
@ -433,7 +442,7 @@ fn parse_config(args: Vec<String>) -> Config {
|
|||
optimize_tests: matches.opt_present("optimize-tests"),
|
||||
rust_randomized_layout: matches.opt_present("rust-randomized-layout"),
|
||||
target,
|
||||
host: opt_str2(matches.opt_str("host")),
|
||||
host,
|
||||
cdb,
|
||||
cdb_version,
|
||||
gdb,
|
||||
|
|
@ -443,11 +452,9 @@ fn parse_config(args: Vec<String>) -> Config {
|
|||
llvm_version,
|
||||
system_llvm: matches.opt_present("system-llvm"),
|
||||
android_cross_path,
|
||||
adb_path: Utf8PathBuf::from(opt_str2(matches.opt_str("adb-path"))),
|
||||
adb_test_dir: Utf8PathBuf::from(opt_str2(matches.opt_str("adb-test-dir"))),
|
||||
adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
|
||||
&& "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
|
||||
&& !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
|
||||
adb_path,
|
||||
adb_test_dir,
|
||||
adb_device_status,
|
||||
verbose: matches.opt_present("verbose"),
|
||||
only_modified: matches.opt_present("only-modified"),
|
||||
color,
|
||||
|
|
@ -493,13 +500,6 @@ fn parse_config(args: Vec<String>) -> Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn opt_str2(maybestr: Option<String>) -> String {
|
||||
match maybestr {
|
||||
None => "(none)".to_owned(),
|
||||
Some(s) => s,
|
||||
}
|
||||
}
|
||||
|
||||
/// Called by `main` after the config has been parsed.
|
||||
fn run_tests(config: Arc<Config>) {
|
||||
debug!(?config, "run_tests");
|
||||
|
|
|
|||
94
tests/pretty/delegation_inline_attribute.pp
Normal file
94
tests/pretty/delegation_inline_attribute.pp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:delegation_inline_attribute.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(fn_delegation)]
|
||||
#[attr = MacroUse {arguments: UseAll}]
|
||||
extern crate std;
|
||||
#[prelude_import]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
|
||||
mod to_reuse {
|
||||
fn foo(x: usize) -> usize { x }
|
||||
}
|
||||
|
||||
// Check that #[inline(hint)] is added to foo reuse
|
||||
#[attr = Inline(Hint)]
|
||||
fn bar(arg0: _) -> _ { to_reuse::foo(self + 1) }
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) { }
|
||||
fn foo1(&self) { }
|
||||
fn foo2(&self) { }
|
||||
fn foo3(&self) { }
|
||||
fn foo4(&self) { }
|
||||
}
|
||||
|
||||
impl Trait for u8 { }
|
||||
|
||||
struct S(u8);
|
||||
|
||||
mod to_import {
|
||||
fn check(arg: &'_ u8) -> &'_ u8 { arg }
|
||||
}
|
||||
|
||||
impl Trait for S {
|
||||
// Check that #[inline(hint)] is added to foo reuse
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo(self: _)
|
||||
->
|
||||
_ {
|
||||
{
|
||||
// Check that #[inline(hint)] is added to foo0 reuse inside another reuse
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) }
|
||||
|
||||
// Check that #[inline(hint)] is added when other attributes present in inner reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
|
||||
// Check that #[inline(never)] is preserved in inner reuse
|
||||
#[attr = Inline(Never)]
|
||||
fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
|
||||
// Check that #[inline(always)] is preserved in inner reuse
|
||||
#[attr = Inline(Always)]
|
||||
fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
|
||||
// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Inline(Never)]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) }
|
||||
}.foo()
|
||||
}
|
||||
|
||||
// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
#[attr = Inline(Hint)]
|
||||
fn foo1(self: _) -> _ { self.0.foo1() }
|
||||
|
||||
// Check that #[inline(never)] is preserved in trait reuse
|
||||
#[attr = Inline(Never)]
|
||||
fn foo2(self: _) -> _ { self.0.foo2() }
|
||||
|
||||
// Check that #[inline(always)] is preserved in trait reuse
|
||||
#[attr = Inline(Always)]
|
||||
fn foo3(self: _) -> _ { self.0.foo3() }
|
||||
|
||||
// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
|
||||
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
|
||||
#[attr = Inline(Never)]
|
||||
#[attr = MustUse]
|
||||
#[attr = Cold]
|
||||
fn foo4(self: _) -> _ { self.0.foo4() }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
104
tests/pretty/delegation_inline_attribute.rs
Normal file
104
tests/pretty/delegation_inline_attribute.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:delegation_inline_attribute.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(fn_delegation)]
|
||||
|
||||
mod to_reuse {
|
||||
pub fn foo(x: usize) -> usize {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
// Check that #[inline(hint)] is added to foo reuse
|
||||
reuse to_reuse::foo as bar {
|
||||
self + 1
|
||||
}
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) {}
|
||||
fn foo1(&self) {}
|
||||
fn foo2(&self) {}
|
||||
fn foo3(&self) {}
|
||||
fn foo4(&self) {}
|
||||
}
|
||||
|
||||
impl Trait for u8 {}
|
||||
|
||||
struct S(u8);
|
||||
|
||||
mod to_import {
|
||||
pub fn check(arg: &u8) -> &u8 { arg }
|
||||
}
|
||||
|
||||
impl Trait for S {
|
||||
// Check that #[inline(hint)] is added to foo reuse
|
||||
reuse Trait::foo {
|
||||
// Check that #[inline(hint)] is added to foo0 reuse inside another reuse
|
||||
reuse to_reuse::foo as foo0 {
|
||||
self + 1
|
||||
}
|
||||
|
||||
// Check that #[inline(hint)] is added when other attributes present in inner reuse
|
||||
#[cold]
|
||||
#[must_use]
|
||||
#[deprecated]
|
||||
reuse to_reuse::foo as foo1 {
|
||||
self / 2
|
||||
}
|
||||
|
||||
// Check that #[inline(never)] is preserved in inner reuse
|
||||
#[inline(never)]
|
||||
reuse to_reuse::foo as foo2 {
|
||||
self / 2
|
||||
}
|
||||
|
||||
// Check that #[inline(always)] is preserved in inner reuse
|
||||
#[inline(always)]
|
||||
reuse to_reuse::foo as foo3 {
|
||||
self / 2
|
||||
}
|
||||
|
||||
// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
|
||||
#[cold]
|
||||
#[must_use]
|
||||
#[inline(never)]
|
||||
#[deprecated]
|
||||
reuse to_reuse::foo as foo4 {
|
||||
self / 2
|
||||
}
|
||||
}
|
||||
|
||||
// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
|
||||
#[cold]
|
||||
#[must_use]
|
||||
#[deprecated]
|
||||
reuse Trait::foo1 {
|
||||
self.0
|
||||
}
|
||||
|
||||
// Check that #[inline(never)] is preserved in trait reuse
|
||||
#[inline(never)]
|
||||
reuse Trait::foo2 {
|
||||
self.0
|
||||
}
|
||||
|
||||
// Check that #[inline(always)] is preserved in trait reuse
|
||||
#[inline(always)]
|
||||
reuse Trait::foo3 {
|
||||
self.0
|
||||
}
|
||||
|
||||
// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
|
||||
#[cold]
|
||||
#[must_use]
|
||||
#[inline(never)]
|
||||
#[deprecated]
|
||||
reuse Trait::foo4 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ use ::std::prelude::rust_2015::*;
|
|||
fn b<C>(e: C) { }
|
||||
|
||||
trait G {
|
||||
#[attr = Inline(Hint)]
|
||||
fn b(arg0: _) -> _ { b({ }) }
|
||||
}
|
||||
|
||||
|
|
@ -19,6 +20,7 @@ mod m {
|
|||
fn add(a: u32, b: u32) -> u32 { a + b }
|
||||
}
|
||||
|
||||
#[attr = Inline(Hint)]
|
||||
fn add(arg0: _, arg1: _) -> _ { m::add(arg0, arg1) }
|
||||
|
||||
fn main() { { let _ = add(1, 2); }; }
|
||||
|
|
|
|||
3
tests/run-make/no-builtins-linker-plugin-lto/main.rs
Normal file
3
tests/run-make/no-builtins-linker-plugin-lto/main.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
no_builtins::foo();
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#![no_builtins]
|
||||
|
||||
#[inline(never)]
|
||||
pub fn foo() {}
|
||||
53
tests/run-make/no-builtins-linker-plugin-lto/rmake.rs
Normal file
53
tests/run-make/no-builtins-linker-plugin-lto/rmake.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
//@ only-x86_64-unknown-linux-gnu
|
||||
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use run_make_support::{cwd, has_extension, llvm_ar, llvm_bcanalyzer, rust_lib_name, rustc};
|
||||
|
||||
// A regression test for #146133.
|
||||
|
||||
fn main() {
|
||||
// Compile a `#![no_builtins]` rlib crate with `-Clinker-plugin-lto`.
|
||||
// It is acceptable to generate bitcode for rlib, so there is no need to check something.
|
||||
rustc().input("no_builtins.rs").crate_type("rlib").linker_plugin_lto("on").run();
|
||||
|
||||
// Checks that rustc's LTO doesn't emit any bitcode to the linker.
|
||||
let stdout = rustc()
|
||||
.input("main.rs")
|
||||
.extern_("no_builtins", rust_lib_name("no_builtins"))
|
||||
.lto("thin")
|
||||
.print("link-args")
|
||||
.arg("-Csave-temps")
|
||||
.arg("-Clinker-features=-lld")
|
||||
.run()
|
||||
.stdout_utf8();
|
||||
for object in stdout
|
||||
.split_whitespace()
|
||||
.map(|s| s.trim_matches('"'))
|
||||
.filter(|path| has_extension(path, "rlib") || has_extension(path, "o"))
|
||||
{
|
||||
let object_path = if !fs::exists(object).unwrap() {
|
||||
cwd().join(object)
|
||||
} else {
|
||||
Path::new(object).to_path_buf()
|
||||
};
|
||||
if has_extension(object, "rlib") {
|
||||
let ar_stdout = llvm_ar().arg("t").arg(&object_path).run().stdout_utf8();
|
||||
llvm_ar().extract().arg(&object_path).run();
|
||||
for object in ar_stdout.split_whitespace().filter(|o| has_extension(o, "o")) {
|
||||
let object_path = cwd().join(object);
|
||||
not_bitcode(&object_path);
|
||||
}
|
||||
} else {
|
||||
not_bitcode(&object_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn not_bitcode(object: &Path) {
|
||||
llvm_bcanalyzer()
|
||||
.input(object)
|
||||
.run_fail()
|
||||
.assert_stderr_contains("llvm-bcanalyzer: Invalid record at top-level");
|
||||
}
|
||||
8
tests/ui/check-cfg/nested-cfg.rs
Normal file
8
tests/ui/check-cfg/nested-cfg.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//@ check-pass
|
||||
|
||||
#[cfg(unknown)] //~ WARN unexpected `cfg` condition name
|
||||
#[cfg(false)]
|
||||
#[cfg(unknown)] // Should not warn
|
||||
fn foo() {}
|
||||
|
||||
fn main() {}
|
||||
23
tests/ui/check-cfg/nested-cfg.stderr
Normal file
23
tests/ui/check-cfg/nested-cfg.stderr
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
warning: unexpected `cfg` condition name: `unknown`
|
||||
--> $DIR/nested-cfg.rs:3:7
|
||||
|
|
||||
LL | #[cfg(unknown)]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: expected names are: `FALSE` and `test` and 31 more
|
||||
= help: to expect this configuration use `--check-cfg=cfg(unknown)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
help: found config with similar value
|
||||
|
|
||||
LL - #[cfg(unknown)]
|
||||
LL + #[cfg(target_os = "unknown")]
|
||||
|
|
||||
help: found config with similar value
|
||||
|
|
||||
LL - #[cfg(unknown)]
|
||||
LL + #[cfg(target_vendor = "unknown")]
|
||||
|
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#[link(name = "foo", cfg(foo))]
|
||||
#[link(name = "foo", cfg(false))]
|
||||
//~^ ERROR: is unstable
|
||||
extern "C" {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0658]: link cfg is unstable
|
||||
--> $DIR/feature-gate-link_cfg.rs:1:22
|
||||
|
|
||||
LL | #[link(name = "foo", cfg(foo))]
|
||||
| ^^^^^^^^
|
||||
LL | #[link(name = "foo", cfg(false))]
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(link_cfg)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
extern crate link_cfg_works_transitive_dylib;
|
||||
extern crate link_cfg_works_transitive_rlib;
|
||||
|
||||
#[link(name = "foo", cfg(foo))]
|
||||
#[link(name = "foo", cfg(false))]
|
||||
extern "C" {}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
10
tests/ui/lint/improper-ctypes/unsafe-binder-basic.rs
Normal file
10
tests/ui/lint/improper-ctypes/unsafe-binder-basic.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#![feature(unsafe_binders)]
|
||||
#![expect(incomplete_features)]
|
||||
#![deny(improper_ctypes)]
|
||||
|
||||
extern "C" {
|
||||
fn exit_2(x: unsafe<'a> &'a ());
|
||||
//~^ ERROR `extern` block uses type `unsafe<'a> &'a ()`, which is not FFI-safe
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
15
tests/ui/lint/improper-ctypes/unsafe-binder-basic.stderr
Normal file
15
tests/ui/lint/improper-ctypes/unsafe-binder-basic.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error: `extern` block uses type `unsafe<'a> &'a ()`, which is not FFI-safe
|
||||
--> $DIR/unsafe-binder-basic.rs:6:18
|
||||
|
|
||||
LL | fn exit_2(x: unsafe<'a> &'a ());
|
||||
| ^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: unsafe binders are incompatible with foreign function interfaces
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unsafe-binder-basic.rs:3:9
|
||||
|
|
||||
LL | #![deny(improper_ctypes)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -2,5 +2,6 @@ fn main() {
|
|||
cfg!(); //~ ERROR macro requires a cfg-pattern
|
||||
cfg!(123); //~ ERROR malformed `cfg` macro input
|
||||
cfg!(foo = 123); //~ ERROR malformed `cfg` macro input
|
||||
cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern
|
||||
cfg!(false, false); //~ ERROR expected 1 cfg-pattern
|
||||
cfg!(foo); //~ WARN unexpected `cfg` condition name: `foo`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,20 @@ LL | cfg!(foo = 123);
|
|||
error: expected 1 cfg-pattern
|
||||
--> $DIR/cfg.rs:5:5
|
||||
|
|
||||
LL | cfg!(foo, bar);
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | cfg!(false, false);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/cfg.rs:6:10
|
||||
|
|
||||
LL | cfg!(foo);
|
||||
| ^^^
|
||||
|
|
||||
= help: expected names are: `FALSE` and `test` and 31 more
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
|
|
|||
|
|
@ -89,9 +89,11 @@ cfg_select! {
|
|||
cfg_select! {
|
||||
a + 1 => {}
|
||||
//~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `+`
|
||||
//~| WARN unexpected `cfg` condition name
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
cfg!() => {}
|
||||
//~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `!`
|
||||
//~| WARN unexpected `cfg` condition name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,12 +60,32 @@ LL | a + 1 => {}
|
|||
| ^ expected one of `(`, `::`, `=>`, or `=`
|
||||
|
||||
error: expected one of `(`, `::`, `=>`, or `=`, found `!`
|
||||
--> $DIR/cfg_select.rs:95:8
|
||||
--> $DIR/cfg_select.rs:96:8
|
||||
|
|
||||
LL | cfg!() => {}
|
||||
| ^ expected one of `(`, `::`, `=>`, or `=`
|
||||
|
||||
error: aborting due to 9 previous errors; 1 warning emitted
|
||||
warning: unexpected `cfg` condition name: `a`
|
||||
--> $DIR/cfg_select.rs:90:5
|
||||
|
|
||||
LL | a + 1 => {}
|
||||
| ^ help: found config with similar value: `target_feature = "a"`
|
||||
|
|
||||
= help: expected names are: `FALSE` and `test` and 31 more
|
||||
= help: to expect this configuration use `--check-cfg=cfg(a)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition name: `cfg`
|
||||
--> $DIR/cfg_select.rs:96:5
|
||||
|
|
||||
LL | cfg!() => {}
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(cfg)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
error: aborting due to 9 previous errors; 3 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0537, E0539.
|
||||
For more information about an error, try `rustc --explain E0537`.
|
||||
|
|
|
|||
13
tests/ui/privacy/auxiliary/non_exhaustive_with_private.rs
Normal file
13
tests/ui/privacy/auxiliary/non_exhaustive_with_private.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Auxiliary crate for testing non-exhaustive struct with private fields
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Foo {
|
||||
pub my_field: u32,
|
||||
private_field: i32,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Bar {
|
||||
pub my_field: u32,
|
||||
pub missing_field: i32,
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//@ aux-build:non_exhaustive_with_private.rs
|
||||
|
||||
extern crate non_exhaustive_with_private;
|
||||
|
||||
use non_exhaustive_with_private::{Bar, Foo};
|
||||
|
||||
fn main() {
|
||||
let foo = Foo {
|
||||
//~^ ERROR cannot create non-exhaustive struct using struct expression
|
||||
my_field: 10,
|
||||
};
|
||||
|
||||
let bar = Bar {
|
||||
//~^ ERROR cannot create non-exhaustive struct using struct expression
|
||||
my_field: 10,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
error[E0639]: cannot create non-exhaustive struct using struct expression
|
||||
--> $DIR/non-exhaustive-with-private-fields-147513.rs:8:15
|
||||
|
|
||||
LL | let foo = Foo {
|
||||
| _______________^
|
||||
LL | |
|
||||
LL | | my_field: 10,
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
||||
error[E0639]: cannot create non-exhaustive struct using struct expression
|
||||
--> $DIR/non-exhaustive-with-private-fields-147513.rs:13:15
|
||||
|
|
||||
LL | let bar = Bar {
|
||||
| _______________^
|
||||
LL | |
|
||||
LL | | my_field: 10,
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0639`.
|
||||
|
|
@ -1679,12 +1679,6 @@ days-threshold = 28
|
|||
# Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
|
||||
[issue-links]
|
||||
|
||||
# Prevents mentions in commits to avoid users being spammed
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/no-mentions.html
|
||||
[no-mentions]
|
||||
# Subtree update authors can't fix it, no point in warning.
|
||||
exclude-titles = ["subtree update"]
|
||||
|
||||
# Allow members to formally register concerns (`@rustbot concern my concern`)
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/concern.html
|
||||
[concern]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue