diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index a16219361c05..2ececee87510 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3417,9 +3417,9 @@ impl Item {
ItemKind::Fn(i) => Some(&i.generics),
ItemKind::TyAlias(i) => Some(&i.generics),
ItemKind::TraitAlias(_, generics, _)
- | ItemKind::Enum(_, _, generics)
- | ItemKind::Struct(_, _, generics)
- | ItemKind::Union(_, _, generics) => Some(&generics),
+ | ItemKind::Enum(_, generics, _)
+ | ItemKind::Struct(_, generics, _)
+ | ItemKind::Union(_, generics, _) => Some(&generics),
ItemKind::Trait(i) => Some(&i.generics),
ItemKind::Impl(i) => Some(&i.generics),
}
@@ -3663,15 +3663,15 @@ pub enum ItemKind {
/// An enum definition (`enum`).
///
/// E.g., `enum Foo { C, D }`.
- Enum(Ident, EnumDef, Generics),
+ Enum(Ident, Generics, EnumDef),
/// A struct definition (`struct`).
///
/// E.g., `struct Foo { x: A }`.
- Struct(Ident, VariantData, Generics),
+ Struct(Ident, Generics, VariantData),
/// A union definition (`union`).
///
/// E.g., `union Foo { x: A, y: B }`.
- Union(Ident, VariantData, Generics),
+ Union(Ident, Generics, VariantData),
/// A trait declaration (`trait`).
///
/// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`.
@@ -3688,10 +3688,8 @@ pub enum ItemKind {
///
/// E.g., `foo!(..)`.
MacCall(P),
-
/// A macro definition.
MacroDef(Ident, MacroDef),
-
/// A single delegation item (`reuse`).
///
/// E.g. `reuse ::name { target_expr_template }`.
@@ -3767,9 +3765,9 @@ impl ItemKind {
Self::Fn(box Fn { generics, .. })
| Self::TyAlias(box TyAlias { generics, .. })
| Self::Const(box ConstItem { generics, .. })
- | Self::Enum(_, _, generics)
- | Self::Struct(_, _, generics)
- | Self::Union(_, _, generics)
+ | Self::Enum(_, generics, _)
+ | Self::Struct(_, generics, _)
+ | Self::Union(_, generics, _)
| Self::Trait(box Trait { generics, .. })
| Self::TraitAlias(_, generics, _)
| Self::Impl(box Impl { generics, .. }) => Some(generics),
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index bf5c402e52e5..1cc11b58dd97 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -508,7 +508,7 @@ macro_rules! common_visitor_and_walkers {
)?
$(>::Result::output())?
}
- ItemKind::Enum(ident, enum_definition, generics) => {
+ ItemKind::Enum(ident, generics, enum_definition) => {
try_visit!(vis.visit_ident(ident));
try_visit!(vis.visit_generics(generics));
$(${ignore($mut)}
@@ -516,8 +516,8 @@ macro_rules! common_visitor_and_walkers {
)?
$(${ignore($lt)}vis.visit_enum_def(enum_definition))?
}
- ItemKind::Struct(ident, variant_data, generics)
- | ItemKind::Union(ident, variant_data, generics) => {
+ ItemKind::Struct(ident, generics, variant_data)
+ | ItemKind::Union(ident, generics, variant_data) => {
try_visit!(vis.visit_ident(ident));
try_visit!(vis.visit_generics(generics));
vis.visit_variant_data(variant_data)
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e98d6c50ee79..7f7d45790ee2 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -306,7 +306,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
hir::ItemKind::TyAlias(ident, ty, generics)
}
- ItemKind::Enum(ident, enum_definition, generics) => {
+ ItemKind::Enum(ident, generics, enum_definition) => {
let ident = self.lower_ident(*ident);
let (generics, variants) = self.lower_generics(
generics,
@@ -320,7 +320,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics)
}
- ItemKind::Struct(ident, struct_def, generics) => {
+ ItemKind::Struct(ident, generics, struct_def) => {
let ident = self.lower_ident(*ident);
let (generics, struct_def) = self.lower_generics(
generics,
@@ -330,7 +330,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
hir::ItemKind::Struct(ident, struct_def, generics)
}
- ItemKind::Union(ident, vdata, generics) => {
+ ItemKind::Union(ident, generics, vdata) => {
let ident = self.lower_ident(*ident);
let (generics, vdata) = self.lower_generics(
generics,
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index cbf4f2f5eb2b..d6fe04d2994b 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1010,7 +1010,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
self.extern_mod_span = old_item;
}
- ItemKind::Enum(_, def, _) => {
+ ItemKind::Enum(_, _, def) => {
for variant in &def.variants {
self.visibility_not_permitted(
&variant.vis,
@@ -1061,7 +1061,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
visit::walk_item(self, item)
}
- ItemKind::Struct(ident, vdata, generics) => match vdata {
+ ItemKind::Struct(ident, generics, vdata) => match vdata {
VariantData::Struct { fields, .. } => {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
self.visit_generics(generics);
@@ -1070,7 +1070,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
_ => visit::walk_item(self, item),
},
- ItemKind::Union(ident, vdata, generics) => {
+ ItemKind::Union(ident, generics, vdata) => {
if vdata.fields().is_empty() {
self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 70cf2f2a4598..3638eb31c618 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -298,14 +298,14 @@ impl<'a> State<'a> {
*defaultness,
);
}
- ast::ItemKind::Enum(ident, enum_definition, params) => {
- self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis);
+ ast::ItemKind::Enum(ident, generics, enum_definition) => {
+ self.print_enum_def(enum_definition, generics, *ident, item.span, &item.vis);
}
- ast::ItemKind::Struct(ident, struct_def, generics) => {
+ ast::ItemKind::Struct(ident, generics, struct_def) => {
let (cb, ib) = self.head(visibility_qualified(&item.vis, "struct"));
self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
}
- ast::ItemKind::Union(ident, struct_def, generics) => {
+ ast::ItemKind::Union(ident, generics, struct_def) => {
let (cb, ib) = self.head(visibility_qualified(&item.vis, "union"));
self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
}
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 628bdee1129a..d32e6f1558e4 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -56,7 +56,6 @@ builtin_macros_assert_requires_expression = macro requires an expression as an a
builtin_macros_autodiff = autodiff must be applied to function
builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode
-builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Reverse`
builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode
builtin_macros_autodiff_not_build = this rustc version does not support autodiff
builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found}
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 1ff4fc6aaab2..dc3bb8ab52a5 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -86,27 +86,23 @@ mod llvm_enzyme {
ecx: &mut ExtCtxt<'_>,
meta_item: &ThinVec,
has_ret: bool,
+ mode: DiffMode,
) -> AutoDiffAttrs {
let dcx = ecx.sess.dcx();
- let mode = name(&meta_item[1]);
- let Ok(mode) = DiffMode::from_str(&mode) else {
- dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode });
- return AutoDiffAttrs::error();
- };
// Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode.
// If he doesn't specify an integer (=width), we default to scalar mode, thus width=1.
- let mut first_activity = 2;
+ let mut first_activity = 1;
- let width = if let [_, _, x, ..] = &meta_item[..]
+ let width = if let [_, x, ..] = &meta_item[..]
&& let Some(x) = width(x)
{
- first_activity = 3;
+ first_activity = 2;
match x.try_into() {
Ok(x) => x,
Err(_) => {
dcx.emit_err(errors::AutoDiffInvalidWidth {
- span: meta_item[2].span(),
+ span: meta_item[1].span(),
width: x,
});
return AutoDiffAttrs::error();
@@ -165,6 +161,24 @@ mod llvm_enzyme {
ts.push(TokenTree::Token(comma.clone(), Spacing::Alone));
}
+ pub(crate) fn expand_forward(
+ ecx: &mut ExtCtxt<'_>,
+ expand_span: Span,
+ meta_item: &ast::MetaItem,
+ item: Annotatable,
+ ) -> Vec {
+ expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Forward)
+ }
+
+ pub(crate) fn expand_reverse(
+ ecx: &mut ExtCtxt<'_>,
+ expand_span: Span,
+ meta_item: &ast::MetaItem,
+ item: Annotatable,
+ ) -> Vec {
+ expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Reverse)
+ }
+
/// We expand the autodiff macro to generate a new placeholder function which passes
/// type-checking and can be called by users. The function body of the placeholder function will
/// later be replaced on LLVM-IR level, so the design of the body is less important and for now
@@ -198,11 +212,12 @@ mod llvm_enzyme {
/// ```
/// FIXME(ZuseZ4): Once autodiff is enabled by default, make this a doc comment which is checked
/// in CI.
- pub(crate) fn expand(
+ pub(crate) fn expand_with_mode(
ecx: &mut ExtCtxt<'_>,
expand_span: Span,
meta_item: &ast::MetaItem,
mut item: Annotatable,
+ mode: DiffMode,
) -> Vec {
if cfg!(not(llvm_enzyme)) {
ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span });
@@ -245,29 +260,41 @@ mod llvm_enzyme {
// create TokenStream from vec elemtents:
// meta_item doesn't have a .tokens field
let mut ts: Vec = vec![];
- if meta_item_vec.len() < 2 {
- // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no
- // input and output args.
+ if meta_item_vec.len() < 1 {
+ // At the bare minimum, we need a fnc name.
dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() });
return vec![item];
}
- meta_item_inner_to_ts(&meta_item_vec[1], &mut ts);
+ let mode_symbol = match mode {
+ DiffMode::Forward => sym::Forward,
+ DiffMode::Reverse => sym::Reverse,
+ _ => unreachable!("Unsupported mode: {:?}", mode),
+ };
+
+ // Insert mode token
+ let mode_token = Token::new(TokenKind::Ident(mode_symbol, false.into()), Span::default());
+ ts.insert(0, TokenTree::Token(mode_token, Spacing::Joint));
+ ts.insert(
+ 1,
+ TokenTree::Token(Token::new(TokenKind::Comma, Span::default()), Spacing::Alone),
+ );
// Now, if the user gave a width (vector aka batch-mode ad), then we copy it.
// If it is not given, we default to 1 (scalar mode).
let start_position;
let kind: LitKind = LitKind::Integer;
let symbol;
- if meta_item_vec.len() >= 3
- && let Some(width) = width(&meta_item_vec[2])
+ if meta_item_vec.len() >= 2
+ && let Some(width) = width(&meta_item_vec[1])
{
- start_position = 3;
+ start_position = 2;
symbol = Symbol::intern(&width.to_string());
} else {
- start_position = 2;
+ start_position = 1;
symbol = sym::integer(1);
}
+
let l: Lit = Lit { kind, symbol, suffix: None };
let t = Token::new(TokenKind::Literal(l), Span::default());
let comma = Token::new(TokenKind::Comma, Span::default());
@@ -289,7 +316,7 @@ mod llvm_enzyme {
ts.pop();
let ts: TokenStream = TokenStream::from_iter(ts);
- let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret);
+ let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret, mode);
if !x.is_active() {
// We encountered an error, so we return the original item.
// This allows us to potentially parse other attributes.
@@ -1017,4 +1044,4 @@ mod llvm_enzyme {
}
}
-pub(crate) use llvm_enzyme::expand;
+pub(crate) use llvm_enzyme::{expand_forward, expand_reverse};
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 44cf215c6622..69f8c273797e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone(
let is_simple;
match item {
Annotatable::Item(annitem) => match &annitem.kind {
- ItemKind::Struct(_, _, Generics { params, .. })
- | ItemKind::Enum(_, _, Generics { params, .. }) => {
+ ItemKind::Struct(_, Generics { params, .. }, _)
+ | ItemKind::Enum(_, Generics { params, .. }, _) => {
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
if has_derive_copy
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index aa01da3151eb..0a076dd670b3 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord(
// Order in which to perform matching
let discr_then_data = if let Annotatable::Item(item) = item
- && let ItemKind::Enum(_, def, _) = &item.kind
+ && let ItemKind::Enum(_, _, def) = &item.kind
{
let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
match dataful.iter().filter(|&&b| b).count() {
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 446d8afeedd7..0794192621a9 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
- && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind
+ && let ItemKind::Struct(ident, g, struct_data) = &aitem.kind
{
if !matches!(
struct_data,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 9aa53f9e4f73..f1bef526c108 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -488,7 +488,7 @@ impl<'a> TraitDef<'a> {
);
let newitem = match &item.kind {
- ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def(
+ ast::ItemKind::Struct(ident, generics, struct_def) => self.expand_struct_def(
cx,
struct_def,
*ident,
@@ -496,7 +496,7 @@ impl<'a> TraitDef<'a> {
from_scratch,
is_packed,
),
- ast::ItemKind::Enum(ident, enum_def, generics) => {
+ ast::ItemKind::Enum(ident, generics, enum_def) => {
// We ignore `is_packed` here, because `repr(packed)`
// enums cause an error later on.
//
@@ -504,7 +504,7 @@ impl<'a> TraitDef<'a> {
// downstream in blatantly illegal code, so it is fine.
self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch)
}
- ast::ItemKind::Union(ident, struct_def, generics) => {
+ ast::ItemKind::Union(ident, generics, struct_def) => {
if self.supports_unions {
self.expand_struct_def(
cx,
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 75d06a8df14c..3a2e96a5e5af 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -180,14 +180,6 @@ mod autodiff {
pub(crate) act: String,
}
- #[derive(Diagnostic)]
- #[diag(builtin_macros_autodiff_mode)]
- pub(crate) struct AutoDiffInvalidMode {
- #[primary_span]
- pub(crate) span: Span,
- pub(crate) mode: String,
- }
-
#[derive(Diagnostic)]
#[diag(builtin_macros_autodiff_width)]
pub(crate) struct AutoDiffInvalidWidth {
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 9cd4d17059a0..b16f3cff5cfb 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -5,10 +5,10 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(not(bootstrap), feature(autodiff))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
-#![feature(autodiff)]
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
@@ -112,7 +112,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
register_attr! {
alloc_error_handler: alloc_error_handler::expand,
- autodiff: autodiff::expand,
+ autodiff_forward: autodiff::expand_forward,
+ autodiff_reverse: autodiff::expand_reverse,
bench: test::expand_bench,
cfg_accessible: cfg_accessible::Expander,
cfg_eval: cfg_eval::expand,
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index ba65c8205a50..1bcb891a2504 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -22,11 +22,11 @@ use rustc_codegen_ssa::traits::{
};
use rustc_middle::bug;
#[cfg(feature = "master")]
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
+use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, Ty};
use rustc_span::{Span, Symbol, sym};
-use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
+use rustc_target::callconv::{ArgAbi, PassMode};
use rustc_target::spec::PanicStrategy;
#[cfg(feature = "master")]
@@ -200,9 +200,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
fn codegen_intrinsic_call(
&mut self,
instance: Instance<'tcx>,
- fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, RValue<'gcc>>],
- llresult: RValue<'gcc>,
+ result: PlaceRef<'tcx, RValue<'gcc>>,
span: Span,
) -> Result<(), Instance<'tcx>> {
let tcx = self.tcx;
@@ -221,7 +220,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
let name_str = name.as_str();
let llret_ty = self.layout_of(ret_ty).gcc_type(self);
- let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
let simple = get_simple_intrinsic(self, name);
let simple_func = get_simple_function(self, name);
@@ -271,7 +269,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
- llresult,
+ result,
);
return Ok(());
}
@@ -286,17 +284,10 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}
sym::volatile_load | sym::unaligned_volatile_load => {
- let tp_ty = fn_args.type_at(0);
let ptr = args[0].immediate();
- let layout = self.layout_of(tp_ty);
- let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
- let gcc_ty = ty.gcc_type(self);
- self.volatile_load(gcc_ty, ptr)
- } else {
- self.volatile_load(layout.gcc_type(self), ptr)
- };
+ let load = self.volatile_load(result.layout.gcc_type(self), ptr);
// TODO(antoyo): set alignment.
- if let BackendRepr::Scalar(scalar) = layout.backend_repr {
+ if let BackendRepr::Scalar(scalar) = result.layout.backend_repr {
self.to_immediate_scalar(load, scalar)
} else {
load
@@ -511,16 +502,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
_ => return Err(Instance::new_raw(instance.def_id(), instance.args)),
};
- if !fn_abi.ret.is_ignore() {
- if let PassMode::Cast { cast: ref ty, .. } = fn_abi.ret.mode {
- let ptr_llty = self.type_ptr_to(ty.gcc_type(self));
- let ptr = self.pointercast(result.val.llval, ptr_llty);
- self.store(value, ptr, result.val.align);
- } else {
- OperandRef::from_immediate_or_packed_pair(self, value, result.layout)
- .val
- .store(self, result);
- }
+ if result.layout.ty.is_bool() {
+ OperandRef::from_immediate_or_packed_pair(self, value, result.layout)
+ .val
+ .store(self, result);
+ } else if !result.layout.ty.is_unit() {
+ let ptr_llty = self.type_ptr_to(result.layout.gcc_type(self));
+ let ptr = self.pointercast(result.val.llval, ptr_llty);
+ self.store(value, ptr, result.val.align);
}
Ok(())
}
@@ -1230,14 +1219,13 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
try_func: RValue<'gcc>,
data: RValue<'gcc>,
_catch_func: RValue<'gcc>,
- dest: RValue<'gcc>,
+ dest: PlaceRef<'tcx, RValue<'gcc>>,
) {
if bx.sess().panic_strategy() == PanicStrategy::Abort {
bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
- let ret_align = bx.tcx.data_layout.i32_align.abi;
- bx.store(bx.const_i32(0), dest, ret_align);
+ OperandValue::Immediate(bx.const_i32(0)).store(bx, dest);
} else {
if wants_msvc_seh(bx.sess()) {
unimplemented!();
@@ -1261,12 +1249,12 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
// functions in play. By calling a shim we're guaranteed that our shim will have
// the right personality function.
#[cfg(feature = "master")]
-fn codegen_gnu_try<'gcc>(
- bx: &mut Builder<'_, 'gcc, '_>,
+fn codegen_gnu_try<'gcc, 'tcx>(
+ bx: &mut Builder<'_, 'gcc, 'tcx>,
try_func: RValue<'gcc>,
data: RValue<'gcc>,
catch_func: RValue<'gcc>,
- dest: RValue<'gcc>,
+ dest: PlaceRef<'tcx, RValue<'gcc>>,
) {
let cx: &CodegenCx<'gcc, '_> = bx.cx;
let (llty, func) = get_rust_try_fn(cx, &mut |mut bx| {
@@ -1322,8 +1310,7 @@ fn codegen_gnu_try<'gcc>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None);
- let i32_align = bx.tcx().data_layout.i32_align.abi;
- bx.store(ret, dest, i32_align);
+ OperandValue::Immediate(ret).store(bx, dest);
}
// Helper function used to get a handle to the `__rust_try` function used to
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 5ca573752922..e8629aeebb95 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -15,11 +15,10 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty};
use rustc_middle::{bug, span_bug};
use rustc_span::{Span, Symbol, sym};
use rustc_symbol_mangling::mangle_internal_symbol;
-use rustc_target::callconv::{FnAbi, PassMode};
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
use tracing::debug;
-use crate::abi::{FnAbiLlvmExt, LlvmType};
+use crate::abi::FnAbiLlvmExt;
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::llvm::{self, Metadata};
@@ -165,9 +164,8 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
fn codegen_intrinsic_call(
&mut self,
instance: ty::Instance<'tcx>,
- fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, &'ll Value>],
- llresult: &'ll Value,
+ result: PlaceRef<'tcx, &'ll Value>,
span: Span,
) -> Result<(), ty::Instance<'tcx>> {
let tcx = self.tcx;
@@ -184,7 +182,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
let name = tcx.item_name(def_id);
let llret_ty = self.layout_of(ret_ty).llvm_type(self);
- let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
let simple = get_simple_intrinsic(self, name);
let llval = match name {
@@ -255,7 +252,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
- llresult,
+ result,
);
return Ok(());
}
@@ -264,7 +261,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
self.call_intrinsic("llvm.va_copy", &[args[0].immediate(), args[1].immediate()])
}
sym::va_arg => {
- match fn_abi.ret.layout.backend_repr {
+ match result.layout.backend_repr {
BackendRepr::Scalar(scalar) => {
match scalar.primitive() {
Primitive::Int(..) => {
@@ -299,18 +296,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
sym::volatile_load | sym::unaligned_volatile_load => {
- let tp_ty = fn_args.type_at(0);
let ptr = args[0].immediate();
- let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
- let llty = ty.llvm_type(self);
- self.volatile_load(llty, ptr)
- } else {
- self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr)
- };
+ let load = self.volatile_load(result.layout.llvm_type(self), ptr);
let align = if name == sym::unaligned_volatile_load {
1
} else {
- self.align_of(tp_ty).bytes() as u32
+ result.layout.align.abi.bytes() as u32
};
unsafe {
llvm::LLVMSetAlignment(load, align);
@@ -629,14 +620,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
};
- if !fn_abi.ret.is_ignore() {
- if let PassMode::Cast { .. } = &fn_abi.ret.mode {
- self.store(llval, result.val.llval, result.val.align);
- } else {
- OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
- .val
- .store(self, result);
- }
+ if result.layout.ty.is_bool() {
+ OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
+ .val
+ .store(self, result);
+ } else if !result.layout.ty.is_unit() {
+ self.store_to_place(llval, result.val);
}
Ok(())
}
@@ -688,20 +677,19 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
}
-fn catch_unwind_intrinsic<'ll>(
- bx: &mut Builder<'_, 'll, '_>,
+fn catch_unwind_intrinsic<'ll, 'tcx>(
+ bx: &mut Builder<'_, 'll, 'tcx>,
try_func: &'ll Value,
data: &'ll Value,
catch_func: &'ll Value,
- dest: &'ll Value,
+ dest: PlaceRef<'tcx, &'ll Value>,
) {
if bx.sess().panic_strategy() == PanicStrategy::Abort {
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.call(try_func_ty, None, None, try_func, &[data], None, None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
- let ret_align = bx.tcx().data_layout.i32_align.abi;
- bx.store(bx.const_i32(0), dest, ret_align);
+ OperandValue::Immediate(bx.const_i32(0)).store(bx, dest);
} else if wants_msvc_seh(bx.sess()) {
codegen_msvc_try(bx, try_func, data, catch_func, dest);
} else if wants_wasm_eh(bx.sess()) {
@@ -720,12 +708,12 @@ fn catch_unwind_intrinsic<'ll>(
// instructions are meant to work for all targets, as of the time of this
// writing, however, LLVM does not recommend the usage of these new instructions
// as the old ones are still more optimized.
-fn codegen_msvc_try<'ll>(
- bx: &mut Builder<'_, 'll, '_>,
+fn codegen_msvc_try<'ll, 'tcx>(
+ bx: &mut Builder<'_, 'll, 'tcx>,
try_func: &'ll Value,
data: &'ll Value,
catch_func: &'ll Value,
- dest: &'ll Value,
+ dest: PlaceRef<'tcx, &'ll Value>,
) {
let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
bx.set_personality_fn(bx.eh_personality());
@@ -865,17 +853,16 @@ fn codegen_msvc_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
- let i32_align = bx.tcx().data_layout.i32_align.abi;
- bx.store(ret, dest, i32_align);
+ OperandValue::Immediate(ret).store(bx, dest);
}
// WASM's definition of the `rust_try` function.
-fn codegen_wasm_try<'ll>(
- bx: &mut Builder<'_, 'll, '_>,
+fn codegen_wasm_try<'ll, 'tcx>(
+ bx: &mut Builder<'_, 'll, 'tcx>,
try_func: &'ll Value,
data: &'ll Value,
catch_func: &'ll Value,
- dest: &'ll Value,
+ dest: PlaceRef<'tcx, &'ll Value>,
) {
let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
bx.set_personality_fn(bx.eh_personality());
@@ -939,8 +926,7 @@ fn codegen_wasm_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
- let i32_align = bx.tcx().data_layout.i32_align.abi;
- bx.store(ret, dest, i32_align);
+ OperandValue::Immediate(ret).store(bx, dest);
}
// Definition of the standard `try` function for Rust using the GNU-like model
@@ -954,12 +940,12 @@ fn codegen_wasm_try<'ll>(
// function calling it, and that function may already have other personality
// functions in play. By calling a shim we're guaranteed that our shim will have
// the right personality function.
-fn codegen_gnu_try<'ll>(
- bx: &mut Builder<'_, 'll, '_>,
+fn codegen_gnu_try<'ll, 'tcx>(
+ bx: &mut Builder<'_, 'll, 'tcx>,
try_func: &'ll Value,
data: &'ll Value,
catch_func: &'ll Value,
- dest: &'ll Value,
+ dest: PlaceRef<'tcx, &'ll Value>,
) {
let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
// Codegens the shims described above:
@@ -1006,19 +992,18 @@ fn codegen_gnu_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
- let i32_align = bx.tcx().data_layout.i32_align.abi;
- bx.store(ret, dest, i32_align);
+ OperandValue::Immediate(ret).store(bx, dest);
}
// Variant of codegen_gnu_try used for emscripten where Rust panics are
// implemented using C++ exceptions. Here we use exceptions of a specific type
// (`struct rust_panic`) to represent Rust panics.
-fn codegen_emcc_try<'ll>(
- bx: &mut Builder<'_, 'll, '_>,
+fn codegen_emcc_try<'ll, 'tcx>(
+ bx: &mut Builder<'_, 'll, 'tcx>,
try_func: &'ll Value,
data: &'ll Value,
catch_func: &'ll Value,
- dest: &'ll Value,
+ dest: PlaceRef<'tcx, &'ll Value>,
) {
let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
// Codegens the shims described above:
@@ -1089,8 +1074,7 @@ fn codegen_emcc_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
- let i32_align = bx.tcx().data_layout.i32_align.abi;
- bx.store(ret, dest, i32_align);
+ OperandValue::Immediate(ret).store(bx, dest);
}
// Helper function to give a Block to a closure to codegen a shim function.
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index c5792da26781..b802284eb325 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -68,6 +68,23 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
}
}
+fn check_link_info_print_request(sess: &Session, crate_types: &[CrateType]) {
+ let print_native_static_libs =
+ sess.opts.prints.iter().any(|p| p.kind == PrintKind::NativeStaticLibs);
+ let has_staticlib = crate_types.iter().any(|ct| *ct == CrateType::Staticlib);
+ if print_native_static_libs {
+ if !has_staticlib {
+ sess.dcx()
+ .warn(format!("cannot output linkage information without staticlib crate-type"));
+ sess.dcx()
+ .note(format!("consider `--crate-type staticlib` to print linkage information"));
+ } else if !sess.opts.output_types.should_link() {
+ sess.dcx()
+ .warn(format!("cannot output linkage information when --emit link is not passed"));
+ }
+ }
+}
+
/// Performs the linkage portion of the compilation phase. This will generate all
/// of the requested outputs for this compilation session.
pub fn link_binary(
@@ -180,6 +197,8 @@ pub fn link_binary(
}
}
+ check_link_info_print_request(sess, &codegen_results.crate_info.crate_types);
+
// Remove the temporary object file and metadata if we aren't saving temps.
sess.time("link_binary_remove_temps", || {
// If the user requests that temporaries are saved, don't delete any.
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 922b8a5824be..1baab62ae43a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -11,8 +11,8 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
+use rustc_span::Span;
use rustc_span::source_map::Spanned;
-use rustc_span::{Span, sym};
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use tracing::{debug, info};
@@ -827,7 +827,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
helper: &TerminatorCodegenHelper<'tcx>,
bx: &mut Bx,
intrinsic: ty::IntrinsicDef,
- instance: Option>,
+ instance: Instance<'tcx>,
source_info: mir::SourceInfo,
target: Option,
unwind: mir::UnwindAction,
@@ -836,58 +836,56 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Emit a panic or a no-op for `assert_*` intrinsics.
// These are intrinsics that compile to panics so that we can get a message
// which mentions the offending type, even from a const context.
- if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
- let ty = instance.unwrap().args.type_at(0);
+ let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) else {
+ return None;
+ };
- let do_panic = !bx
- .tcx()
- .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
- .expect("expect to have layout during codegen");
+ let ty = instance.args.type_at(0);
- let layout = bx.layout_of(ty);
+ let is_valid = bx
+ .tcx()
+ .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
+ .expect("expect to have layout during codegen");
- Some(if do_panic {
- let msg_str = with_no_visible_paths!({
- with_no_trimmed_paths!({
- if layout.is_uninhabited() {
- // Use this error even for the other intrinsics as it is more precise.
- format!("attempted to instantiate uninhabited type `{ty}`")
- } else if requirement == ValidityRequirement::Zero {
- format!("attempted to zero-initialize type `{ty}`, which is invalid")
- } else {
- format!(
- "attempted to leave type `{ty}` uninitialized, which is invalid"
- )
- }
- })
- });
- let msg = bx.const_str(&msg_str);
-
- // Obtain the panic entry point.
- let (fn_abi, llfn, instance) =
- common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
-
- // Codegen the actual panic invoke/call.
- helper.do_call(
- self,
- bx,
- fn_abi,
- llfn,
- &[msg.0, msg.1],
- target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
- unwind,
- &[],
- Some(instance),
- mergeable_succ,
- )
- } else {
- // a NOP
- let target = target.unwrap();
- helper.funclet_br(self, bx, target, mergeable_succ)
- })
- } else {
- None
+ if is_valid {
+ // a NOP
+ let target = target.unwrap();
+ return Some(helper.funclet_br(self, bx, target, mergeable_succ));
}
+
+ let layout = bx.layout_of(ty);
+
+ let msg_str = with_no_visible_paths!({
+ with_no_trimmed_paths!({
+ if layout.is_uninhabited() {
+ // Use this error even for the other intrinsics as it is more precise.
+ format!("attempted to instantiate uninhabited type `{ty}`")
+ } else if requirement == ValidityRequirement::Zero {
+ format!("attempted to zero-initialize type `{ty}`, which is invalid")
+ } else {
+ format!("attempted to leave type `{ty}` uninitialized, which is invalid")
+ }
+ })
+ });
+ let msg = bx.const_str(&msg_str);
+
+ // Obtain the panic entry point.
+ let (fn_abi, llfn, instance) =
+ common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
+
+ // Codegen the actual panic invoke/call.
+ Some(helper.do_call(
+ self,
+ bx,
+ fn_abi,
+ llfn,
+ &[msg.0, msg.1],
+ target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
+ unwind,
+ &[],
+ Some(instance),
+ mergeable_succ,
+ ))
}
fn codegen_call_terminator(
@@ -903,42 +901,127 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn_span: Span,
mergeable_succ: bool,
) -> MergingSucc {
- let source_info = terminator.source_info;
- let span = source_info.span;
+ let source_info = mir::SourceInfo { span: fn_span, ..terminator.source_info };
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
let callee = self.codegen_operand(bx, func);
let (instance, mut llfn) = match *callee.layout.ty.kind() {
- ty::FnDef(def_id, args) => (
- Some(ty::Instance::expect_resolve(
+ ty::FnDef(def_id, generic_args) => {
+ let instance = ty::Instance::expect_resolve(
bx.tcx(),
bx.typing_env(),
def_id,
- args,
+ generic_args,
fn_span,
- )),
- None,
- ),
+ );
+
+ let instance = match instance.def {
+ // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
+ // it is `func returning noop future`
+ ty::InstanceKind::DropGlue(_, None) => {
+ // Empty drop glue; a no-op.
+ let target = target.unwrap();
+ return helper.funclet_br(self, bx, target, mergeable_succ);
+ }
+ ty::InstanceKind::Intrinsic(def_id) => {
+ let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
+ if let Some(merging_succ) = self.codegen_panic_intrinsic(
+ &helper,
+ bx,
+ intrinsic,
+ instance,
+ source_info,
+ target,
+ unwind,
+ mergeable_succ,
+ ) {
+ return merging_succ;
+ }
+
+ let result_layout =
+ self.cx.layout_of(self.monomorphized_place_ty(destination.as_ref()));
+
+ let (result, store_in_local) = if result_layout.is_zst() {
+ (
+ PlaceRef::new_sized(bx.const_undef(bx.type_ptr()), result_layout),
+ None,
+ )
+ } else if let Some(local) = destination.as_local() {
+ match self.locals[local] {
+ LocalRef::Place(dest) => (dest, None),
+ LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
+ LocalRef::PendingOperand => {
+ // Currently, intrinsics always need a location to store
+ // the result, so we create a temporary `alloca` for the
+ // result.
+ let tmp = PlaceRef::alloca(bx, result_layout);
+ tmp.storage_live(bx);
+ (tmp, Some(local))
+ }
+ LocalRef::Operand(_) => {
+ bug!("place local already assigned to");
+ }
+ }
+ } else {
+ (self.codegen_place(bx, destination.as_ref()), None)
+ };
+
+ if result.val.align < result.layout.align.abi {
+ // Currently, MIR code generation does not create calls
+ // that store directly to fields of packed structs (in
+ // fact, the calls it creates write only to temps).
+ //
+ // If someone changes that, please update this code path
+ // to create a temporary.
+ span_bug!(self.mir.span, "can't directly store to unaligned value");
+ }
+
+ let args: Vec<_> =
+ args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
+
+ match self.codegen_intrinsic_call(bx, instance, &args, result, source_info)
+ {
+ Ok(()) => {
+ if let Some(local) = store_in_local {
+ let op = bx.load_operand(result);
+ result.storage_dead(bx);
+ self.overwrite_local(local, LocalRef::Operand(op));
+ self.debug_introduce_local(bx, local);
+ }
+
+ return if let Some(target) = target {
+ helper.funclet_br(self, bx, target, mergeable_succ)
+ } else {
+ bx.unreachable();
+ MergingSucc::False
+ };
+ }
+ Err(instance) => {
+ if intrinsic.must_be_overridden {
+ span_bug!(
+ fn_span,
+ "intrinsic {} must be overridden by codegen backend, but isn't",
+ intrinsic.name,
+ );
+ }
+ instance
+ }
+ }
+ }
+ _ => instance,
+ };
+
+ (Some(instance), None)
+ }
ty::FnPtr(..) => (None, Some(callee.immediate())),
_ => bug!("{} is not callable", callee.layout.ty),
};
- let def = instance.map(|i| i.def);
-
- // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
- // it is `func returning noop future`
- if let Some(ty::InstanceKind::DropGlue(_, None)) = def {
- // Empty drop glue; a no-op.
- let target = target.unwrap();
- return helper.funclet_br(self, bx, target, mergeable_succ);
- }
-
// FIXME(eddyb) avoid computing this if possible, when `instance` is
// available - right now `sig` is only needed for getting the `abi`
// and figuring out how many extra args were passed to a C-variadic `fn`.
let sig = callee.layout.ty.fn_sig(bx.tcx());
- let abi = sig.abi();
let extra_args = &args[sig.inputs().skip_binder().len()..];
let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
@@ -954,93 +1037,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// The arguments we'll be passing. Plus one to account for outptr, if used.
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
- let instance = match def {
- Some(ty::InstanceKind::Intrinsic(def_id)) => {
- let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
- if let Some(merging_succ) = self.codegen_panic_intrinsic(
- &helper,
- bx,
- intrinsic,
- instance,
- source_info,
- target,
- unwind,
- mergeable_succ,
- ) {
- return merging_succ;
- }
-
- let mut llargs = Vec::with_capacity(1);
- let ret_dest = self.make_return_dest(
- bx,
- destination,
- &fn_abi.ret,
- &mut llargs,
- Some(intrinsic),
- );
- let dest = match ret_dest {
- _ if fn_abi.ret.is_indirect() => llargs[0],
- ReturnDest::Nothing => bx.const_undef(bx.type_ptr()),
- ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.val.llval,
- ReturnDest::DirectOperand(_) => {
- bug!("Cannot use direct operand with an intrinsic call")
- }
- };
-
- let args: Vec<_> =
- args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
-
- if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) {
- let location = self
- .get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
-
- assert_eq!(llargs, []);
- if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
- location.val.store(bx, tmp);
- }
- self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate());
- return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ);
- }
-
- let instance = *instance.as_ref().unwrap();
- match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) {
- Ok(()) => {
- if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
- self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval);
- }
-
- return if let Some(target) = target {
- helper.funclet_br(self, bx, target, mergeable_succ)
- } else {
- bx.unreachable();
- MergingSucc::False
- };
- }
- Err(instance) => {
- if intrinsic.must_be_overridden {
- span_bug!(
- span,
- "intrinsic {} must be overridden by codegen backend, but isn't",
- intrinsic.name,
- );
- }
- Some(instance)
- }
- }
- }
- _ => instance,
- };
-
let mut llargs = Vec::with_capacity(arg_count);
// We still need to call `make_return_dest` even if there's no `target`, since
// `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
// and `make_return_dest` adds the return-place indirect pointer to `llargs`.
- let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None);
+ let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs);
let destination = target.map(|target| (return_dest, target));
// Split the rust-call tupled arguments off.
- let (first_args, untuple) = if abi == ExternAbi::RustCall
+ let (first_args, untuple) = if sig.abi() == ExternAbi::RustCall
&& let Some((tup, args)) = args.split_last()
{
(args, Some(tup))
@@ -1055,7 +1061,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
'make_args: for (i, arg) in first_args.iter().enumerate() {
let mut op = self.codegen_operand(bx, &arg.node);
- if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, def) {
+ if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, instance.map(|i| i.def)) {
match op.val {
Pair(data_ptr, meta) => {
// In the case of Rc, we need to explicitly pass a
@@ -1109,7 +1115,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Make sure that we've actually unwrapped the rcvr down
// to a pointer or ref to `dyn* Trait`.
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
- span_bug!(span, "can't codegen a virtual call on {:#?}", op);
+ span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
}
let place = op.deref(bx.cx());
let data_place = place.project_field(bx, 0);
@@ -1125,7 +1131,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
continue;
}
_ => {
- span_bug!(span, "can't codegen a virtual call on {:#?}", op);
+ span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
}
}
}
@@ -1175,8 +1181,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir_args + 1,
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {instance:?} {fn_span:?} {fn_abi:?}",
);
- let location =
- self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
+ let location = self.get_caller_location(bx, source_info);
debug!(
"codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
terminator, location, fn_span
@@ -1195,9 +1200,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let fn_ptr = match (instance, llfn) {
(Some(instance), None) => bx.get_fn_addr(instance),
(_, Some(llfn)) => llfn,
- _ => span_bug!(span, "no instance or llfn for call"),
+ _ => span_bug!(fn_span, "no instance or llfn for call"),
};
- self.set_debug_loc(bx, mir::SourceInfo { span: fn_span, ..source_info });
+ self.set_debug_loc(bx, source_info);
helper.do_call(
self,
bx,
@@ -1667,7 +1672,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
tuple.layout.fields.count()
}
- fn get_caller_location(
+ pub(super) fn get_caller_location(
&mut self,
bx: &mut Bx,
source_info: mir::SourceInfo,
@@ -1868,7 +1873,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
dest: mir::Place<'tcx>,
fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
llargs: &mut Vec,
- intrinsic: Option,
) -> ReturnDest<'tcx, Bx::Value> {
// If the return is ignored, we can just return a do-nothing `ReturnDest`.
if fn_ret.is_ignore() {
@@ -1888,13 +1892,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
tmp.storage_live(bx);
llargs.push(tmp.val.llval);
ReturnDest::IndirectOperand(tmp, index)
- } else if intrinsic.is_some() {
- // Currently, intrinsics always need a location to store
- // the result, so we create a temporary `alloca` for the
- // result.
- let tmp = PlaceRef::alloca(bx, fn_ret.layout);
- tmp.storage_live(bx);
- ReturnDest::IndirectOperand(tmp, index)
} else {
ReturnDest::DirectOperand(index)
};
@@ -1904,7 +1901,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
} else {
- self.codegen_place(bx, mir::PlaceRef { local: dest.local, projection: dest.projection })
+ self.codegen_place(bx, dest.as_ref())
};
if fn_ret.is_indirect() {
if dest.val.align < dest.layout.align.abi {
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index b0fcfee2adf5..a6d159c51e13 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -1,9 +1,9 @@
use rustc_abi::WrappingRange;
+use rustc_middle::mir::SourceInfo;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
-use rustc_span::{Span, sym};
-use rustc_target::callconv::{FnAbi, PassMode};
+use rustc_span::sym;
use super::FunctionCx;
use super::operand::OperandRef;
@@ -52,13 +52,14 @@ fn memset_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
/// In the `Err` case, returns the instance that should be called instead.
pub fn codegen_intrinsic_call(
+ &mut self,
bx: &mut Bx,
instance: ty::Instance<'tcx>,
- fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Bx::Value>],
- llresult: Bx::Value,
- span: Span,
+ result: PlaceRef<'tcx, Bx::Value>,
+ source_info: SourceInfo,
) -> Result<(), ty::Instance<'tcx>> {
+ let span = source_info.span;
let callee_ty = instance.ty(bx.tcx(), bx.typing_env());
let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
@@ -97,7 +98,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
let llret_ty = bx.backend_type(bx.layout_of(ret_ty));
- let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
let llval = match name {
sym::abort => {
@@ -105,6 +105,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
return Ok(());
}
+ sym::caller_location => {
+ let location = self.get_caller_location(bx, source_info);
+ location.val.store(bx, result);
+ return Ok(());
+ }
+
sym::va_start => bx.va_start(args[0].immediate()),
sym::va_end => bx.va_end(args[0].immediate()),
sym::size_of_val => {
@@ -528,18 +534,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
_ => {
// Need to use backend-specific things in the implementation.
- return bx.codegen_intrinsic_call(instance, fn_abi, args, llresult, span);
+ return bx.codegen_intrinsic_call(instance, args, result, span);
}
};
- if !fn_abi.ret.is_ignore() {
- if let PassMode::Cast { .. } = &fn_abi.ret.mode {
- bx.store_to_place(llval, result.val);
- } else {
- OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
- .val
- .store(bx, result);
- }
+ if result.layout.ty.is_bool() {
+ OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
+ .val
+ .store(bx, result);
+ } else if !result.layout.ty.is_unit() {
+ bx.store_to_place(llval, result.val);
}
Ok(())
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 88cf8dbf0c5c..a07c569a0323 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -1,9 +1,9 @@
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty;
use rustc_span::Span;
-use rustc_target::callconv::FnAbi;
use super::BackendTypes;
use crate::mir::operand::OperandRef;
+use crate::mir::place::PlaceRef;
pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
/// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
@@ -14,9 +14,8 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
fn codegen_intrinsic_call(
&mut self,
instance: ty::Instance<'tcx>,
- fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
- llresult: Self::Value,
+ result: PlaceRef<'tcx, Self::Value>,
span: Span,
) -> Result<(), ty::Instance<'tcx>>;
diff --git a/compiler/rustc_error_codes/src/error_codes/E0658.md b/compiler/rustc_error_codes/src/error_codes/E0658.md
index 24245a38ae07..65c82e4fb6ef 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0658.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0658.md
@@ -3,10 +3,7 @@ An unstable feature was used.
Erroneous code example:
```compile_fail,E0658
-#[repr(u128)] // error: use of unstable library feature 'repr128'
-enum Foo {
- Bar(u64),
-}
+use std::intrinsics; // error: use of unstable library feature `core_intrinsics`
```
If you're using a stable or a beta version of rustc, you won't be able to use
@@ -17,12 +14,9 @@ If you're using a nightly version of rustc, just add the corresponding feature
to be able to use it:
```
-#![feature(repr128)]
+#![feature(core_intrinsics)]
-#[repr(u128)] // ok!
-enum Foo {
- Bar(u64),
-}
+use std::intrinsics; // ok!
```
[rustup]: https://rust-lang.github.io/rustup/concepts/channels.html
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 55751aa49089..2accfba383e6 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1424,7 +1424,7 @@ pub fn parse_macro_name_and_helper_attrs(
/// See #73345 and #83125 for more details.
/// FIXME(#73933): Remove this eventually.
fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
- if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind
+ if let ast::ItemKind::Enum(ident, _, enum_def) = &item.kind
&& ident.name == sym::ProceduralMasqueradeDummyType
&& let [variant] = &*enum_def.variants
&& variant.ident.name == sym::Input
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 81d4d59ee045..e5749ba96a6d 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1319,10 +1319,10 @@ impl InvocationCollectorNode for P {
let mut idents = Vec::new();
collect_use_tree_leaves(ut, &mut idents);
- return idents;
+ idents
+ } else {
+ self.kind.ident().into_iter().collect()
}
-
- if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] }
}
}
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 820af9ac84b2..ffa6ffb40b61 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -360,6 +360,8 @@ declare_features! (
(accepted, relaxed_adts, "1.19.0", Some(35626)),
/// Lessens the requirements for structs to implement `Unsize`.
(accepted, relaxed_struct_unsize, "1.58.0", Some(81793)),
+ /// Allows the `#[repr(i128)]` attribute for enums.
+ (accepted, repr128, "CURRENT_RUSTC_VERSION", Some(56071)),
/// Allows `repr(align(16))` struct attribute (RFC 1358).
(accepted, repr_align, "1.25.0", Some(33626)),
/// Allows using `#[repr(align(X))]` on enums with equivalent semantics
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 3e408a031118..b46eac6d8a60 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -621,8 +621,6 @@ declare_features! (
(incomplete, ref_pat_eat_one_layer_2024_structural, "1.81.0", Some(123076)),
/// Allows using the `#[register_tool]` attribute.
(unstable, register_tool, "1.41.0", Some(66079)),
- /// Allows the `#[repr(i128)]` attribute for enums.
- (incomplete, repr128, "1.16.0", Some(56071)),
/// Allows `repr(simd)` and importing the various simd intrinsics.
(unstable, repr_simd, "1.4.0", Some(27731)),
/// Allows bounding the return type of AFIT/RPITIT.
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index db7a5fe78976..846eacce9e10 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -18,7 +18,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
-use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::util::Discr;
use rustc_middle::ty::{
AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, fold_regions,
@@ -1385,19 +1385,6 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
);
}
- let repr_type_ty = def.repr().discr_type().to_ty(tcx);
- if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
- if !tcx.features().repr128() {
- feature_err(
- &tcx.sess,
- sym::repr128,
- tcx.def_span(def_id),
- "repr with 128-bit type is unstable",
- )
- .emit();
- }
- }
-
for v in def.variants() {
if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
tcx.ensure_ok().typeck(discr_def_id.expect_local());
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 476ce0e86911..f85ff5a6f4be 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -298,11 +298,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
check_item_fn(tcx, def_id, ident, item.span, sig.decl)
}
hir::ItemKind::Static(_, ty, ..) => {
- check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
- }
- hir::ItemKind::Const(_, ty, ..) => {
- check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
+ check_static_item(tcx, def_id, ty.span, UnsizedHandling::Forbid)
}
+ hir::ItemKind::Const(_, ty, ..) => check_const_item(tcx, def_id, ty.span, item.span),
hir::ItemKind::Struct(_, _, hir_generics) => {
let res = check_type_defn(tcx, item, false);
check_variances_for_type_defn(tcx, item, hir_generics);
@@ -366,7 +364,7 @@ fn check_foreign_item<'tcx>(
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
}
hir::ForeignItemKind::Static(ty, ..) => {
- check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
+ check_static_item(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
}
hir::ForeignItemKind::Type => Ok(()),
}
@@ -1048,8 +1046,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
match ty.kind() {
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
// Arrays and slices use the inner type's `ConstParamTy`.
- ty::Array(ty, ..) => ty_is_local(*ty),
- ty::Slice(ty) => ty_is_local(*ty),
+ ty::Array(ty, ..) | ty::Slice(ty) => ty_is_local(*ty),
// `&` references use the inner type's `ConstParamTy`.
// `&mut` are not supported.
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
@@ -1331,14 +1328,13 @@ enum UnsizedHandling {
AllowIfForeignTail,
}
-fn check_item_type(
+#[instrument(level = "debug", skip(tcx, ty_span, unsized_handling))]
+fn check_static_item(
tcx: TyCtxt<'_>,
item_id: LocalDefId,
ty_span: Span,
unsized_handling: UnsizedHandling,
) -> Result<(), ErrorGuaranteed> {
- debug!("check_item_type: {:?}", item_id);
-
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
let ty = tcx.type_of(item_id).instantiate_identity();
let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
@@ -1388,6 +1384,34 @@ fn check_item_type(
})
}
+fn check_const_item(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+ ty_span: Span,
+ item_span: Span,
+) -> Result<(), ErrorGuaranteed> {
+ enter_wf_checking_ctxt(tcx, ty_span, def_id, |wfcx| {
+ let ty = tcx.type_of(def_id).instantiate_identity();
+ let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
+
+ wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
+ wfcx.register_bound(
+ traits::ObligationCause::new(
+ ty_span,
+ wfcx.body_def_id,
+ ObligationCauseCode::SizedConstOrStatic,
+ ),
+ wfcx.param_env,
+ ty,
+ tcx.require_lang_item(LangItem::Sized, None),
+ );
+
+ check_where_clauses(wfcx, item_span, def_id);
+
+ Ok(())
+ })
+}
+
#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))]
fn check_impl<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 010c6c376fe3..a64c24f5455b 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -203,7 +203,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
tcx.ensure_ok().eval_static_initializer(item_def_id);
check::maybe_check_static_with_link_section(tcx, item_def_id);
}
- DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
+ DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() => {
+ // FIXME(generic_const_items): Passing empty instead of identity args is fishy but
+ // seems to be fine for now. Revisit this!
let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
let cid = GlobalId { instance, promoted: None };
let typing_env = ty::TypingEnv::fully_monomorphized();
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 1d86f7d223ce..082ddac7e5ae 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1793,10 +1793,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let element_ty = if !args.is_empty() {
let coerce_to = expected
.to_option(self)
- .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() {
- ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
- _ => None,
- })
+ .and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index())
.unwrap_or_else(|| self.next_ty_var(expr.span));
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
assert_eq!(self.diverges.get(), Diverges::Maybe);
@@ -1874,10 +1871,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let uty = match expected {
- ExpectHasType(uty) => match *uty.kind() {
- ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
- _ => None,
- },
+ ExpectHasType(uty) => uty.builtin_index(),
_ => None,
};
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 0b543f091f73..060447ba7206 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -497,6 +497,10 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> {
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
if p.flags().intersects(self.needs_canonical_flags) { p.super_fold_with(self) } else { p }
}
+
+ fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+ if c.flags().intersects(self.needs_canonical_flags) { c.super_fold_with(self) } else { c }
+ }
}
impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 4b0ace8c554d..a95f24b5b95d 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -55,6 +55,14 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticVarResolver<'a, 'tcx> {
ct.super_fold_with(self)
}
}
+
+ fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+ if !p.has_non_region_infer() { p } else { p.super_fold_with(self) }
+ }
+
+ fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+ if !c.has_non_region_infer() { c } else { c.super_fold_with(self) }
+ }
}
/// The opportunistic region resolver opportunistically resolves regions
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index f17747558fc5..dd55d039794f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -512,7 +512,7 @@ impl Allocation {
pub fn adjust_from_tcx<'tcx, Prov: Provenance, Bytes: AllocBytes>(
&self,
cx: &impl HasDataLayout,
- mut alloc_bytes: impl FnMut(&[u8], Align) -> InterpResult<'tcx, Bytes>,
+ alloc_bytes: impl FnOnce(&[u8], Align) -> InterpResult<'tcx, Bytes>,
mut adjust_ptr: impl FnMut(Pointer) -> InterpResult<'tcx, Pointer>,
) -> InterpResult<'tcx, Allocation> {
// Copy the data.
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 4a5c42c721c1..97db45a70d7f 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -9,7 +9,6 @@ use super::{
ReportedErrorInfo,
};
use crate::mir;
-use crate::query::TyCtxtEnsureOk;
use crate::ty::{self, GenericArgs, TyCtxt, TypeVisitableExt};
impl<'tcx> TyCtxt<'tcx> {
@@ -197,24 +196,3 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
}
-
-impl<'tcx> TyCtxtEnsureOk<'tcx> {
- /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
- /// that can't take any generic arguments like const items or enum discriminants. If a
- /// generic parameter is used within the constant `ErrorHandled::TooGeneric` will be returned.
- #[instrument(skip(self), level = "debug")]
- pub fn const_eval_poly(self, def_id: DefId) {
- // In some situations def_id will have generic parameters within scope, but they aren't allowed
- // to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
- // into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
- // encountered.
- let args = GenericArgs::identity_for_item(self.tcx, def_id);
- let instance = ty::Instance::new_raw(def_id, self.tcx.erase_regions(args));
- let cid = GlobalId { instance, promoted: None };
- let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id);
- // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
- // improve caching of queries.
- let inputs = self.tcx.erase_regions(typing_env.as_query_input(cid));
- self.eval_to_const_value_raw(inputs)
- }
-}
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index ff9096695d4d..df67bb505a68 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -117,6 +117,10 @@ impl<'tcx> CapturedPlace<'tcx> {
}
},
+ HirProjectionKind::UnwrapUnsafeBinder => {
+ write!(&mut symbol, "__unwrap").unwrap();
+ }
+
// Ignore derefs for now, as they are likely caused by
// autoderefs that don't appear in the original code.
HirProjectionKind::Deref => {}
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 45a0b1288db8..f4fead7e9526 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -86,4 +86,12 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> {
p
}
}
+
+ fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+ if c.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
+ c.super_fold_with(self)
+ } else {
+ c
+ }
+ }
}
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 8d6871d2f1fe..b2057fa36d7f 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -177,6 +177,10 @@ where
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
}
+
+ fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+ if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c }
+ }
}
impl<'tcx> TyCtxt<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 551d816941b6..bc2ac42b6b1f 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -238,6 +238,8 @@ impl<'tcx> Clause<'tcx> {
}
}
+impl<'tcx> rustc_type_ir::inherent::Clauses> for ty::Clauses<'tcx> {}
+
#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
impl<'tcx> ExistentialPredicate<'tcx> {
/// Compares via an ordering that will not change if modules are reordered or other changes are
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7a7c33fb34db..000ba7b6fa79 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -570,6 +570,19 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> {
}
}
+impl<'tcx> TypeFoldable> for ty::Clauses<'tcx> {
+ fn try_fold_with>>(
+ self,
+ folder: &mut F,
+ ) -> Result {
+ folder.try_fold_clauses(self)
+ }
+
+ fn fold_with>>(self, folder: &mut F) -> Self {
+ folder.fold_clauses(self)
+ }
+}
+
impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> {
fn visit_with>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_predicate(*self)
@@ -615,6 +628,19 @@ impl<'tcx> TypeSuperVisitable> for ty::Clauses<'tcx> {
}
}
+impl<'tcx> TypeSuperFoldable> for ty::Clauses<'tcx> {
+ fn try_super_fold_with>>(
+ self,
+ folder: &mut F,
+ ) -> Result {
+ ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
+ }
+
+ fn super_fold_with>>(self, folder: &mut F) -> Self {
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
+ }
+}
+
impl<'tcx> TypeFoldable> for ty::Const<'tcx> {
fn try_fold_with>>(
self,
@@ -775,7 +801,6 @@ macro_rules! list_fold {
}
list_fold! {
- ty::Clauses<'tcx> : mk_clauses,
&'tcx ty::List> : mk_poly_existential_predicates,
&'tcx ty::List> : mk_place_elems,
&'tcx ty::List> : mk_patterns,
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
index 830a129c5854..f8c64d7d13ed 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
@@ -101,12 +101,12 @@ fn convert_to_hir_projections_and_truncate_for_capture(
variant = Some(*idx);
continue;
}
+ ProjectionElem::UnwrapUnsafeBinder(_) => HirProjectionKind::UnwrapUnsafeBinder,
// These do not affect anything, they just make sure we know the right type.
ProjectionElem::OpaqueCast(_) | ProjectionElem::Subtype(..) => continue,
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
- | ProjectionElem::Subslice { .. }
- | ProjectionElem::UnwrapUnsafeBinder(_) => {
+ | ProjectionElem::Subslice { .. } => {
// We don't capture array-access projections.
// We can stop here as arrays are captured completely.
break;
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 2a30777e98c4..67988f1fcbc2 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -209,7 +209,7 @@ const ROOT_NODE: DropIdx = DropIdx::ZERO;
#[derive(Debug)]
struct DropTree {
/// Nodes in the drop tree, containing drop data and a link to the next node.
- drops: IndexVec,
+ drop_nodes: IndexVec,
/// Map for finding the index of an existing node, given its contents.
existing_drops_map: FxHashMap,
/// Edges into the `DropTree` that need to be added once it's lowered.
@@ -230,7 +230,6 @@ struct DropNode {
struct DropNodeKey {
next: DropIdx,
local: Local,
- kind: DropKind,
}
impl Scope {
@@ -278,8 +277,8 @@ impl DropTree {
let fake_source_info = SourceInfo::outermost(DUMMY_SP);
let fake_data =
DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage };
- let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
- Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
+ let drop_nodes = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
+ Self { drop_nodes, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
}
/// Adds a node to the drop tree, consisting of drop data and the index of
@@ -288,12 +287,12 @@ impl DropTree {
/// If there is already an equivalent node in the tree, nothing is added, and
/// that node's index is returned. Otherwise, the new node's index is returned.
fn add_drop(&mut self, data: DropData, next: DropIdx) -> DropIdx {
- let drops = &mut self.drops;
+ let drop_nodes = &mut self.drop_nodes;
*self
.existing_drops_map
- .entry(DropNodeKey { next, local: data.local, kind: data.kind })
+ .entry(DropNodeKey { next, local: data.local })
// Create a new node, and also add its index to the map.
- .or_insert_with(|| drops.push(DropNode { data, next }))
+ .or_insert_with(|| drop_nodes.push(DropNode { data, next }))
}
/// Registers `from` as an entry point to this drop tree, at `to`.
@@ -301,7 +300,7 @@ impl DropTree {
/// During [`Self::build_mir`], `from` will be linked to the corresponding
/// block within the drop tree.
fn add_entry_point(&mut self, from: BasicBlock, to: DropIdx) {
- debug_assert!(to < self.drops.next_index());
+ debug_assert!(to < self.drop_nodes.next_index());
self.entry_points.push((to, from));
}
@@ -341,10 +340,10 @@ impl DropTree {
Own,
}
- let mut blocks = IndexVec::from_elem(None, &self.drops);
+ let mut blocks = IndexVec::from_elem(None, &self.drop_nodes);
blocks[ROOT_NODE] = root_node;
- let mut needs_block = IndexVec::from_elem(Block::None, &self.drops);
+ let mut needs_block = IndexVec::from_elem(Block::None, &self.drop_nodes);
if root_node.is_some() {
// In some cases (such as drops for `continue`) the root node
// already has a block. In this case, make sure that we don't
@@ -356,7 +355,7 @@ impl DropTree {
let entry_points = &mut self.entry_points;
entry_points.sort();
- for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
+ for (drop_idx, drop_node) in self.drop_nodes.iter_enumerated().rev() {
if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg));
needs_block[drop_idx] = Block::Own;
@@ -396,7 +395,7 @@ impl DropTree {
cfg: &mut CFG<'tcx>,
blocks: &IndexSlice>,
) {
- for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
+ for (drop_idx, drop_node) in self.drop_nodes.iter_enumerated().rev() {
let Some(block) = blocks[drop_idx] else { continue };
match drop_node.data.kind {
DropKind::Value => {
@@ -726,11 +725,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
drops
};
- let drop_idx = self.scopes.scopes[scope_index + 1..]
- .iter()
- .flat_map(|scope| &scope.drops)
- .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx));
-
+ let mut drop_idx = ROOT_NODE;
+ for scope in &self.scopes.scopes[scope_index + 1..] {
+ for drop in &scope.drops {
+ drop_idx = drops.add_drop(*drop, drop_idx);
+ }
+ }
drops.add_entry_point(block, drop_idx);
// `build_drop_trees` doesn't have access to our source_info, so we
@@ -829,9 +829,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// `unwind_to` should drop the value that we're about to
// schedule. If dropping this value panics, then we continue
// with the *next* value on the unwind path.
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
- unwind_to = unwind_drops.drops[unwind_to].next;
+ debug_assert_eq!(
+ unwind_drops.drop_nodes[unwind_to].data.local,
+ drop_data.local
+ );
+ debug_assert_eq!(
+ unwind_drops.drop_nodes[unwind_to].data.kind,
+ drop_data.kind
+ );
+ unwind_to = unwind_drops.drop_nodes[unwind_to].next;
let mut unwind_entry_point = unwind_to;
@@ -1551,14 +1557,14 @@ where
//
// We adjust this BEFORE we create the drop (e.g., `drops[n]`)
// because `drops[n]` should unwind to `drops[n-1]`.
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
- unwind_to = unwind_drops.drops[unwind_to].next;
+ debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.local, drop_data.local);
+ debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind);
+ unwind_to = unwind_drops.drop_nodes[unwind_to].next;
if let Some(idx) = dropline_to {
- debug_assert_eq!(coroutine_drops.drops[idx].data.local, drop_data.local);
- debug_assert_eq!(coroutine_drops.drops[idx].data.kind, drop_data.kind);
- dropline_to = Some(coroutine_drops.drops[idx].next);
+ debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.local, drop_data.local);
+ debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.kind, drop_data.kind);
+ dropline_to = Some(coroutine_drops.drop_nodes[idx].next);
}
// If the operand has been moved, and we are not on an unwind
@@ -1598,9 +1604,12 @@ where
// cases we emit things ALSO on the unwind path, so we need to adjust
// `unwind_to` in that case.
if storage_dead_on_unwind {
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
- unwind_to = unwind_drops.drops[unwind_to].next;
+ debug_assert_eq!(
+ unwind_drops.drop_nodes[unwind_to].data.local,
+ drop_data.local
+ );
+ debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind);
+ unwind_to = unwind_drops.drop_nodes[unwind_to].next;
}
// If the operand has been moved, and we are not on an unwind
@@ -1629,14 +1638,17 @@ where
// the storage-dead has completed, we need to adjust the `unwind_to` pointer
// so that any future drops we emit will not register storage-dead.
if storage_dead_on_unwind {
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
- debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
- unwind_to = unwind_drops.drops[unwind_to].next;
+ debug_assert_eq!(
+ unwind_drops.drop_nodes[unwind_to].data.local,
+ drop_data.local
+ );
+ debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind);
+ unwind_to = unwind_drops.drop_nodes[unwind_to].next;
}
if let Some(idx) = dropline_to {
- debug_assert_eq!(coroutine_drops.drops[idx].data.local, drop_data.local);
- debug_assert_eq!(coroutine_drops.drops[idx].data.kind, drop_data.kind);
- dropline_to = Some(coroutine_drops.drops[idx].next);
+ debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.local, drop_data.local);
+ debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.kind, drop_data.kind);
+ dropline_to = Some(coroutine_drops.drop_nodes[idx].next);
}
// Only temps and vars need their storage dead.
assert!(local.index() > arg_count);
@@ -1663,10 +1675,10 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
let is_coroutine = self.coroutine.is_some();
// Link the exit drop tree to unwind drop tree.
- if drops.drops.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) {
+ if drops.drop_nodes.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) {
let unwind_target = self.diverge_cleanup_target(else_scope, span);
let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1);
- for (drop_idx, drop_node) in drops.drops.iter_enumerated().skip(1) {
+ for (drop_idx, drop_node) in drops.drop_nodes.iter_enumerated().skip(1) {
match drop_node.data.kind {
DropKind::Storage | DropKind::ForLint => {
if is_coroutine {
@@ -1695,35 +1707,29 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
}
// Link the exit drop tree to dropline drop tree (coroutine drop path) for async drops
if is_coroutine
- && drops.drops.iter().any(|DropNode { data, next: _ }| {
+ && drops.drop_nodes.iter().any(|DropNode { data, next: _ }| {
data.kind == DropKind::Value && self.is_async_drop(data.local)
})
{
let dropline_target = self.diverge_dropline_target(else_scope, span);
let mut dropline_indices = IndexVec::from_elem_n(dropline_target, 1);
- for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) {
+ for (drop_idx, drop_data) in drops.drop_nodes.iter_enumerated().skip(1) {
+ let coroutine_drop = self
+ .scopes
+ .coroutine_drops
+ .add_drop(drop_data.data, dropline_indices[drop_data.next]);
match drop_data.data.kind {
- DropKind::Storage | DropKind::ForLint => {
- let coroutine_drop = self
- .scopes
- .coroutine_drops
- .add_drop(drop_data.data, dropline_indices[drop_data.next]);
- dropline_indices.push(coroutine_drop);
- }
+ DropKind::Storage | DropKind::ForLint => {}
DropKind::Value => {
- let coroutine_drop = self
- .scopes
- .coroutine_drops
- .add_drop(drop_data.data, dropline_indices[drop_data.next]);
if self.is_async_drop(drop_data.data.local) {
self.scopes.coroutine_drops.add_entry_point(
blocks[drop_idx].unwrap(),
dropline_indices[drop_data.next],
);
}
- dropline_indices.push(coroutine_drop);
}
}
+ dropline_indices.push(coroutine_drop);
}
}
blocks[ROOT_NODE].map(BasicBlock::unit)
@@ -1769,11 +1775,11 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
// prevent drop elaboration from creating drop flags that would have
// to be captured by the coroutine. I'm not sure how important this
// optimization is, but it is here.
- for (drop_idx, drop_node) in drops.drops.iter_enumerated() {
+ for (drop_idx, drop_node) in drops.drop_nodes.iter_enumerated() {
if let DropKind::Value = drop_node.data.kind
&& let Some(bb) = blocks[drop_idx]
{
- debug_assert!(drop_node.next < drops.drops.next_index());
+ debug_assert!(drop_node.next < drops.drop_nodes.next_index());
drops.entry_points.push((drop_node.next, bb));
}
}
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index b3d7eaf332b2..1ee977a5457e 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1483,7 +1483,7 @@ impl<'v> RootCollector<'_, 'v> {
// But even just declaring them must collect the items they refer to
// unless their generics require monomorphization.
- if !self.tcx.generics_of(id.owner_id).requires_monomorphization(self.tcx)
+ if !self.tcx.generics_of(id.owner_id).own_requires_monomorphization()
&& let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id())
{
collect_const_value(self.tcx, val, self.output);
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index addeb3e2b78e..e5ca2bda4592 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -572,4 +572,15 @@ impl, I: Interner> TypeFolder for Canonicaliz
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p }
}
+
+ fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+ match self.canonicalize_mode {
+ CanonicalizeMode::Input { keep_static: true }
+ | CanonicalizeMode::Response { max_input_universe: _ } => {}
+ CanonicalizeMode::Input { keep_static: false } => {
+ panic!("erasing 'static in env")
+ }
+ }
+ if c.flags().intersects(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c }
+ }
}
diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs
index 39abec2d7d8d..c3c57eccd6ef 100644
--- a/compiler/rustc_next_trait_solver/src/resolve.rs
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -11,7 +11,7 @@ use crate::delegate::SolverDelegate;
// EAGER RESOLUTION
/// Resolves ty, region, and const vars to their inferred values or their root vars.
-pub struct EagerResolver<'a, D, I = ::Interner>
+struct EagerResolver<'a, D, I = ::Interner>
where
D: SolverDelegate,
I: Interner,
@@ -22,8 +22,20 @@ where
cache: DelayedMap,
}
+pub fn eager_resolve_vars>(
+ delegate: &D,
+ value: T,
+) -> T {
+ if value.has_infer() {
+ let mut folder = EagerResolver::new(delegate);
+ value.fold_with(&mut folder)
+ } else {
+ value
+ }
+}
+
impl<'a, D: SolverDelegate> EagerResolver<'a, D> {
- pub fn new(delegate: &'a D) -> Self {
+ fn new(delegate: &'a D) -> Self {
EagerResolver { delegate, cache: Default::default() }
}
}
@@ -90,4 +102,8 @@ impl, I: Interner> TypeFolder for EagerResolv
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
if p.has_infer() { p.super_fold_with(self) } else { p }
}
+
+ fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+ if c.has_infer() { c.super_fold_with(self) } else { c }
+ }
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 66d4cd23112d..cb7c498b94e2 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -22,7 +22,7 @@ use tracing::{debug, instrument, trace};
use crate::canonicalizer::Canonicalizer;
use crate::delegate::SolverDelegate;
-use crate::resolve::EagerResolver;
+use crate::resolve::eager_resolve_vars;
use crate::solve::eval_ctxt::CurrentGoalKind;
use crate::solve::{
CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, ExternalConstraintsData, Goal,
@@ -61,8 +61,7 @@ where
// so we only canonicalize the lookup table and ignore
// duplicate entries.
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
- let (goal, opaque_types) =
- (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
+ let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
let mut orig_values = Default::default();
let canonical = Canonicalizer::canonicalize_input(
@@ -162,8 +161,8 @@ where
let external_constraints =
self.compute_external_query_constraints(certainty, normalization_nested_goals);
- let (var_values, mut external_constraints) = (self.var_values, external_constraints)
- .fold_with(&mut EagerResolver::new(self.delegate));
+ let (var_values, mut external_constraints) =
+ eager_resolve_vars(self.delegate, (self.var_values, external_constraints));
// Remove any trivial or duplicated region constraints once we've resolved regions
let mut unique = HashSet::default();
@@ -474,7 +473,7 @@ where
{
let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) };
let state = inspect::State { var_values, data };
- let state = state.fold_with(&mut EagerResolver::new(delegate));
+ let state = eager_resolve_vars(delegate, state);
Canonicalizer::canonicalize_response(delegate, max_input_universe, &mut vec![], state)
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 2924208173d2..b1a842e04af5 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -925,6 +925,22 @@ where
}
}
}
+
+ fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
+ if p.has_non_region_infer() || p.has_placeholders() {
+ p.super_visit_with(self)
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
+
+ fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
+ if c.has_non_region_infer() || c.has_placeholders() {
+ c.super_visit_with(self)
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
}
let mut visitor = ContainsTermOrNotNameable {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index babc55ccc0f9..c7b0eb11e5a0 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1577,7 +1577,7 @@ impl<'a> Parser<'a> {
};
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
- Ok(ItemKind::Enum(ident, enum_definition, generics))
+ Ok(ItemKind::Enum(ident, generics, enum_definition))
}
fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option> {
@@ -1732,7 +1732,7 @@ impl<'a> Parser<'a> {
return Err(self.dcx().create_err(err));
};
- Ok(ItemKind::Struct(ident, vdata, generics))
+ Ok(ItemKind::Struct(ident, generics, vdata))
}
/// Parses `union Foo { ... }`.
@@ -1764,7 +1764,7 @@ impl<'a> Parser<'a> {
return Err(err);
};
- Ok(ItemKind::Union(ident, vdata, generics))
+ Ok(ItemKind::Union(ident, generics, vdata))
}
/// This function parses the fields of record structs:
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 396ded96bde1..ccc3410674b4 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -515,8 +515,8 @@ impl<'a> Parser<'a> {
fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> {
let prev = self.prev_token.span;
let sp = self.token.span;
- let mut e = self.dcx().struct_span_err(sp, msg);
- self.label_expected_raw_ref(&mut e);
+ let mut err = self.dcx().struct_span_err(sp, msg);
+ self.label_expected_raw_ref(&mut err);
let do_not_suggest_help = self.token.is_keyword(kw::In)
|| self.token == token::Colon
@@ -558,20 +558,19 @@ impl<'a> Parser<'a> {
stmt.span
};
self.suggest_fixes_misparsed_for_loop_head(
- &mut e,
+ &mut err,
prev.between(sp),
stmt_span,
&stmt.kind,
);
}
Err(e) => {
- self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
- e.cancel();
+ e.delay_as_bug();
}
_ => {}
}
- e.span_label(sp, "expected `{`");
- e
+ err.span_label(sp, "expected `{`");
+ err
}
fn suggest_fixes_misparsed_for_loop_head(
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1d0246940499..df8b5a6b1818 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -255,7 +255,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.check_generic_attr(hir_id, attr, target, Target::Fn);
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
}
- [sym::autodiff, ..] => {
+ [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
}
[sym::coroutine, ..] => {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index d9f1888bfd9a..46ced7500ea2 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -249,12 +249,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
ty::Ref(_, rty, _) => reveal_and_alloc(cx, once(*rty)),
_ => bug!("Unexpected type for `Ref` constructor: {ty:?}"),
},
- Slice(slice) => match *ty.kind() {
- ty::Slice(ty) | ty::Array(ty, _) => {
+ Slice(slice) => match ty.builtin_index() {
+ Some(ty) => {
let arity = slice.arity();
reveal_and_alloc(cx, (0..arity).map(|_| ty))
}
- _ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
+ None => bug!("bad slice pattern {:?} {:?}", ctor, ty),
},
DerefPattern(pointee_ty) => reveal_and_alloc(cx, once(pointee_ty.inner())),
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 3460c53782f3..c30ed781f35f 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -823,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
}
// These items live in both the type and value namespaces.
- ItemKind::Struct(ident, ref vdata, _) => {
+ ItemKind::Struct(ident, _, ref vdata) => {
self.build_reduced_graph_for_struct_variant(
vdata.fields(),
ident,
@@ -874,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
}
}
- ItemKind::Union(ident, ref vdata, _) => {
+ ItemKind::Union(ident, _, ref vdata) => {
self.build_reduced_graph_for_struct_variant(
vdata.fields(),
ident,
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 13dfb59f27fc..25485be56226 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -162,8 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
self.with_parent(def_id, |this| {
this.with_impl_trait(ImplTraitContext::Existential, |this| {
match i.kind {
- ItemKind::Struct(_, ref struct_def, _)
- | ItemKind::Union(_, ref struct_def, _) => {
+ ItemKind::Struct(_, _, ref struct_def)
+ | ItemKind::Union(_, _, ref struct_def) => {
// If this is a unit or tuple-like struct, register the constructor.
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
this.create_def(
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d09750fa281b..201b1c0a493b 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -6,7 +6,7 @@ use rustc_ast::{
};
use rustc_ast_pretty::pprust;
use rustc_attr_data_structures::{self as attr, Stability};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::{
@@ -2623,7 +2623,53 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
for &StrippedCfgItem { parent_module, ident, ref cfg } in symbols {
- if parent_module != module || ident.name != *segment {
+ if ident.name != *segment {
+ continue;
+ }
+
+ fn comes_from_same_module_for_glob(
+ r: &Resolver<'_, '_>,
+ parent_module: DefId,
+ module: DefId,
+ visited: &mut FxHashMap,
+ ) -> bool {
+ if let Some(&cached) = visited.get(&parent_module) {
+ // this branch is prevent from being called recursively infinity,
+ // because there has some cycles in globs imports,
+ // see more spec case at `tests/ui/cfg/diagnostics-reexport-2.rs#reexport32`
+ return cached;
+ }
+ visited.insert(parent_module, false);
+ let res = r.module_map.get(&parent_module).is_some_and(|m| {
+ for importer in m.glob_importers.borrow().iter() {
+ if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
+ {
+ if next_parent_module == module
+ || comes_from_same_module_for_glob(
+ r,
+ next_parent_module,
+ module,
+ visited,
+ )
+ {
+ return true;
+ }
+ }
+ }
+ false
+ });
+ visited.insert(parent_module, res);
+ res
+ }
+
+ let comes_from_same_module = parent_module == module
+ || comes_from_same_module_for_glob(
+ self,
+ parent_module,
+ module,
+ &mut Default::default(),
+ );
+ if !comes_from_same_module {
continue;
}
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index a5ca4565d7b4..5de80de3f8d3 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
self.current_private_vis = prev_private_vis;
}
- ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => {
+ ast::ItemKind::Enum(_, _, EnumDef { ref variants }) => {
self.set_bindings_effective_visibilities(def_id);
for variant in variants {
let variant_def_id = self.r.local_def_id(variant.id);
@@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
}
}
- ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => {
+ ast::ItemKind::Struct(_, _, ref def) | ast::ItemKind::Union(_, _, ref def) => {
for field in def.fields() {
self.update_field(self.r.local_def_id(field.id), def_id);
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fd977a8eb6c0..4cfa079e49b4 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2694,9 +2694,9 @@ impl<'a, 'ast, 'ra: 'ast, '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(_, ref generics, _)
+ | ItemKind::Struct(_, ref generics, _)
+ | ItemKind::Union(_, ref generics, _) => {
self.resolve_adt(item, generics);
}
@@ -5243,9 +5243,9 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
ItemKind::TyAlias(box TyAlias { generics, .. })
| ItemKind::Const(box ConstItem { generics, .. })
| ItemKind::Fn(box Fn { generics, .. })
- | ItemKind::Enum(_, _, generics)
- | ItemKind::Struct(_, _, generics)
- | ItemKind::Union(_, _, generics)
+ | ItemKind::Enum(_, generics, _)
+ | ItemKind::Struct(_, generics, _)
+ | ItemKind::Union(_, generics, _)
| ItemKind::Impl(box Impl { generics, .. })
| ItemKind::Trait(box Trait { generics, .. })
| ItemKind::TraitAlias(_, generics, _) => {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0447713fb05d..29c3d58f9358 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -244,6 +244,7 @@ symbols! {
FnMut,
FnOnce,
Formatter,
+ Forward,
From,
FromIterator,
FromResidual,
@@ -339,6 +340,7 @@ symbols! {
Result,
ResumeTy,
Return,
+ Reverse,
Right,
Rust,
RustaceansAreAwesome,
@@ -522,7 +524,8 @@ symbols! {
audit_that,
augmented_assignments,
auto_traits,
- autodiff,
+ autodiff_forward,
+ autodiff_reverse,
automatically_derived,
avx,
avx10_target_feature,
@@ -2071,6 +2074,9 @@ symbols! {
sym,
sync,
synthetic,
+ sys_mutex_lock,
+ sys_mutex_try_lock,
+ sys_mutex_unlock,
t32,
target,
target_abi,
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index fda2c97ed56f..1193a9059ca9 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -15,9 +15,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_macros::extension;
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
-use rustc_middle::ty::{TyCtxt, TypeFoldable, VisitorResult, try_visit};
+use rustc_middle::ty::{TyCtxt, VisitorResult, try_visit};
use rustc_middle::{bug, ty};
-use rustc_next_trait_solver::resolve::EagerResolver;
+use rustc_next_trait_solver::resolve::eager_resolve_vars;
use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state};
use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _};
use rustc_span::{DUMMY_SP, Span};
@@ -187,8 +187,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
let _ = term_hack.constrain(infcx, span, param_env);
}
- let opt_impl_args =
- opt_impl_args.map(|impl_args| impl_args.fold_with(&mut EagerResolver::new(infcx)));
+ let opt_impl_args = opt_impl_args.map(|impl_args| eager_resolve_vars(infcx, impl_args));
let goals = instantiated_goals
.into_iter()
@@ -392,7 +391,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
infcx,
depth,
orig_values,
- goal: uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)),
+ goal: eager_resolve_vars(infcx, uncanonicalized_goal),
result,
evaluation_kind: evaluation.kind,
normalizes_to_term_hack,
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 1e6ca0dcf5d3..55c0a3bba9f2 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -711,6 +711,14 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> {
c.super_fold_with(self)
}
}
+
+ fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
+ if p.has_param() { p.super_fold_with(self) } else { p }
+ }
+
+ fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+ if c.has_param() { c.super_fold_with(self) } else { c }
+ }
}
impl<'a, I: Interner> ArgFolder<'a, I> {
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index ce1188070ca7..a5eb8699e5fc 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -152,6 +152,10 @@ pub trait TypeFolder: Sized {
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
p.super_fold_with(self)
}
+
+ fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+ c.super_fold_with(self)
+ }
}
/// This trait is implemented for every folding traversal. There is a fold
@@ -190,6 +194,10 @@ pub trait FallibleTypeFolder: Sized {
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result {
p.try_super_fold_with(self)
}
+
+ fn try_fold_clauses(&mut self, c: I::Clauses) -> Result {
+ c.try_super_fold_with(self)
+ }
}
///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index dde55effc3d0..fa88bcb891a9 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -511,6 +511,18 @@ pub trait Clause>:
fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder>) -> Self;
}
+pub trait Clauses>:
+ Copy
+ + Debug
+ + Hash
+ + Eq
+ + TypeSuperVisitable
+ + TypeSuperFoldable
+ + Flags
+ + SliceLike-
+{
+}
+
/// Common capabilities of placeholder kinds
pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
fn universe(self) -> ty::UniverseIndex;
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 7e88114df460..a9917192144f 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -12,7 +12,7 @@ use crate::ir_print::IrPrint;
use crate::lang_items::TraitSolverLangItem;
use crate::relate::Relate;
use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
-use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
+use crate::visit::{Flags, TypeVisitable};
use crate::{self as ty, search_graph};
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")]
@@ -146,7 +146,7 @@ pub trait Interner:
type ParamEnv: ParamEnv;
type Predicate: Predicate;
type Clause: Clause;
- type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags;
+ type Clauses: Clauses;
fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R;
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index ccb84e259112..fc3864dd5ae6 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -120,8 +120,8 @@ pub trait TypeVisitor: Sized {
p.super_visit_with(self)
}
- fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result {
- p.super_visit_with(self)
+ fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
+ c.super_visit_with(self)
}
fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 825402116e5b..bb2bf128be1f 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -632,6 +632,30 @@ impl CStr {
// instead of doing it afterwards.
str::from_utf8(self.to_bytes())
}
+
+ /// Returns an object that implements [`Display`] for safely printing a [`CStr`] that may
+ /// contain non-Unicode data.
+ ///
+ /// Behaves as if `self` were first lossily converted to a `str`, with invalid UTF-8 presented
+ /// as the Unicode replacement character: �.
+ ///
+ /// [`Display`]: fmt::Display
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(cstr_display)]
+ ///
+ /// let cstr = c"Hello, world!";
+ /// println!("{}", cstr.display());
+ /// ```
+ #[unstable(feature = "cstr_display", issue = "139984")]
+ #[must_use = "this does not display the `CStr`; \
+ it returns an object that can be displayed"]
+ #[inline]
+ pub fn display(&self) -> impl fmt::Display {
+ crate::bstr::ByteStr::from_bytes(self.to_bytes())
+ }
}
// `.to_bytes()` representations are compared instead of the inner `[c_char]`s,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index c49513f7a6d3..989ab80b77d4 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -225,10 +225,11 @@ pub mod assert_matches {
// We don't export this through #[macro_export] for now, to avoid breakage.
#[unstable(feature = "autodiff", issue = "124509")]
+#[cfg(not(bootstrap))]
/// Unstable module containing the unstable `autodiff` macro.
pub mod autodiff {
#[unstable(feature = "autodiff", issue = "124509")]
- pub use crate::macros::builtin::autodiff;
+ pub use crate::macros::builtin::{autodiff_forward, autodiff_reverse};
}
#[unstable(feature = "contracts", issue = "128044")]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 4742add09577..e70a1dab6e9a 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1519,20 +1519,41 @@ pub(crate) mod builtin {
($file:expr $(,)?) => {{ /* compiler built-in */ }};
}
- /// Automatic Differentiation macro which allows generating a new function to compute
- /// the derivative of a given function. It may only be applied to a function.
- /// The expected usage syntax is
- /// `#[autodiff(NAME, MODE, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]`
- /// where:
- /// NAME is a string that represents a valid function name.
- /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst.
- /// INPUT_ACTIVITIES consists of one valid activity for each input parameter.
- /// OUTPUT_ACTIVITY must not be set if we implicitly return nothing (or explicitly return
- /// `-> ()`). Otherwise it must be set to one of the allowed activities.
+ /// This macro uses forward-mode automatic differentiation to generate a new function.
+ /// It may only be applied to a function. The new function will compute the derivative
+ /// of the function to which the macro was applied.
+ ///
+ /// The expected usage syntax is:
+ /// `#[autodiff_forward(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]`
+ ///
+ /// - `NAME`: A string that represents a valid function name.
+ /// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
+ /// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
+ /// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[rustc_builtin_macro]
- pub macro autodiff($item:item) {
+ #[cfg(not(bootstrap))]
+ pub macro autodiff_forward($item:item) {
+ /* compiler built-in */
+ }
+
+ /// This macro uses reverse-mode automatic differentiation to generate a new function.
+ /// It may only be applied to a function. The new function will compute the derivative
+ /// of the function to which the macro was applied.
+ ///
+ /// The expected usage syntax is:
+ /// `#[autodiff_reverse(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]`
+ ///
+ /// - `NAME`: A string that represents a valid function name.
+ /// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
+ /// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
+ /// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
+ #[unstable(feature = "autodiff", issue = "124509")]
+ #[allow_internal_unstable(rustc_attrs)]
+ #[rustc_builtin_macro]
+ #[cfg(not(bootstrap))]
+ pub macro autodiff_reverse($item:item) {
/* compiler built-in */
}
diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs
index 235f8a3bb79f..f9638fea225b 100644
--- a/library/core/src/marker/variance.rs
+++ b/library/core/src/marker/variance.rs
@@ -131,6 +131,8 @@ phantom_lifetime! {
///
/// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
///
+ /// Note: If `'a` is otherwise contravariant or invariant, the resulting type is invariant.
+ ///
/// ## Layout
///
/// For all `'a`, the following are guaranteed:
@@ -146,6 +148,8 @@ phantom_lifetime! {
///
/// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
///
+ /// Note: If `'a` is otherwise covariant or invariant, the resulting type is invariant.
+ ///
/// ## Layout
///
/// For all `'a`, the following are guaranteed:
@@ -180,6 +184,8 @@ phantom_type! {
///
/// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
///
+ /// Note: If `T` is otherwise contravariant or invariant, the resulting type is invariant.
+ ///
/// ## Layout
///
/// For all `T`, the following are guaranteed:
@@ -196,6 +202,8 @@ phantom_type! {
///
/// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
///
+ /// Note: If `T` is otherwise covariant or invariant, the resulting type is invariant.
+ ///
/// ## Layout
///
/// For all `T`, the following are guaranteed:
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index bd5a58d74ba0..6bc6bee682df 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -3885,10 +3885,13 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T {
}
}
+/// Publicly exposed for stdarch; nobody else should use this.
#[inline]
#[cfg(target_has_atomic)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_compare_exchange(
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[doc(hidden)]
+pub unsafe fn atomic_compare_exchange(
dst: *mut T,
old: T,
new: T,
diff --git a/library/coretests/tests/ffi/cstr.rs b/library/coretests/tests/ffi/cstr.rs
index 0d85b22c585a..dc34240cd99d 100644
--- a/library/coretests/tests/ffi/cstr.rs
+++ b/library/coretests/tests/ffi/cstr.rs
@@ -19,3 +19,9 @@ fn debug() {
let s = c"abc\x01\x02\n\xE2\x80\xA6\xFF";
assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#);
}
+
+#[test]
+fn display() {
+ let s = c"\xf0\x28\x8c\xbc";
+ assert_eq!(format!("{}", s.display()), "�(��");
+}
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index b13012009815..693b14ef7620 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -23,6 +23,7 @@
#![feature(core_io_borrowed_buf)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
+#![feature(cstr_display)]
#![feature(dec2flt)]
#![feature(duration_constants)]
#![feature(duration_constructors)]
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index a6b75f702660..1212d36a1b15 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -732,7 +732,7 @@ assume_usize_width! {
}
macro_rules! test_float {
- ($modname: ident, $fassert: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
+ ($modname: ident, $fassert: ident, $fty: ty) => {
mod $modname {
#[test]
fn min() {
@@ -747,19 +747,19 @@ macro_rules! test_float {
$fassert!((-0.0 as $fty).min(9.0), -0.0);
$fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
$fassert!((-0.0 as $fty).min(-9.0), -9.0);
- $fassert!(($inf as $fty).min(9.0), 9.0);
- $fassert!((9.0 as $fty).min($inf), 9.0);
- $fassert!(($inf as $fty).min(-9.0), -9.0);
- $fassert!((-9.0 as $fty).min($inf), -9.0);
- $fassert!(($neginf as $fty).min(9.0), $neginf);
- $fassert!((9.0 as $fty).min($neginf), $neginf);
- $fassert!(($neginf as $fty).min(-9.0), $neginf);
- $fassert!((-9.0 as $fty).min($neginf), $neginf);
- $fassert!(($nan as $fty).min(9.0), 9.0);
- $fassert!(($nan as $fty).min(-9.0), -9.0);
- $fassert!((9.0 as $fty).min($nan), 9.0);
- $fassert!((-9.0 as $fty).min($nan), -9.0);
- $fassert!(($nan as $fty).min($nan).is_nan());
+ $fassert!(<$fty>::INFINITY.min(9.0), 9.0);
+ $fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0);
+ $fassert!(<$fty>::INFINITY.min(-9.0), -9.0);
+ $fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0);
+ $fassert!(<$fty>::NEG_INFINITY.min(9.0), <$fty>::NEG_INFINITY);
+ $fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+ $fassert!(<$fty>::NEG_INFINITY.min(-9.0), <$fty>::NEG_INFINITY);
+ $fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+ $fassert!(<$fty>::NAN.min(9.0), 9.0);
+ $fassert!(<$fty>::NAN.min(-9.0), -9.0);
+ $fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0);
+ $fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0);
+ $fassert!(<$fty>::NAN.min(<$fty>::NAN).is_nan());
}
#[test]
fn max() {
@@ -777,19 +777,19 @@ macro_rules! test_float {
$fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
$fassert!((-0.0 as $fty).max(-9.0), -0.0);
$fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
- $fassert!(($inf as $fty).max(9.0), $inf);
- $fassert!((9.0 as $fty).max($inf), $inf);
- $fassert!(($inf as $fty).max(-9.0), $inf);
- $fassert!((-9.0 as $fty).max($inf), $inf);
- $fassert!(($neginf as $fty).max(9.0), 9.0);
- $fassert!((9.0 as $fty).max($neginf), 9.0);
- $fassert!(($neginf as $fty).max(-9.0), -9.0);
- $fassert!((-9.0 as $fty).max($neginf), -9.0);
- $fassert!(($nan as $fty).max(9.0), 9.0);
- $fassert!(($nan as $fty).max(-9.0), -9.0);
- $fassert!((9.0 as $fty).max($nan), 9.0);
- $fassert!((-9.0 as $fty).max($nan), -9.0);
- $fassert!(($nan as $fty).max($nan).is_nan());
+ $fassert!(<$fty>::INFINITY.max(9.0), <$fty>::INFINITY);
+ $fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
+ $fassert!(<$fty>::INFINITY.max(-9.0), <$fty>::INFINITY);
+ $fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
+ $fassert!(<$fty>::NEG_INFINITY.max(9.0), 9.0);
+ $fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0);
+ $fassert!(<$fty>::NEG_INFINITY.max(-9.0), -9.0);
+ $fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0);
+ $fassert!(<$fty>::NAN.max(9.0), 9.0);
+ $fassert!(<$fty>::NAN.max(-9.0), -9.0);
+ $fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0);
+ $fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0);
+ $fassert!(<$fty>::NAN.max(<$fty>::NAN).is_nan());
}
#[test]
fn minimum() {
@@ -806,19 +806,19 @@ macro_rules! test_float {
$fassert!((-0.0 as $fty).minimum(9.0), -0.0);
$fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
$fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
- $fassert!(($inf as $fty).minimum(9.0), 9.0);
- $fassert!((9.0 as $fty).minimum($inf), 9.0);
- $fassert!(($inf as $fty).minimum(-9.0), -9.0);
- $fassert!((-9.0 as $fty).minimum($inf), -9.0);
- $fassert!(($neginf as $fty).minimum(9.0), $neginf);
- $fassert!((9.0 as $fty).minimum($neginf), $neginf);
- $fassert!(($neginf as $fty).minimum(-9.0), $neginf);
- $fassert!((-9.0 as $fty).minimum($neginf), $neginf);
- $fassert!(($nan as $fty).minimum(9.0).is_nan());
- $fassert!(($nan as $fty).minimum(-9.0).is_nan());
- $fassert!((9.0 as $fty).minimum($nan).is_nan());
- $fassert!((-9.0 as $fty).minimum($nan).is_nan());
- $fassert!(($nan as $fty).minimum($nan).is_nan());
+ $fassert!(<$fty>::INFINITY.minimum(9.0), 9.0);
+ $fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0);
+ $fassert!(<$fty>::INFINITY.minimum(-9.0), -9.0);
+ $fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0);
+ $fassert!(<$fty>::NEG_INFINITY.minimum(9.0), <$fty>::NEG_INFINITY);
+ $fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+ $fassert!(<$fty>::NEG_INFINITY.minimum(-9.0), <$fty>::NEG_INFINITY);
+ $fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+ $fassert!(<$fty>::NAN.minimum(9.0).is_nan());
+ $fassert!(<$fty>::NAN.minimum(-9.0).is_nan());
+ $fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan());
+ $fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan());
+ $fassert!(<$fty>::NAN.minimum(<$fty>::NAN).is_nan());
}
#[test]
fn maximum() {
@@ -838,19 +838,19 @@ macro_rules! test_float {
$fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
$fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
$fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
- $fassert!(($inf as $fty).maximum(9.0), $inf);
- $fassert!((9.0 as $fty).maximum($inf), $inf);
- $fassert!(($inf as $fty).maximum(-9.0), $inf);
- $fassert!((-9.0 as $fty).maximum($inf), $inf);
- $fassert!(($neginf as $fty).maximum(9.0), 9.0);
- $fassert!((9.0 as $fty).maximum($neginf), 9.0);
- $fassert!(($neginf as $fty).maximum(-9.0), -9.0);
- $fassert!((-9.0 as $fty).maximum($neginf), -9.0);
- $fassert!(($nan as $fty).maximum(9.0).is_nan());
- $fassert!(($nan as $fty).maximum(-9.0).is_nan());
- $fassert!((9.0 as $fty).maximum($nan).is_nan());
- $fassert!((-9.0 as $fty).maximum($nan).is_nan());
- $fassert!(($nan as $fty).maximum($nan).is_nan());
+ $fassert!(<$fty>::INFINITY.maximum(9.0), <$fty>::INFINITY);
+ $fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
+ $fassert!(<$fty>::INFINITY.maximum(-9.0), <$fty>::INFINITY);
+ $fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
+ $fassert!(<$fty>::NEG_INFINITY.maximum(9.0), 9.0);
+ $fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0);
+ $fassert!(<$fty>::NEG_INFINITY.maximum(-9.0), -9.0);
+ $fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0);
+ $fassert!(<$fty>::NAN.maximum(9.0).is_nan());
+ $fassert!(<$fty>::NAN.maximum(-9.0).is_nan());
+ $fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan());
+ $fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan());
+ $fassert!(<$fty>::NAN.maximum(<$fty>::NAN).is_nan());
}
#[test]
fn midpoint() {
@@ -863,38 +863,47 @@ macro_rules! test_float {
$fassert!((0.0 as $fty).midpoint(0.0), 0.0);
$fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
$fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
- $fassert!(($max as $fty).midpoint($min), 0.0);
- $fassert!(($min as $fty).midpoint($max), -0.0);
- $fassert!(($max as $fty).midpoint($min_pos), $max / 2.);
- $fassert!((-$max as $fty).midpoint($min_pos), -$max / 2.);
- $fassert!(($max as $fty).midpoint(-$min_pos), $max / 2.);
- $fassert!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
- $fassert!(($min_pos as $fty).midpoint($max), $max / 2.);
- $fassert!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
- $fassert!((-$min_pos as $fty).midpoint($max), $max / 2.);
- $fassert!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
- $fassert!(($max as $fty).midpoint($max), $max);
- $fassert!(($min_pos as $fty).midpoint($min_pos), $min_pos);
- $fassert!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
- $fassert!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
- $fassert!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
- $fassert!(($inf as $fty).midpoint($inf), $inf);
- $fassert!(($neginf as $fty).midpoint($neginf), $neginf);
- $fassert!(($nan as $fty).midpoint(1.0).is_nan());
- $fassert!((1.0 as $fty).midpoint($nan).is_nan());
- $fassert!(($nan as $fty).midpoint($nan).is_nan());
+ $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN), 0.0);
+ $fassert!(<$fty>::MIN.midpoint(<$fty>::MAX), -0.0);
+ $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
+ $fassert!((-<$fty>::MAX).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
+ $fassert!(<$fty>::MAX.midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
+ $fassert!((-<$fty>::MAX).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
+ $fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
+ $fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
+ $fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
+ $fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
+ $fassert!(<$fty>::MAX.midpoint(<$fty>::MAX), <$fty>::MAX);
+ $fassert!(
+ (<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE),
+ <$fty>::MIN_POSITIVE
+ );
+ $fassert!(
+ (-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE),
+ -<$fty>::MIN_POSITIVE
+ );
+ $fassert!(<$fty>::MAX.midpoint(5.0), <$fty>::MAX / 2.0 + 2.5);
+ $fassert!(<$fty>::MAX.midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5);
+ $fassert!(<$fty>::INFINITY.midpoint(<$fty>::INFINITY), <$fty>::INFINITY);
+ $fassert!(
+ <$fty>::NEG_INFINITY.midpoint(<$fty>::NEG_INFINITY),
+ <$fty>::NEG_INFINITY
+ );
+ $fassert!(<$fty>::NAN.midpoint(1.0).is_nan());
+ $fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan());
+ $fassert!(<$fty>::NAN.midpoint(<$fty>::NAN).is_nan());
// test if large differences in magnitude are still correctly computed.
// NOTE: that because of how small x and y are, x + y can never overflow
// so (x + y) / 2.0 is always correct
// in particular, `2.pow(i)` will never be at the max exponent, so it could
// be safely doubled, while j is significantly smaller.
- for i in $max_exp.saturating_sub(64)..$max_exp {
+ for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP {
for j in 0..64u8 {
- let large = <$fty>::from(2.0f32).powi(i);
+ let large = (2.0 as $fty).powi(i);
// a much smaller number, such that there is no chance of overflow to test
// potential double rounding in midpoint's implementation.
- let small = <$fty>::from(2.0f32).powi($max_exp - 1)
+ let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1)
* <$fty>::EPSILON
* <$fty>::from(j);
@@ -906,23 +915,37 @@ macro_rules! test_float {
}
}
#[test]
+ fn abs() {
+ $fassert!((-1.0 as $fty).abs(), 1.0);
+ $fassert!((1.0 as $fty).abs(), 1.0);
+ $fassert!(<$fty>::NEG_INFINITY.abs(), <$fty>::INFINITY);
+ $fassert!(<$fty>::INFINITY.abs(), <$fty>::INFINITY);
+ }
+ #[test]
+ fn copysign() {
+ $fassert!((1.0 as $fty).copysign(-2.0), -1.0);
+ $fassert!((-1.0 as $fty).copysign(2.0), 1.0);
+ $fassert!(<$fty>::INFINITY.copysign(-0.0), <$fty>::NEG_INFINITY);
+ $fassert!(<$fty>::NEG_INFINITY.copysign(0.0), <$fty>::INFINITY);
+ }
+ #[test]
fn rem_euclid() {
// FIXME: Use $fassert when rem_euclid becomes const
- assert!($inf.rem_euclid((42.0 as $fty)).is_nan());
- assert_eq!((42.0 as $fty).rem_euclid($inf), (42.0 as $fty));
- assert!((42.0 as $fty).rem_euclid($nan).is_nan());
- assert!($inf.rem_euclid($inf).is_nan());
- assert!($inf.rem_euclid($nan).is_nan());
- assert!($nan.rem_euclid($inf).is_nan());
+ assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan());
+ assert_eq!((42.0 as $fty).rem_euclid(<$fty>::INFINITY), (42.0 as $fty));
+ assert!((42.0 as $fty).rem_euclid(<$fty>::NAN).is_nan());
+ assert!(<$fty>::INFINITY.rem_euclid(<$fty>::INFINITY).is_nan());
+ assert!(<$fty>::INFINITY.rem_euclid(<$fty>::NAN).is_nan());
+ assert!(<$fty>::NAN.rem_euclid(<$fty>::INFINITY).is_nan());
}
#[test]
fn div_euclid() {
// FIXME: Use $fassert when div_euclid becomes const
- assert_eq!((42.0 as $fty).div_euclid($inf), 0.0);
- assert!((42.0 as $fty).div_euclid($nan).is_nan());
- assert!($inf.div_euclid($inf).is_nan());
- assert!($inf.div_euclid($nan).is_nan());
- assert!($nan.div_euclid($inf).is_nan());
+ assert_eq!((42.0 as $fty).div_euclid(<$fty>::INFINITY), 0.0);
+ assert!((42.0 as $fty).div_euclid(<$fty>::NAN).is_nan());
+ assert!(<$fty>::INFINITY.div_euclid(<$fty>::INFINITY).is_nan());
+ assert!(<$fty>::INFINITY.div_euclid(<$fty>::NAN).is_nan());
+ assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan());
}
}
};
@@ -948,51 +971,7 @@ macro_rules! float_const_assert {
};
}
-test_float!(
- f32,
- float_assert,
- f32,
- f32::INFINITY,
- f32::NEG_INFINITY,
- f32::NAN,
- f32::MIN,
- f32::MAX,
- f32::MIN_POSITIVE,
- f32::MAX_EXP
-);
-test_float!(
- f32_const,
- float_const_assert,
- f32,
- f32::INFINITY,
- f32::NEG_INFINITY,
- f32::NAN,
- f32::MIN,
- f32::MAX,
- f32::MIN_POSITIVE,
- f32::MAX_EXP
-);
-test_float!(
- f64,
- float_assert,
- f64,
- f64::INFINITY,
- f64::NEG_INFINITY,
- f64::NAN,
- f64::MIN,
- f64::MAX,
- f64::MIN_POSITIVE,
- f64::MAX_EXP
-);
-test_float!(
- f64_const,
- float_const_assert,
- f64,
- f64::INFINITY,
- f64::NEG_INFINITY,
- f64::NAN,
- f64::MIN,
- f64::MAX,
- f64::MIN_POSITIVE,
- f64::MAX_EXP
-);
+test_float!(f32, float_assert, f32);
+test_float!(f32_const, float_const_assert, f32);
+test_float!(f64, float_assert, f64);
+test_float!(f64_const, float_const_assert, f64);
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 8da6d75b73e1..c81e3af2f0d4 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1782,8 +1782,30 @@ fn test_eq_windows_file_type() {
// Change the readonly attribute of one file.
let mut perms = file1.metadata().unwrap().permissions();
perms.set_readonly(true);
- file1.set_permissions(perms).unwrap();
+ file1.set_permissions(perms.clone()).unwrap();
+ #[cfg(target_vendor = "win7")]
+ let _g = ReadonlyGuard { file: &file1, perms };
assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type());
+
+ // Reset the attribute before the `TmpDir`'s drop that removes the
+ // associated directory, which fails with a `PermissionDenied` error when
+ // running under Windows 7.
+ #[cfg(target_vendor = "win7")]
+ struct ReadonlyGuard<'f> {
+ file: &'f File,
+ perms: fs::Permissions,
+ }
+ #[cfg(target_vendor = "win7")]
+ impl<'f> Drop for ReadonlyGuard<'f> {
+ fn drop(&mut self) {
+ self.perms.set_readonly(false);
+ let res = self.file.set_permissions(self.perms.clone());
+
+ if !thread::panicking() {
+ res.unwrap();
+ }
+ }
+ }
}
/// Regression test for https://github.com/rust-lang/rust/issues/50619.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 4d9846177391..4b2418a49858 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -276,12 +276,12 @@
// tidy-alphabetical-start
// stabilization was reverted after it hit beta
+#![cfg_attr(not(bootstrap), feature(autodiff))]
#![feature(alloc_error_handler)]
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(asm_experimental_arch)]
-#![feature(autodiff)]
#![feature(cfg_sanitizer_cfi)]
#![feature(cfg_target_thread_local)]
#![feature(cfi_encoding)]
@@ -636,12 +636,15 @@ pub mod simd {
#[doc(inline)]
pub use crate::std_float::StdFloat;
}
+
#[unstable(feature = "autodiff", issue = "124509")]
+#[cfg(not(bootstrap))]
/// This module provides support for automatic differentiation.
pub mod autodiff {
/// This macro handles automatic differentiation.
- pub use core::autodiff::autodiff;
+ pub use core::autodiff::{autodiff_forward, autodiff_reverse};
}
+
#[stable(feature = "futures_api", since = "1.36.0")]
pub mod task {
//! Types and Traits for working with asynchronous tasks.
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 2cdded1dfcf9..050c617f5649 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2746,15 +2746,30 @@ impl Path {
/// # Examples
///
/// ```
- /// use std::path::{Path, PathBuf};
+ /// use std::path::Path;
///
/// let path = Path::new("foo.rs");
- /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
+ /// assert_eq!(path.with_extension("txt"), Path::new("foo.txt"));
+ /// assert_eq!(path.with_extension(""), Path::new("foo"));
+ /// ```
+ ///
+ /// Handling multiple extensions:
+ ///
+ /// ```
+ /// use std::path::Path;
///
/// let path = Path::new("foo.tar.gz");
- /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
- /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
- /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
+ /// assert_eq!(path.with_extension("xz"), Path::new("foo.tar.xz"));
+ /// assert_eq!(path.with_extension("").with_extension("txt"), Path::new("foo.txt"));
+ /// ```
+ ///
+ /// Adding an extension where one did not exist:
+ ///
+ /// ```
+ /// use std::path::Path;
+ ///
+ /// let path = Path::new("foo");
+ /// assert_eq!(path.with_extension("rs"), Path::new("foo.rs"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_extension>(&self, extension: S) -> PathBuf {
diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs
index 1c29c619edc3..30325be685c3 100644
--- a/library/std/src/sync/poison/mutex.rs
+++ b/library/std/src/sync/poison/mutex.rs
@@ -608,6 +608,17 @@ impl Mutex {
let data = self.data.get_mut();
poison::map_result(self.poison.borrow(), |()| data)
}
+
+ /// Returns a raw pointer to the underlying data.
+ ///
+ /// The returned pointer is always non-null and properly aligned, but it is
+ /// the user's responsibility to ensure that any reads and writes through it
+ /// are properly synchronized to avoid data races, and that it is not read
+ /// or written through after the mutex is dropped.
+ #[unstable(feature = "mutex_data_ptr", issue = "140368")]
+ pub fn data_ptr(&self) -> *mut T {
+ self.data.get()
+ }
}
#[stable(feature = "mutex_from", since = "1.24.0")]
diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs
index 6976c0a64e23..a060e2ea57a7 100644
--- a/library/std/src/sync/poison/rwlock.rs
+++ b/library/std/src/sync/poison/rwlock.rs
@@ -634,6 +634,17 @@ impl RwLock {
let data = self.data.get_mut();
poison::map_result(self.poison.borrow(), |()| data)
}
+
+ /// Returns a raw pointer to the underlying data.
+ ///
+ /// The returned pointer is always non-null and properly aligned, but it is
+ /// the user's responsibility to ensure that any reads and writes through it
+ /// are properly synchronized to avoid data races, and that it is not read
+ /// or written through after the lock is dropped.
+ #[unstable(feature = "rwlock_data_ptr", issue = "140368")]
+ pub fn data_ptr(&self) -> *mut T {
+ self.data.get()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 96a4cf12659c..727252f03a24 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -349,6 +349,17 @@ impl ReentrantLock {
}
}
+ /// Returns a raw pointer to the underlying data.
+ ///
+ /// The returned pointer is always non-null and properly aligned, but it is
+ /// the user's responsibility to ensure that any reads through it are
+ /// properly synchronized to avoid data races, and that it is not read
+ /// through after the lock is dropped.
+ #[unstable(feature = "reentrant_lock_data_ptr", issue = "140368")]
+ pub fn data_ptr(&self) -> *const T {
+ &raw const self.data
+ }
+
unsafe fn increment_lock_count(&self) -> Option<()> {
unsafe {
*self.lock_count.get() = (*self.lock_count.get()).checked_add(1)?;
diff --git a/library/std/src/sys/sync/mutex/futex.rs b/library/std/src/sys/sync/mutex/futex.rs
index ce9b2daa5f80..70e2ea9f6058 100644
--- a/library/std/src/sys/sync/mutex/futex.rs
+++ b/library/std/src/sys/sync/mutex/futex.rs
@@ -19,11 +19,15 @@ impl Mutex {
}
#[inline]
+ // Make this a diagnostic item for Miri's concurrency model checker.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")]
pub fn try_lock(&self) -> bool {
self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok()
}
#[inline]
+ // Make this a diagnostic item for Miri's concurrency model checker.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")]
pub fn lock(&self) {
if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() {
self.lock_contended();
@@ -80,6 +84,8 @@ impl Mutex {
}
#[inline]
+ // Make this a diagnostic item for Miri's concurrency model checker.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")]
pub unsafe fn unlock(&self) {
if self.futex.swap(UNLOCKED, Release) == CONTENDED {
// We only wake up one thread. When that thread locks the mutex, it
diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs
index 75b4b9c6dad9..a7a3b47d0ec6 100644
--- a/library/std/src/sys/sync/mutex/pthread.rs
+++ b/library/std/src/sys/sync/mutex/pthread.rs
@@ -6,7 +6,7 @@ use crate::sys::pal::sync as pal;
use crate::sys::sync::OnceBox;
pub struct Mutex {
- pub pal: OnceBox,
+ pub(in crate::sys::sync) pal: OnceBox,
}
impl Mutex {
@@ -28,6 +28,8 @@ impl Mutex {
}
#[inline]
+ // Make this a diagnostic item for Miri's concurrency model checker.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")]
pub fn lock(&self) {
// SAFETY: we call `init` above, therefore reentrant locking is safe.
// In `drop` we ensure that the mutex is not destroyed while locked.
@@ -35,6 +37,8 @@ impl Mutex {
}
#[inline]
+ // Make this a diagnostic item for Miri's concurrency model checker.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")]
pub unsafe fn unlock(&self) {
// SAFETY: the mutex can only be locked if it is already initialized
// and we observed this initialization since we observed the locking.
@@ -42,6 +46,8 @@ impl Mutex {
}
#[inline]
+ // Make this a diagnostic item for Miri's concurrency model checker.
+ #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")]
pub fn try_lock(&self) -> bool {
// SAFETY: we call `init` above, therefore reentrant locking is safe.
// In `drop` we ensure that the mutex is not destroyed while locked.
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index a37881974716..5e4a1c7d9f07 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -1430,6 +1430,7 @@ impl Step for Libunwind {
cfg.flag("-funwind-tables");
cfg.flag("-fvisibility=hidden");
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
+ cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1");
cfg.include(root.join("include"));
cfg.cargo_metadata(false);
cfg.out_dir(&out_dir);
@@ -1447,12 +1448,10 @@ impl Step for Libunwind {
cfg.define("__NO_STRING_INLINES", None);
cfg.define("__NO_MATH_INLINES", None);
cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
- cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
cfg.define("NDEBUG", None);
}
if self.target.is_windows() {
cfg.define("_LIBUNWIND_HIDE_SYMBOLS", "1");
- cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1");
}
}
diff --git a/src/ci/citool/src/jobs/tests.rs b/src/ci/citool/src/jobs/tests.rs
index a489656fa5dc..ed5444d4333d 100644
--- a/src/ci/citool/src/jobs/tests.rs
+++ b/src/ci/citool/src/jobs/tests.rs
@@ -1,4 +1,8 @@
+use std::path::Path;
+
+use super::Job;
use crate::jobs::{JobDatabase, load_job_db};
+use crate::{DOCKER_DIRECTORY, JOBS_YML_PATH, utils};
#[test]
fn lookup_job_pattern() {
@@ -62,3 +66,65 @@ fn check_pattern(db: &JobDatabase, pattern: &str, expected: &[&str]) {
assert_eq!(jobs, expected);
}
+
+/// Validate that CodeBuild jobs use Docker images from ghcr.io registry.
+/// This is needed because otherwise from CodeBuild we get rate limited by Docker Hub.
+fn validate_codebuild_image(job: &Job) -> anyhow::Result<()> {
+ let is_job_on_codebuild = job.codebuild.unwrap_or(false);
+ if !is_job_on_codebuild {
+ // Jobs in GitHub Actions don't get rate limited by Docker Hub.
+ return Ok(());
+ }
+
+ let image_name = job.image();
+ // we hardcode host-x86_64 here, because in codebuild we only run jobs for this architecture.
+ let dockerfile_path =
+ Path::new(DOCKER_DIRECTORY).join("host-x86_64").join(&image_name).join("Dockerfile");
+
+ if !dockerfile_path.exists() {
+ return Err(anyhow::anyhow!(
+ "Dockerfile not found for CodeBuild job '{}' at path: {}",
+ job.name,
+ dockerfile_path.display()
+ ));
+ }
+
+ let dockerfile_content = utils::read_to_string(&dockerfile_path)?;
+
+ // Check if all FROM statement uses ghcr.io registry
+ let has_ghcr_from = dockerfile_content
+ .lines()
+ .filter(|line| line.trim_start().to_lowercase().starts_with("from "))
+ .all(|line| line.contains("ghcr.io"));
+
+ if !has_ghcr_from {
+ return Err(anyhow::anyhow!(
+ "CodeBuild job '{}' must use ghcr.io registry in its Dockerfile FROM statement. \
+ Dockerfile path: {dockerfile_path:?}",
+ job.name,
+ ));
+ }
+
+ Ok(())
+}
+
+#[test]
+fn validate_jobs() {
+ let db = {
+ let default_jobs_file = Path::new(JOBS_YML_PATH);
+ let db_str = utils::read_to_string(default_jobs_file).unwrap();
+ load_job_db(&db_str).expect("Failed to load job database")
+ };
+
+ let all_jobs =
+ db.pr_jobs.iter().chain(db.try_jobs.iter()).chain(db.auto_jobs.iter()).collect::>();
+
+ let errors: Vec =
+ all_jobs.into_iter().filter_map(|job| validate_codebuild_image(job).err()).collect();
+
+ if !errors.is_empty() {
+ let error_messages =
+ errors.into_iter().map(|e| format!("- {e}")).collect::>().join("\n");
+ panic!("Job validation failed:\n{error_messages}");
+ }
+}
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
index 87ce09cfb233..bb73a5ef909f 100644
--- a/src/ci/citool/src/main.rs
+++ b/src/ci/citool/src/main.rs
@@ -27,7 +27,7 @@ use crate::test_dashboard::generate_test_dashboard;
use crate::utils::{load_env_var, output_details};
const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
-const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
+pub const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml");
struct GitHubContext {
diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile
new file mode 100644
index 000000000000..2f9d0010573a
--- /dev/null
+++ b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile
@@ -0,0 +1,58 @@
+FROM ubuntu:24.10
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ bzip2 \
+ g++ \
+ make \
+ ninja-build \
+ file \
+ curl \
+ ca-certificates \
+ python3 \
+ git \
+ cmake \
+ sudo \
+ gdb \
+ llvm-19-tools \
+ llvm-19-dev \
+ libedit-dev \
+ libssl-dev \
+ pkg-config \
+ zlib1g-dev \
+ xz-utils \
+ nodejs \
+ mingw-w64 \
+ # libgccjit dependencies
+ flex \
+ libmpfr-dev \
+ libgmp-dev \
+ libmpc3 \
+ libmpc-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+ENV EXTERNAL_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+ --build=aarch64-unknown-linux-gnu \
+ --llvm-root=/usr/lib/llvm-19 \
+ --enable-llvm-link-shared \
+ --set rust.randomize-layout=true \
+ --set rust.thin-lto-import-instr-limit=10
+
+COPY scripts/shared.sh /scripts/
+
+ARG SCRIPT_ARG
+
+COPY scripts/stage_2_test_set1.sh /tmp/
+COPY scripts/stage_2_test_set2.sh /tmp/
+
+ENV SCRIPT "/tmp/${SCRIPT_ARG}"
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
index e0435a3ff5c1..5fa17d954c3b 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
@@ -2,8 +2,8 @@
set -ex
-# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
-../x.py --stage 2 test --skip src/tools/tidy
+# NOTE: intentionally uses `x`, and `x.ps1` to make sure they work on Linux.
+# Make sure that `x.py` is tested elsewhere.
# Run the `mir-opt` tests again but this time for a 32-bit target.
# This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index e257f231184d..f9a463966302 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -121,7 +121,17 @@ pr:
env:
ENABLE_GCC_CODEGEN: "1"
DOCKER_SCRIPT: x86_64-gnu-llvm.sh
- <<: *job-linux-16c
+ <<: *job-linux-4c
+ - name: aarch64-gnu-llvm-19-1
+ env:
+ IMAGE: aarch64-gnu-llvm-19
+ DOCKER_SCRIPT: stage_2_test_set1.sh
+ <<: *job-aarch64-linux-8c
+ - name: aarch64-gnu-llvm-19-2
+ env:
+ IMAGE: aarch64-gnu-llvm-19
+ DOCKER_SCRIPT: stage_2_test_set2.sh
+ <<: *job-aarch64-linux
- name: x86_64-gnu-tools
<<: *job-linux-36c-codebuild
@@ -132,7 +142,7 @@ try:
- name: dist-x86_64-linux
env:
CODEGEN_BACKENDS: llvm,cranelift
- <<: *job-linux-16c
+ <<: *job-linux-36c-codebuild
# Main CI jobs that have to be green to merge a commit into master
# These jobs automatically inherit envs.auto, to avoid repeating
@@ -228,7 +238,7 @@ auto:
- name: dist-x86_64-linux
env:
CODEGEN_BACKENDS: llvm,cranelift
- <<: *job-linux-16c
+ <<: *job-linux-36c-codebuild
- name: dist-x86_64-linux-alt
env:
@@ -459,7 +469,9 @@ auto:
- name: aarch64-apple
env:
- SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin
+ SCRIPT: >
+ ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin &&
+ ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin src/tools/cargo
RUST_CONFIGURE_ARGS: >-
--enable-sanitizers
--enable-profiler
diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md
index eeb4a813980a..f766a51898e4 100644
--- a/src/doc/rustc-dev-guide/src/memory.md
+++ b/src/doc/rustc-dev-guide/src/memory.md
@@ -63,7 +63,7 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
[`mk_args`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args
[adtdefid]: ./ty_module/generic_arguments.md#adtdef-and-defid
[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
-[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
+[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html
[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html
[traits]: ./traits/resolution.md
diff --git a/src/doc/unstable-book/src/language-features/repr128.md b/src/doc/unstable-book/src/language-features/repr128.md
deleted file mode 100644
index 146f50ee67b5..000000000000
--- a/src/doc/unstable-book/src/language-features/repr128.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# `repr128`
-
-The tracking issue for this feature is: [#56071]
-
-[#56071]: https://github.com/rust-lang/rust/issues/56071
-
-------------------------
-
-The `repr128` feature adds support for `#[repr(u128)]` on `enum`s.
-
-```rust
-#![feature(repr128)]
-
-#[repr(u128)]
-enum Foo {
- Bar(u64),
-}
-```
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 37628f166002..1daaba3b86c5 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -22,6 +22,7 @@ use rustc_resolve::rustdoc::{
MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
source_span_for_markdown_range, strip_generics_from_path,
};
+use rustc_session::config::CrateType;
use rustc_session::lint::Lint;
use rustc_span::BytePos;
use rustc_span::hygiene::MacroKind;
@@ -1169,7 +1170,6 @@ impl LinkCollector<'_, '_> {
#[allow(rustc::potential_query_instability)]
pub(crate) fn resolve_ambiguities(&mut self) {
let mut ambiguous_links = mem::take(&mut self.ambiguous_links);
-
for ((item_id, path_str), info_items) in ambiguous_links.iter_mut() {
for info in info_items {
info.resolved.retain(|(res, _)| match res {
@@ -2227,15 +2227,35 @@ fn ambiguity_error(
emit_error: bool,
) -> bool {
let mut descrs = FxHashSet::default();
- let kinds = candidates
+ // proc macro can exist in multiple namespaces at once, so we need to compare `DefIds`
+ // to remove the candidate in the fn namespace.
+ let mut possible_proc_macro_id = None;
+ let is_proc_macro_crate = cx.tcx.crate_types() == &[CrateType::ProcMacro];
+ let mut kinds = candidates
.iter()
- .map(
- |(res, def_id)| {
- if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res }
- },
- )
- .filter(|res| descrs.insert(res.descr()))
+ .map(|(res, def_id)| {
+ let r =
+ if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res };
+ if is_proc_macro_crate && let Res::Def(DefKind::Macro(_), id) = r {
+ possible_proc_macro_id = Some(id);
+ }
+ r
+ })
.collect::>();
+ // In order to properly dedup proc macros, we have to do it in two passes:
+ // 1. Completing the full traversal to find the possible duplicate in the macro namespace,
+ // 2. Another full traversal to eliminate the candidate in the fn namespace.
+ //
+ // Thus, we have to do an iteration after collection is finished.
+ //
+ // As an optimization, we only deduplicate if we're in a proc-macro crate,
+ // and only if we already found something that looks like a proc macro.
+ if is_proc_macro_crate && let Some(macro_id) = possible_proc_macro_id {
+ kinds.retain(|res| !matches!(res, Res::Def(DefKind::Fn, fn_id) if macro_id == *fn_id));
+ }
+
+ kinds.retain(|res| descrs.insert(res.descr()));
+
if descrs.len() == 1 {
// There is no way for users to disambiguate at this point, so better return the first
// candidate and not show a warning.
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index aae8291905d3..dfb0b4f103c5 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO
impl EarlyLintPass for FieldScopedVisibilityModifiers {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- let ItemKind::Struct(_, ref st, _) = item.kind else {
+ let ItemKind::Struct(_, _, ref st) = item.kind else {
return;
};
for field in st.fields() {
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 0b1cae30ca50..3d131a7825af 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -12,7 +12,6 @@ use rustc_hir::HirId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
-use rustc_middle::ty;
use rustc_session::impl_lint_pass;
use rustc_span::Span;
use rustc_span::symbol::Ident;
@@ -109,11 +108,11 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap [PARTIAL_PUB_FIELDS]);
impl EarlyLintPass for PartialPubFields {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- let ItemKind::Struct(_, ref st, _) = item.kind else {
+ let ItemKind::Struct(_, _, ref st) = item.kind else {
return;
};
diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
index 95ce19975c7e..3c21d194b81d 100644
--- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
@@ -66,7 +66,7 @@ impl LateLintPass<'_> for TupleArrayConversions {
}
fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) {
- let (ty::Array(ty, _) | ty::Slice(ty)) = cx.typeck_results().expr_ty(expr).kind() else {
+ let Some(ty) = cx.typeck_results().expr_ty(expr).builtin_index() else {
unreachable!("`expr` must be an array or slice due to `ExprKind::Array`");
};
@@ -85,7 +85,7 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &
ExprKind::Path(_) => Some(elements.iter().collect()),
_ => None,
})
- && all_bindings_are_for_conv(cx, &[*ty], expr, elements, &locals, ToType::Array)
+ && all_bindings_are_for_conv(cx, &[ty], expr, elements, &locals, ToType::Array)
&& !is_from_proc_macro(cx, expr)
{
span_lint_and_help(
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 8996b694ed8f..a0503a699e69 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -436,11 +436,11 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
&& over(lb, rb, eq_generic_bound)
&& both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
},
- (Enum(li, le, lg), Enum(ri, re, rg)) => {
- eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
+ (Enum(li, lg, le), Enum(ri, rg, re)) => {
+ eq_id(*li, *ri) && eq_generics(lg, rg) && over(&le.variants, &re.variants, eq_variant)
},
- (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
- eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
+ (Struct(li, lg, lv), Struct(ri, rg, rv)) | (Union(li, lg, lv), Union(ri, rg, rv)) => {
+ eq_id(*li, *ri) && eq_generics(lg, rg) && eq_variant_data(lv, rv)
},
(
Trait(box ast::Trait {
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 6f5b0ec54cd8..1ec5d11384f5 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -235,9 +235,7 @@ impl Constant<'_> {
_ => None,
},
(Self::Vec(l), Self::Vec(r)) => {
- let (ty::Array(cmp_type, _) | ty::Slice(cmp_type)) = *cmp_type.kind() else {
- return None;
- };
+ let cmp_type = cmp_type.builtin_index()?;
iter::zip(l, r)
.map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
.find(|r| r.is_none_or(|o| o != Ordering::Equal))
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index 4c61c5accd39..9b8e62867f0a 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -1,5 +1,4 @@
-#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
-#![allow(incomplete_features)]
+#![feature(proc_macro_hygiene, proc_macro_quote, box_patterns)]
#![allow(clippy::useless_conversion, clippy::uninlined_format_args)]
extern crate proc_macro;
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index 1815dd58f510..5992d15935d5 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -1,5 +1,4 @@
-#![feature(repr128, proc_macro_quote, proc_macro_span)]
-#![allow(incomplete_features)]
+#![feature(proc_macro_quote, proc_macro_span)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::eq_op)]
#![allow(clippy::literal_string_with_formatting_args)]
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index 77329cf5455d..525be8216500 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -1,7 +1,5 @@
//@no-rustfix: only some diagnostics have suggestions
-#![feature(repr128)]
-#![allow(incomplete_features)]
#![warn(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 4d03282f6676..1cb30d956679 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -1,5 +1,5 @@
error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
- --> tests/ui/cast.rs:25:5
+ --> tests/ui/cast.rs:23:5
|
LL | x0 as f32;
| ^^^^^^^^^
@@ -8,37 +8,37 @@ LL | x0 as f32;
= help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]`
error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
- --> tests/ui/cast.rs:29:5
+ --> tests/ui/cast.rs:27:5
|
LL | x1 as f32;
| ^^^^^^^^^
error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
- --> tests/ui/cast.rs:32:5
+ --> tests/ui/cast.rs:30:5
|
LL | x1 as f64;
| ^^^^^^^^^
error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
- --> tests/ui/cast.rs:36:5
+ --> tests/ui/cast.rs:34:5
|
LL | x2 as f32;
| ^^^^^^^^^
error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
- --> tests/ui/cast.rs:40:5
+ --> tests/ui/cast.rs:38:5
|
LL | x3 as f32;
| ^^^^^^^^^
error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
- --> tests/ui/cast.rs:43:5
+ --> tests/ui/cast.rs:41:5
|
LL | x3 as f64;
| ^^^^^^^^^
error: casting `f32` to `i32` may truncate the value
- --> tests/ui/cast.rs:47:5
+ --> tests/ui/cast.rs:45:5
|
LL | 1f32 as i32;
| ^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL | 1f32 as i32;
= help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]`
error: casting `f32` to `u32` may truncate the value
- --> tests/ui/cast.rs:50:5
+ --> tests/ui/cast.rs:48:5
|
LL | 1f32 as u32;
| ^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL | 1f32 as u32;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:50:5
+ --> tests/ui/cast.rs:48:5
|
LL | 1f32 as u32;
| ^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL | 1f32 as u32;
= help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]`
error: casting `f64` to `f32` may truncate the value
- --> tests/ui/cast.rs:54:5
+ --> tests/ui/cast.rs:52:5
|
LL | 1f64 as f32;
| ^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL | 1f64 as f32;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `i32` to `i8` may truncate the value
- --> tests/ui/cast.rs:57:5
+ --> tests/ui/cast.rs:55:5
|
LL | 1i32 as i8;
| ^^^^^^^^^^
@@ -86,7 +86,7 @@ LL + i8::try_from(1i32);
|
error: casting `i32` to `u8` may truncate the value
- --> tests/ui/cast.rs:60:5
+ --> tests/ui/cast.rs:58:5
|
LL | 1i32 as u8;
| ^^^^^^^^^^
@@ -99,7 +99,7 @@ LL + u8::try_from(1i32);
|
error: casting `f64` to `isize` may truncate the value
- --> tests/ui/cast.rs:63:5
+ --> tests/ui/cast.rs:61:5
|
LL | 1f64 as isize;
| ^^^^^^^^^^^^^
@@ -107,7 +107,7 @@ LL | 1f64 as isize;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f64` to `usize` may truncate the value
- --> tests/ui/cast.rs:66:5
+ --> tests/ui/cast.rs:64:5
|
LL | 1f64 as usize;
| ^^^^^^^^^^^^^
@@ -115,13 +115,13 @@ LL | 1f64 as usize;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f64` to `usize` may lose the sign of the value
- --> tests/ui/cast.rs:66:5
+ --> tests/ui/cast.rs:64:5
|
LL | 1f64 as usize;
| ^^^^^^^^^^^^^
error: casting `u32` to `u16` may truncate the value
- --> tests/ui/cast.rs:70:5
+ --> tests/ui/cast.rs:68:5
|
LL | 1f32 as u32 as u16;
| ^^^^^^^^^^^^^^^^^^
@@ -134,7 +134,7 @@ LL + u16::try_from(1f32 as u32);
|
error: casting `f32` to `u32` may truncate the value
- --> tests/ui/cast.rs:70:5
+ --> tests/ui/cast.rs:68:5
|
LL | 1f32 as u32 as u16;
| ^^^^^^^^^^^
@@ -142,13 +142,13 @@ LL | 1f32 as u32 as u16;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:70:5
+ --> tests/ui/cast.rs:68:5
|
LL | 1f32 as u32 as u16;
| ^^^^^^^^^^^
error: casting `i32` to `i8` may truncate the value
- --> tests/ui/cast.rs:76:22
+ --> tests/ui/cast.rs:74:22
|
LL | let _x: i8 = 1i32 as _;
| ^^^^^^^^^
@@ -161,7 +161,7 @@ LL + let _x: i8 = 1i32.try_into();
|
error: casting `f32` to `i32` may truncate the value
- --> tests/ui/cast.rs:79:9
+ --> tests/ui/cast.rs:77:9
|
LL | 1f32 as i32;
| ^^^^^^^^^^^
@@ -169,7 +169,7 @@ LL | 1f32 as i32;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f64` to `i32` may truncate the value
- --> tests/ui/cast.rs:82:9
+ --> tests/ui/cast.rs:80:9
|
LL | 1f64 as i32;
| ^^^^^^^^^^^
@@ -177,7 +177,7 @@ LL | 1f64 as i32;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f32` to `u8` may truncate the value
- --> tests/ui/cast.rs:85:9
+ --> tests/ui/cast.rs:83:9
|
LL | 1f32 as u8;
| ^^^^^^^^^^
@@ -185,13 +185,13 @@ LL | 1f32 as u8;
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
error: casting `f32` to `u8` may lose the sign of the value
- --> tests/ui/cast.rs:85:9
+ --> tests/ui/cast.rs:83:9
|
LL | 1f32 as u8;
| ^^^^^^^^^^
error: casting `u8` to `i8` may wrap around the value
- --> tests/ui/cast.rs:90:5
+ --> tests/ui/cast.rs:88:5
|
LL | 1u8 as i8;
| ^^^^^^^^^
@@ -200,31 +200,31 @@ LL | 1u8 as i8;
= help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]`
error: casting `u16` to `i16` may wrap around the value
- --> tests/ui/cast.rs:93:5
+ --> tests/ui/cast.rs:91:5
|
LL | 1u16 as i16;
| ^^^^^^^^^^^
error: casting `u32` to `i32` may wrap around the value
- --> tests/ui/cast.rs:96:5
+ --> tests/ui/cast.rs:94:5
|
LL | 1u32 as i32;
| ^^^^^^^^^^^
error: casting `u64` to `i64` may wrap around the value
- --> tests/ui/cast.rs:99:5
+ --> tests/ui/cast.rs:97:5
|
LL | 1u64 as i64;
| ^^^^^^^^^^^
error: casting `usize` to `isize` may wrap around the value
- --> tests/ui/cast.rs:102:5
+ --> tests/ui/cast.rs:100:5
|
LL | 1usize as isize;
| ^^^^^^^^^^^^^^^
error: casting `usize` to `i8` may truncate the value
- --> tests/ui/cast.rs:106:5
+ --> tests/ui/cast.rs:104:5
|
LL | 1usize as i8;
| ^^^^^^^^^^^^
@@ -237,7 +237,7 @@ LL + i8::try_from(1usize);
|
error: casting `usize` to `i16` may truncate the value
- --> tests/ui/cast.rs:110:5
+ --> tests/ui/cast.rs:108:5
|
LL | 1usize as i16;
| ^^^^^^^^^^^^^
@@ -250,7 +250,7 @@ LL + i16::try_from(1usize);
|
error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers
- --> tests/ui/cast.rs:110:5
+ --> tests/ui/cast.rs:108:5
|
LL | 1usize as i16;
| ^^^^^^^^^^^^^
@@ -259,7 +259,7 @@ LL | 1usize as i16;
= note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
- --> tests/ui/cast.rs:115:5
+ --> tests/ui/cast.rs:113:5
|
LL | 1usize as i32;
| ^^^^^^^^^^^^^
@@ -272,19 +272,19 @@ LL + i32::try_from(1usize);
|
error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
- --> tests/ui/cast.rs:115:5
+ --> tests/ui/cast.rs:113:5
|
LL | 1usize as i32;
| ^^^^^^^^^^^^^
error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers
- --> tests/ui/cast.rs:120:5
+ --> tests/ui/cast.rs:118:5
|
LL | 1usize as i64;
| ^^^^^^^^^^^^^
error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers
- --> tests/ui/cast.rs:126:5
+ --> tests/ui/cast.rs:124:5
|
LL | 1u16 as isize;
| ^^^^^^^^^^^^^
@@ -293,13 +293,13 @@ LL | 1u16 as isize;
= note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
- --> tests/ui/cast.rs:130:5
+ --> tests/ui/cast.rs:128:5
|
LL | 1u32 as isize;
| ^^^^^^^^^^^^^
error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
- --> tests/ui/cast.rs:134:5
+ --> tests/ui/cast.rs:132:5
|
LL | 1u64 as isize;
| ^^^^^^^^^^^^^
@@ -312,55 +312,55 @@ LL + isize::try_from(1u64);
|
error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
- --> tests/ui/cast.rs:134:5
+ --> tests/ui/cast.rs:132:5
|
LL | 1u64 as isize;
| ^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:140:5
+ --> tests/ui/cast.rs:138:5
|
LL | -1i32 as u32;
| ^^^^^^^^^^^^
error: casting `isize` to `usize` may lose the sign of the value
- --> tests/ui/cast.rs:144:5
+ --> tests/ui/cast.rs:142:5
|
LL | -1isize as usize;
| ^^^^^^^^^^^^^^^^
error: casting `i8` to `u8` may lose the sign of the value
- --> tests/ui/cast.rs:156:5
+ --> tests/ui/cast.rs:154:5
|
LL | (i8::MIN).abs() as u8;
| ^^^^^^^^^^^^^^^^^^^^^
error: casting `i64` to `u64` may lose the sign of the value
- --> tests/ui/cast.rs:161:5
+ --> tests/ui/cast.rs:159:5
|
LL | (-1i64).abs() as u64;
| ^^^^^^^^^^^^^^^^^^^^
error: casting `isize` to `usize` may lose the sign of the value
- --> tests/ui/cast.rs:163:5
+ --> tests/ui/cast.rs:161:5
|
LL | (-1isize).abs() as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i64` to `u64` may lose the sign of the value
- --> tests/ui/cast.rs:171:5
+ --> tests/ui/cast.rs:169:5
|
LL | (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i64` to `u64` may lose the sign of the value
- --> tests/ui/cast.rs:187:5
+ --> tests/ui/cast.rs:185:5
|
LL | (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i64` to `i8` may truncate the value
- --> tests/ui/cast.rs:239:5
+ --> tests/ui/cast.rs:237:5
|
LL | (-99999999999i64).min(1) as i8;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -373,7 +373,7 @@ LL + i8::try_from((-99999999999i64).min(1));
|
error: casting `u64` to `u8` may truncate the value
- --> tests/ui/cast.rs:253:5
+ --> tests/ui/cast.rs:251:5
|
LL | 999999u64.clamp(0, 256) as u8;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -386,7 +386,7 @@ LL + u8::try_from(999999u64.clamp(0, 256));
|
error: casting `main::E2` to `u8` may truncate the value
- --> tests/ui/cast.rs:276:21
+ --> tests/ui/cast.rs:274:21
|
LL | let _ = self as u8;
| ^^^^^^^^^^
@@ -399,7 +399,7 @@ LL + let _ = u8::try_from(self);
|
error: casting `main::E2::B` to `u8` will truncate the value
- --> tests/ui/cast.rs:279:21
+ --> tests/ui/cast.rs:277:21
|
LL | let _ = Self::B as u8;
| ^^^^^^^^^^^^^
@@ -408,7 +408,7 @@ LL | let _ = Self::B as u8;
= help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]`
error: casting `main::E5` to `i8` may truncate the value
- --> tests/ui/cast.rs:321:21
+ --> tests/ui/cast.rs:319:21
|
LL | let _ = self as i8;
| ^^^^^^^^^^
@@ -421,13 +421,13 @@ LL + let _ = i8::try_from(self);
|
error: casting `main::E5::A` to `i8` will truncate the value
- --> tests/ui/cast.rs:324:21
+ --> tests/ui/cast.rs:322:21
|
LL | let _ = Self::A as i8;
| ^^^^^^^^^^^^^
error: casting `main::E6` to `i16` may truncate the value
- --> tests/ui/cast.rs:342:21
+ --> tests/ui/cast.rs:340:21
|
LL | let _ = self as i16;
| ^^^^^^^^^^^
@@ -440,7 +440,7 @@ LL + let _ = i16::try_from(self);
|
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
- --> tests/ui/cast.rs:362:21
+ --> tests/ui/cast.rs:360:21
|
LL | let _ = self as usize;
| ^^^^^^^^^^^^^
@@ -453,7 +453,7 @@ LL + let _ = usize::try_from(self);
|
error: casting `main::E10` to `u16` may truncate the value
- --> tests/ui/cast.rs:410:21
+ --> tests/ui/cast.rs:408:21
|
LL | let _ = self as u16;
| ^^^^^^^^^^^
@@ -466,7 +466,7 @@ LL + let _ = u16::try_from(self);
|
error: casting `u32` to `u8` may truncate the value
- --> tests/ui/cast.rs:422:13
+ --> tests/ui/cast.rs:420:13
|
LL | let c = (q >> 16) as u8;
| ^^^^^^^^^^^^^^^
@@ -479,7 +479,7 @@ LL + let c = u8::try_from(q >> 16);
|
error: casting `u32` to `u8` may truncate the value
- --> tests/ui/cast.rs:427:13
+ --> tests/ui/cast.rs:425:13
|
LL | let c = (q / 1000) as u8;
| ^^^^^^^^^^^^^^^^
@@ -492,85 +492,85 @@ LL + let c = u8::try_from(q / 1000);
|
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:440:9
+ --> tests/ui/cast.rs:438:9
|
LL | (x * x) as u32;
| ^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:446:32
+ --> tests/ui/cast.rs:444:32
|
LL | let _a = |x: i32| -> u32 { (x * x * x * x) as u32 };
| ^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:449:5
+ --> tests/ui/cast.rs:447:5
|
LL | (2_i32).checked_pow(3).unwrap() as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:451:5
+ --> tests/ui/cast.rs:449:5
|
LL | (-2_i32).pow(3) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:456:5
+ --> tests/ui/cast.rs:454:5
|
LL | (-5_i32 % 2) as u32;
| ^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:459:5
+ --> tests/ui/cast.rs:457:5
|
LL | (-5_i32 % -2) as u32;
| ^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:463:5
+ --> tests/ui/cast.rs:461:5
|
LL | (-2_i32 >> 1) as u32;
| ^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:467:5
+ --> tests/ui/cast.rs:465:5
|
LL | (x * x) as u32;
| ^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:469:5
+ --> tests/ui/cast.rs:467:5
|
LL | (x * x * x) as u32;
| ^^^^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:473:5
+ --> tests/ui/cast.rs:471:5
|
LL | (y * y * y * y * -2) as u16;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:476:5
+ --> tests/ui/cast.rs:474:5
|
LL | (y * y * y / y * 2) as u16;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:478:5
+ --> tests/ui/cast.rs:476:5
|
LL | (y * y / y * 2) as u16;
| ^^^^^^^^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:481:5
+ --> tests/ui/cast.rs:479:5
|
LL | (y / y * y * -2) as u16;
| ^^^^^^^^^^^^^^^^^^^^^^^
error: equal expressions as operands to `/`
- --> tests/ui/cast.rs:481:6
+ --> tests/ui/cast.rs:479:6
|
LL | (y / y * y * -2) as u16;
| ^^^^^
@@ -578,97 +578,97 @@ LL | (y / y * y * -2) as u16;
= note: `#[deny(clippy::eq_op)]` on by default
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:485:5
+ --> tests/ui/cast.rs:483:5
|
LL | (y + y + y + -2) as u16;
| ^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:488:5
+ --> tests/ui/cast.rs:486:5
|
LL | (y + y + y + 2) as u16;
| ^^^^^^^^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:492:5
+ --> tests/ui/cast.rs:490:5
|
LL | (z + -2) as u16;
| ^^^^^^^^^^^^^^^
error: casting `i16` to `u16` may lose the sign of the value
- --> tests/ui/cast.rs:495:5
+ --> tests/ui/cast.rs:493:5
|
LL | (z + z + 2) as u16;
| ^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:499:9
+ --> tests/ui/cast.rs:497:9
|
LL | (a * a * b * b * c * c) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:501:9
+ --> tests/ui/cast.rs:499:9
|
LL | (a * b * c) as u32;
| ^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:504:9
+ --> tests/ui/cast.rs:502:9
|
LL | (a * -b * c) as u32;
| ^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:507:9
+ --> tests/ui/cast.rs:505:9
|
LL | (a * b * c * c) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:509:9
+ --> tests/ui/cast.rs:507:9
|
LL | (a * -2) as u32;
| ^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:512:9
+ --> tests/ui/cast.rs:510:9
|
LL | (a * b * c * -2) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:515:9
+ --> tests/ui/cast.rs:513:9
|
LL | (a / b) as u32;
| ^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:517:9
+ --> tests/ui/cast.rs:515:9
|
LL | (a / b * c) as u32;
| ^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:520:9
+ --> tests/ui/cast.rs:518:9
|
LL | (a / b + b * c) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:523:9
+ --> tests/ui/cast.rs:521:9
|
LL | a.saturating_pow(3) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:526:9
+ --> tests/ui/cast.rs:524:9
|
LL | (a.abs() * b.pow(2) / c.abs()) as u32
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> tests/ui/cast.rs:534:21
+ --> tests/ui/cast.rs:532:21
|
LL | let _ = i32::MIN as u32; // cast_sign_loss
| ^^^^^^^^^^^^^^^
@@ -679,7 +679,7 @@ LL | m!();
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: casting `u32` to `u8` may truncate the value
- --> tests/ui/cast.rs:537:21
+ --> tests/ui/cast.rs:535:21
|
LL | let _ = u32::MAX as u8; // cast_possible_truncation
| ^^^^^^^^^^^^^^
@@ -696,7 +696,7 @@ LL + let _ = u8::try_from(u32::MAX); // cast_possible_truncation
|
error: casting `f64` to `f32` may truncate the value
- --> tests/ui/cast.rs:540:21
+ --> tests/ui/cast.rs:538:21
|
LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -708,7 +708,7 @@ LL | m!();
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
- --> tests/ui/cast.rs:551:5
+ --> tests/ui/cast.rs:549:5
|
LL | bar.unwrap().unwrap() as usize
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -721,13 +721,13 @@ LL + usize::try_from(bar.unwrap().unwrap())
|
error: casting `i64` to `usize` may lose the sign of the value
- --> tests/ui/cast.rs:551:5
+ --> tests/ui/cast.rs:549:5
|
LL | bar.unwrap().unwrap() as usize
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting `u64` to `u8` may truncate the value
- --> tests/ui/cast.rs:568:5
+ --> tests/ui/cast.rs:566:5
|
LL | (256 & 999999u64) as u8;
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -740,7 +740,7 @@ LL + u8::try_from(256 & 999999u64);
|
error: casting `u64` to `u8` may truncate the value
- --> tests/ui/cast.rs:571:5
+ --> tests/ui/cast.rs:569:5
|
LL | (255 % 999999u64) as u8;
| ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
index 5dffddc119aa..cf37a4c5c4bb 100644
--- a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
+++ b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
@@ -1,6 +1,3 @@
-#![feature(repr128)]
-#![allow(incomplete_features)]
-
extern crate proc_macro;
use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index bd8146defae9..01de430925dc 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -17,15 +17,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
[[package]]
name = "allocator-api2"
version = "0.2.21"
@@ -124,12 +115,9 @@ dependencies = [
[[package]]
name = "boxcar"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6740c6e2fc6360fa57c35214c7493826aee95993926092606f27c983b40837be"
-dependencies = [
- "loom",
-]
+checksum = "66bb12751a83493ef4b8da1120451a262554e216a247f14b48cb5e8fe7ed8bdf"
[[package]]
name = "camino"
@@ -511,19 +499,6 @@ version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
-[[package]]
-name = "generator"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd"
-dependencies = [
- "cfg-if",
- "libc",
- "log",
- "rustversion",
- "windows 0.58.0",
-]
-
[[package]]
name = "getrandom"
version = "0.2.15"
@@ -1213,19 +1188,6 @@ version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
-[[package]]
-name = "loom"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
-dependencies = [
- "cfg-if",
- "generator",
- "scoped-tls",
- "tracing",
- "tracing-subscriber",
-]
-
[[package]]
name = "lsp-server"
version = "0.7.8"
@@ -1265,15 +1227,6 @@ dependencies = [
"url",
]
-[[package]]
-name = "matchers"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
-dependencies = [
- "regex-automata 0.1.10",
-]
-
[[package]]
name = "mbe"
version = "0.0.0"
@@ -1400,16 +1353,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
-[[package]]
-name = "nu-ansi-term"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
-dependencies = [
- "overload",
- "winapi",
-]
-
[[package]]
name = "nu-ansi-term"
version = "0.50.1"
@@ -1471,12 +1414,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
-[[package]]
-name = "overload"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
-
[[package]]
name = "parking_lot"
version = "0.12.3"
@@ -1648,7 +1585,7 @@ dependencies = [
"indexmap",
"nix",
"tracing",
- "windows 0.61.1",
+ "windows",
]
[[package]]
@@ -1864,50 +1801,6 @@ dependencies = [
"thiserror 2.0.12",
]
-[[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-dependencies = [
- "regex-syntax 0.6.29",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
[[package]]
name = "rowan"
version = "0.15.15"
@@ -2026,12 +1919,6 @@ dependencies = [
"smallvec",
]
-[[package]]
-name = "rustversion"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
-
[[package]]
name = "ryu"
version = "1.0.20"
@@ -2040,9 +1927,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "salsa"
-version = "0.21.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f80d5cf3c3fcab2cef898012f242a670477a1baa609267376af9cb4409026c5"
+checksum = "c8fff508e3d6ef42a32607f7538e17171a877a12015e32036f46e99d00c95781"
dependencies = [
"boxcar",
"crossbeam-queue",
@@ -2063,15 +1950,15 @@ dependencies = [
[[package]]
name = "salsa-macro-rules"
-version = "0.21.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05303d72606fbf2b9c9523cda2039bb8ecb00304027a3cd7e52b02a65c7d9185"
+checksum = "8ea72b3c06f2ce6350fe3a0eeb7aaaf842d1d8352b706973c19c4f02e298a87c"
[[package]]
name = "salsa-macros"
-version = "0.21.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb2f0e2a30c65cb3cd63440c491dde68d9af7e1be2b77832ac7057141107db50"
+checksum = "0ce92025bc160b27814a207cb78d680973af17f863c7f4fc56cf3a535e22f378"
dependencies = [
"heck",
"proc-macro2",
@@ -2556,15 +2443,9 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
- "matchers",
- "nu-ansi-term 0.46.0",
- "once_cell",
- "regex",
"sharded-slab",
- "smallvec",
"thread_local",
"time",
- "tracing",
"tracing-core",
"tracing-log",
]
@@ -2575,7 +2456,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c"
dependencies = [
- "nu-ansi-term 0.50.1",
+ "nu-ansi-term",
"tracing-core",
"tracing-log",
"tracing-subscriber",
@@ -2709,22 +2590,6 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
[[package]]
name = "winapi-util"
version = "0.1.9"
@@ -2734,22 +2599,6 @@ dependencies = [
"windows-sys 0.59.0",
]
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
-dependencies = [
- "windows-core 0.58.0",
- "windows-targets 0.52.6",
-]
-
[[package]]
name = "windows"
version = "0.61.1"
@@ -2757,7 +2606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
dependencies = [
"windows-collections",
- "windows-core 0.61.0",
+ "windows-core",
"windows-future",
"windows-link",
"windows-numerics",
@@ -2769,20 +2618,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
dependencies = [
- "windows-core 0.61.0",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
-dependencies = [
- "windows-implement 0.58.0",
- "windows-interface 0.58.0",
- "windows-result 0.2.0",
- "windows-strings 0.1.0",
- "windows-targets 0.52.6",
+ "windows-core",
]
[[package]]
@@ -2791,11 +2627,11 @@ version = "0.61.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
dependencies = [
- "windows-implement 0.60.0",
- "windows-interface 0.59.1",
+ "windows-implement",
+ "windows-interface",
"windows-link",
- "windows-result 0.3.2",
- "windows-strings 0.4.0",
+ "windows-result",
+ "windows-strings",
]
[[package]]
@@ -2804,21 +2640,10 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
"windows-link",
]
-[[package]]
-name = "windows-implement"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "windows-implement"
version = "0.60.0"
@@ -2830,17 +2655,6 @@ dependencies = [
"syn",
]
-[[package]]
-name = "windows-interface"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "windows-interface"
version = "0.59.1"
@@ -2864,19 +2678,10 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
"windows-link",
]
-[[package]]
-name = "windows-result"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
[[package]]
name = "windows-result"
version = "0.3.2"
@@ -2886,16 +2691,6 @@ dependencies = [
"windows-link",
]
-[[package]]
-name = "windows-strings"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
-dependencies = [
- "windows-result 0.2.0",
- "windows-targets 0.52.6",
-]
-
[[package]]
name = "windows-strings"
version = "0.4.0"
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 07731bae3f30..8c5071898466 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -132,11 +132,8 @@ pulldown-cmark-to-cmark = "10.0.4"
pulldown-cmark = { version = "0.9.6", default-features = false }
rayon = "1.10.0"
rowan = "=0.15.15"
-salsa = { version = "0.21.1", default-features = false, features = [
- "rayon",
- "salsa_unstable",
-] }
-salsa-macros = "0.21.1"
+salsa = { version = "0.22.0", default-features = false, features = ["rayon","salsa_unstable"] }
+salsa-macros = "0.22.0"
semver = "1.0.26"
serde = { version = "1.0.219" }
serde_derive = { version = "1.0.219" }
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index d42d7e5707d3..745238167bc1 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -395,21 +395,21 @@ impl BuiltDependency {
pub type CratesIdMap = FxHashMap;
#[salsa_macros::input]
-#[derive(Debug)]
+#[derive(Debug, PartialOrd, Ord)]
pub struct Crate {
- #[return_ref]
+ #[returns(ref)]
pub data: BuiltCrateData,
/// Crate data that is not needed for analysis.
///
/// This is split into a separate field to increase incrementality.
- #[return_ref]
+ #[returns(ref)]
pub extra_data: ExtraCrateData,
// This is in `Arc` because it is shared for all crates in a workspace.
- #[return_ref]
+ #[returns(ref)]
pub workspace_data: Arc,
- #[return_ref]
+ #[returns(ref)]
pub cfg_options: CfgOptions,
- #[return_ref]
+ #[returns(ref)]
pub env: Env,
}
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index a67fbf75c02f..4d4e6cae0373 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -32,6 +32,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}
macro_rules! impl_intern_key {
($id:ident, $loc:ident) => {
#[salsa_macros::interned(no_lifetime)]
+ #[derive(PartialOrd, Ord)]
pub struct $id {
pub loc: $loc,
}
@@ -165,6 +166,7 @@ impl Files {
}
#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)]
+#[derive(PartialOrd, Ord)]
pub struct EditionedFileId {
pub editioned_file_id: span::EditionedFileId,
}
@@ -356,7 +358,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse Option<&[SyntaxError]> {
- #[salsa_macros::tracked(return_ref)]
+ #[salsa_macros::tracked(returns(ref))]
fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option> {
let errors = db.parse(file_id).errors();
match &*errors {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 59344641f47a..4ad44775ea14 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -85,7 +85,7 @@ impl LangItemTarget {
}
/// Salsa query. This will look for lang items in a specific crate.
-#[salsa_macros::tracked(return_ref)]
+#[salsa_macros::tracked(returns(ref))]
pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option> {
let _p = tracing::info_span!("crate_lang_items_query").entered();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 3027aff3163a..293868df613a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -509,24 +509,6 @@ fn main() { "s"; }
);
}
-#[test]
-fn test_concat_idents_expand() {
- check(
- r##"
-#[rustc_builtin_macro]
-macro_rules! concat_idents {}
-
-fn main() { concat_idents!(foo, bar); }
-"##,
- expect![[r##"
-#[rustc_builtin_macro]
-macro_rules! concat_idents {}
-
-fn main() { foobar; }
-"##]],
- );
-}
-
#[test]
fn test_quote_string() {
check(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index d4b30a1d3e68..f337f83156a9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -381,15 +381,15 @@ mod __ {
#[salsa_macros::tracked]
pub(crate) struct DefMapPair<'db> {
#[tracked]
- #[return_ref]
+ #[returns(ref)]
pub(crate) def_map: DefMap,
- #[return_ref]
+ #[returns(ref)]
pub(crate) local: LocalDefMap,
}
}
pub(crate) use __::DefMapPair;
-#[salsa_macros::tracked(return_ref)]
+#[salsa_macros::tracked(returns(ref))]
pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefMapPair<'_> {
let krate = crate_id.data(db);
let _p = tracing::info_span!(
@@ -420,7 +420,7 @@ pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefM
DefMapPair::new(db, def_map, local_def_map)
}
-#[salsa_macros::tracked(return_ref)]
+#[salsa_macros::tracked(returns(ref))]
pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
let BlockLoc { ast_id, module } = block_id.lookup(db);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
index d45709b8b903..86225d33b4e1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
@@ -75,7 +75,7 @@ impl TraitItems {
})
}
- pub fn attribute_calls(&self) -> impl Iterator
- , MacroCallId)> + '_ {
+ pub fn macro_calls(&self) -> impl Iterator
- , MacroCallId)> + '_ {
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
}
}
@@ -109,7 +109,7 @@ impl ImplItems {
(Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics))
}
- pub fn attribute_calls(&self) -> impl Iterator
- , MacroCallId)> + '_ {
+ pub fn macro_calls(&self) -> impl Iterator
- , MacroCallId)> + '_ {
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index 6c995ab6c23f..e30a5b65a1f7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -30,9 +30,18 @@ pub(crate) struct TestDB {
impl Default for TestDB {
fn default() -> Self {
+ let events = >>>>::default();
let mut this = Self {
- storage: Default::default(),
- events: Default::default(),
+ storage: salsa::Storage::new(Some(Box::new({
+ let events = events.clone();
+ move |event| {
+ let mut events = events.lock().unwrap();
+ if let Some(events) = &mut *events {
+ events.push(event);
+ }
+ }
+ }))),
+ events,
files: Default::default(),
crates_map: Default::default(),
};
@@ -45,15 +54,7 @@ impl Default for TestDB {
}
#[salsa_macros::db]
-impl salsa::Database for TestDB {
- fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) {
- let mut events = self.events.lock().unwrap();
- if let Some(events) = &mut *events {
- let event = event();
- events.push(event);
- }
- }
-}
+impl salsa::Database for TestDB {}
impl fmt::Debug for TestDB {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 539c72772843..3180b8dae10e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -140,7 +140,6 @@ register_builtin! {
EagerExpander:
(compile_error, CompileError) => compile_error_expand,
(concat, Concat) => concat_expand,
- (concat_idents, ConcatIdents) => concat_idents_expand,
(concat_bytes, ConcatBytes) => concat_bytes_expand,
(include, Include) => include_expand,
(include_bytes, IncludeBytes) => include_bytes_expand,
@@ -660,30 +659,6 @@ fn concat_bytes_expand_subtree(
Ok(())
}
-fn concat_idents_expand(
- _db: &dyn ExpandDatabase,
- _arg_id: MacroCallId,
- tt: &tt::TopSubtree,
- span: Span,
-) -> ExpandResult {
- let mut err = None;
- let mut ident = String::new();
- for (i, t) in tt.iter().enumerate() {
- match t {
- TtElement::Leaf(tt::Leaf::Ident(id)) => {
- ident.push_str(id.sym.as_str());
- }
- TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
- _ => {
- err.get_or_insert(ExpandError::other(span, "unexpected token"));
- }
- }
- }
- // FIXME merge spans
- let ident = tt::Ident { sym: Symbol::intern(&ident), span, is_raw: tt::IdentIsRaw::No };
- ExpandResult { value: quote!(span =>#ident), err }
-}
-
fn relative_file(
db: &dyn ExpandDatabase,
call_id: MacroCallId,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index cd799c03ddf7..22b96b55cbb9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -259,7 +259,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> {
}
fn well_known_trait_id(
&self,
- well_known_trait: rust_ir::WellKnownTrait,
+ well_known_trait: WellKnownTrait,
) -> Option> {
let lang_attr = lang_item_from_well_known_trait(well_known_trait);
let trait_ = lang_attr.resolve_trait(self.db, self.krate)?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index e4a23cbbacff..9eb7ffe1c719 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -25,7 +25,7 @@ use triomphe::Arc;
use typed_arena::Arena;
use crate::{
- Adjust, InferenceResult, Interner, Ty, TyExt, TyKind,
+ Adjust, InferenceResult, Interner, TraitEnvironment, Ty, TyExt, TyKind,
db::HirDatabase,
diagnostics::match_check::{
self,
@@ -74,8 +74,9 @@ impl BodyValidationDiagnostic {
let _p = tracing::info_span!("BodyValidationDiagnostic::collect").entered();
let infer = db.infer(owner);
let body = db.body(owner);
+ let env = db.trait_environment_for_body(owner);
let mut validator =
- ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints };
+ ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints, env };
validator.validate_body(db);
validator.diagnostics
}
@@ -85,6 +86,7 @@ struct ExprValidator {
owner: DefWithBodyId,
body: Arc,
infer: Arc,
+ env: Arc,
diagnostics: Vec,
validate_lints: bool,
}
@@ -190,7 +192,7 @@ impl ExprValidator {
return;
}
- let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db);
+ let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db, self.env.clone());
let pattern_arena = Arena::new();
let mut m_arms = Vec::with_capacity(arms.len());
@@ -317,11 +319,14 @@ impl ExprValidator {
return;
};
let pattern_arena = Arena::new();
- let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db);
+ let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db, self.env.clone());
for stmt in &**statements {
let &Statement::Let { pat, initializer, else_branch: None, .. } = stmt else {
continue;
};
+ if self.infer.type_mismatch_for_pat(pat).is_some() {
+ continue;
+ }
let Some(initializer) = initializer else { continue };
let ty = &self.infer[initializer];
if ty.contains_unknown() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 785277d70c64..dd82a0f45ca4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -12,9 +12,10 @@ use rustc_pattern_analysis::{
};
use smallvec::{SmallVec, smallvec};
use stdx::never;
+use triomphe::Arc;
use crate::{
- AdtId, Interner, Scalar, Ty, TyExt, TyKind,
+ AdtId, Interner, Scalar, TraitEnvironment, Ty, TyExt, TyKind,
db::HirDatabase,
infer::normalize,
inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
@@ -69,13 +70,19 @@ pub(crate) struct MatchCheckCtx<'db> {
body: DefWithBodyId,
pub(crate) db: &'db dyn HirDatabase,
exhaustive_patterns: bool,
+ env: Arc,
}
impl<'db> MatchCheckCtx<'db> {
- pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self {
+ pub(crate) fn new(
+ module: ModuleId,
+ body: DefWithBodyId,
+ db: &'db dyn HirDatabase,
+ env: Arc,
+ ) -> Self {
let def_map = module.crate_def_map(db);
let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
- Self { module, body, db, exhaustive_patterns }
+ Self { module, body, db, exhaustive_patterns, env }
}
pub(crate) fn compute_match_usefulness(
@@ -100,7 +107,7 @@ impl<'db> MatchCheckCtx<'db> {
}
fn is_uninhabited(&self, ty: &Ty) -> bool {
- is_ty_uninhabited_from(self.db, ty, self.module)
+ is_ty_uninhabited_from(self.db, ty, self.module, self.env.clone())
}
/// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`.
@@ -459,8 +466,13 @@ impl PatCx for MatchCheckCtx<'_> {
} else {
let mut variants = IndexVec::with_capacity(enum_data.variants.len());
for &(variant, _) in enum_data.variants.iter() {
- let is_uninhabited =
- is_enum_variant_uninhabited_from(cx.db, variant, subst, cx.module);
+ let is_uninhabited = is_enum_variant_uninhabited_from(
+ cx.db,
+ variant,
+ subst,
+ cx.module,
+ self.env.clone(),
+ );
let visibility = if is_uninhabited {
VariantVisibility::Empty
} else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index f0989d9de91f..f210dd8799f9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1463,6 +1463,8 @@ impl HirDisplay for Ty {
}
if f.closure_style == ClosureStyle::RANotation || !sig.ret().is_unit() {
write!(f, " -> ")?;
+ // FIXME: We display `AsyncFn` as `-> impl Future`, but this is hard to fix because
+ // we don't have a trait environment here, required to normalize `::Output`.
sig.ret().hir_fmt(f)?;
}
} else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 800897c6fc3a..bd57ca891620 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -38,7 +38,7 @@ use crate::{
infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever},
make_binders,
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
- to_chalk_trait_id,
+ to_assoc_type_id, to_chalk_trait_id,
traits::FnTrait,
utils::{self, elaborate_clause_supertraits},
};
@@ -245,7 +245,7 @@ impl InferenceContext<'_> {
}
fn deduce_closure_kind_from_predicate_clauses(
- &self,
+ &mut self,
expected_ty: &Ty,
clauses: impl DoubleEndedIterator
- ,
closure_kind: ClosureKind,
@@ -378,7 +378,7 @@ impl InferenceContext<'_> {
}
fn deduce_sig_from_projection(
- &self,
+ &mut self,
closure_kind: ClosureKind,
projection_ty: &ProjectionTy,
projected_ty: &Ty,
@@ -392,13 +392,16 @@ impl InferenceContext<'_> {
// For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
// for closures and async closures, respectively.
- match closure_kind {
- ClosureKind::Closure | ClosureKind::Async
- if self.fn_trait_kind_from_trait_id(trait_).is_some() =>
- {
- self.extract_sig_from_projection(projection_ty, projected_ty)
- }
- _ => None,
+ let fn_trait_kind = self.fn_trait_kind_from_trait_id(trait_)?;
+ if !matches!(closure_kind, ClosureKind::Closure | ClosureKind::Async) {
+ return None;
+ }
+ if fn_trait_kind.is_async() {
+ // If the expected trait is `AsyncFn(...) -> X`, we don't know what the return type is,
+ // but we do know it must implement `Future