Merge pull request #4832 from rust-lang/rustup-2026-01-25
Automatic Rustup
This commit is contained in:
commit
a109785719
362 changed files with 8518 additions and 2816 deletions
10
Cargo.lock
10
Cargo.lock
|
|
@ -630,7 +630,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
|||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.94"
|
||||
version = "0.1.95"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"askama",
|
||||
|
|
@ -657,7 +657,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_config"
|
||||
version = "0.1.94"
|
||||
version = "0.1.95"
|
||||
dependencies = [
|
||||
"clippy_utils",
|
||||
"itertools",
|
||||
|
|
@ -681,7 +681,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.94"
|
||||
version = "0.1.95"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cargo_metadata 0.18.1",
|
||||
|
|
@ -713,7 +713,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.94"
|
||||
version = "0.1.95"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"itertools",
|
||||
|
|
@ -1117,7 +1117,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.94"
|
||||
version = "0.1.95"
|
||||
|
||||
[[package]]
|
||||
name = "derive-where"
|
||||
|
|
|
|||
|
|
@ -3626,6 +3626,7 @@ impl Item {
|
|||
pub fn opt_generics(&self) -> Option<&Generics> {
|
||||
match &self.kind {
|
||||
ItemKind::ExternCrate(..)
|
||||
| ItemKind::ConstBlock(_)
|
||||
| ItemKind::Use(_)
|
||||
| ItemKind::Mod(..)
|
||||
| ItemKind::ForeignMod(_)
|
||||
|
|
@ -3895,6 +3896,17 @@ impl ConstItemRhs {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct ConstBlockItem {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub block: Box<Block>,
|
||||
}
|
||||
|
||||
impl ConstBlockItem {
|
||||
pub const IDENT: Ident = Ident { name: kw::Underscore, span: DUMMY_SP };
|
||||
}
|
||||
|
||||
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum ItemKind {
|
||||
|
|
@ -3914,6 +3926,11 @@ pub enum ItemKind {
|
|||
///
|
||||
/// E.g., `const FOO: i32 = 42;`.
|
||||
Const(Box<ConstItem>),
|
||||
/// A module-level const block.
|
||||
/// Equivalent to `const _: () = const { ... };`.
|
||||
///
|
||||
/// E.g., `const { assert!(true) }`.
|
||||
ConstBlock(ConstBlockItem),
|
||||
/// A function declaration (`fn`).
|
||||
///
|
||||
/// E.g., `fn foo(bar: usize) -> usize { .. }`.
|
||||
|
|
@ -3990,6 +4007,8 @@ impl ItemKind {
|
|||
| ItemKind::MacroDef(ident, _)
|
||||
| ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
|
||||
|
||||
ItemKind::ConstBlock(_) => Some(ConstBlockItem::IDENT),
|
||||
|
||||
ItemKind::Use(_)
|
||||
| ItemKind::ForeignMod(_)
|
||||
| ItemKind::GlobalAsm(_)
|
||||
|
|
@ -4003,9 +4022,9 @@ impl ItemKind {
|
|||
pub fn article(&self) -> &'static str {
|
||||
use ItemKind::*;
|
||||
match self {
|
||||
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
|
||||
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
|
||||
| Delegation(..) | DelegationMac(..) => "a",
|
||||
Use(..) | Static(..) | Const(..) | ConstBlock(..) | Fn(..) | Mod(..)
|
||||
| GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..)
|
||||
| MacroDef(..) | Delegation(..) | DelegationMac(..) => "a",
|
||||
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
|
||||
}
|
||||
}
|
||||
|
|
@ -4016,6 +4035,7 @@ impl ItemKind {
|
|||
ItemKind::Use(..) => "`use` import",
|
||||
ItemKind::Static(..) => "static item",
|
||||
ItemKind::Const(..) => "constant item",
|
||||
ItemKind::ConstBlock(..) => "const block",
|
||||
ItemKind::Fn(..) => "function",
|
||||
ItemKind::Mod(..) => "module",
|
||||
ItemKind::ForeignMod(..) => "extern block",
|
||||
|
|
@ -4045,7 +4065,18 @@ impl ItemKind {
|
|||
| Self::Trait(box Trait { generics, .. })
|
||||
| Self::TraitAlias(box TraitAlias { generics, .. })
|
||||
| Self::Impl(Impl { generics, .. }) => Some(generics),
|
||||
_ => None,
|
||||
|
||||
Self::ExternCrate(..)
|
||||
| Self::Use(..)
|
||||
| Self::Static(..)
|
||||
| Self::ConstBlock(..)
|
||||
| Self::Mod(..)
|
||||
| Self::ForeignMod(..)
|
||||
| Self::GlobalAsm(..)
|
||||
| Self::MacCall(..)
|
||||
| Self::MacroDef(..)
|
||||
| Self::Delegation(..)
|
||||
| Self::DelegationMac(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
ByRef,
|
||||
Closure,
|
||||
Const,
|
||||
ConstBlockItem,
|
||||
ConstItem,
|
||||
ConstItemRhs,
|
||||
Defaultness,
|
||||
|
|
@ -825,6 +826,8 @@ macro_rules! common_visitor_and_walkers {
|
|||
visit_visitable!($($mut)? vis, use_tree),
|
||||
ItemKind::Static(item) =>
|
||||
visit_visitable!($($mut)? vis, item),
|
||||
ItemKind::ConstBlock(item) =>
|
||||
visit_visitable!($($mut)? vis, item),
|
||||
ItemKind::Const(item) =>
|
||||
visit_visitable!($($mut)? vis, item),
|
||||
ItemKind::Mod(safety, ident, mod_kind) =>
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
| ItemKind::Use(..)
|
||||
| ItemKind::Static(..)
|
||||
| ItemKind::Const(..)
|
||||
| ItemKind::ConstBlock(..)
|
||||
| ItemKind::Mod(..)
|
||||
| ItemKind::ForeignMod(..)
|
||||
| ItemKind::GlobalAsm(..)
|
||||
|
|
@ -282,8 +283,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_define_opaque(hir_id, define_opaque);
|
||||
hir::ItemKind::Static(*m, ident, ty, body_id)
|
||||
}
|
||||
ItemKind::Const(box ast::ConstItem {
|
||||
ident, generics, ty, rhs, define_opaque, ..
|
||||
ItemKind::Const(box ConstItem {
|
||||
defaultness: _,
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
define_opaque,
|
||||
}) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
let (generics, (ty, rhs)) = self.lower_generics(
|
||||
|
|
@ -302,6 +308,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_define_opaque(hir_id, &define_opaque);
|
||||
hir::ItemKind::Const(ident, generics, ty, rhs)
|
||||
}
|
||||
ItemKind::ConstBlock(ConstBlockItem { span, id, block }) => hir::ItemKind::Const(
|
||||
self.lower_ident(ConstBlockItem::IDENT),
|
||||
hir::Generics::empty(),
|
||||
self.arena.alloc(self.ty_tup(DUMMY_SP, &[])),
|
||||
hir::ConstItemRhs::Body({
|
||||
let body = hir::Expr {
|
||||
hir_id: self.lower_node_id(*id),
|
||||
kind: hir::ExprKind::Block(self.lower_block(block, false), None),
|
||||
span: self.lower_span(*span),
|
||||
};
|
||||
self.record_body(&[], body)
|
||||
}),
|
||||
),
|
||||
ItemKind::Fn(box Fn {
|
||||
sig: FnSig { decl, header, span: fn_sig_span },
|
||||
ident,
|
||||
|
|
|
|||
|
|
@ -537,6 +537,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(super_let, "`super let` is experimental");
|
||||
gate_all!(frontmatter, "frontmatters are experimental");
|
||||
gate_all!(coroutines, "coroutine syntax is experimental");
|
||||
gate_all!(const_block_items, "const block items are experimental");
|
||||
|
||||
if !visitor.features.never_patterns() {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
|
|
|||
|
|
@ -205,6 +205,17 @@ impl<'a> State<'a> {
|
|||
define_opaque.as_deref(),
|
||||
);
|
||||
}
|
||||
ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => {
|
||||
let ib = self.ibox(INDENT_UNIT);
|
||||
self.word("const");
|
||||
self.nbsp();
|
||||
{
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
self.print_block_with_attrs(block, &[], cb, ib);
|
||||
}
|
||||
self.end(ib);
|
||||
}
|
||||
ast::ItemKind::Const(box ast::ConstItem {
|
||||
defaultness,
|
||||
ident,
|
||||
|
|
|
|||
|
|
@ -360,7 +360,8 @@ fn parse_cfg_attr_internal<'a>(
|
|||
) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> {
|
||||
// Parse cfg predicate
|
||||
let pred_start = parser.token.span;
|
||||
let meta = MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints)?;
|
||||
let meta =
|
||||
MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?;
|
||||
let pred_span = pred_start.with_hi(parser.token.span.hi());
|
||||
|
||||
let cfg_predicate = AttributeParser::parse_single_args(
|
||||
|
|
@ -375,7 +376,7 @@ fn parse_cfg_attr_internal<'a>(
|
|||
CRATE_NODE_ID,
|
||||
Target::Crate,
|
||||
features,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&CFG_ATTR_TEMPLATE,
|
||||
|
|
|
|||
|
|
@ -78,8 +78,9 @@ pub fn parse_cfg_select(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints)
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let meta =
|
||||
MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true })
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let cfg_span = meta.span();
|
||||
let cfg = AttributeParser::parse_single_args(
|
||||
sess,
|
||||
|
|
@ -94,7 +95,7 @@ pub fn parse_cfg_select(
|
|||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
features,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&AttributeTemplate::default(),
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ impl Stage for Late {
|
|||
}
|
||||
|
||||
fn should_emit(&self) -> ShouldEmit {
|
||||
ShouldEmit::ErrorsAndLints
|
||||
ShouldEmit::ErrorsAndLints { recover: true }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
|
|||
pub(crate) fn emit_lint(&mut self, lint: &'static Lint, kind: AttributeLintKind, span: Span) {
|
||||
if !matches!(
|
||||
self.stage.should_emit(),
|
||||
ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
|
||||
ShouldEmit::ErrorsAndLints { .. } | ShouldEmit::EarlyFatal { also_emit_lints: true }
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -765,9 +765,18 @@ pub enum ShouldEmit {
|
|||
EarlyFatal { also_emit_lints: bool },
|
||||
/// The operation will emit errors and lints.
|
||||
/// This is usually what you need.
|
||||
ErrorsAndLints,
|
||||
/// The operation will emit *not* errors and lints.
|
||||
/// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`.
|
||||
ErrorsAndLints {
|
||||
/// Whether [`ArgParser`] will attempt to recover from errors.
|
||||
///
|
||||
/// If true, it will attempt to recover from bad input (like an invalid literal). Setting
|
||||
/// this to false will instead return early, and not raise errors except at the top level
|
||||
/// (in [`ArgParser::from_attr_args`]).
|
||||
recover: bool,
|
||||
},
|
||||
/// The operation will *not* emit errors and lints.
|
||||
///
|
||||
/// The parser can still call `delay_bug`, so you *must* ensure that this operation will also be
|
||||
/// called with `ShouldEmit::ErrorsAndLints`.
|
||||
Nothing,
|
||||
}
|
||||
|
||||
|
|
@ -776,7 +785,7 @@ impl ShouldEmit {
|
|||
match self {
|
||||
ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
|
||||
ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
|
||||
ShouldEmit::ErrorsAndLints => diag.emit(),
|
||||
ShouldEmit::ErrorsAndLints { .. } => diag.emit(),
|
||||
ShouldEmit::Nothing => diag.delay_as_bug(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_errors::{Diag, PResult};
|
|||
use rustc_hir::{self as hir, AttrPath};
|
||||
use rustc_parse::exp;
|
||||
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr};
|
||||
use rustc_session::errors::{create_lit_error, report_lit_error};
|
||||
use rustc_session::errors::create_lit_error;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
@ -113,16 +113,29 @@ impl ArgParser {
|
|||
Some(match value {
|
||||
AttrArgs::Empty => Self::NoArgs,
|
||||
AttrArgs::Delimited(args) => {
|
||||
// The arguments of rustc_dummy and diagnostic::do_not_recommend are not validated
|
||||
// if the arguments are delimited.
|
||||
// See https://doc.rust-lang.org/reference/attributes/diagnostics.html#r-attributes.diagnostic.namespace.unknown-invalid-syntax
|
||||
if parts == &[sym::rustc_dummy]
|
||||
|| parts == &[sym::diagnostic, sym::do_not_recommend]
|
||||
{
|
||||
return Some(ArgParser::List(MetaItemListParser {
|
||||
sub_parsers: ThinVec::new(),
|
||||
span: args.dspan.entire(),
|
||||
}));
|
||||
// Diagnostic attributes can't error if they encounter non meta item syntax.
|
||||
// However, the current syntax for diagnostic attributes is meta item syntax.
|
||||
// Therefore we can substitute with a dummy value on invalid syntax.
|
||||
if matches!(parts, [sym::rustc_dummy] | [sym::diagnostic, ..]) {
|
||||
match MetaItemListParser::new(
|
||||
&args.tokens,
|
||||
args.dspan.entire(),
|
||||
psess,
|
||||
ShouldEmit::ErrorsAndLints { recover: false },
|
||||
) {
|
||||
Ok(p) => return Some(ArgParser::List(p)),
|
||||
Err(e) => {
|
||||
// We can just dispose of the diagnostic and not bother with a lint,
|
||||
// because this will look like `#[diagnostic::attr()]` was used. This
|
||||
// is invalid for all diagnostic attrs, so a lint explaining the proper
|
||||
// form will be issued later.
|
||||
e.cancel();
|
||||
return Some(ArgParser::List(MetaItemListParser {
|
||||
sub_parsers: ThinVec::new(),
|
||||
span: args.dspan.entire(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if args.delim != Delimiter::Parenthesis {
|
||||
|
|
@ -141,7 +154,9 @@ impl ArgParser {
|
|||
}
|
||||
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
|
||||
eq_span: *eq_span,
|
||||
value: expr_to_lit(psess, &expr, expr.span, should_emit)?,
|
||||
value: expr_to_lit(psess, &expr, expr.span, should_emit)
|
||||
.map_err(|e| should_emit.emit_err(e))
|
||||
.ok()??,
|
||||
value_span: expr.span,
|
||||
}),
|
||||
})
|
||||
|
|
@ -336,58 +351,53 @@ impl NameValueParser {
|
|||
}
|
||||
}
|
||||
|
||||
fn expr_to_lit(
|
||||
psess: &ParseSess,
|
||||
fn expr_to_lit<'sess>(
|
||||
psess: &'sess ParseSess,
|
||||
expr: &Expr,
|
||||
span: Span,
|
||||
should_emit: ShouldEmit,
|
||||
) -> Option<MetaItemLit> {
|
||||
) -> PResult<'sess, Option<MetaItemLit>> {
|
||||
if let ExprKind::Lit(token_lit) = expr.kind {
|
||||
let res = MetaItemLit::from_token_lit(token_lit, expr.span);
|
||||
match res {
|
||||
Ok(lit) => {
|
||||
if token_lit.suffix.is_some() {
|
||||
should_emit.emit_err(
|
||||
psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
|
||||
);
|
||||
None
|
||||
Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }))
|
||||
} else {
|
||||
if !lit.kind.is_unsuffixed() {
|
||||
// Emit error and continue, we can still parse the attribute as if the suffix isn't there
|
||||
should_emit.emit_err(
|
||||
psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
|
||||
);
|
||||
if lit.kind.is_unsuffixed() {
|
||||
Ok(Some(lit))
|
||||
} else {
|
||||
Err(psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }))
|
||||
}
|
||||
|
||||
Some(lit)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let guar = report_lit_error(psess, err, token_lit, expr.span);
|
||||
let lit = MetaItemLit {
|
||||
symbol: token_lit.symbol,
|
||||
suffix: token_lit.suffix,
|
||||
kind: LitKind::Err(guar),
|
||||
span: expr.span,
|
||||
};
|
||||
Some(lit)
|
||||
let err = create_lit_error(psess, err, token_lit, expr.span);
|
||||
if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) {
|
||||
Err(err)
|
||||
} else {
|
||||
let lit = MetaItemLit {
|
||||
symbol: token_lit.symbol,
|
||||
suffix: token_lit.suffix,
|
||||
kind: LitKind::Err(err.emit()),
|
||||
span: expr.span,
|
||||
};
|
||||
Ok(Some(lit))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if matches!(should_emit, ShouldEmit::Nothing) {
|
||||
return None;
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// Example cases:
|
||||
// - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
|
||||
// - `#[foo = include_str!("nonexistent-file.rs")]`:
|
||||
// results in `ast::ExprKind::Err`. In that case we delay
|
||||
// the error because an earlier error will have already
|
||||
// been reported.
|
||||
// results in `ast::ExprKind::Err`.
|
||||
let msg = "attribute value must be a literal";
|
||||
let err = psess.dcx().struct_span_err(span, msg);
|
||||
should_emit.emit_err(err);
|
||||
None
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -420,9 +430,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
|
|||
|
||||
if !lit.kind.is_unsuffixed() {
|
||||
// Emit error and continue, we can still parse the attribute as if the suffix isn't there
|
||||
self.should_emit.emit_err(
|
||||
self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
|
||||
);
|
||||
let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span });
|
||||
if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) {
|
||||
return Err(err);
|
||||
} else {
|
||||
self.should_emit.emit_err(err)
|
||||
};
|
||||
}
|
||||
|
||||
Ok(lit)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ pub(super) fn convert_typeck_constraints<'tcx>(
|
|||
{
|
||||
localize_statement_constraint(
|
||||
tcx,
|
||||
body,
|
||||
stmt,
|
||||
&outlives_constraint,
|
||||
point,
|
||||
|
|
@ -74,7 +73,6 @@ pub(super) fn convert_typeck_constraints<'tcx>(
|
|||
/// needed CFG `from`-`to` intra-block nodes.
|
||||
fn localize_statement_constraint<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
stmt: &Statement<'tcx>,
|
||||
outlives_constraint: &OutlivesConstraint<'tcx>,
|
||||
current_point: PointIndex,
|
||||
|
|
@ -114,28 +112,22 @@ fn localize_statement_constraint<'tcx>(
|
|||
},
|
||||
"there should be no common regions between the LHS and RHS of an assignment"
|
||||
);
|
||||
|
||||
let lhs_ty = body.local_decls[lhs.local].ty;
|
||||
let successor_point = current_point;
|
||||
compute_constraint_direction(
|
||||
tcx,
|
||||
outlives_constraint,
|
||||
&lhs_ty,
|
||||
current_point,
|
||||
successor_point,
|
||||
universal_regions,
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
// For the other cases, we localize an outlives constraint to where it arises.
|
||||
LocalizedOutlivesConstraint {
|
||||
source: outlives_constraint.sup,
|
||||
from: current_point,
|
||||
target: outlives_constraint.sub,
|
||||
to: current_point,
|
||||
}
|
||||
// Assignments should be the only statement that can both generate constraints that
|
||||
// apply on entry (specific to the RHS place) *and* others that only apply on exit (the
|
||||
// subset of RHS regions that actually flow into the LHS): i.e., where midpoints would
|
||||
// be used to ensure the former happen before the latter, within the same MIR Location.
|
||||
}
|
||||
}
|
||||
|
||||
// We generally localize an outlives constraint to where it arises.
|
||||
LocalizedOutlivesConstraint {
|
||||
source: outlives_constraint.sup,
|
||||
from: current_point,
|
||||
target: outlives_constraint.sub,
|
||||
to: current_point,
|
||||
}
|
||||
}
|
||||
|
||||
/// For a given outlives constraint arising from a MIR terminator, localize the constraint with the
|
||||
|
|
@ -150,14 +142,12 @@ fn localize_terminator_constraint<'tcx>(
|
|||
universal_regions: &UniversalRegions<'tcx>,
|
||||
) -> LocalizedOutlivesConstraint {
|
||||
// FIXME: check if other terminators need the same handling as `Call`s, in particular
|
||||
// Assert/Yield/Drop. A handful of tests are failing with Drop related issues, as well as some
|
||||
// coroutine tests, and that may be why.
|
||||
// Assert/Yield/Drop.
|
||||
match &terminator.kind {
|
||||
// FIXME: also handle diverging calls.
|
||||
TerminatorKind::Call { destination, target: Some(target), .. } => {
|
||||
// Calls are similar to assignments, and thus follow the same pattern. If there is a
|
||||
// target for the call we also relate what flows into the destination here to entry to
|
||||
// that successor.
|
||||
// If there is a target for the call we also relate what flows into the destination here
|
||||
// to entry to that successor.
|
||||
let destination_ty = destination.ty(&body.local_decls, tcx);
|
||||
let successor_location = Location { block: *target, statement_index: 0 };
|
||||
let successor_point = liveness.point_from_location(successor_location);
|
||||
|
|
|
|||
|
|
@ -40,8 +40,11 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
|
|||
return Err(cx.dcx().emit_err(errors::RequiresCfgPattern { span }));
|
||||
}
|
||||
|
||||
let meta = MetaItemOrLitParser::parse_single(&mut parser, ShouldEmit::ErrorsAndLints)
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let meta = MetaItemOrLitParser::parse_single(
|
||||
&mut parser,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
)
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let cfg = AttributeParser::parse_single_args(
|
||||
cx.sess,
|
||||
span,
|
||||
|
|
@ -55,7 +58,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
|
|||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
Some(cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&CFG_TEMPLATE,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
|
|||
use rustc_expand::config::StripUnconfigured;
|
||||
use rustc_expand::configure;
|
||||
use rustc_feature::Features;
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{Span, sym};
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -110,7 +110,8 @@ impl CfgEval<'_> {
|
|||
let res: PResult<'_, Annotatable> = try {
|
||||
match annotatable {
|
||||
Annotatable::Item(_) => {
|
||||
let item = parser.parse_item(ForceCollect::Yes)?.unwrap();
|
||||
let item =
|
||||
parser.parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)?.unwrap();
|
||||
Annotatable::Item(self.flat_map_item(item).pop().unwrap())
|
||||
}
|
||||
Annotatable::AssocItem(_, ctxt) => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_expand::base::{
|
|||
};
|
||||
use rustc_expand::module::DirOwnership;
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect};
|
||||
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
|
||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
|
@ -168,7 +168,7 @@ pub(crate) fn expand_include<'cx>(
|
|||
));
|
||||
let mut ret = SmallVec::new();
|
||||
loop {
|
||||
match p.parse_item(ForceCollect::No) {
|
||||
match p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -348,6 +348,31 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
ret.write_cvalue(fx, ret_lane);
|
||||
}
|
||||
|
||||
sym::simd_splat => {
|
||||
intrinsic_args!(fx, args => (value); intrinsic);
|
||||
|
||||
if !ret.layout().ty.is_simd() {
|
||||
report_simd_type_validation_error(fx, intrinsic, span, ret.layout().ty);
|
||||
return;
|
||||
}
|
||||
let (lane_count, lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
|
||||
|
||||
if value.layout().ty != lane_ty {
|
||||
fx.tcx.dcx().span_fatal(
|
||||
span,
|
||||
format!(
|
||||
"[simd_splat] expected element type {lane_ty:?}, got {got:?}",
|
||||
got = value.layout().ty
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for i in 0..lane_count {
|
||||
let ret_lane = ret.place_lane(fx, i.into());
|
||||
ret_lane.write_cvalue(fx, value);
|
||||
}
|
||||
}
|
||||
|
||||
sym::simd_neg
|
||||
| sym::simd_bswap
|
||||
| sym::simd_bitreverse
|
||||
|
|
|
|||
|
|
@ -121,6 +121,42 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate()));
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
if name == sym::simd_splat {
|
||||
let (out_len, out_ty) = require_simd2!(ret_ty, SimdReturn);
|
||||
|
||||
require!(
|
||||
args[0].layout.ty == out_ty,
|
||||
InvalidMonomorphization::ExpectedVectorElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: out_ty,
|
||||
vector_type: ret_ty,
|
||||
}
|
||||
);
|
||||
|
||||
let vec_ty = llret_ty.unqualified().dyncast_vector().expect("vector return type");
|
||||
let elem_ty = vec_ty.get_element_type();
|
||||
|
||||
// Cast pointer type to usize (GCC does not support pointer SIMD vectors).
|
||||
let value = args[0];
|
||||
let scalar = if value.layout.ty.is_numeric() {
|
||||
value.immediate()
|
||||
} else if value.layout.ty.is_raw_ptr() {
|
||||
bx.ptrtoint(value.immediate(), elem_ty)
|
||||
} else {
|
||||
return_error!(InvalidMonomorphization::UnsupportedOperation {
|
||||
span,
|
||||
name,
|
||||
in_ty: ret_ty,
|
||||
in_elem: value.layout.ty
|
||||
});
|
||||
};
|
||||
|
||||
let elements = vec![scalar; out_len as usize];
|
||||
return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &elements));
|
||||
}
|
||||
|
||||
// every intrinsic below takes a SIMD vector as its first argument
|
||||
require_simd!(
|
||||
args[0].layout.ty,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ impl OwnedTargetMachine {
|
|||
debug_info_compression: llvm::CompressionKind,
|
||||
use_emulated_tls: bool,
|
||||
use_wasm_eh: bool,
|
||||
large_data_threshold: u64,
|
||||
) -> Result<Self, LlvmError<'static>> {
|
||||
// SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data
|
||||
let tm_ptr = unsafe {
|
||||
|
|
@ -65,6 +66,7 @@ impl OwnedTargetMachine {
|
|||
debug_info_compression,
|
||||
use_emulated_tls,
|
||||
use_wasm_eh,
|
||||
large_data_threshold,
|
||||
)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -275,6 +275,8 @@ pub(crate) fn target_machine_factory(
|
|||
|
||||
let use_wasm_eh = wants_wasm_eh(sess);
|
||||
|
||||
let large_data_threshold = sess.opts.unstable_opts.large_data_threshold.unwrap_or(0);
|
||||
|
||||
let prof = SelfProfilerRef::clone(&sess.prof);
|
||||
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||
// Self-profile timer for invoking a factory to create a target machine.
|
||||
|
|
@ -316,6 +318,7 @@ pub(crate) fn target_machine_factory(
|
|||
debuginfo_compression,
|
||||
use_emulated_tls,
|
||||
use_wasm_eh,
|
||||
large_data_threshold,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -665,8 +665,8 @@ impl MsvcBasicName for ty::UintTy {
|
|||
|
||||
impl MsvcBasicName for ty::FloatTy {
|
||||
fn msvc_basic_name(self) -> &'static str {
|
||||
// FIXME(f16_f128): `f16` and `f128` have no MSVC representation. We could improve the
|
||||
// debuginfo. See: <https://github.com/rust-lang/rust/issues/121837>
|
||||
// FIXME(f128): `f128` has no MSVC representation. We could improve the debuginfo.
|
||||
// See: <https://github.com/rust-lang/rust/issues/121837>
|
||||
match self {
|
||||
ty::FloatTy::F16 => {
|
||||
bug!("`f16` should have been handled in `build_basic_type_di_node`")
|
||||
|
|
|
|||
|
|
@ -1581,6 +1581,31 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
|
||||
}
|
||||
|
||||
if name == sym::simd_splat {
|
||||
let (_out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
|
||||
|
||||
require!(
|
||||
args[0].layout.ty == out_ty,
|
||||
InvalidMonomorphization::ExpectedVectorElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: out_ty,
|
||||
vector_type: ret_ty,
|
||||
}
|
||||
);
|
||||
|
||||
// `insertelement <N x elem> poison, elem %x, i32 0`
|
||||
let poison_vec = bx.const_poison(llret_ty);
|
||||
let idx0 = bx.const_i32(0);
|
||||
let v0 = bx.insert_element(poison_vec, args[0].immediate(), idx0);
|
||||
|
||||
// `shufflevector <N x elem> v0, <N x elem> poison, <N x i32> zeroinitializer`
|
||||
// The masks is all zeros, so this splats lane 0 (which has our element in it).
|
||||
let splat = bx.shuffle_vector(v0, poison_vec, bx.const_null(llret_ty));
|
||||
|
||||
return Ok(splat);
|
||||
}
|
||||
|
||||
// every intrinsic below takes a SIMD vector as its first argument
|
||||
let (in_len, in_elem) = require_simd!(args[0].layout.ty, SimdInput);
|
||||
let in_ty = args[0].layout.ty;
|
||||
|
|
|
|||
|
|
@ -2347,6 +2347,7 @@ unsafe extern "C" {
|
|||
DebugInfoCompression: CompressionKind,
|
||||
UseEmulatedTls: bool,
|
||||
UseWasmEH: bool,
|
||||
LargeDataThreshold: u64,
|
||||
) -> *mut TargetMachine;
|
||||
|
||||
pub(crate) fn LLVMRustAddLibraryInfo<'a>(
|
||||
|
|
|
|||
|
|
@ -1827,9 +1827,9 @@ fn exported_symbols_for_non_proc_macro(
|
|||
// Mark allocator shim symbols as exported only if they were generated.
|
||||
if export_threshold == SymbolExportLevel::Rust
|
||||
&& needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type)
|
||||
&& tcx.allocator_kind(()).is_some()
|
||||
&& let Some(kind) = tcx.allocator_kind(())
|
||||
{
|
||||
symbols.extend(allocator_shim_symbols(tcx));
|
||||
symbols.extend(allocator_shim_symbols(tcx, kind));
|
||||
}
|
||||
|
||||
symbols
|
||||
|
|
|
|||
|
|
@ -118,8 +118,10 @@ pub(super) fn exported_symbols_for_lto(
|
|||
}
|
||||
|
||||
// Mark allocator shim symbols as exported only if they were generated.
|
||||
if export_threshold == SymbolExportLevel::Rust && allocator_kind_for_codegen(tcx).is_some() {
|
||||
symbols_below_threshold.extend(allocator_shim_symbols(tcx).map(|(name, _kind)| name));
|
||||
if export_threshold == SymbolExportLevel::Rust
|
||||
&& let Some(kind) = allocator_kind_for_codegen(tcx)
|
||||
{
|
||||
symbols_below_threshold.extend(allocator_shim_symbols(tcx, kind).map(|(name, _kind)| name));
|
||||
}
|
||||
|
||||
symbols_below_threshold
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
use std::collections::hash_map::Entry::*;
|
||||
|
||||
use rustc_abi::{CanonAbi, X86Call};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name,
|
||||
};
|
||||
use rustc_ast::expand::allocator::{AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
|
||||
|
|
@ -21,6 +19,7 @@ use rustc_target::spec::{Arch, Os, TlsModel};
|
|||
use tracing::debug;
|
||||
|
||||
use crate::back::symbol_export;
|
||||
use crate::base::allocator_shim_contents;
|
||||
|
||||
fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
|
||||
crates_export_threshold(tcx.crate_types())
|
||||
|
|
@ -490,14 +489,12 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
|
||||
pub(crate) fn allocator_shim_symbols(
|
||||
tcx: TyCtxt<'_>,
|
||||
kind: AllocatorKind,
|
||||
) -> impl Iterator<Item = (String, SymbolExportKind)> {
|
||||
ALLOCATOR_METHODS
|
||||
.iter()
|
||||
allocator_shim_contents(tcx, kind)
|
||||
.into_iter()
|
||||
.map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
|
||||
.chain([
|
||||
mangle_internal_symbol(tcx, global_fn_name(ALLOC_ERROR_HANDLER).as_str()),
|
||||
mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
|
||||
])
|
||||
.chain([mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)])
|
||||
.map(move |symbol_name| {
|
||||
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
|
||||
|
||||
|
|
|
|||
|
|
@ -1074,8 +1074,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if constant_ty.is_simd() {
|
||||
// However, some SIMD types do not actually use the vector ABI
|
||||
// (in particular, packed SIMD types do not). Ensure we exclude those.
|
||||
//
|
||||
// We also have to exclude vectors of pointers because `immediate_const_vector`
|
||||
// does not work for those.
|
||||
let layout = bx.layout_of(constant_ty);
|
||||
if let BackendRepr::SimdVector { .. } = layout.backend_repr {
|
||||
let (_, element_ty) = constant_ty.simd_size_and_type(bx.tcx());
|
||||
if let BackendRepr::SimdVector { .. } = layout.backend_repr
|
||||
&& element_ty.is_numeric()
|
||||
{
|
||||
let (llval, ty) = self.immediate_const_vector(bx, constant);
|
||||
return OperandRef {
|
||||
val: OperandValue::Immediate(llval),
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
self.copy_op(&self.project_index(&input, index)?, &dest)?;
|
||||
}
|
||||
sym::simd_splat => {
|
||||
let elem = &args[0];
|
||||
let (dest, dest_len) = self.project_to_simd(&dest)?;
|
||||
|
||||
for i in 0..dest_len {
|
||||
let place = self.project_index(&dest, i)?;
|
||||
self.copy_op(elem, &place)?;
|
||||
}
|
||||
}
|
||||
sym::simd_neg
|
||||
| sym::simd_fabs
|
||||
| sym::simd_ceil
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use rustc_hir::limit::Limit;
|
|||
use rustc_hir::{Stability, find_attr};
|
||||
use rustc_lint_defs::RegisteredTools;
|
||||
use rustc_parse::MACRO_ARGUMENTS;
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
|
||||
|
|
@ -1472,7 +1472,7 @@ pub(crate) fn stream_pretty_printing_compatibility_hack(
|
|||
let mut parser = Parser::new(psess, stream.clone(), None);
|
||||
// No need to collect tokens for this simple check.
|
||||
parser
|
||||
.parse_item(ForceCollect::No)
|
||||
.parse_item(ForceCollect::No, AllowConstBlockItems::No)
|
||||
.expect("failed to reparse item")
|
||||
.expect("an actual item")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -393,9 +393,10 @@ 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, ShouldEmit::ErrorsAndLints).as_bool())
|
||||
attrs.iter().all(|attr| {
|
||||
!is_cfg(attr)
|
||||
|| self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn cfg_true(&self, attr: &Attribute, emit_errors: ShouldEmit) -> EvalConfigResult {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ use rustc_hir::Target;
|
|||
use rustc_hir::def::MacroKinds;
|
||||
use rustc_hir::limit::Limit;
|
||||
use rustc_parse::parser::{
|
||||
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
|
||||
token_descr,
|
||||
AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser,
|
||||
RecoverColon, RecoverComma, token_descr,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
|
||||
|
|
@ -1099,7 +1099,7 @@ pub fn parse_ast_fragment<'a>(
|
|||
Ok(match kind {
|
||||
AstFragmentKind::Items => {
|
||||
let mut items = SmallVec::new();
|
||||
while let Some(item) = this.parse_item(ForceCollect::No)? {
|
||||
while let Some(item) = this.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? {
|
||||
items.push(item);
|
||||
}
|
||||
AstFragment::Items(items)
|
||||
|
|
@ -2170,7 +2170,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
call.span(),
|
||||
self.cx.current_expansion.lint_node_id,
|
||||
Some(self.cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
);
|
||||
|
||||
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
||||
|
|
@ -2220,7 +2220,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
// Target doesn't matter for `cfg` parsing.
|
||||
Target::Crate,
|
||||
self.cfg().features,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
parse_cfg,
|
||||
&CFG_TEMPLATE,
|
||||
) else {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ProcMacroExecutionStrategy;
|
||||
use rustc_span::profiling::SpannedEventArgRecorder;
|
||||
|
|
@ -160,7 +160,10 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
let mut items = vec![];
|
||||
|
||||
loop {
|
||||
match parser.parse_item(ForceCollect::No) {
|
||||
match parser.parse_item(
|
||||
ForceCollect::No,
|
||||
if is_stmt { AllowConstBlockItems::No } else { AllowConstBlockItems::Yes },
|
||||
) {
|
||||
Ok(None) => break,
|
||||
Ok(Some(item)) => {
|
||||
if is_stmt {
|
||||
|
|
|
|||
|
|
@ -414,6 +414,8 @@ declare_features! (
|
|||
(unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
|
||||
/// Allows `async {}` expressions in const contexts.
|
||||
(unstable, const_async_blocks, "1.53.0", Some(85368)),
|
||||
/// Allows `const { ... }` as a shorthand for `const _: () = const { ... };` for module items.
|
||||
(unstable, const_block_items, "CURRENT_RUSTC_VERSION", Some(149226)),
|
||||
/// Allows `const || {}` closures in const contexts.
|
||||
(incomplete, const_closures, "1.68.0", Some(106003)),
|
||||
/// Allows using `[const] Destruct` bounds and calling drop impls in const contexts.
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ impl Target {
|
|||
ast::ItemKind::Use(..) => Target::Use,
|
||||
ast::ItemKind::Static { .. } => Target::Static,
|
||||
ast::ItemKind::Const(..) => Target::Const,
|
||||
ast::ItemKind::ConstBlock(..) => Target::Const,
|
||||
ast::ItemKind::Fn { .. } => Target::Fn,
|
||||
ast::ItemKind::Mod(..) => Target::Mod,
|
||||
ast::ItemKind::ForeignMod { .. } => Target::ForeignMod,
|
||||
|
|
|
|||
|
|
@ -746,6 +746,7 @@ pub(crate) fn check_intrinsic_type(
|
|||
sym::simd_extract | sym::simd_extract_dyn => {
|
||||
(2, 0, vec![param(0), tcx.types.u32], param(1))
|
||||
}
|
||||
sym::simd_splat => (2, 0, vec![param(1)], param(0)),
|
||||
sym::simd_cast
|
||||
| sym::simd_as
|
||||
| sym::simd_cast_ptr
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
|
|||
bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray,
|
||||
const char *SplitDwarfFile, const char *OutputObjFile,
|
||||
LLVMRustCompressionKind DebugInfoCompression, bool UseEmulatedTls,
|
||||
bool UseWasmEH) {
|
||||
bool UseWasmEH, uint64_t LargeDataThreshold) {
|
||||
|
||||
auto OptLevel = fromRust(RustOptLevel);
|
||||
auto RM = fromRust(RustReloc);
|
||||
|
|
@ -381,6 +381,11 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
|
|||
TargetMachine *TM = TheTarget->createTargetMachine(
|
||||
Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
|
||||
#endif
|
||||
|
||||
if (LargeDataThreshold != 0) {
|
||||
TM->setLargeDataThreshold(LargeDataThreshold);
|
||||
}
|
||||
|
||||
return wrap(TM);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::hir_id::OwnerId;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_query_system::HandleCycleError;
|
||||
use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
|
||||
pub(crate) use rustc_query_system::query::QueryJobId;
|
||||
use rustc_query_system::query::*;
|
||||
use rustc_query_system::query::{CycleError, CycleErrorHandling, HashResult, QueryCache};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
pub use sealed::IntoQueryParam;
|
||||
|
||||
|
|
@ -23,7 +22,8 @@ pub struct DynamicQuery<'tcx, C: QueryCache> {
|
|||
pub name: &'static str,
|
||||
pub eval_always: bool,
|
||||
pub dep_kind: DepKind,
|
||||
pub handle_cycle_error: HandleCycleError,
|
||||
/// How this query deals with query cycle errors.
|
||||
pub cycle_error_handling: CycleErrorHandling,
|
||||
// Offset of this query's state field in the QueryStates struct
|
||||
pub query_state: usize,
|
||||
// Offset of this query's cache field in the QueryCaches struct
|
||||
|
|
|
|||
|
|
@ -807,12 +807,22 @@ pub enum PatKind<'tcx> {
|
|||
subpatterns: Vec<FieldPat<'tcx>>,
|
||||
},
|
||||
|
||||
/// `box P`, `&P`, `&mut P`, etc.
|
||||
/// Explicit or implicit `&P` or `&mut P`, for some subpattern `P`.
|
||||
///
|
||||
/// Implicit `&`/`&mut` patterns can be inserted by match-ergonomics.
|
||||
///
|
||||
/// With `feature(pin_ergonomics)`, this can also be `&pin const P` or
|
||||
/// `&pin mut P`, as indicated by the `pin` field.
|
||||
Deref {
|
||||
#[type_visitable(ignore)]
|
||||
pin: hir::Pinnedness,
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
/// Deref pattern, written `box P` for now.
|
||||
/// Explicit or implicit `deref!(..)` pattern, under `feature(deref_patterns)`.
|
||||
/// Represents a call to `Deref` or `DerefMut`, or a deref-move of `Box`.
|
||||
///
|
||||
/// `box P` patterns also lower to this, under `feature(box_patterns)`.
|
||||
DerefPattern {
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
/// Whether the pattern scrutinee needs to be borrowed in order to call `Deref::deref` or
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
|
|||
| PatKind::Error(_) => {}
|
||||
|
||||
PatKind::Binding { subpattern: Some(subpattern), .. }
|
||||
| PatKind::Deref { subpattern }
|
||||
| PatKind::Deref { subpattern, .. }
|
||||
| PatKind::DerefPattern { subpattern, .. } => callback(subpattern),
|
||||
|
||||
PatKind::Variant { subpatterns, .. } | PatKind::Leaf { subpatterns } => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::sync::Arc;
|
|||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
|
||||
|
|
@ -314,23 +315,24 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
// FIXME: Pin-patterns should probably have their own pattern kind,
|
||||
// instead of overloading `PatKind::Deref` via the pattern type.
|
||||
PatKind::Deref { ref subpattern }
|
||||
if let Some(ref_ty) = pattern.ty.pinned_ty()
|
||||
&& ref_ty.is_ref() =>
|
||||
{
|
||||
PatKind::Deref { pin: Pinnedness::Pinned, ref subpattern } => {
|
||||
let pinned_ref_ty = match pattern.ty.pinned_ty() {
|
||||
Some(p_ty) if p_ty.is_ref() => p_ty,
|
||||
_ => span_bug!(pattern.span, "bad type for pinned deref: {:?}", pattern.ty),
|
||||
};
|
||||
MatchPairTree::for_pattern(
|
||||
place_builder.field(FieldIdx::ZERO, ref_ty).deref(),
|
||||
// Project into the `Pin(_)` struct, then deref the inner `&` or `&mut`.
|
||||
place_builder.field(FieldIdx::ZERO, pinned_ref_ty).deref(),
|
||||
subpattern,
|
||||
cx,
|
||||
&mut subpairs,
|
||||
extra_data,
|
||||
);
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
PatKind::Deref { ref subpattern }
|
||||
PatKind::Deref { pin: Pinnedness::Not, ref subpattern }
|
||||
| PatKind::DerefPattern { ref subpattern, borrow: DerefPatBorrowMode::Box } => {
|
||||
MatchPairTree::for_pattern(
|
||||
place_builder.deref(),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use std::mem;
|
|||
use std::sync::Arc;
|
||||
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_abi::{FIRST_VARIANT, VariantIdx};
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::debug_assert_matches;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
|
|
@ -909,7 +909,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
| PatKind::Never
|
||||
| PatKind::Error(_) => {}
|
||||
|
||||
PatKind::Deref { ref subpattern } => {
|
||||
PatKind::Deref { pin: Pinnedness::Pinned, ref subpattern } => {
|
||||
// Project into the `Pin(_)` struct, then deref the inner `&` or `&mut`.
|
||||
visit_subpat(self, subpattern, &user_tys.leaf(FieldIdx::ZERO).deref(), f);
|
||||
}
|
||||
PatKind::Deref { pin: Pinnedness::Not, ref subpattern } => {
|
||||
visit_subpat(self, subpattern, &user_tys.deref(), f);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -294,8 +294,12 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
|| pointee_ty.is_slice()
|
||||
|| pointee_ty.is_sized(tcx, self.typing_env)
|
||||
{
|
||||
// References have the same valtree representation as their pointee.
|
||||
PatKind::Deref {
|
||||
// This node has type `ty::Ref`, so it's not a pin-deref.
|
||||
pin: hir::Pinnedness::Not,
|
||||
// Lower the valtree to a pattern as the pointee type.
|
||||
// This works because references have the same valtree
|
||||
// representation as their pointee.
|
||||
subpattern: self.valtree_to_pat(ty::Value { ty: *pointee_ty, valtree }),
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -132,12 +132,16 @@ impl<'tcx> PatCtxt<'tcx> {
|
|||
debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
|
||||
let span = thir_pat.span;
|
||||
let kind = match adjust.kind {
|
||||
PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat },
|
||||
PatAdjust::BuiltinDeref => {
|
||||
PatKind::Deref { pin: hir::Pinnedness::Not, subpattern: thir_pat }
|
||||
}
|
||||
PatAdjust::OverloadedDeref => {
|
||||
let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
|
||||
PatKind::DerefPattern { subpattern: thir_pat, borrow }
|
||||
}
|
||||
PatAdjust::PinDeref => PatKind::Deref { subpattern: thir_pat },
|
||||
PatAdjust::PinDeref => {
|
||||
PatKind::Deref { pin: hir::Pinnedness::Pinned, subpattern: thir_pat }
|
||||
}
|
||||
};
|
||||
Box::new(Pat { span, ty: adjust.source, kind, extra: None })
|
||||
});
|
||||
|
|
@ -334,7 +338,7 @@ impl<'tcx> PatCtxt<'tcx> {
|
|||
let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
|
||||
PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow }
|
||||
}
|
||||
hir::PatKind::Ref(subpattern, _, _) => {
|
||||
hir::PatKind::Ref(subpattern, pin, _) => {
|
||||
// Track the default binding mode for the Rust 2024 migration suggestion.
|
||||
let opt_old_mode_span =
|
||||
self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
|
||||
|
|
@ -342,7 +346,7 @@ impl<'tcx> PatCtxt<'tcx> {
|
|||
if let Some(s) = &mut self.rust_2024_migration {
|
||||
s.leave_ref(opt_old_mode_span);
|
||||
}
|
||||
PatKind::Deref { subpattern }
|
||||
PatKind::Deref { pin, subpattern }
|
||||
}
|
||||
hir::PatKind::Box(subpattern) => PatKind::DerefPattern {
|
||||
subpattern: self.lower_pattern(subpattern),
|
||||
|
|
|
|||
|
|
@ -774,8 +774,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
print_indented!(self, "]", depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::Deref { subpattern } => {
|
||||
PatKind::Deref { pin, subpattern } => {
|
||||
print_indented!(self, "Deref { ", depth_lvl + 1);
|
||||
print_indented!(self, format_args!("pin: {pin:?}"), depth_lvl + 2);
|
||||
print_indented!(self, "subpattern:", depth_lvl + 2);
|
||||
self.print_pat(subpattern, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ use thin_vec::ThinVec;
|
|||
use tracing::debug;
|
||||
|
||||
use super::{
|
||||
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos,
|
||||
AllowConstBlockItems, AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle,
|
||||
Trailing, UsePreAttrPos,
|
||||
};
|
||||
use crate::parser::FnContext;
|
||||
use crate::{errors, exp, fluent_generated as fluent};
|
||||
|
|
@ -203,6 +204,7 @@ impl<'a> Parser<'a> {
|
|||
false,
|
||||
FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true },
|
||||
ForceCollect::No,
|
||||
AllowConstBlockItems::Yes,
|
||||
) {
|
||||
Ok(Some(item)) => {
|
||||
// FIXME(#100717)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ use tracing::debug;
|
|||
use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
|
||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||
use super::{
|
||||
AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect, Parser, PathStyle,
|
||||
Recovered, Trailing, UsePreAttrPos,
|
||||
AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect,
|
||||
Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
|
||||
};
|
||||
use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField};
|
||||
use crate::{exp, fluent_generated as fluent};
|
||||
|
|
@ -69,7 +69,7 @@ impl<'a> Parser<'a> {
|
|||
// `parse_item` consumes the appropriate semicolons so any leftover is an error.
|
||||
loop {
|
||||
while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons
|
||||
let Some(item) = self.parse_item(ForceCollect::No)? else {
|
||||
let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
|
||||
break;
|
||||
};
|
||||
items.push(item);
|
||||
|
|
@ -123,21 +123,34 @@ enum ReuseKind {
|
|||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> {
|
||||
pub fn parse_item(
|
||||
&mut self,
|
||||
force_collect: ForceCollect,
|
||||
allow_const_block_items: AllowConstBlockItems,
|
||||
) -> PResult<'a, Option<Box<Item>>> {
|
||||
let fn_parse_mode =
|
||||
FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
|
||||
self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new))
|
||||
self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
|
||||
.map(|i| i.map(Box::new))
|
||||
}
|
||||
|
||||
fn parse_item_(
|
||||
&mut self,
|
||||
fn_parse_mode: FnParseMode,
|
||||
force_collect: ForceCollect,
|
||||
const_block_items_allowed: AllowConstBlockItems,
|
||||
) -> PResult<'a, Option<Item>> {
|
||||
self.recover_vcs_conflict_marker();
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
self.recover_vcs_conflict_marker();
|
||||
self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect)
|
||||
self.parse_item_common(
|
||||
attrs,
|
||||
true,
|
||||
false,
|
||||
fn_parse_mode,
|
||||
force_collect,
|
||||
const_block_items_allowed,
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn parse_item_common(
|
||||
|
|
@ -147,10 +160,11 @@ impl<'a> Parser<'a> {
|
|||
attrs_allowed: bool,
|
||||
fn_parse_mode: FnParseMode,
|
||||
force_collect: ForceCollect,
|
||||
allow_const_block_items: AllowConstBlockItems,
|
||||
) -> PResult<'a, Option<Item>> {
|
||||
if let Some(item) =
|
||||
self.eat_metavar_seq(MetaVarKind::Item, |this| this.parse_item(ForceCollect::Yes))
|
||||
{
|
||||
if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
|
||||
this.parse_item(ForceCollect::Yes, allow_const_block_items)
|
||||
}) {
|
||||
let mut item = item.expect("an actual item");
|
||||
attrs.prepend_to_nt_inner(&mut item.attrs);
|
||||
return Ok(Some(*item));
|
||||
|
|
@ -163,6 +177,7 @@ impl<'a> Parser<'a> {
|
|||
let kind = this.parse_item_kind(
|
||||
&mut attrs,
|
||||
mac_allowed,
|
||||
allow_const_block_items,
|
||||
lo,
|
||||
&vis,
|
||||
&mut def,
|
||||
|
|
@ -209,6 +224,7 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
attrs: &mut AttrVec,
|
||||
macros_allowed: bool,
|
||||
allow_const_block_items: AllowConstBlockItems,
|
||||
lo: Span,
|
||||
vis: &Visibility,
|
||||
def: &mut Defaultness,
|
||||
|
|
@ -257,6 +273,15 @@ impl<'a> Parser<'a> {
|
|||
} else if self.check_impl_frontmatter(0) {
|
||||
// IMPL ITEM
|
||||
self.parse_item_impl(attrs, def_(), false)?
|
||||
} else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
|
||||
allow_const_block_items
|
||||
&& self.check_inline_const(0)
|
||||
{
|
||||
// CONST BLOCK ITEM
|
||||
if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
|
||||
debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
|
||||
};
|
||||
ItemKind::ConstBlock(self.parse_const_block_item()?)
|
||||
} else if let Const::Yes(const_span) = self.parse_constness(case) {
|
||||
// CONST ITEM
|
||||
self.recover_const_mut(const_span);
|
||||
|
|
@ -316,6 +341,7 @@ impl<'a> Parser<'a> {
|
|||
return self.parse_item_kind(
|
||||
attrs,
|
||||
macros_allowed,
|
||||
allow_const_block_items,
|
||||
lo,
|
||||
vis,
|
||||
def,
|
||||
|
|
@ -1068,8 +1094,13 @@ impl<'a> Parser<'a> {
|
|||
fn_parse_mode: FnParseMode,
|
||||
force_collect: ForceCollect,
|
||||
) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
|
||||
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
|
||||
|Item { attrs, id, span, vis, kind, tokens }| {
|
||||
Ok(self
|
||||
.parse_item_(
|
||||
fn_parse_mode,
|
||||
force_collect,
|
||||
AllowConstBlockItems::DoesNotMatter, // due to `AssocItemKind::try_from` below
|
||||
)?
|
||||
.map(|Item { attrs, id, span, vis, kind, tokens }| {
|
||||
let kind = match AssocItemKind::try_from(kind) {
|
||||
Ok(kind) => kind,
|
||||
Err(kind) => match kind {
|
||||
|
|
@ -1096,8 +1127,7 @@ impl<'a> Parser<'a> {
|
|||
},
|
||||
};
|
||||
Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
|
||||
},
|
||||
))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parses a `type` alias with the following grammar:
|
||||
|
|
@ -1320,8 +1350,13 @@ impl<'a> Parser<'a> {
|
|||
context: FnContext::Free,
|
||||
req_body: false,
|
||||
};
|
||||
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
|
||||
|Item { attrs, id, span, vis, kind, tokens }| {
|
||||
Ok(self
|
||||
.parse_item_(
|
||||
fn_parse_mode,
|
||||
force_collect,
|
||||
AllowConstBlockItems::DoesNotMatter, // due to `ForeignItemKind::try_from` below
|
||||
)?
|
||||
.map(|Item { attrs, id, span, vis, kind, tokens }| {
|
||||
let kind = match ForeignItemKind::try_from(kind) {
|
||||
Ok(kind) => kind,
|
||||
Err(kind) => match kind {
|
||||
|
|
@ -1348,8 +1383,7 @@ impl<'a> Parser<'a> {
|
|||
},
|
||||
};
|
||||
Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
|
||||
},
|
||||
))
|
||||
}))
|
||||
}
|
||||
|
||||
fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
|
||||
|
|
@ -1437,6 +1471,14 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
|
||||
self.expect_keyword(exp!(Const))?;
|
||||
let const_span = self.prev_token.span;
|
||||
self.psess.gated_spans.gate(sym::const_block_items, const_span);
|
||||
let block = self.parse_block()?;
|
||||
Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
|
||||
}
|
||||
|
||||
/// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
|
||||
/// `mutability`.
|
||||
///
|
||||
|
|
@ -2394,7 +2436,10 @@ impl<'a> Parser<'a> {
|
|||
{
|
||||
let kw_token = self.token;
|
||||
let kw_str = pprust::token_to_string(&kw_token);
|
||||
let item = self.parse_item(ForceCollect::No)?;
|
||||
let item = self.parse_item(
|
||||
ForceCollect::No,
|
||||
AllowConstBlockItems::DoesNotMatter, // self.token != kw::Const
|
||||
)?;
|
||||
let mut item = item.unwrap().span;
|
||||
if self.token == token::Comma {
|
||||
item = item.to(self.token.span);
|
||||
|
|
|
|||
|
|
@ -145,6 +145,14 @@ pub enum ForceCollect {
|
|||
No,
|
||||
}
|
||||
|
||||
/// Whether to accept `const { ... }` as a shorthand for `const _: () = const { ... }`.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum AllowConstBlockItems {
|
||||
Yes,
|
||||
No,
|
||||
DoesNotMatter,
|
||||
}
|
||||
|
||||
/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
|
||||
#[macro_export]
|
||||
macro_rules! maybe_recover_from_interpolated_ty_qpath {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ use rustc_span::{Ident, kw};
|
|||
|
||||
use crate::errors::UnexpectedNonterminal;
|
||||
use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
||||
use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle};
|
||||
use crate::parser::{
|
||||
AllowConstBlockItems, FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle,
|
||||
};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
/// Checks whether a non-terminal may begin with a particular token.
|
||||
|
|
@ -118,7 +120,9 @@ impl<'a> Parser<'a> {
|
|||
match kind {
|
||||
// Note that TT is treated differently to all the others.
|
||||
NonterminalKind::TT => Ok(ParseNtResult::Tt(self.parse_token_tree())),
|
||||
NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
|
||||
NonterminalKind::Item => match self
|
||||
.parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)?
|
||||
{
|
||||
Some(item) => Ok(ParseNtResult::Item(item)),
|
||||
None => Err(self.dcx().create_err(UnexpectedNonterminal::Item(self.token.span))),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ use super::diagnostics::AttemptLocalParseRecovery;
|
|||
use super::pat::{PatternLocation, RecoverComma};
|
||||
use super::path::PathStyle;
|
||||
use super::{
|
||||
AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, Restrictions,
|
||||
SemiColonMode, Trailing, UsePreAttrPos,
|
||||
AllowConstBlockItems, AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser,
|
||||
Restrictions, SemiColonMode, Trailing, UsePreAttrPos,
|
||||
};
|
||||
use crate::errors::{self, MalformedLoopLabel};
|
||||
use crate::exp;
|
||||
|
|
@ -156,6 +156,7 @@ impl<'a> Parser<'a> {
|
|||
true,
|
||||
FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true },
|
||||
force_collect,
|
||||
AllowConstBlockItems::No,
|
||||
)? {
|
||||
self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item)))
|
||||
} else if self.eat(exp!(Semi)) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use rustc_span::{
|
|||
};
|
||||
|
||||
use crate::lexer::StripTokens;
|
||||
use crate::parser::{ForceCollect, Parser};
|
||||
use crate::parser::{AllowConstBlockItems, ForceCollect, Parser};
|
||||
use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
||||
|
||||
fn psess() -> ParseSess {
|
||||
|
|
@ -2233,7 +2233,7 @@ fn parse_item_from_source_str(
|
|||
psess: &ParseSess,
|
||||
) -> PResult<'_, Option<Box<ast::Item>>> {
|
||||
unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source, StripTokens::Nothing))
|
||||
.parse_item(ForceCollect::No)
|
||||
.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)
|
||||
}
|
||||
|
||||
// Produces a `rustc_span::span`.
|
||||
|
|
@ -2248,7 +2248,9 @@ fn string_to_expr(source_str: String) -> Box<ast::Expr> {
|
|||
|
||||
/// Parses a string, returns an item.
|
||||
fn string_to_item(source_str: String) -> Option<Box<ast::Item>> {
|
||||
with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No))
|
||||
with_error_checking_parse(source_str, &psess(), |p| {
|
||||
p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -572,6 +572,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
Use,
|
||||
Static,
|
||||
Const,
|
||||
ConstBlock,
|
||||
Fn,
|
||||
Mod,
|
||||
ForeignMod,
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
|
|||
ast::ItemKind::ExternCrate(..) => Target::ExternCrate,
|
||||
ast::ItemKind::Use(_) => Target::Use,
|
||||
ast::ItemKind::Static(_) => Target::Static,
|
||||
ast::ItemKind::Const(_) => Target::Const,
|
||||
ast::ItemKind::Const(_) | ast::ItemKind::ConstBlock(_) => Target::Const,
|
||||
ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn,
|
||||
ast::ItemKind::Mod(..) => Target::Mod,
|
||||
ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(unused_crate_dependencies)]
|
||||
#![cfg_attr(feature = "rustc", feature(if_let_guard))]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
pub(crate) mod checks;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use std::iter::once;
|
|||
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
|
||||
use rustc_arena::DroplessArena;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
|
||||
|
|
@ -468,12 +468,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
fields = vec![];
|
||||
arity = 0;
|
||||
}
|
||||
PatKind::Deref { subpattern } => {
|
||||
PatKind::Deref { pin, subpattern } => {
|
||||
fields = vec![self.lower_pat(subpattern).at_index(0)];
|
||||
arity = 1;
|
||||
ctor = match ty.pinned_ref() {
|
||||
None if ty.is_ref() => Ref,
|
||||
Some((inner_ty, _)) => {
|
||||
ctor = match pin {
|
||||
hir::Pinnedness::Not if ty.is_ref() => Ref,
|
||||
hir::Pinnedness::Pinned if let Some((inner_ty, _)) = ty.pinned_ref() => {
|
||||
self.internal_state.has_lowered_deref_pat.set(true);
|
||||
DerefPattern(RevealedTy(inner_ty))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ use rustc_middle::query::{
|
|||
queries,
|
||||
};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_query_system::Value;
|
||||
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_query_system::query::{
|
||||
CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryState,
|
||||
get_query_incr, get_query_non_incr,
|
||||
CycleError, CycleErrorHandling, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode,
|
||||
QueryState, get_query_incr, get_query_non_incr,
|
||||
};
|
||||
use rustc_query_system::{HandleCycleError, Value};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
|
||||
use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
|
||||
|
|
@ -181,8 +181,8 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn handle_cycle_error(self) -> HandleCycleError {
|
||||
self.dynamic.handle_cycle_error
|
||||
fn cycle_error_handling(self) -> CycleErrorHandling {
|
||||
self.dynamic.cycle_error_handling
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -199,21 +199,21 @@ pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! handle_cycle_error {
|
||||
macro_rules! cycle_error_handling {
|
||||
([]) => {{
|
||||
rustc_query_system::HandleCycleError::Error
|
||||
rustc_query_system::query::CycleErrorHandling::Error
|
||||
}};
|
||||
([(cycle_fatal) $($rest:tt)*]) => {{
|
||||
rustc_query_system::HandleCycleError::Fatal
|
||||
rustc_query_system::query::CycleErrorHandling::Fatal
|
||||
}};
|
||||
([(cycle_stash) $($rest:tt)*]) => {{
|
||||
rustc_query_system::HandleCycleError::Stash
|
||||
rustc_query_system::query::CycleErrorHandling::Stash
|
||||
}};
|
||||
([(cycle_delay_bug) $($rest:tt)*]) => {{
|
||||
rustc_query_system::HandleCycleError::DelayBug
|
||||
rustc_query_system::query::CycleErrorHandling::DelayBug
|
||||
}};
|
||||
([$other:tt $($modifiers:tt)*]) => {
|
||||
handle_cycle_error!([$($modifiers)*])
|
||||
cycle_error_handling!([$($modifiers)*])
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -618,7 +618,7 @@ macro_rules! define_queries {
|
|||
name: stringify!($name),
|
||||
eval_always: is_eval_always!([$($modifiers)*]),
|
||||
dep_kind: dep_graph::dep_kinds::$name,
|
||||
handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
|
||||
cycle_error_handling: cycle_error_handling!([$($modifiers)*]),
|
||||
query_state: std::mem::offset_of!(QueryStates<'tcx>, $name),
|
||||
query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name),
|
||||
cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
|
||||
|
|
|
|||
|
|
@ -11,14 +11,6 @@ pub(crate) struct CycleStack {
|
|||
pub desc: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum HandleCycleError {
|
||||
Error,
|
||||
Fatal,
|
||||
DelayBug,
|
||||
Stash,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum StackCount {
|
||||
#[note(query_system_cycle_stack_single)]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub mod ich;
|
|||
pub mod query;
|
||||
mod values;
|
||||
|
||||
pub use error::{HandleCycleError, QueryOverflow, QueryOverflowNote};
|
||||
pub use error::{QueryOverflow, QueryOverflowNote};
|
||||
pub use values::Value;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
|||
use rustc_span::ErrorGuaranteed;
|
||||
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
|
||||
use crate::error::HandleCycleError;
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::query::caches::QueryCache;
|
||||
use crate::query::{CycleError, DepNodeIndex, QueryContext, QueryState};
|
||||
use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState};
|
||||
|
||||
pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
|
||||
|
||||
|
|
@ -67,7 +66,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
|
|||
fn feedable(self) -> bool;
|
||||
|
||||
fn dep_kind(self) -> DepKind;
|
||||
fn handle_cycle_error(self) -> HandleCycleError;
|
||||
fn cycle_error_handling(self) -> CycleErrorHandling;
|
||||
fn hash_result(self) -> HashResult<Self::Value>;
|
||||
|
||||
// Just here for convenience and checking that the key matches the kind, don't override this.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,18 @@ mod config;
|
|||
mod job;
|
||||
mod plumbing;
|
||||
|
||||
/// How a particular query deals with query cycle errors.
|
||||
///
|
||||
/// Inspected by the code that actually handles cycle errors, to decide what
|
||||
/// approach to use.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum CycleErrorHandling {
|
||||
Error,
|
||||
Fatal,
|
||||
DelayBug,
|
||||
Stash,
|
||||
}
|
||||
|
||||
/// Description of a frame in the query stack.
|
||||
///
|
||||
/// This is mostly used in case of cycles for error reporting.
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@ use rustc_span::{DUMMY_SP, Span};
|
|||
use tracing::instrument;
|
||||
|
||||
use super::QueryConfig;
|
||||
use crate::HandleCycleError;
|
||||
use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::query::caches::QueryCache;
|
||||
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
|
||||
use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex};
|
||||
use crate::query::{
|
||||
CycleErrorHandling, QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex,
|
||||
};
|
||||
|
||||
#[inline]
|
||||
fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ {
|
||||
|
|
@ -142,22 +143,21 @@ where
|
|||
Q: QueryConfig<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
{
|
||||
use HandleCycleError::*;
|
||||
match query.handle_cycle_error() {
|
||||
Error => {
|
||||
match query.cycle_error_handling() {
|
||||
CycleErrorHandling::Error => {
|
||||
let guar = error.emit();
|
||||
query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
|
||||
}
|
||||
Fatal => {
|
||||
CycleErrorHandling::Fatal => {
|
||||
error.emit();
|
||||
qcx.dep_context().sess().dcx().abort_if_errors();
|
||||
unreachable!()
|
||||
}
|
||||
DelayBug => {
|
||||
CycleErrorHandling::DelayBug => {
|
||||
let guar = error.delay_as_bug();
|
||||
query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
|
||||
}
|
||||
Stash => {
|
||||
CycleErrorHandling::Stash => {
|
||||
let guar = if let Some(root) = cycle_error.cycle.first()
|
||||
&& let Some(span) = root.query.span
|
||||
{
|
||||
|
|
|
|||
|
|
@ -959,7 +959,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||
}
|
||||
|
||||
// These items do not add names to modules.
|
||||
ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
|
||||
ItemKind::Impl { .. }
|
||||
| ItemKind::ForeignMod(..)
|
||||
| ItemKind::GlobalAsm(..)
|
||||
| ItemKind::ConstBlock(..) => {}
|
||||
|
||||
ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
|
||||
unreachable!()
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
|
|||
mutability: s.mutability,
|
||||
nested: false,
|
||||
},
|
||||
ItemKind::Const(..) => DefKind::Const,
|
||||
ItemKind::Const(..) | ItemKind::ConstBlock(..) => DefKind::Const,
|
||||
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
||||
ItemKind::MacroDef(ident, def) => {
|
||||
let edition = i.span.edition();
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
|
|||
| ast::ItemKind::Use(..)
|
||||
| ast::ItemKind::Static(..)
|
||||
| ast::ItemKind::Const(..)
|
||||
| ast::ItemKind::ConstBlock(..)
|
||||
| ast::ItemKind::GlobalAsm(..)
|
||||
| ast::ItemKind::TyAlias(..)
|
||||
| ast::ItemKind::TraitAlias(..)
|
||||
|
|
|
|||
|
|
@ -2727,8 +2727,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind);
|
||||
|
||||
let def_kind = self.r.local_def_kind(item.id);
|
||||
match item.kind {
|
||||
ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
|
||||
match &item.kind {
|
||||
ItemKind::TyAlias(box TyAlias { generics, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
|
|
@ -2739,7 +2739,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
ItemKind::Fn(box Fn { ref generics, ref define_opaque, .. }) => {
|
||||
ItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
|
|
@ -2751,19 +2751,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
self.resolve_define_opaques(define_opaque);
|
||||
}
|
||||
|
||||
ItemKind::Enum(_, ref generics, _)
|
||||
| ItemKind::Struct(_, ref generics, _)
|
||||
| ItemKind::Union(_, ref generics, _) => {
|
||||
ItemKind::Enum(_, generics, _)
|
||||
| ItemKind::Struct(_, generics, _)
|
||||
| ItemKind::Union(_, generics, _) => {
|
||||
self.resolve_adt(item, generics);
|
||||
}
|
||||
|
||||
ItemKind::Impl(Impl {
|
||||
ref generics,
|
||||
ref of_trait,
|
||||
ref self_ty,
|
||||
items: ref impl_items,
|
||||
..
|
||||
}) => {
|
||||
ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, .. }) => {
|
||||
self.diag_metadata.current_impl_items = Some(impl_items);
|
||||
self.resolve_implementation(
|
||||
&item.attrs,
|
||||
|
|
@ -2776,7 +2770,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
self.diag_metadata.current_impl_items = None;
|
||||
}
|
||||
|
||||
ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
|
||||
ItemKind::Trait(box Trait { generics, bounds, items, .. }) => {
|
||||
// Create a new rib for the trait-wide type parameters.
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
|
|
@ -2795,7 +2789,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
ItemKind::TraitAlias(box TraitAlias { ref generics, ref bounds, .. }) => {
|
||||
ItemKind::TraitAlias(box TraitAlias { generics, bounds, .. }) => {
|
||||
// Create a new rib for the trait-wide type parameters.
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
|
|
@ -2835,13 +2829,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
self.parent_scope.module = orig_module;
|
||||
}
|
||||
|
||||
ItemKind::Static(box ast::StaticItem {
|
||||
ident,
|
||||
ref ty,
|
||||
ref expr,
|
||||
ref define_opaque,
|
||||
..
|
||||
}) => {
|
||||
ItemKind::Static(box ast::StaticItem { ident, ty, expr, define_opaque, .. }) => {
|
||||
self.with_static_rib(def_kind, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
||||
this.visit_ty(ty);
|
||||
|
|
@ -2849,7 +2837,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
if let Some(expr) = expr {
|
||||
// We already forbid generic params because of the above item rib,
|
||||
// so it doesn't matter whether this is a trivial constant.
|
||||
this.resolve_static_body(expr, Some((ident, ConstantItemKind::Static)));
|
||||
this.resolve_static_body(expr, Some((*ident, ConstantItemKind::Static)));
|
||||
}
|
||||
});
|
||||
self.resolve_define_opaques(define_opaque);
|
||||
|
|
@ -2857,11 +2845,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
|
||||
ItemKind::Const(box ast::ConstItem {
|
||||
ident,
|
||||
ref generics,
|
||||
ref ty,
|
||||
ref rhs,
|
||||
ref define_opaque,
|
||||
..
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
define_opaque,
|
||||
defaultness: _,
|
||||
}) => {
|
||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
||||
self.with_generic_param_rib(
|
||||
|
|
@ -2903,15 +2891,36 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
if let Some(rhs) = rhs {
|
||||
this.resolve_const_item_rhs(
|
||||
rhs,
|
||||
Some((ident, ConstantItemKind::Const)),
|
||||
Some((*ident, ConstantItemKind::Const)),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
self.resolve_define_opaques(define_opaque);
|
||||
}
|
||||
ItemKind::ConstBlock(ConstBlockItem { id: _, span: _, block }) => self
|
||||
.with_generic_param_rib(
|
||||
&[],
|
||||
RibKind::Item(HasGenericParams::No, def_kind),
|
||||
item.id,
|
||||
LifetimeBinderKind::ConstItem,
|
||||
DUMMY_SP,
|
||||
|this| {
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::Elided(LifetimeRes::Infer),
|
||||
|this| {
|
||||
this.with_constant_rib(
|
||||
IsRepeatExpr::No,
|
||||
ConstantHasGenerics::Yes,
|
||||
Some((ConstBlockItem::IDENT, ConstantItemKind::Const)),
|
||||
|this| this.resolve_labeled_block(None, block.id, block),
|
||||
)
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
ItemKind::Use(ref use_tree) => {
|
||||
ItemKind::Use(use_tree) => {
|
||||
let maybe_exported = match use_tree.kind {
|
||||
UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
|
||||
UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis),
|
||||
|
|
@ -2921,7 +2930,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
self.future_proof_import(use_tree);
|
||||
}
|
||||
|
||||
ItemKind::MacroDef(_, ref macro_def) => {
|
||||
ItemKind::MacroDef(_, macro_def) => {
|
||||
// Maintain macro_rules scopes in the same way as during early resolution
|
||||
// for diagnostics and doc links.
|
||||
if macro_def.macro_rules {
|
||||
|
|
@ -2945,7 +2954,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
visit::walk_item(self, item);
|
||||
}
|
||||
|
||||
ItemKind::Delegation(ref delegation) => {
|
||||
ItemKind::Delegation(delegation) => {
|
||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||
self.with_generic_param_rib(
|
||||
&[],
|
||||
|
|
@ -5477,6 +5486,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
|
|||
|
||||
ItemKind::Mod(..)
|
||||
| ItemKind::Static(..)
|
||||
| ItemKind::ConstBlock(..)
|
||||
| ItemKind::Use(..)
|
||||
| ItemKind::ExternCrate(..)
|
||||
| ItemKind::MacroDef(..)
|
||||
|
|
|
|||
|
|
@ -2426,6 +2426,9 @@ options! {
|
|||
`=skip-entry`
|
||||
`=skip-exit`
|
||||
Multiple options can be combined with commas."),
|
||||
large_data_threshold: Option<u64> = (None, parse_opt_number, [TRACKED],
|
||||
"set the threshold for objects to be stored in a \"large data\" section \
|
||||
(only effective with -Ccode-model=medium, default: 65536)"),
|
||||
layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED],
|
||||
"seed layout randomization"),
|
||||
link_directives: bool = (true, parse_bool, [TRACKED],
|
||||
|
|
|
|||
|
|
@ -731,6 +731,7 @@ symbols! {
|
|||
console,
|
||||
const_allocate,
|
||||
const_async_blocks,
|
||||
const_block_items,
|
||||
const_closures,
|
||||
const_compare_raw_pointers,
|
||||
const_constructor,
|
||||
|
|
@ -2140,6 +2141,7 @@ symbols! {
|
|||
simd_shr,
|
||||
simd_shuffle,
|
||||
simd_shuffle_const_generic,
|
||||
simd_splat,
|
||||
simd_sub,
|
||||
simd_trunc,
|
||||
simd_with_exposed_provenance,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ impl RiscVInlineAsmRegClass {
|
|||
types! { _: I8, I16, I32, F16, F32; }
|
||||
}
|
||||
}
|
||||
// FIXME(f16_f128): Add `q: F128;` once LLVM support the `Q` extension.
|
||||
// FIXME(f128): Add `q: F128;` once LLVM support the `Q` extension.
|
||||
Self::freg => types! { f: F16, F32; d: F64; },
|
||||
Self::vreg => &[],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1596,8 +1596,11 @@ supported_targets! {
|
|||
("armebv7r-none-eabi", armebv7r_none_eabi),
|
||||
("armebv7r-none-eabihf", armebv7r_none_eabihf),
|
||||
("armv7r-none-eabi", armv7r_none_eabi),
|
||||
("thumbv7r-none-eabi", thumbv7r_none_eabi),
|
||||
("armv7r-none-eabihf", armv7r_none_eabihf),
|
||||
("thumbv7r-none-eabihf", thumbv7r_none_eabihf),
|
||||
("armv8r-none-eabihf", armv8r_none_eabihf),
|
||||
("thumbv8r-none-eabihf", thumbv8r_none_eabihf),
|
||||
|
||||
("armv7-rtems-eabihf", armv7_rtems_eabihf),
|
||||
|
||||
|
|
@ -1649,7 +1652,9 @@ supported_targets! {
|
|||
("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
|
||||
|
||||
("armv7a-none-eabi", armv7a_none_eabi),
|
||||
("thumbv7a-none-eabi", thumbv7a_none_eabi),
|
||||
("armv7a-none-eabihf", armv7a_none_eabihf),
|
||||
("thumbv7a-none-eabihf", thumbv7a_none_eabihf),
|
||||
("armv7a-nuttx-eabi", armv7a_nuttx_eabi),
|
||||
("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf),
|
||||
("armv7a-vex-v5", armv7a_vex_v5),
|
||||
|
|
@ -1741,10 +1746,14 @@ supported_targets! {
|
|||
("mipsel-unknown-none", mipsel_unknown_none),
|
||||
("mips-mti-none-elf", mips_mti_none_elf),
|
||||
("mipsel-mti-none-elf", mipsel_mti_none_elf),
|
||||
("thumbv4t-none-eabi", thumbv4t_none_eabi),
|
||||
|
||||
("armv4t-none-eabi", armv4t_none_eabi),
|
||||
("thumbv5te-none-eabi", thumbv5te_none_eabi),
|
||||
("armv5te-none-eabi", armv5te_none_eabi),
|
||||
("armv6-none-eabi", armv6_none_eabi),
|
||||
("armv6-none-eabihf", armv6_none_eabihf),
|
||||
("thumbv4t-none-eabi", thumbv4t_none_eabi),
|
||||
("thumbv5te-none-eabi", thumbv5te_none_eabi),
|
||||
("thumbv6-none-eabi", thumbv6_none_eabi),
|
||||
|
||||
("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
|
||||
("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Targets the ARMv4T, with code as `a32` code by default.
|
||||
//! Targets the ARMv4T architecture, with `a32` code by default.
|
||||
//!
|
||||
//! Primarily of use for the GBA, but usable with other devices too.
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Targets the ARMv5TE, with code as `a32` code by default.
|
||||
//! Targets the ARMv5TE architecture, with `a32` code by default.
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
|
||||
|
||||
|
|
|
|||
29
compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs
Normal file
29
compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//! Targets the ARMv6K architecture, with `a32` code by default.
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "armv6-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Bare ARMv6 soft-float".into()),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
arch: Arch::Arm,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
options: TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
|
||||
features: "+soft-float,+strict-align,+v6k".into(),
|
||||
atomic_cas: true,
|
||||
has_thumb_interworking: true,
|
||||
// LDREXD/STREXD available as of ARMv6K
|
||||
max_atomic_width: Some(64),
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
29
compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs
Normal file
29
compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//! Targets the ARMv6K architecture, with `a32` code by default, and hard-float ABI
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "armv6-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Bare ARMv6 hard-float".into()),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
arch: Arch::Arm,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
|
||||
features: "+strict-align,+v6k,+vfp2,-d32".into(),
|
||||
atomic_cas: true,
|
||||
has_thumb_interworking: true,
|
||||
// LDREXD/STREXD available as of ARMv6K
|
||||
max_atomic_width: Some(64),
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +1,8 @@
|
|||
// Generic ARMv7-A target for bare-metal code - floating point disabled
|
||||
//
|
||||
// This is basically the `armv7-unknown-linux-gnueabi` target with some changes
|
||||
// (listed below) to bring it closer to the bare-metal `thumb` & `aarch64`
|
||||
// targets:
|
||||
//
|
||||
// - `TargetOptions.features`: added `+strict-align`. rationale: unaligned
|
||||
// memory access is disabled on boot on these cores
|
||||
// - linker changed to LLD. rationale: C is not strictly needed to build
|
||||
// bare-metal binaries (the `gcc` linker has the advantage that it knows where C
|
||||
// libraries and crt*.o are but it's not much of an advantage here); LLD is also
|
||||
// faster
|
||||
// - `panic_strategy` set to `abort`. rationale: matches `thumb` targets
|
||||
// - `relocation-model` set to `static`; also no PIE, no relro and no dynamic
|
||||
// linking. rationale: matches `thumb` targets
|
||||
// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
|
||||
TargetOptions,
|
||||
};
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let opts = TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(),
|
||||
relocation_model: RelocModel::Static,
|
||||
disable_redzone: true,
|
||||
max_atomic_width: Some(64),
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
emit_debug_gdb_scripts: false,
|
||||
c_enum_min_bits: Some(8),
|
||||
has_thumb_interworking: true,
|
||||
..Default::default()
|
||||
};
|
||||
Target {
|
||||
llvm_target: "armv7a-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
|
|
@ -46,6 +14,13 @@ pub(crate) fn target() -> Target {
|
|||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
options: opts,
|
||||
options: TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
features: "+soft-float,-neon,+strict-align".into(),
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,8 @@
|
|||
// Generic ARMv7-A target for bare-metal code - floating point enabled (assumes
|
||||
// FPU is present and emits FPU instructions)
|
||||
//
|
||||
// This is basically the `armv7-unknown-linux-gnueabihf` target with some
|
||||
// changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal
|
||||
// `thumb` & `aarch64` targets.
|
||||
// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
|
||||
TargetOptions,
|
||||
};
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let opts = TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
features: "+v7,+vfp3d16,+thumb2,-neon,+strict-align".into(),
|
||||
relocation_model: RelocModel::Static,
|
||||
disable_redzone: true,
|
||||
max_atomic_width: Some(64),
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
emit_debug_gdb_scripts: false,
|
||||
// GCC defaults to 8 for arm-none here.
|
||||
c_enum_min_bits: Some(8),
|
||||
has_thumb_interworking: true,
|
||||
..Default::default()
|
||||
};
|
||||
Target {
|
||||
llvm_target: "armv7a-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
|
|
@ -38,6 +14,13 @@ pub(crate) fn target() -> Target {
|
|||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
options: opts,
|
||||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
features: "+vfp3d16,-neon,+strict-align".into(),
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
|
||||
TargetOptions,
|
||||
};
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "armv7r-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Armv7-R".into()),
|
||||
description: Some("Bare Armv7-R".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
|
|
@ -17,20 +14,12 @@ pub(crate) fn target() -> Target {
|
|||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
|
||||
options: TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
relocation_model: RelocModel::Static,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
max_atomic_width: Some(64),
|
||||
emit_debug_gdb_scripts: false,
|
||||
// GCC defaults to 8 for arm-none here.
|
||||
c_enum_min_bits: Some(8),
|
||||
has_thumb_interworking: true,
|
||||
..Default::default()
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
|
||||
TargetOptions,
|
||||
};
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "armv7r-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Armv7-R, hardfloat".into()),
|
||||
description: Some("Bare Armv7-R, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
|
|
@ -17,21 +14,13 @@ pub(crate) fn target() -> Target {
|
|||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
|
||||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
relocation_model: RelocModel::Static,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
features: "+vfp3d16".into(),
|
||||
max_atomic_width: Some(64),
|
||||
emit_debug_gdb_scripts: false,
|
||||
// GCC defaults to 8 for arm-none here.
|
||||
c_enum_min_bits: Some(8),
|
||||
has_thumb_interworking: true,
|
||||
..Default::default()
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
// Targets the Little-endian Cortex-R52 processor (ARMv8-R)
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
|
||||
TargetOptions,
|
||||
};
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
|
|
@ -21,10 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
relocation_model: RelocModel::Static,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
// Armv8-R requires a minimum set of floating-point features equivalent to:
|
||||
// fp-armv8, SP-only, with 16 DP (32 SP) registers
|
||||
// LLVM defines Armv8-R to include these features automatically.
|
||||
|
|
@ -36,11 +29,8 @@ pub(crate) fn target() -> Target {
|
|||
// Arm Cortex-R52 Processor Technical Reference Manual
|
||||
// - Chapter 15 Advanced SIMD and floating-point support
|
||||
max_atomic_width: Some(64),
|
||||
emit_debug_gdb_scripts: false,
|
||||
// GCC defaults to 8 for arm-none here.
|
||||
c_enum_min_bits: Some(8),
|
||||
has_thumb_interworking: true,
|
||||
..Default::default()
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ pub(crate) fn target() -> Target {
|
|||
llvm_target: "powerpc64-unknown-linux-musl".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("64-bit PowerPC Linux with musl 1.2.5".into()),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
tier: Some(2),
|
||||
host_tools: Some(true),
|
||||
std: Some(true),
|
||||
},
|
||||
pointer_width: 64,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Targets the ARMv4T, with code as `t32` code by default.
|
||||
//! Targets the ARMv4T architecture, with `t32` code by default.
|
||||
//!
|
||||
//! Primarily of use for the GBA, but usable with other devices too.
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Targets the ARMv5TE, with code as `t32` code by default.
|
||||
//! Targets the ARMv5TE architecture, with `t32` code by default.
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
|
||||
|
||||
|
|
|
|||
30
compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs
Normal file
30
compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//! Targets the ARMv6K architecture, with `t32` code by default.
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "thumbv6-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare ARMv6 soft-float".into()),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
arch: Arch::Arm,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
options: TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
|
||||
features: "+soft-float,+strict-align,+v6k".into(),
|
||||
// CAS atomics are implemented in LLVM on this target using __sync* functions,
|
||||
// which were added to compiler-builtins in https://github.com/rust-lang/compiler-builtins/pull/1050
|
||||
atomic_cas: true,
|
||||
has_thumb_interworking: true,
|
||||
max_atomic_width: Some(32),
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
26
compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs
Normal file
26
compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "thumbv7a-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-A".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
options: TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
features: "+soft-float,-neon,+strict-align".into(),
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "thumbv7a-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-A, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
features: "+vfp3d16,-neon,+strict-align".into(),
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
25
compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs
Normal file
25
compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "thumbv7r-none-eabi".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-R".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
options: TargetOptions {
|
||||
abi: Abi::Eabi,
|
||||
llvm_floatabi: Some(FloatAbi::Soft),
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "thumbv7r-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv7-R, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
features: "+vfp3d16".into(),
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Targets the Little-endian Cortex-R52 processor (ARMv8-R)
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
llvm_target: "thumbv8r-none-eabihf".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Thumb-mode Bare Armv8-R, hardfloat".into()),
|
||||
tier: Some(2),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
|
||||
arch: Arch::Arm,
|
||||
|
||||
options: TargetOptions {
|
||||
abi: Abi::EabiHf,
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
// Armv8-R requires a minimum set of floating-point features equivalent to:
|
||||
// fp-armv8, SP-only, with 16 DP (32 SP) registers
|
||||
// LLVM defines Armv8-R to include these features automatically.
|
||||
//
|
||||
// The Cortex-R52 supports these default features and optionally includes:
|
||||
// neon-fp-armv8, SP+DP, with 32 DP registers
|
||||
//
|
||||
// Reference:
|
||||
// Arm Cortex-R52 Processor Technical Reference Manual
|
||||
// - Chapter 15 Advanced SIMD and floating-point support
|
||||
max_atomic_width: Some(64),
|
||||
has_thumb_interworking: true,
|
||||
..base::arm_none::opts()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -492,7 +492,22 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
|||
const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||
// tidy-alphabetical-start
|
||||
("hvx", Unstable(sym::hexagon_target_feature), &[]),
|
||||
("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]),
|
||||
("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]),
|
||||
("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
|
||||
("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]),
|
||||
("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]),
|
||||
("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]),
|
||||
("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]),
|
||||
("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]),
|
||||
("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]),
|
||||
("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]),
|
||||
("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]),
|
||||
("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]),
|
||||
("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]),
|
||||
("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]),
|
||||
("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]),
|
||||
("zreg", Unstable(sym::hexagon_target_feature), &[]),
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
||||
|
|
@ -949,7 +964,7 @@ const SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'stat
|
|||
&[/*(64, "vis")*/];
|
||||
|
||||
const HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
|
||||
&[/*(512, "hvx-length64b"),*/ (1024, "hvx-length128b")];
|
||||
&[(512, "hvx-length64b"), (1024, "hvx-length128b")];
|
||||
const MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
|
||||
&[(128, "msa")];
|
||||
const CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
|
||||
|
|
|
|||
|
|
@ -865,9 +865,13 @@ const fn handle_error(e: TryReserveError) -> ! {
|
|||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
|
||||
const fn layout_array(cap: usize, elem_layout: Layout) -> Result<Layout, TryReserveError> {
|
||||
// This is only used with `elem_layout`s which are those of real rust types,
|
||||
// which lets us use the much-simpler `repeat_packed`.
|
||||
debug_assert!(elem_layout.size() == elem_layout.pad_to_align().size());
|
||||
|
||||
// FIXME(const-hack) return to using `map` and `map_err` once `const_closures` is implemented
|
||||
match elem_layout.repeat(cap) {
|
||||
Ok((layout, _pad)) => Ok(layout),
|
||||
match elem_layout.repeat_packed(cap) {
|
||||
Ok(layout) => Ok(layout),
|
||||
Err(_) => Err(CapacityOverflow.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,12 +118,12 @@ use crate::{cmp, ptr};
|
|||
///
|
||||
/// # Re-entrance
|
||||
///
|
||||
/// When implementing a global allocator one has to be careful not to create an infinitely recursive
|
||||
/// When implementing a global allocator, one has to be careful not to create an infinitely recursive
|
||||
/// implementation by accident, as many constructs in the Rust standard library may allocate in
|
||||
/// their implementation. For example, on some platforms [`std::sync::Mutex`] may allocate, so using
|
||||
/// their implementation. For example, on some platforms, [`std::sync::Mutex`] may allocate, so using
|
||||
/// it is highly problematic in a global allocator.
|
||||
///
|
||||
/// Generally speaking for this reason one should stick to library features available through
|
||||
/// For this reason, one should generally stick to library features available through
|
||||
/// [`core`], and avoid using [`std`] in a global allocator. A few features from [`std`] are
|
||||
/// guaranteed to not use `#[global_allocator]` to allocate:
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//! impl bool {}
|
||||
|
||||
use crate::marker::Destruct;
|
||||
|
||||
impl bool {
|
||||
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
|
||||
/// or `None` otherwise.
|
||||
|
|
@ -29,8 +31,9 @@ impl bool {
|
|||
/// assert_eq!(a, 2);
|
||||
/// ```
|
||||
#[stable(feature = "bool_to_option", since = "1.62.0")]
|
||||
#[rustc_const_unstable(feature = "const_bool", issue = "151531")]
|
||||
#[inline]
|
||||
pub fn then_some<T>(self, t: T) -> Option<T> {
|
||||
pub const fn then_some<T: [const] Destruct>(self, t: T) -> Option<T> {
|
||||
if self { Some(t) } else { None }
|
||||
}
|
||||
|
||||
|
|
@ -57,8 +60,9 @@ impl bool {
|
|||
#[doc(alias = "then_with")]
|
||||
#[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
|
||||
#[rustc_diagnostic_item = "bool_then"]
|
||||
#[rustc_const_unstable(feature = "const_bool", issue = "151531")]
|
||||
#[inline]
|
||||
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
|
||||
pub const fn then<T, F: [const] FnOnce() -> T + [const] Destruct>(self, f: F) -> Option<T> {
|
||||
if self { Some(f()) } else { None }
|
||||
}
|
||||
|
||||
|
|
@ -94,8 +98,9 @@ impl bool {
|
|||
/// assert_eq!(a, 2);
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_result", issue = "142748")]
|
||||
#[rustc_const_unstable(feature = "const_bool", issue = "151531")]
|
||||
#[inline]
|
||||
pub fn ok_or<E>(self, err: E) -> Result<(), E> {
|
||||
pub const fn ok_or<E: [const] Destruct>(self, err: E) -> Result<(), E> {
|
||||
if self { Ok(()) } else { Err(err) }
|
||||
}
|
||||
|
||||
|
|
@ -124,8 +129,12 @@ impl bool {
|
|||
/// assert_eq!(a, 1);
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_result", issue = "142748")]
|
||||
#[rustc_const_unstable(feature = "const_bool", issue = "151531")]
|
||||
#[inline]
|
||||
pub fn ok_or_else<E, F: FnOnce() -> E>(self, f: F) -> Result<(), E> {
|
||||
pub const fn ok_or_else<E, F: [const] FnOnce() -> E + [const] Destruct>(
|
||||
self,
|
||||
f: F,
|
||||
) -> Result<(), E> {
|
||||
if self { Ok(()) } else { Err(f()) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ impl_from!(i16 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.2
|
|||
// * 53 bits in f64
|
||||
// * 113 bits in f128
|
||||
// Lossy float conversions are not implemented at this time.
|
||||
// FIXME(f16_f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference
|
||||
// FIXME(f16,f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference
|
||||
// `f16`/`f128` when they are stabilised (trait impls have to have a `#[stable]` attribute, but none
|
||||
// of the `f16`/`f128` impls can be used on stable as the `f16` and `f128` types are unstable).
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ impl_from!(i16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
|
|||
impl_from!(i16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
impl_from!(i32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised.
|
||||
// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised.
|
||||
// impl_from!(i64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
|
||||
// unsigned integer -> float
|
||||
|
|
@ -181,11 +181,11 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
|
|||
impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
impl_from!(u32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised.
|
||||
// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised.
|
||||
// impl_from!(u64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
|
||||
// float -> float
|
||||
// FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See
|
||||
// FIXME(f16,f128): adding additional `From<{float}>` impls to `f32` breaks inference. See
|
||||
// <https://github.com/rust-lang/rust/issues/123831>
|
||||
impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ floating! { f32 f64 }
|
|||
#[cfg(target_has_reliable_f16)]
|
||||
floating! { f16 }
|
||||
|
||||
// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
|
||||
// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
|
||||
// to avoid ICEs.
|
||||
|
||||
#[cfg(not(target_has_reliable_f16))]
|
||||
|
|
|
|||
|
|
@ -292,9 +292,18 @@ pub fn spin_loop() {
|
|||
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
|
||||
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }
|
||||
}
|
||||
all(target_arch = "arm", target_feature = "v6") => {
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on arm targets
|
||||
// with support for the v6 feature.
|
||||
all(
|
||||
target_arch = "arm",
|
||||
any(
|
||||
all(target_feature = "v6k", not(target_feature = "thumb-mode")),
|
||||
target_feature = "v6t2",
|
||||
all(target_feature = "v6", target_feature = "mclass"),
|
||||
)
|
||||
) => {
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on arm
|
||||
// targets with support for the this feature. On ARMv6 in Thumb
|
||||
// mode, T2 is required (see Arm DDI0406C Section A8.8.427),
|
||||
// otherwise ARMv6-M or ARMv6K is enough
|
||||
unsafe { crate::arch::arm::__yield() }
|
||||
}
|
||||
target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(),
|
||||
|
|
|
|||
|
|
@ -52,6 +52,13 @@ pub const unsafe fn simd_insert_dyn<T, U>(x: T, idx: u32, val: U) -> T;
|
|||
#[rustc_intrinsic]
|
||||
pub const unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U;
|
||||
|
||||
/// Creates a vector where every lane has the provided value.
|
||||
///
|
||||
/// `T` must be a vector with element type `U`.
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
pub const unsafe fn simd_splat<T, U>(value: U) -> T;
|
||||
|
||||
/// Adds two simd vectors elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers or floats.
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ from_str_float_impl!(f16);
|
|||
from_str_float_impl!(f32);
|
||||
from_str_float_impl!(f64);
|
||||
|
||||
// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
|
||||
// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
|
||||
// to avoid ICEs.
|
||||
|
||||
#[cfg(not(target_has_reliable_f16))]
|
||||
|
|
|
|||
|
|
@ -137,10 +137,8 @@ pub mod consts {
|
|||
pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128;
|
||||
}
|
||||
|
||||
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))]
|
||||
impl f128 {
|
||||
// FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
|
||||
// implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
|
||||
|
||||
/// The radix or base of the internal representation of `f128`.
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
pub const RADIX: u32 = 2;
|
||||
|
|
@ -277,8 +275,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `unordtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let nan = f128::NAN;
|
||||
/// let f = 7.0_f128;
|
||||
|
|
@ -300,8 +297,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let f = 7.0f128;
|
||||
/// let inf = f128::INFINITY;
|
||||
|
|
@ -326,8 +322,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `lttf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let f = 7.0f128;
|
||||
/// let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -355,8 +350,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128
|
||||
/// let max = f128::MAX;
|
||||
|
|
@ -386,8 +380,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128
|
||||
/// let max = f128::MAX;
|
||||
|
|
@ -419,8 +412,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// use std::num::FpCategory;
|
||||
///
|
||||
|
|
@ -514,8 +506,7 @@ impl f128 {
|
|||
///
|
||||
/// ```rust
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// // f128::EPSILON is the difference between 1.0 and the next number up.
|
||||
/// assert_eq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
|
||||
|
|
@ -569,8 +560,7 @@ impl f128 {
|
|||
///
|
||||
/// ```rust
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// // Clamp value into range [0, 1).
|
||||
|
|
@ -613,8 +603,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let x = 2.0_f128;
|
||||
/// let abs_difference = (x.recip() - (1.0 / x)).abs();
|
||||
|
|
@ -640,8 +629,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let angle = std::f128::consts::PI;
|
||||
///
|
||||
|
|
@ -671,8 +659,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let angle = 180.0f128;
|
||||
///
|
||||
|
|
@ -706,8 +693,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // Using aarch64 because `reliable_f128_math` is needed
|
||||
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// let y = 2.0f128;
|
||||
|
|
@ -738,8 +724,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // Using aarch64 because `reliable_f128_math` is needed
|
||||
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// let y = 2.0f128;
|
||||
|
|
@ -771,8 +756,7 @@ impl f128 {
|
|||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(float_minimum_maximum)]
|
||||
/// # // Using aarch64 because `reliable_f128_math` is needed
|
||||
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// let y = 2.0f128;
|
||||
|
|
@ -804,8 +788,7 @@ impl f128 {
|
|||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(float_minimum_maximum)]
|
||||
/// # // Using aarch64 because `reliable_f128_math` is needed
|
||||
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// let y = 2.0f128;
|
||||
|
|
@ -831,8 +814,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // Using aarch64 because `reliable_f128_math` is needed
|
||||
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// assert_eq!(1f128.midpoint(4.0), 2.5);
|
||||
/// assert_eq!((-5.5f128).midpoint(8.0), 1.25);
|
||||
|
|
@ -862,8 +844,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `float*itf` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let value = 4.6_f128;
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
|
||||
|
|
@ -906,10 +887,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// # // FIXME(f16_f128): enable this once const casting works
|
||||
/// # // assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting!
|
||||
/// assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting!
|
||||
/// assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
|
|
@ -952,8 +934,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let v = f128::from_bits(0x40029000000000000000000000000000);
|
||||
/// assert_eq!(v, 12.5);
|
||||
|
|
@ -1064,8 +1045,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let value = f128::from_be_bytes(
|
||||
/// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
|
@ -1090,8 +1070,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let value = f128::from_le_bytes(
|
||||
/// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
|
@ -1123,8 +1102,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `eqtf2` is available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let value = f128::from_ne_bytes(if cfg!(target_endian = "big") {
|
||||
/// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
|
@ -1257,8 +1235,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # // FIXME(f16_f128): remove when `{eq,gt,unord}tf` are available
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// assert!((-3.0f128).clamp(-2.0, 1.0) == -2.0);
|
||||
/// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0);
|
||||
|
|
@ -1333,7 +1310,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let x = 3.5_f128;
|
||||
/// let y = -3.5_f128;
|
||||
|
|
@ -1349,9 +1326,7 @@ impl f128 {
|
|||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn abs(self) -> Self {
|
||||
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
|
||||
// We don't do this now because LLVM has lowering bugs for f128 math.
|
||||
Self::from_bits(self.to_bits() & !(1 << 127))
|
||||
intrinsics::fabsf128(self)
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
|
|
@ -1364,7 +1339,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let f = 3.5_f128;
|
||||
///
|
||||
|
|
@ -1400,7 +1375,7 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// # #[cfg(target_has_reliable_f128)] {
|
||||
///
|
||||
/// let f = 3.5_f128;
|
||||
///
|
||||
|
|
@ -1477,8 +1452,6 @@ impl f128 {
|
|||
}
|
||||
|
||||
// Functions in this module fall into `core_float_math`
|
||||
// FIXME(f16_f128): all doctests must be gated to platforms that have `long double` === `_Float128`
|
||||
// due to https://github.com/llvm/llvm-project/issues/44744. aarch64 linux matches this.
|
||||
// #[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[cfg(not(test))]
|
||||
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))]
|
||||
|
|
|
|||
|
|
@ -134,9 +134,6 @@ pub mod consts {
|
|||
|
||||
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))]
|
||||
impl f16 {
|
||||
// FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
|
||||
// implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
|
||||
|
||||
/// The radix or base of the internal representation of `f16`.
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
pub const RADIX: u32 = 2;
|
||||
|
|
@ -887,8 +884,7 @@ impl f16 {
|
|||
/// #![feature(f16)]
|
||||
/// # #[cfg(target_has_reliable_f16)] {
|
||||
///
|
||||
/// # // FIXME(f16_f128): enable this once const casting works
|
||||
/// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting!
|
||||
/// assert_ne!((1f16).to_bits(), 1f16 as u16); // to_bits() is not casting!
|
||||
/// assert_eq!((12.5f16).to_bits(), 0x4a40);
|
||||
/// # }
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -3,10 +3,7 @@
|
|||
use core::ascii::EscapeDefault;
|
||||
|
||||
use crate::fmt::{self, Write};
|
||||
#[cfg(not(any(
|
||||
all(target_arch = "x86_64", target_feature = "sse2"),
|
||||
all(target_arch = "loongarch64", target_feature = "lsx")
|
||||
)))]
|
||||
#[cfg(not(all(target_arch = "loongarch64", target_feature = "lsx")))]
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::{ascii, iter, ops};
|
||||
|
||||
|
|
@ -463,19 +460,101 @@ const fn is_ascii(s: &[u8]) -> bool {
|
|||
)
|
||||
}
|
||||
|
||||
/// ASCII test optimized to use the `pmovmskb` instruction on `x86-64` and the
|
||||
/// `vmskltz.b` instruction on `loongarch64`.
|
||||
/// Chunk size for vectorized ASCII checking (two 16-byte SSE registers).
|
||||
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
|
||||
const CHUNK_SIZE: usize = 32;
|
||||
|
||||
/// SSE2 implementation using `_mm_movemask_epi8` (compiles to `pmovmskb`) to
|
||||
/// avoid LLVM's broken AVX-512 auto-vectorization of counting loops.
|
||||
///
|
||||
/// FIXME(llvm#176906): Remove this workaround once LLVM generates efficient code.
|
||||
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
|
||||
fn is_ascii_sse2(bytes: &[u8]) -> bool {
|
||||
use crate::arch::x86_64::{__m128i, _mm_loadu_si128, _mm_movemask_epi8, _mm_or_si128};
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i + CHUNK_SIZE <= bytes.len() {
|
||||
// SAFETY: We have verified that `i + CHUNK_SIZE <= bytes.len()`.
|
||||
let ptr = unsafe { bytes.as_ptr().add(i) };
|
||||
|
||||
// Load two 16-byte chunks and combine them.
|
||||
// SAFETY: We verified `i + 32 <= len`, so ptr is valid for 32 bytes.
|
||||
// `_mm_loadu_si128` allows unaligned loads.
|
||||
let chunk1 = unsafe { _mm_loadu_si128(ptr as *const __m128i) };
|
||||
// SAFETY: Same as above - ptr.add(16) is within the valid 32-byte range.
|
||||
let chunk2 = unsafe { _mm_loadu_si128(ptr.add(16) as *const __m128i) };
|
||||
|
||||
// OR them together - if any byte has the high bit set, the result will too.
|
||||
// SAFETY: SSE2 is guaranteed by the cfg predicate.
|
||||
let combined = unsafe { _mm_or_si128(chunk1, chunk2) };
|
||||
|
||||
// Create a mask from the MSBs of each byte.
|
||||
// If any byte is >= 128, its MSB is 1, so the mask will be non-zero.
|
||||
// SAFETY: SSE2 is guaranteed by the cfg predicate.
|
||||
let mask = unsafe { _mm_movemask_epi8(combined) };
|
||||
|
||||
if mask != 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
i += CHUNK_SIZE;
|
||||
}
|
||||
|
||||
// Handle remaining bytes with simple loop
|
||||
while i < bytes.len() {
|
||||
if !bytes[i].is_ascii() {
|
||||
return false;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// ASCII test optimized to use the `pmovmskb` instruction on `x86-64`.
|
||||
///
|
||||
/// Uses explicit SSE2 intrinsics to prevent LLVM from auto-vectorizing with
|
||||
/// broken AVX-512 code that extracts mask bits one-by-one.
|
||||
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
|
||||
#[inline]
|
||||
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||
const fn is_ascii(bytes: &[u8]) -> bool {
|
||||
const USIZE_SIZE: usize = size_of::<usize>();
|
||||
const NONASCII_MASK: usize = usize::MAX / 255 * 0x80;
|
||||
|
||||
const_eval_select!(
|
||||
@capture { bytes: &[u8] } -> bool:
|
||||
if const {
|
||||
is_ascii_simple(bytes)
|
||||
} else {
|
||||
// For small inputs, use usize-at-a-time processing to avoid SSE2 call overhead.
|
||||
if bytes.len() < CHUNK_SIZE {
|
||||
let chunks = bytes.chunks_exact(USIZE_SIZE);
|
||||
let remainder = chunks.remainder();
|
||||
for chunk in chunks {
|
||||
let word = usize::from_ne_bytes(chunk.try_into().unwrap());
|
||||
if (word & NONASCII_MASK) != 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return remainder.iter().all(|b| b.is_ascii());
|
||||
}
|
||||
|
||||
is_ascii_sse2(bytes)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// ASCII test optimized to use the `vmskltz.b` instruction on `loongarch64`.
|
||||
///
|
||||
/// Other platforms are not likely to benefit from this code structure, so they
|
||||
/// use SWAR techniques to test for ASCII in `usize`-sized chunks.
|
||||
#[cfg(any(
|
||||
all(target_arch = "x86_64", target_feature = "sse2"),
|
||||
all(target_arch = "loongarch64", target_feature = "lsx")
|
||||
))]
|
||||
#[cfg(all(target_arch = "loongarch64", target_feature = "lsx"))]
|
||||
#[inline]
|
||||
const fn is_ascii(bytes: &[u8]) -> bool {
|
||||
// Process chunks of 32 bytes at a time in the fast path to enable
|
||||
// auto-vectorization and use of `pmovmskb`. Two 128-bit vector registers
|
||||
// auto-vectorization and use of `vmskltz.b`. Two 128-bit vector registers
|
||||
// can be OR'd together and then the resulting vector can be tested for
|
||||
// non-ASCII bytes.
|
||||
const CHUNK_SIZE: usize = 32;
|
||||
|
|
@ -485,7 +564,7 @@ const fn is_ascii(bytes: &[u8]) -> bool {
|
|||
while i + CHUNK_SIZE <= bytes.len() {
|
||||
let chunk_end = i + CHUNK_SIZE;
|
||||
|
||||
// Get LLVM to produce a `pmovmskb` instruction on x86-64 which
|
||||
// Get LLVM to produce a `vmskltz.b` instruction on loongarch64 which
|
||||
// creates a mask from the most significant bit of each byte.
|
||||
// ASCII bytes are less than 128 (0x80), so their most significant
|
||||
// bit is unset.
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ pub fn test_bool_not() {
|
|||
}
|
||||
}
|
||||
|
||||
const fn zero() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_to_option() {
|
||||
assert_eq!(false.then_some(0), None);
|
||||
|
|
@ -89,11 +93,6 @@ fn test_bool_to_option() {
|
|||
assert_eq!(false.then(|| 0), None);
|
||||
assert_eq!(true.then(|| 0), Some(0));
|
||||
|
||||
/* FIXME(#110395)
|
||||
const fn zero() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
const A: Option<i32> = false.then_some(0);
|
||||
const B: Option<i32> = true.then_some(0);
|
||||
const C: Option<i32> = false.then(zero);
|
||||
|
|
@ -103,7 +102,6 @@ fn test_bool_to_option() {
|
|||
assert_eq!(B, Some(0));
|
||||
assert_eq!(C, None);
|
||||
assert_eq!(D, Some(0));
|
||||
*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -112,4 +110,14 @@ fn test_bool_to_result() {
|
|||
assert_eq!(true.ok_or(0), Ok(()));
|
||||
assert_eq!(false.ok_or_else(|| 0), Err(0));
|
||||
assert_eq!(true.ok_or_else(|| 0), Ok(()));
|
||||
|
||||
const A: Result<(), i32> = false.ok_or(0);
|
||||
const B: Result<(), i32> = true.ok_or(0);
|
||||
const C: Result<(), i32> = false.ok_or_else(zero);
|
||||
const D: Result<(), i32> = true.ok_or_else(zero);
|
||||
|
||||
assert_eq!(A, Err(0));
|
||||
assert_eq!(B, Ok(()));
|
||||
assert_eq!(C, Err(0));
|
||||
assert_eq!(D, Ok(()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ float_test! {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(f16_f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on
|
||||
// FIXME(f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on
|
||||
// all platforms.
|
||||
float_test! {
|
||||
name: num_rem,
|
||||
|
|
@ -1357,15 +1357,11 @@ float_test! {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(f16): Tests involving sNaN are disabled because without optimizations, `total_cmp` is
|
||||
// getting incorrectly lowered to code that includes a `extend`/`trunc` round trip, which quiets
|
||||
// sNaNs. See: https://github.com/llvm/llvm-project/issues/104915
|
||||
|
||||
float_test! {
|
||||
name: total_cmp_s_nan,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
f16: #[cfg(miri)],
|
||||
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
|
||||
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
|
||||
},
|
||||
test<Float> {
|
||||
|
|
@ -1636,7 +1632,7 @@ float_test! {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(f16_f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added.
|
||||
// FIXME(f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added.
|
||||
// float_test! {
|
||||
// name: from_u64_i64,
|
||||
// attrs: {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#![feature(clamp_magnitude)]
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(const_array)]
|
||||
#![feature(const_bool)]
|
||||
#![feature(const_cell_traits)]
|
||||
#![feature(const_clone)]
|
||||
#![feature(const_cmp)]
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue