Rollup merge of #144150 - Gelbpunkt:globalmerge, r=Mark-Simulacrum
tests: assembly: cstring-merging: Disable GlobalMerge pass
The test relies on LLVM not merging all the globals into one and would currently otherwise fail on powerpc64le.
See https://github.com/llvm/llvm-project/blob/release/20.x/llvm/lib/CodeGen/GlobalMerge.cpp and here's the assembly generated prior to disabling the pass:
<details>
<summary>Expand me</summary>
```asm
.abiversion 2
.file "cstring_merging.5aa81ea7b99b31fe-cgu.0"
.section .text.cstr,"ax",``@progbits``
.globl cstr
.p2align 4
.type cstr,``@function``
cstr:
.Lfunc_begin0:
.cfi_startproc
.Lfunc_gep0:
addis 2, 12, .TOC.-.Lfunc_gep0@ha
addi 2, 2, .TOC.-.Lfunc_gep0@l
.Lfunc_lep0:
.localentry cstr, .Lfunc_lep0-.Lfunc_gep0
addis 3, 2, .L_MergedGlobals@toc@ha
li 4, 4
addi 3, 3, .L_MergedGlobals@toc@l
addi 3, 3, 4
blr
.long 0
.quad 0
.Lfunc_end0:
.size cstr, .Lfunc_end0-.Lfunc_begin0
.cfi_endproc
.section .text.manual_cstr,"ax",``@progbits``
.globl manual_cstr
.p2align 4
.type manual_cstr,``@function``
manual_cstr:
.Lfunc_begin1:
.cfi_startproc
.Lfunc_gep1:
addis 2, 12, .TOC.-.Lfunc_gep1@ha
addi 2, 2, .TOC.-.Lfunc_gep1@l
.Lfunc_lep1:
.localentry manual_cstr, .Lfunc_lep1-.Lfunc_gep1
addis 3, 2, .L_MergedGlobals@toc@ha
li 4, 4
addi 3, 3, .L_MergedGlobals@toc@l
addi 3, 3, 8
blr
.long 0
.quad 0
.Lfunc_end1:
.size manual_cstr, .Lfunc_end1-.Lfunc_begin1
.cfi_endproc
.type CSTR,``@object``
.section .data.rel.ro.CSTR,"aw",``@progbits``
.globl CSTR
.p2align 3, 0x0
CSTR:
.quad .L_MergedGlobals
.size CSTR, 8
.type .L_MergedGlobals,``@object``
.section .rodata..L_MergedGlobals,"a",``@progbits``
.L_MergedGlobals:
.asciz "foo"
.asciz "bar"
.asciz "baz"
.size .L_MergedGlobals, 12
.set .Lanon.a643e9a6bba67b7953be2b5f96e0e802.0, .L_MergedGlobals
.size .Lanon.a643e9a6bba67b7953be2b5f96e0e802.0, 4
.set .Lanon.a643e9a6bba67b7953be2b5f96e0e802.1, .L_MergedGlobals+4
.size .Lanon.a643e9a6bba67b7953be2b5f96e0e802.1, 4
.set .Lanon.a643e9a6bba67b7953be2b5f96e0e802.2, .L_MergedGlobals+8
.size .Lanon.a643e9a6bba67b7953be2b5f96e0e802.2, 4
.ident "rustc version 1.90.0-dev"
.section ".note.GNU-stack","",``@progbits``
```
</details>
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dc8ac53..e92afc1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -182,11 +182,6 @@
- name: install MinGW
run: src/ci/scripts/install-mingw.sh
- # Workaround for spurious ci failures after mingw install
- # see https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/Spurious.20bors.20CI.20failures/near/528915775
- - name: ensure home dir exists
- run: mkdir -p ~
-
- name: install ninja
run: src/ci/scripts/install-ninja.sh
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index de4b5a4..5bd7350 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -43,7 +43,7 @@
#[cfg(feature = "nightly")]
use std::iter::Step;
use std::num::{NonZeroUsize, ParseIntError};
-use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
+use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
use std::str::FromStr;
use bitflags::bitflags;
@@ -1391,12 +1391,45 @@ fn with_end(mut self, end: u128) -> Self {
}
/// Returns `true` if `size` completely fills the range.
+ ///
+ /// Note that this is *not* the same as `self == WrappingRange::full(size)`.
+ /// Niche calculations can produce full ranges which are not the canonical one;
+ /// for example `Option<NonZero<u16>>` gets `valid_range: (..=0) | (1..)`.
#[inline]
fn is_full_for(&self, size: Size) -> bool {
let max_value = size.unsigned_int_max();
debug_assert!(self.start <= max_value && self.end <= max_value);
self.start == (self.end.wrapping_add(1) & max_value)
}
+
+ /// Checks whether this range is considered non-wrapping when the values are
+ /// interpreted as *unsigned* numbers of width `size`.
+ ///
+ /// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
+ /// and `Err(..)` if the range is full so it depends how you think about it.
+ #[inline]
+ pub fn no_unsigned_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
+ if self.is_full_for(size) { Err(..) } else { Ok(self.start <= self.end) }
+ }
+
+ /// Checks whether this range is considered non-wrapping when the values are
+ /// interpreted as *signed* numbers of width `size`.
+ ///
+ /// This is heavily dependent on the `size`, as `100..=200` does wrap when
+ /// interpreted as `i8`, but doesn't when interpreted as `i16`.
+ ///
+ /// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
+ /// and `Err(..)` if the range is full so it depends how you think about it.
+ #[inline]
+ pub fn no_signed_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
+ if self.is_full_for(size) {
+ Err(..)
+ } else {
+ let start: i128 = size.sign_extend(self.start);
+ let end: i128 = size.sign_extend(self.end);
+ Ok(start <= end)
+ }
+ }
}
impl fmt::Debug for WrappingRange {
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index c6472fd4..370b15d 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -127,9 +127,6 @@
`impl Trait` is not allowed in {$position}
.note = `impl Trait` is only allowed in arguments and return types of functions and methods
-ast_lowering_misplaced_relax_trait_bound =
- `?Trait` bounds are only permitted at the point where a type parameter is declared
-
ast_lowering_never_pattern_with_body =
a never pattern is always unreachable
.label = this will never be executed
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index b444324..83f3a97 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -325,13 +325,6 @@ pub(crate) struct MisplacedDoubleDot {
}
#[derive(Diagnostic)]
-#[diag(ast_lowering_misplaced_relax_trait_bound)]
-pub(crate) struct MisplacedRelaxTraitBound {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(ast_lowering_match_arm_with_no_body)]
pub(crate) struct MatchArmWithNoBody {
#[primary_span]
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index abd70c7..ddf01b6 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -16,14 +16,11 @@
use thin_vec::ThinVec;
use tracing::instrument;
-use super::errors::{
- InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
- UnionWithDefault,
-};
+use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
use super::stability::{enabled_names, gate_unstable_abi};
use super::{
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
- ResolverAstLoweringExt,
+ RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
};
pub(super) struct ItemLowerer<'a, 'hir> {
@@ -435,6 +432,7 @@ fn lower_item_kind(
|this| {
let bounds = this.lower_param_bounds(
bounds,
+ RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
);
let items = this.arena.alloc_from_iter(
@@ -455,6 +453,7 @@ fn lower_item_kind(
|this| {
this.lower_param_bounds(
bounds,
+ RelaxedBoundPolicy::Allowed,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
)
},
@@ -940,6 +939,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
hir::TraitItemKind::Type(
this.lower_param_bounds(
bounds,
+ RelaxedBoundPolicy::Allowed,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
),
ty,
@@ -1677,61 +1677,6 @@ fn lower_generics<T>(
assert!(self.impl_trait_defs.is_empty());
assert!(self.impl_trait_bounds.is_empty());
- // Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
- // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
- // these into hir when we lower thee where clauses), but this makes it quite difficult to
- // keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
- // checks both param bounds and where clauses for `?Sized`.
- for pred in &generics.where_clause.predicates {
- let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else {
- continue;
- };
- let compute_is_param = || {
- // Check if the where clause type is a plain type parameter.
- match self
- .resolver
- .get_partial_res(bound_pred.bounded_ty.id)
- .and_then(|r| r.full_res())
- {
- Some(Res::Def(DefKind::TyParam, def_id))
- if bound_pred.bound_generic_params.is_empty() =>
- {
- generics
- .params
- .iter()
- .any(|p| def_id == self.local_def_id(p.id).to_def_id())
- }
- // Either the `bounded_ty` is not a plain type parameter, or
- // it's not found in the generic type parameters list.
- _ => false,
- }
- };
- // We only need to compute this once per `WherePredicate`, but don't
- // need to compute this at all unless there is a Maybe bound.
- let mut is_param: Option<bool> = None;
- for bound in &bound_pred.bounds {
- if !matches!(
- *bound,
- GenericBound::Trait(PolyTraitRef {
- modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
- ..
- })
- ) {
- continue;
- }
- let is_param = *is_param.get_or_insert_with(compute_is_param);
- if !is_param && !self.tcx.features().more_maybe_bounds() {
- self.tcx
- .sess
- .create_feature_err(
- MisplacedRelaxTraitBound { span: bound.span() },
- sym::more_maybe_bounds,
- )
- .emit();
- }
- }
- }
-
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| {
self.lower_generic_bound_predicate(
@@ -1741,6 +1686,7 @@ fn lower_generics<T>(
¶m.bounds,
param.colon_span,
generics.span,
+ RelaxedBoundPolicy::Allowed,
itctx,
PredicateOrigin::GenericParam,
)
@@ -1750,7 +1696,7 @@ fn lower_generics<T>(
.where_clause
.predicates
.iter()
- .map(|predicate| self.lower_where_predicate(predicate)),
+ .map(|predicate| self.lower_where_predicate(predicate, &generics.params)),
);
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
@@ -1827,6 +1773,7 @@ pub(super) fn lower_generic_bound_predicate(
bounds: &[GenericBound],
colon_span: Option<Span>,
parent_span: Span,
+ rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
origin: PredicateOrigin,
) -> Option<hir::WherePredicate<'hir>> {
@@ -1835,7 +1782,7 @@ pub(super) fn lower_generic_bound_predicate(
return None;
}
- let bounds = self.lower_param_bounds(bounds, itctx);
+ let bounds = self.lower_param_bounds(bounds, rbp, itctx);
let param_span = ident.span;
@@ -1887,7 +1834,11 @@ pub(super) fn lower_generic_bound_predicate(
Some(hir::WherePredicate { hir_id, span, kind })
}
- fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
+ fn lower_where_predicate(
+ &mut self,
+ pred: &WherePredicate,
+ params: &[ast::GenericParam],
+ ) -> hir::WherePredicate<'hir> {
let hir_id = self.lower_node_id(pred.id);
let span = self.lower_span(pred.span);
self.lower_attrs(hir_id, &pred.attrs, span);
@@ -1896,17 +1847,29 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
bound_generic_params,
bounded_ty,
bounds,
- }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
- bound_generic_params: self
- .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
- bounded_ty: self
- .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
- bounds: self.lower_param_bounds(
- bounds,
- ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
- ),
- origin: PredicateOrigin::WhereClause,
- }),
+ }) => {
+ let rbp = if bound_generic_params.is_empty() {
+ RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params)
+ } else {
+ RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope)
+ };
+ hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
+ bound_generic_params: self.lower_generic_params(
+ bound_generic_params,
+ hir::GenericParamSource::Binder,
+ ),
+ bounded_ty: self.lower_ty(
+ bounded_ty,
+ ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+ ),
+ bounds: self.lower_param_bounds(
+ bounds,
+ rbp,
+ ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+ ),
+ origin: PredicateOrigin::WhereClause,
+ })
+ }
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
lifetime: self.lower_lifetime(
@@ -1916,6 +1879,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
),
bounds: self.lower_param_bounds(
bounds,
+ RelaxedBoundPolicy::Allowed,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
in_where_clause: true,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 1c96a37..533ee9b 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -53,8 +53,8 @@
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::lints::DelayedLint;
use rustc_hir::{
- self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
- LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
+ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
+ LifetimeSyntax, ParamName, TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@@ -281,6 +281,24 @@ fn extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeR
}
}
+/// How relaxed bounds `?Trait` should be treated.
+///
+/// Relaxed bounds should only be allowed in places where we later
+/// (namely during HIR ty lowering) perform *sized elaboration*.
+#[derive(Clone, Copy, Debug)]
+enum RelaxedBoundPolicy<'a> {
+ Allowed,
+ AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]),
+ Forbidden(RelaxedBoundForbiddenReason),
+}
+
+#[derive(Clone, Copy, Debug)]
+enum RelaxedBoundForbiddenReason {
+ TraitObjectTy,
+ SuperTrait,
+ LateBoundVarsInScope,
+}
+
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
/// and if so, what meaning it has.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -1084,10 +1102,9 @@ fn lower_assoc_item_constraint(
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
} else {
- // Desugar `AssocTy: Bounds` into an assoc type binding where the
- // later desugars into a trait predicate.
- let bounds = self.lower_param_bounds(bounds, itctx);
-
+ // FIXME(#135229): These should be forbidden!
+ let bounds =
+ self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx);
hir::AssocItemConstraintKind::Bound { bounds }
}
}
@@ -1216,6 +1233,7 @@ fn lower_path_ty(
span: t.span,
parens: ast::Parens::No,
},
+ RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),
itctx,
);
let bounds = this.arena.alloc_from_iter([bound]);
@@ -1271,7 +1289,7 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
parenthesized: hir::GenericArgsParentheses::No,
span_ext: span,
});
- let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
+ let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args));
hir::TyKind::Path(path)
}
TyKind::FnPtr(f) => {
@@ -1332,7 +1350,13 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
// takes care of rejecting invalid modifier combinations and
// const trait bounds in trait object types.
GenericBound::Trait(ty) => {
- let trait_ref = this.lower_poly_trait_ref(ty, itctx);
+ let trait_ref = this.lower_poly_trait_ref(
+ ty,
+ RelaxedBoundPolicy::Forbidden(
+ RelaxedBoundForbiddenReason::TraitObjectTy,
+ ),
+ itctx,
+ );
Some(trait_ref)
}
GenericBound::Outlives(lifetime) => {
@@ -1387,9 +1411,9 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
}
path
}
- ImplTraitContext::InBinding => {
- hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
- }
+ ImplTraitContext::InBinding => hir::TyKind::TraitAscription(
+ self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx),
+ ),
ImplTraitContext::FeatureGated(position, feature) => {
let guar = self
.tcx
@@ -1505,7 +1529,7 @@ fn lower_opaque_impl_trait(
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
- this.lower_param_bounds(bounds, itctx)
+ this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx)
})
}
@@ -1799,10 +1823,13 @@ fn lower_coroutine_fn_output_type_to_bound(
fn lower_param_bound(
&mut self,
tpb: &GenericBound,
+ rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> hir::GenericBound<'hir> {
match tpb {
- GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
+ GenericBound::Trait(p) => {
+ hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx))
+ }
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
lifetime,
LifetimeSource::OutlivesBound,
@@ -2017,21 +2044,93 @@ fn lower_trait_ref(
#[instrument(level = "debug", skip(self))]
fn lower_poly_trait_ref(
&mut self,
- p: &PolyTraitRef,
+ PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef,
+ rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
- self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
- let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
- let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
+ self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params);
+ let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx);
+ let modifiers = self.lower_trait_bound_modifiers(*modifiers);
+
+ if let ast::BoundPolarity::Maybe(_) = modifiers.polarity {
+ self.validate_relaxed_bound(trait_ref, *span, rbp);
+ }
+
hir::PolyTraitRef {
bound_generic_params,
modifiers,
trait_ref,
- span: self.lower_span(p.span),
+ span: self.lower_span(*span),
}
}
+ fn validate_relaxed_bound(
+ &self,
+ trait_ref: hir::TraitRef<'_>,
+ span: Span,
+ rbp: RelaxedBoundPolicy<'_>,
+ ) {
+ // Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
+ // relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
+ // (via a feature gate) since it's super internal. Besides this, it'd be quite distracting.
+ //
+ // [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
+ // no longer fully consistent with default trait elaboration in HIR ty lowering.
+
+ match rbp {
+ RelaxedBoundPolicy::Allowed => return,
+ RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => {
+ if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
+ && let Res::Def(DefKind::TyParam, def_id) = res
+ && params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
+ {
+ return;
+ }
+ if self.tcx.features().more_maybe_bounds() {
+ return;
+ }
+ }
+ RelaxedBoundPolicy::Forbidden(reason) => {
+ if self.tcx.features().more_maybe_bounds() {
+ return;
+ }
+
+ match reason {
+ RelaxedBoundForbiddenReason::TraitObjectTy => {
+ self.dcx().span_err(
+ span,
+ "relaxed bounds are not permitted in trait object types",
+ );
+ return;
+ }
+ RelaxedBoundForbiddenReason::SuperTrait => {
+ let mut diag = self.dcx().struct_span_err(
+ span,
+ "relaxed bounds are not permitted in supertrait bounds",
+ );
+ if let Some(def_id) = trait_ref.trait_def_id()
+ && self.tcx.is_lang_item(def_id, hir::LangItem::Sized)
+ {
+ diag.note("traits are `?Sized` by default");
+ }
+ diag.emit();
+ return;
+ }
+ RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
+ };
+ }
+ }
+
+ self.dcx()
+ .struct_span_err(span, "this relaxed bound is not permitted here")
+ .with_note(
+ "in this context, relaxed bounds are only allowed on \
+ type parameters defined by the closest item",
+ )
+ .emit();
+ }
+
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
}
@@ -2040,17 +2139,19 @@ fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir>
fn lower_param_bounds(
&mut self,
bounds: &[GenericBound],
+ rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> hir::GenericBounds<'hir> {
- self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
+ self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx))
}
fn lower_param_bounds_mut(
&mut self,
bounds: &[GenericBound],
+ rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> impl Iterator<Item = hir::GenericBound<'hir>> {
- bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
+ bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx))
}
#[instrument(level = "debug", skip(self), ret)]
@@ -2084,6 +2185,7 @@ fn lower_universal_param_and_bounds(
bounds,
/* colon_span */ None,
span,
+ RelaxedBoundPolicy::Allowed,
ImplTraitContext::Universal,
hir::PredicateOrigin::ImplTrait,
);
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index e419154..af93d55 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -212,11 +212,6 @@
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
.help = use `auto trait Trait {"{}"}` instead
-ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
-
-ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
- .note = traits are `?{$path_str}` by default
-
ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
.suggestion = reorder the parameters: lifetimes, then consts and types
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index c69250c..a08dae1 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1381,29 +1381,6 @@ fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
match bound {
GenericBound::Trait(trait_ref) => {
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
- (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
- if !self.features.more_maybe_bounds() =>
- {
- self.sess
- .create_feature_err(
- errors::OptionalTraitSupertrait {
- span: trait_ref.span,
- path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
- },
- sym::more_maybe_bounds,
- )
- .emit();
- }
- (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
- if !self.features.more_maybe_bounds() =>
- {
- self.sess
- .create_feature_err(
- errors::OptionalTraitObject { span: trait_ref.span },
- sym::more_maybe_bounds,
- )
- .emit();
- }
(
BoundKind::TraitObject,
BoundConstness::Always(_),
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index c1ebd02..fd4b252 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -567,22 +567,6 @@ pub(crate) struct NestedLifetimes {
}
#[derive(Diagnostic)]
-#[diag(ast_passes_optional_trait_supertrait)]
-#[note]
-pub(crate) struct OptionalTraitSupertrait {
- #[primary_span]
- pub span: Span,
- pub path_str: String,
-}
-
-#[derive(Diagnostic)]
-#[diag(ast_passes_optional_trait_object)]
-pub(crate) struct OptionalTraitObject {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(ast_passes_const_bound_trait_object)]
pub(crate) struct ConstBoundTraitObject {
#[primary_span]
diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
index 8a3eb2a..86d9ddb 100644
--- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
+++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
@@ -41,9 +41,9 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
Fundamental { .. } => Yes,
Ignore { .. } => No,
Inline(..) => No,
- LinkName { .. } => Yes,
+ LinkName { .. } => Yes, // Needed for rustdoc
LinkOrdinal { .. } => No,
- LinkSection { .. } => No,
+ LinkSection { .. } => Yes, // Needed for rustdoc
LoopMatch(..) => No,
MacroTransparency(..) => Yes,
Marker(..) => No,
@@ -51,8 +51,8 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
MustUse { .. } => Yes,
Naked(..) => No,
NoImplicitPrelude(..) => No,
- NoMangle(..) => No,
- NonExhaustive(..) => Yes,
+ NoMangle(..) => Yes, // Needed for rustdoc
+ NonExhaustive(..) => Yes, // Needed for rustdoc
OmitGdbPrettyPrinterSection => No,
Optimize(..) => No,
ParenSugar(..) => No,
diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs
index 8f8ce57..ecca0e3 100644
--- a/compiler/rustc_attr_data_structures/src/lib.rs
+++ b/compiler/rustc_attr_data_structures/src/lib.rs
@@ -24,7 +24,7 @@
use rustc_ast::{AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
use rustc_span::hygiene::Transparency;
-use rustc_span::{Span, Symbol};
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
pub use stability::*;
use thin_vec::ThinVec;
pub use version::*;
@@ -170,7 +170,7 @@ fn print_attribute(&self, p: &mut Printer) {
}
print_tup!(A B C D E F G H);
-print_skip!(Span, ());
+print_skip!(Span, (), ErrorGuaranteed);
print_disp!(u16, bool, NonZero<u32>);
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
diff --git a/compiler/rustc_attr_data_structures/src/stability.rs b/compiler/rustc_attr_data_structures/src/stability.rs
index 218e771..bd31c06 100644
--- a/compiler/rustc_attr_data_structures/src/stability.rs
+++ b/compiler/rustc_attr_data_structures/src/stability.rs
@@ -1,7 +1,7 @@
use std::num::NonZero;
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
-use rustc_span::{Symbol, sym};
+use rustc_span::{ErrorGuaranteed, Symbol, sym};
use crate::{PrintAttribute, RustcVersion};
@@ -153,7 +153,7 @@ pub enum StableSince {
/// Stabilized in the upcoming version, whatever number that is.
Current,
/// Failed to parse a stabilization version.
- Err,
+ Err(ErrorGuaranteed),
}
impl StabilityLevel {
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index 8f405e5..5933774 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -292,12 +292,12 @@ pub(crate) fn parse_stability<S: Stage>(
} else if let Some(version) = parse_version(since) {
StableSince::Version(version)
} else {
- cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
- StableSince::Err
+ let err = cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
+ StableSince::Err(err)
}
} else {
- cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
- StableSince::Err
+ let err = cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
+ StableSince::Err(err)
};
match feature {
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
index 245bee7..759d0d5 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -14,8 +14,6 @@
env:
# Enable backtraces for easier debugging
RUST_BACKTRACE: 1
- # TODO: remove when confish.sh is removed.
- OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
jobs:
build:
@@ -59,14 +57,12 @@
- name: Setup path to libgccjit
run: |
- sudo dpkg -i gcc-m68k-15.deb
+ sudo dpkg --force-overwrite -i gcc-m68k-15.deb
echo 'gcc-path = "/usr/lib/"' > config.toml
- name: Set env
run: |
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
-
-
#- name: Cache rust repository
## We only clone the rust repository for rustc tests
@@ -86,16 +82,20 @@
- name: Build sample project with target defined as JSON spec
run: |
./y.sh prepare --only-libcore --cross
- ./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
- ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
+ ./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
+ CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
./y.sh clean all
- name: Build
run: |
./y.sh prepare --only-libcore --cross
- ./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
- ./y.sh test --mini-tests
- CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests
+ ./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
+ ./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
+ # FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
+ # supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
+ # And as such, a wrong order of the object files in the linker command now fails with an undefined reference
+ # to some symbols like __rustc::rust_panic.
+ #CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
./y.sh clean all
- name: Prepare dependencies
@@ -104,9 +104,23 @@
git config --global user.name "User"
./y.sh prepare --cross
- - name: Run tests
- run: |
- ./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
+ # FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
+ #- name: Run tests
+ #run: |
+ #./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
+
+ # FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
+ #- name: Run Hello World!
+ #run: |
+ #./y.sh build --target-triple m68k-unknown-linux-gnu
+
+ #vm_dir=$(pwd)/vm
+ #cd tests/hello-world
+ #CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
+ #sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
+ #sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
+ #expected_output="40"
+ #test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
index 1d8eaf9..b7e2583 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
@@ -78,7 +78,8 @@
- name: Run tests
run: |
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
- echo -n 'lto = "fat"' >> build_system/build_sysroot/Cargo.toml
+ # FIXME(antoyo): this should probably not be needed since we embed the LTO bitcode.
+ printf '[profile.release]\nlto = "fat"\n' >> build/build_sysroot/sysroot_src/library/Cargo.toml
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
- name: Run y.sh cargo build
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock
deleted file mode 100644
index 0c75977..0000000
--- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock
+++ /dev/null
@@ -1,502 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "addr2line"
-version = "0.24.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
-dependencies = [
- "compiler_builtins",
- "gimli",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "adler2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "alloc"
-version = "0.0.0"
-dependencies = [
- "compiler_builtins",
- "core",
-]
-
-[[package]]
-name = "alloctests"
-version = "0.0.0"
-dependencies = [
- "rand",
- "rand_xorshift",
-]
-
-[[package]]
-name = "cc"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
-dependencies = [
- "shlex",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "compiler_builtins"
-version = "0.1.160"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6376049cfa92c0aa8b9ac95fae22184b981c658208d4ed8a1dc553cd83612895"
-dependencies = [
- "cc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "core"
-version = "0.0.0"
-
-[[package]]
-name = "coretests"
-version = "0.0.0"
-dependencies = [
- "rand",
- "rand_xorshift",
-]
-
-[[package]]
-name = "dlmalloc"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
-dependencies = [
- "cfg-if",
- "compiler_builtins",
- "libc",
- "rustc-std-workspace-core",
- "windows-sys",
-]
-
-[[package]]
-name = "fortanix-sgx-abi"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "getopts"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
-dependencies = [
- "rustc-std-workspace-core",
- "rustc-std-workspace-std",
- "unicode-width",
-]
-
-[[package]]
-name = "gimli"
-version = "0.31.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.172"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
-dependencies = [
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "memchr"
-version = "2.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
-dependencies = [
- "adler2",
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "object"
-version = "0.36.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
-dependencies = [
- "compiler_builtins",
- "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "panic_abort"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "compiler_builtins",
- "core",
- "libc",
-]
-
-[[package]]
-name = "panic_unwind"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "cfg-if",
- "compiler_builtins",
- "core",
- "libc",
- "unwind",
-]
-
-[[package]]
-name = "proc_macro"
-version = "0.0.0"
-dependencies = [
- "core",
- "rustc-literal-escaper",
- "std",
-]
-
-[[package]]
-name = "profiler_builtins"
-version = "0.0.0"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "r-efi"
-version = "5.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "r-efi-alloc"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e43c53ff1a01d423d1cb762fd991de07d32965ff0ca2e4f80444ac7804198203"
-dependencies = [
- "compiler_builtins",
- "r-efi",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "rand"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
-
-[[package]]
-name = "rand_xorshift"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "rustc-literal-escaper"
-version = "0.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
-dependencies = [
- "rustc-std-workspace-std",
-]
-
-[[package]]
-name = "rustc-std-workspace-alloc"
-version = "1.99.0"
-dependencies = [
- "alloc",
-]
-
-[[package]]
-name = "rustc-std-workspace-core"
-version = "1.99.0"
-dependencies = [
- "core",
-]
-
-[[package]]
-name = "rustc-std-workspace-std"
-version = "1.99.0"
-dependencies = [
- "std",
-]
-
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "std"
-version = "0.0.0"
-dependencies = [
- "addr2line",
- "alloc",
- "cfg-if",
- "compiler_builtins",
- "core",
- "dlmalloc",
- "fortanix-sgx-abi",
- "hashbrown",
- "hermit-abi",
- "libc",
- "miniz_oxide",
- "object",
- "panic_abort",
- "panic_unwind",
- "r-efi",
- "r-efi-alloc",
- "rand",
- "rand_xorshift",
- "rustc-demangle",
- "std_detect",
- "unwind",
- "wasi",
- "windows-targets 0.0.0",
-]
-
-[[package]]
-name = "std_detect"
-version = "0.1.5"
-dependencies = [
- "cfg-if",
- "compiler_builtins",
- "libc",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "sysroot"
-version = "0.0.0"
-dependencies = [
- "proc_macro",
- "profiler_builtins",
- "std",
- "test",
-]
-
-[[package]]
-name = "test"
-version = "0.0.0"
-dependencies = [
- "core",
- "getopts",
- "libc",
- "std",
-]
-
-[[package]]
-name = "unicode-width"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
- "rustc-std-workspace-std",
-]
-
-[[package]]
-name = "unwind"
-version = "0.0.0"
-dependencies = [
- "cfg-if",
- "compiler_builtins",
- "core",
- "libc",
- "unwinding",
-]
-
-[[package]]
-name = "unwinding"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345"
-dependencies = [
- "compiler_builtins",
- "gimli",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.0.0"
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
deleted file mode 100644
index 29a3bce..0000000
--- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-[package]
-authors = ["rustc_codegen_gcc devs"]
-name = "sysroot"
-version = "0.0.0"
-resolver = "2"
-
-[dependencies]
-core = { path = "./sysroot_src/library/core" }
-compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
-alloc = { path = "./sysroot_src/library/alloc" }
-std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
-test = { path = "./sysroot_src/library/test" }
-proc_macro = { path = "./sysroot_src/library/proc_macro" }
-
-[patch.crates-io]
-rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
-rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
-rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
-compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
-
-# For compiler-builtins we always use a high number of codegen units.
-# The goal here is to place every single intrinsic into its own object
-# file to avoid symbol clashes with the system libgcc if possible. Note
-# that this number doesn't actually produce this many object files, we
-# just don't create more than this number of object files.
-#
-# It's a bit of a bummer that we have to pass this here, unfortunately.
-# Ideally this would be specified through an env var to Cargo so Cargo
-# knows how many CGUs are for this specific crate, but for now
-# per-crate configuration isn't specifiable in the environment.
-[profile.dev.package.compiler_builtins]
-codegen-units = 10000
-
-[profile.release.package.compiler_builtins]
-codegen-units = 10000
-
-[profile.release]
-debug = "limited"
-#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed.
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/lib.rs b/compiler/rustc_codegen_gcc/build_system/build_sysroot/lib.rs
deleted file mode 100644
index 0c9ac1a..0000000
--- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-#![no_std]
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs
index ecc4c1b..94b4031 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/build.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs
@@ -5,7 +5,7 @@
use crate::config::{Channel, ConfigInfo};
use crate::utils::{
- copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
+ create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
};
#[derive(Default)]
@@ -53,11 +53,11 @@ fn usage() {
}
}
-fn cleanup_sysroot_previous_build(start_dir: &Path) {
+fn cleanup_sysroot_previous_build(library_dir: &Path) {
// Cleanup for previous run
// Clean target dir except for build scripts and incremental cache
let _ = walk_dir(
- start_dir.join("target"),
+ library_dir.join("target"),
&mut |dir: &Path| {
for top in &["debug", "release"] {
let _ = fs::remove_dir_all(dir.join(top).join("build"));
@@ -95,31 +95,13 @@ fn cleanup_sysroot_previous_build(start_dir: &Path) {
&mut |_| Ok(()),
false,
);
-
- let _ = fs::remove_file(start_dir.join("Cargo.lock"));
- let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
- let _ = fs::remove_dir_all(start_dir.join("sysroot"));
-}
-
-pub fn create_build_sysroot_content(start_dir: &Path) -> Result<(), String> {
- if !start_dir.is_dir() {
- create_dir(start_dir)?;
- }
- copy_file("build_system/build_sysroot/Cargo.toml", start_dir.join("Cargo.toml"))?;
- copy_file("build_system/build_sysroot/Cargo.lock", start_dir.join("Cargo.lock"))?;
-
- let src_dir = start_dir.join("src");
- if !src_dir.is_dir() {
- create_dir(&src_dir)?;
- }
- copy_file("build_system/build_sysroot/lib.rs", start_dir.join("src/lib.rs"))
}
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
let start_dir = get_sysroot_dir();
- cleanup_sysroot_previous_build(&start_dir);
- create_build_sysroot_content(&start_dir)?;
+ let library_dir = start_dir.join("sysroot_src").join("library");
+ cleanup_sysroot_previous_build(&library_dir);
// Builds libs
let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
@@ -157,9 +139,13 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
rustflags.push_str(&cg_rustflags);
}
+ args.push(&"--features");
+ args.push(&"backtrace");
+
let mut env = env.clone();
env.insert("RUSTFLAGS".to_string(), rustflags);
- run_command_with_output_and_env(&args, Some(&start_dir), Some(&env))?;
+ let sysroot_dir = library_dir.join("sysroot");
+ run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?;
// Copy files to sysroot
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
@@ -169,7 +155,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
};
walk_dir(
- start_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
+ library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
&mut copier.clone(),
&mut copier,
false,
@@ -178,7 +164,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
// Copy the source files to the sysroot (Rust for Linux needs this).
let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
create_dir(&sysroot_src_path)?;
- run_command(&[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], None)?;
+ run_command(&[&"cp", &"-r", &library_dir, &sysroot_src_path], None)?;
Ok(())
}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs
index 650c030..a5f802e 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/config.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs
@@ -352,11 +352,6 @@ pub fn setup(
None => return Err("no host found".to_string()),
};
- if self.target_triple.is_empty()
- && let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE")
- {
- self.target_triple = overwrite.clone();
- }
if self.target_triple.is_empty() {
self.target_triple = self.host_triple.clone();
}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/utils.rs b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
index d77707d..fc948c5 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/utils.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
@@ -303,19 +303,6 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
})
}
-pub fn copy_file<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<(), String> {
- fs::copy(&from, &to)
- .map_err(|error| {
- format!(
- "Failed to copy file `{}` into `{}`: {:?}",
- from.as_ref().display(),
- to.as_ref().display(),
- error
- )
- })
- .map(|_| ())
-}
-
/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
diff --git a/compiler/rustc_codegen_gcc/doc/tips.md b/compiler/rustc_codegen_gcc/doc/tips.md
index 86c22db..e62c340 100644
--- a/compiler/rustc_codegen_gcc/doc/tips.md
+++ b/compiler/rustc_codegen_gcc/doc/tips.md
@@ -62,14 +62,14 @@
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
* Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
- * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
- * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`.
+ * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. You can specify which linker to use via `CG_RUSTFLAGS="-Clinker=<linker>"`, for instance: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc"`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
+ * Build your project by specifying the target and the linker to use: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../y.sh cargo build --target m68k-unknown-linux-gnu`.
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
Then, you can use it the following way:
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
- * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
+ * Build your project by specifying the target specification file: `../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
If you get the following error:
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index 6b6f71e..85489f8 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -6,7 +6,7 @@
)]
#![no_core]
#![allow(dead_code, internal_features, non_camel_case_types)]
-#![rustfmt::skip]
+#![rustfmt_skip]
extern crate mini_core;
@@ -198,10 +198,17 @@ fn main() {
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
- assert!(!const { intrinsics::needs_drop::<u8>() });
- assert!(!const { intrinsics::needs_drop::<[u8]>() });
- assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
- assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
+ /*
+ * TODO: re-enable in the next sync.
+ let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
+ assert!(!u8_needs_drop);
+ let slice_needs_drop = const { intrinsics::needs_drop::<[u8]>() };
+ assert!(!slice_needs_drop);
+ let noisy_drop = const { intrinsics::needs_drop::<NoisyDrop>() };
+ assert!(noisy_drop);
+ let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
+ assert!(noisy_unsized_drop);
+ */
Unique {
pointer: 0 as *const &str,
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index bccbc6c..2fe8ec4 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2025-06-28"
+channel = "nightly-2025-07-04"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 28d1ec7..a4ec4bf 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -971,7 +971,11 @@ fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> R
fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer());
- ptr.dereference(self.location).to_rvalue()
+ // (FractalFir): We insert a local here, to ensure this volatile load can't move across
+ // blocks.
+ let local = self.current_func().new_local(self.location, ty, "volatile_tmp");
+ self.block.add_assignment(self.location, local, ptr.dereference(self.location).to_rvalue());
+ local.to_rvalue()
}
fn atomic_load(
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index d81bcc5..af41692 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -273,6 +273,10 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
}
impl ExtraBackendMethods for GccCodegenBackend {
+ fn supports_parallel(&self) -> bool {
+ false
+ }
+
fn codegen_allocator(
&self,
tcx: TyCtxt<'_>,
@@ -341,8 +345,7 @@ fn deref(&self) -> &Self::Target {
}
unsafe impl Send for SyncContext {}
-// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm".
-// TODO: disable it here by returning false in CodegenBackend::supports_parallel().
+// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()".
unsafe impl Sync for SyncContext {}
impl WriteBackendMethods for GccCodegenBackend {
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index 51f35cb..ff188c4 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -64,7 +64,7 @@ fn predefine_fn(
if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
#[cfg(feature = "master")]
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
- } else {
+ } else if visibility != Visibility::Default {
#[cfg(feature = "master")]
decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility)));
}
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index 544d0bf..6979c04 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -80,3 +80,5 @@
tests/ui/coroutine/panic-drops-resume.rs
tests/ui/coroutine/panic-drops.rs
tests/ui/coroutine/panic-safe.rs
+tests/ui/process/nofile-limit.rs
+tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs
index 2dbf43b..9b15a28 100644
--- a/compiler/rustc_codegen_gcc/tests/run/asm.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs
@@ -16,6 +16,7 @@
ret"
);
+#[cfg(target_arch = "x86_64")]
extern "C" {
fn add_asm(a: i64, b: i64) -> i64;
}
diff --git a/compiler/rustc_codegen_gcc/tests/run/float.rs b/compiler/rustc_codegen_gcc/tests/run/float.rs
index 424fa1c..df555f3 100644
--- a/compiler/rustc_codegen_gcc/tests/run/float.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/float.rs
@@ -3,8 +3,6 @@
// Run-time:
// status: 0
-#![feature(const_black_box)]
-
fn main() {
use std::hint::black_box;
@@ -15,14 +13,14 @@ macro_rules! check {
}};
}
- check!(i32, (black_box(0.0f32) as i32));
+ check!(i32, black_box(0.0f32) as i32);
- check!(u64, (black_box(f32::NAN) as u64));
- check!(u128, (black_box(f32::NAN) as u128));
+ check!(u64, black_box(f32::NAN) as u64);
+ check!(u128, black_box(f32::NAN) as u128);
- check!(i64, (black_box(f64::NAN) as i64));
- check!(u64, (black_box(f64::NAN) as u64));
+ check!(i64, black_box(f64::NAN) as i64);
+ check!(u64, black_box(f64::NAN) as u64);
- check!(i16, (black_box(f32::MIN) as i16));
- check!(i16, (black_box(f32::MAX) as i16));
+ check!(i16, black_box(f32::MIN) as i16);
+ check!(i16, black_box(f32::MAX) as i16);
}
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index 47b5dea..e20ecc2 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -3,8 +3,6 @@
// Run-time:
// status: 0
-#![feature(const_black_box)]
-
fn main() {
use std::hint::black_box;
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile.rs b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
index 8b04331..94a7bdc 100644
--- a/compiler/rustc_codegen_gcc/tests/run/volatile.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
@@ -5,13 +5,14 @@
use std::mem::MaybeUninit;
+#[allow(dead_code)]
#[derive(Debug)]
struct Struct {
pointer: *const (),
func: unsafe fn(*const ()),
}
-fn func(ptr: *const ()) {
+fn func(_ptr: *const ()) {
}
fn main() {
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile2.rs b/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
index a177b81..bdcb825 100644
--- a/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
@@ -6,8 +6,6 @@
mod libc {
#[link(name = "c")]
extern "C" {
- pub fn puts(s: *const u8) -> i32;
-
pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
@@ -61,7 +59,7 @@ fn main() {
panic!("error: mmap failed");
}
- let p_count = (&mut COUNT) as *mut u32;
+ let p_count = (&raw mut COUNT) as *mut u32;
p_count.write_volatile(0);
// Trigger segfaults
@@ -94,7 +92,7 @@ fn main() {
}
unsafe extern "C" fn segv_handler(_: i32, _: *mut (), _: *mut ()) {
- let p_count = (&mut COUNT) as *mut u32;
+ let p_count = (&raw mut COUNT) as *mut u32;
p_count.write_volatile(p_count.read_volatile() + 1);
let count = p_count.read_volatile();
diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
index dfde459..8e82013 100644
--- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
+++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
@@ -39,6 +39,7 @@ pub(crate) fn new(
debug_info_compression: &CStr,
use_emulated_tls: bool,
args_cstr_buff: &[u8],
+ use_wasm_eh: bool,
) -> Result<Self, LlvmError<'static>> {
assert!(args_cstr_buff.len() > 0);
assert!(
@@ -72,6 +73,7 @@ pub(crate) fn new(
use_emulated_tls,
args_cstr_buff.as_ptr() as *const c_char,
args_cstr_buff.len(),
+ use_wasm_eh,
)
};
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 6827900..6f8fba2 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -15,6 +15,7 @@
BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
TargetMachineFactoryFn,
};
+use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::profiling::SelfProfilerRef;
@@ -285,6 +286,8 @@ pub(crate) fn target_machine_factory(
let file_name_display_preference =
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
+ let use_wasm_eh = wants_wasm_eh(sess);
+
Arc::new(move |config: TargetMachineFactoryConfig| {
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
let path = path.unwrap_or_default();
@@ -321,6 +324,7 @@ pub(crate) fn target_machine_factory(
&debuginfo_compression,
use_emulated_tls,
&args_cstr_buff,
+ use_wasm_eh,
)
})
}
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 6a23bec..34bed2a 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -207,6 +207,11 @@ pub(crate) unsafe fn create_module<'ll>(
// LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
target_data_layout = target_data_layout.replace("e-p6:32:32-i64", "e-i64");
}
+ if sess.target.arch == "amdgpu" {
+ // LLVM 21 adds the address width for address space 8.
+ // See https://github.com/llvm/llvm-project/pull/139419
+ target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
+ }
}
// Ensure the data-layout values hardcoded remain the defaults.
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 0b1e632..80a0e5c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2425,6 +2425,7 @@ pub(crate) fn LLVMRustCreateTargetMachine(
UseEmulatedTls: bool,
ArgsCstrBuff: *const c_char,
ArgsCstrBuffLen: usize,
+ UseWasmEH: bool,
) -> *mut TargetMachine;
pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index b0d1915..6a3fdb6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -486,6 +486,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
// value and the variant index match, since that's all `Niche` can encode.
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+ let niche_start_const = bx.cx().const_uint_big(tag_llty, niche_start);
// We have a subrange `niche_start..=niche_end` inside `range`.
// If the value of the tag is inside this subrange, it's a
@@ -511,35 +512,88 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
// } else {
// untagged_variant
// }
- let niche_start = bx.cx().const_uint_big(tag_llty, niche_start);
- let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start);
+ let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start_const);
let tagged_discr =
bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64);
(is_niche, tagged_discr, 0)
} else {
- // The special cases don't apply, so we'll have to go with
- // the general algorithm.
- let relative_discr = bx.sub(tag, bx.cx().const_uint_big(tag_llty, niche_start));
- let cast_tag = bx.intcast(relative_discr, cast_to, false);
- let is_niche = bx.icmp(
- IntPredicate::IntULE,
- relative_discr,
- bx.cx().const_uint(tag_llty, relative_max as u64),
- );
+ // With multiple niched variants we'll have to actually compute
+ // the variant index from the stored tag.
+ //
+ // However, there's still one small optimization we can often do for
+ // determining *whether* a tag value is a natural value or a niched
+ // variant. The general algorithm involves a subtraction that often
+ // wraps in practice, making it tricky to analyse. However, in cases
+ // where there are few enough possible values of the tag that it doesn't
+ // need to wrap around, we can instead just look for the contiguous
+ // tag values on the end of the range with a single comparison.
+ //
+ // For example, take the type `enum Demo { A, B, Untagged(bool) }`.
+ // The `bool` is {0, 1}, and the two other variants are given the
+ // tags {2, 3} respectively. That means the `tag_range` is
+ // `[0, 3]`, which doesn't wrap as unsigned (nor as signed), so
+ // we can test for the niched variants with just `>= 2`.
+ //
+ // That means we're looking either for the niche values *above*
+ // the natural values of the untagged variant:
+ //
+ // niche_start niche_end
+ // | |
+ // v v
+ // MIN -------------+---------------------------+---------- MAX
+ // ^ | is niche |
+ // | +---------------------------+
+ // | |
+ // tag_range.start tag_range.end
+ //
+ // Or *below* the natural values:
+ //
+ // niche_start niche_end
+ // | |
+ // v v
+ // MIN ----+-----------------------+---------------------- MAX
+ // | is niche | ^
+ // +-----------------------+ |
+ // | |
+ // tag_range.start tag_range.end
+ //
+ // With those two options and having the flexibility to choose
+ // between a signed or unsigned comparison on the tag, that
+ // covers most realistic scenarios. The tests have a (contrived)
+ // example of a 1-byte enum with over 128 niched variants which
+ // wraps both as signed as unsigned, though, and for something
+ // like that we're stuck with the general algorithm.
- // Thanks to parameter attributes and load metadata, LLVM already knows
- // the general valid range of the tag. It's possible, though, for there
- // to be an impossible value *in the middle*, which those ranges don't
- // communicate, so it's worth an `assume` to let the optimizer know.
- if niche_variants.contains(&untagged_variant)
- && bx.cx().sess().opts.optimize != OptLevel::No
- {
- let impossible =
- u64::from(untagged_variant.as_u32() - niche_variants.start().as_u32());
- let impossible = bx.cx().const_uint(tag_llty, impossible);
- let ne = bx.icmp(IntPredicate::IntNE, relative_discr, impossible);
- bx.assume(ne);
- }
+ let tag_range = tag_scalar.valid_range(&dl);
+ let tag_size = tag_scalar.size(&dl);
+ let niche_end = u128::from(relative_max).wrapping_add(niche_start);
+ let niche_end = tag_size.truncate(niche_end);
+
+ let relative_discr = bx.sub(tag, niche_start_const);
+ let cast_tag = bx.intcast(relative_discr, cast_to, false);
+ let is_niche = if tag_range.no_unsigned_wraparound(tag_size) == Ok(true) {
+ if niche_start == tag_range.start {
+ let niche_end_const = bx.cx().const_uint_big(tag_llty, niche_end);
+ bx.icmp(IntPredicate::IntULE, tag, niche_end_const)
+ } else {
+ assert_eq!(niche_end, tag_range.end);
+ bx.icmp(IntPredicate::IntUGE, tag, niche_start_const)
+ }
+ } else if tag_range.no_signed_wraparound(tag_size) == Ok(true) {
+ if niche_start == tag_range.start {
+ let niche_end_const = bx.cx().const_uint_big(tag_llty, niche_end);
+ bx.icmp(IntPredicate::IntSLE, tag, niche_end_const)
+ } else {
+ assert_eq!(niche_end, tag_range.end);
+ bx.icmp(IntPredicate::IntSGE, tag, niche_start_const)
+ }
+ } else {
+ bx.icmp(
+ IntPredicate::IntULE,
+ relative_discr,
+ bx.cx().const_uint(tag_llty, relative_max as u64),
+ )
+ };
(is_niche, cast_tag, niche_variants.start().as_u32() as u128)
};
@@ -550,11 +604,24 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
bx.add(tagged_discr, bx.cx().const_uint_big(cast_to, delta))
};
- let discr = bx.select(
- is_niche,
- tagged_discr,
- bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64),
- );
+ let untagged_variant_const =
+ bx.cx().const_uint(cast_to, u64::from(untagged_variant.as_u32()));
+
+ // Thanks to parameter attributes and load metadata, LLVM already knows
+ // the general valid range of the tag. It's possible, though, for there
+ // to be an impossible value *in the middle*, which those ranges don't
+ // communicate, so it's worth an `assume` to let the optimizer know.
+ // Most importantly, this means when optimizing a variant test like
+ // `SELECT(is_niche, complex, CONST) == CONST` it's ok to simplify that
+ // to `!is_niche` because the `complex` part can't possibly match.
+ if niche_variants.contains(&untagged_variant)
+ && bx.cx().sess().opts.optimize != OptLevel::No
+ {
+ let ne = bx.icmp(IntPredicate::IntNE, tagged_discr, untagged_variant_const);
+ bx.assume(ne);
+ }
+
+ let discr = bx.select(is_niche, tagged_discr, untagged_variant_const);
// In principle we could insert assumes on the possible range of `discr`, but
// currently in LLVM this isn't worth it because the original `tag` will
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 2587e89..e872f84 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -630,7 +630,17 @@ pub(crate) fn codegen_rvalue_operand(
OperandRef { val: OperandValue::Immediate(static_), layout }
}
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
- mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
+ mir::Rvalue::Repeat(ref elem, len_const) => {
+ // All arrays have `BackendRepr::Memory`, so only the ZST cases
+ // end up here. Anything else forces the destination local to be
+ // `Memory`, and thus ends up handled in `codegen_rvalue` instead.
+ let operand = self.codegen_operand(bx, elem);
+ let array_ty = Ty::new_array_with_const_len(bx.tcx(), operand.layout.ty, len_const);
+ let array_ty = self.monomorphize(array_ty);
+ let array_layout = bx.layout_of(array_ty);
+ assert!(array_layout.is_zst());
+ OperandRef { val: OperandValue::ZeroSized, layout: array_layout }
+ }
mir::Rvalue::Aggregate(ref kind, ref fields) => {
let (variant_index, active_field_index) = match **kind {
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
@@ -1000,12 +1010,10 @@ pub(crate) fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool
mir::Rvalue::NullaryOp(..) |
mir::Rvalue::ThreadLocalRef(_) |
mir::Rvalue::Use(..) |
+ mir::Rvalue::Repeat(..) | // (*)
mir::Rvalue::Aggregate(..) | // (*)
mir::Rvalue::WrapUnsafeBinder(..) => // (*)
true,
- // Arrays are always aggregates, so it's not worth checking anything here.
- // (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
- mir::Rvalue::Repeat(..) => false,
}
// (*) this is only true if the type is suitable
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 53df999..def4ec1 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -149,14 +149,14 @@ fn parse_rust_feature_flag<'a>(
if let Some(base_feature) = feature.strip_prefix('+') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
- return;
+ continue;
}
callback(base_feature, sess.target.implied_target_features(base_feature), true)
} else if let Some(base_feature) = feature.strip_prefix('-') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
- return;
+ continue;
}
// If `f1` implies `f2`, then `!f2` implies `!f1` -- this is standard logical
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 3e880d0..e00fb2c 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -2,17 +2,17 @@
use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
use rustc_middle::mir::AssertKind;
-use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo};
+use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo, UndefinedBehaviorInfo};
use rustc_middle::query::TyCtxtAt;
+use rustc_middle::ty::ConstInt;
use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{ConstInt, TyCtxt};
use rustc_span::{Span, Symbol};
use super::CompileTimeMachine;
use crate::errors::{self, FrameNote, ReportErrorExt};
use crate::interpret::{
- CtfeProvenance, ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType,
- Pointer, err_inval, err_machine_stop,
+ CtfeProvenance, ErrorHandled, Frame, InterpCx, InterpErrorInfo, InterpErrorKind,
+ MachineStopType, Pointer, err_inval, err_machine_stop,
};
/// The CTFE machine has some custom error kinds.
@@ -163,7 +163,7 @@ pub fn get_span_and_frames<'tcx>(
/// You can use it to add a stacktrace of current execution according to
/// `get_span_and_frames` or just give context on where the const eval error happened.
pub(super) fn report<'tcx, C, F>(
- tcx: TyCtxt<'tcx>,
+ ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
error: InterpErrorKind<'tcx>,
span: Span,
get_span_and_frames: C,
@@ -173,6 +173,7 @@ pub(super) fn report<'tcx, C, F>(
C: FnOnce() -> (Span, Vec<FrameNote>),
F: FnOnce(&mut Diag<'_>, Span, Vec<FrameNote>),
{
+ let tcx = ecx.tcx.tcx;
// Special handling for certain errors
match error {
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
@@ -198,6 +199,20 @@ pub(super) fn report<'tcx, C, F>(
InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
);
+ if let InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(
+ Some((alloc_id, _access)),
+ )) = error
+ {
+ let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
+ let info = ecx.get_alloc_info(alloc_id);
+ let raw_bytes = errors::RawBytesNote {
+ size: info.size.bytes(),
+ align: info.align.bytes(),
+ bytes,
+ };
+ err.subdiagnostic(raw_bytes);
+ }
+
error.add_args(&mut err);
mk(&mut err, span, frames);
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index ce72d59..f584f6c 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -411,7 +411,7 @@ fn report_eval_error<'tcx>(
let instance = with_no_trimmed_paths!(cid.instance.to_string());
super::report(
- *ecx.tcx,
+ ecx,
error,
DUMMY_SP,
|| super::get_span_and_frames(ecx.tcx, ecx.stack()),
@@ -451,7 +451,7 @@ fn report_validation_error<'tcx>(
errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
crate::const_eval::report(
- *ecx.tcx,
+ ecx,
error,
DUMMY_SP,
|| crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 7a73d70..de4fbc7 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -17,6 +17,7 @@
throw_ub_custom,
};
use crate::fluent_generated as fluent;
+use crate::interpret::Writeable;
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn cast(
@@ -358,7 +359,7 @@ fn cast_from_float<F>(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar<M::Provenance>
fn unsize_into_ptr(
&mut self,
src: &OpTy<'tcx, M::Provenance>,
- dest: &PlaceTy<'tcx, M::Provenance>,
+ dest: &impl Writeable<'tcx, M::Provenance>,
// The pointee types
source_ty: Ty<'tcx>,
cast_ty: Ty<'tcx>,
@@ -455,7 +456,7 @@ pub fn unsize_into(
&mut self,
src: &OpTy<'tcx, M::Provenance>,
cast_ty: TyAndLayout<'tcx>,
- dest: &PlaceTy<'tcx, M::Provenance>,
+ dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty);
match (src.layout.ty.kind(), cast_ty.ty.kind()) {
@@ -496,7 +497,7 @@ pub fn unsize_into(
self.cur_span(),
"unsize_into: invalid conversion: {:?} -> {:?}",
src.layout,
- dest.layout
+ dest.layout()
)
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 47228de..20c8e98 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -67,8 +67,8 @@ pub enum AllocKind {
LiveData,
/// A function allocation (that fn ptrs point to).
Function,
- /// A (symbolic) vtable allocation.
- VTable,
+ /// A "virtual" allocation, used for vtables and TypeId.
+ Virtual,
/// A dead allocation.
Dead,
}
@@ -950,11 +950,9 @@ pub fn get_alloc_info(&self, id: AllocId) -> AllocInfo {
let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
let kind = match global_alloc {
- GlobalAlloc::TypeId { .. }
- | GlobalAlloc::Static { .. }
- | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
+ GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
- GlobalAlloc::VTable { .. } => AllocKind::VTable,
+ GlobalAlloc::VTable { .. } | GlobalAlloc::TypeId { .. } => AllocKind::Virtual,
};
return AllocInfo::new(size, align, kind, mutbl);
}
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 62f591c..693b378 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -394,7 +394,7 @@ fn read_immediate(
interp_ok(try_validation!(
self.ecx.read_immediate(val),
self.path,
- Ub(InvalidUninitBytes(None)) =>
+ Ub(InvalidUninitBytes(_)) =>
Uninit { expected },
// The `Unsup` cases can only occur during CTFE
Unsup(ReadPointerAsInt(_)) =>
diff --git a/compiler/rustc_error_codes/src/error_codes/E0203.md b/compiler/rustc_error_codes/src/error_codes/E0203.md
index 1edb519..a4dceed 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0203.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0203.md
@@ -1,15 +1,15 @@
-Having multiple relaxed default bounds is unsupported.
+Having duplicate relaxed default bounds is unsupported.
Erroneous code example:
```compile_fail,E0203
-struct Bad<T: ?Sized + ?Send>{
- inner: T
+struct Bad<T: ?Sized + ?Sized>{
+ inner: T,
}
```
-Here the type `T` cannot have a relaxed bound for multiple default traits
-(`Sized` and `Send`). This can be fixed by only using one relaxed bound.
+Here the type parameter `T` cannot have duplicate relaxed bounds for default
+trait `Sized`. This can be fixed by only using one relaxed bound:
```
struct Good<T: ?Sized>{
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index a128f8d..96c7ba6 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1421,7 +1421,7 @@ pub fn emit(self) -> G::EmitResult {
///
/// See `emit` and `delay_as_bug` for details.
#[track_caller]
- pub fn emit_unless(mut self, delay: bool) -> G::EmitResult {
+ pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
if delay {
self.downgrade_to_delayed_bug();
}
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index 6018980..d617f44 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -41,7 +41,7 @@ pub enum Target {
Union,
Trait,
TraitAlias,
- Impl,
+ Impl { of_trait: bool },
Expression,
Statement,
Arm,
@@ -51,7 +51,7 @@ pub enum Target {
ForeignFn,
ForeignStatic,
ForeignTy,
- GenericParam(GenericParamKind),
+ GenericParam { kind: GenericParamKind, has_default: bool },
MacroDef,
Param,
PatField,
@@ -86,14 +86,14 @@ pub fn is_associated_item(self) -> bool {
| Target::Union
| Target::Trait
| Target::TraitAlias
- | Target::Impl
+ | Target::Impl { .. }
| Target::Expression
| Target::Statement
| Target::Arm
| Target::ForeignFn
| Target::ForeignStatic
| Target::ForeignTy
- | Target::GenericParam(_)
+ | Target::GenericParam { .. }
| Target::MacroDef
| Target::Param
| Target::PatField
@@ -119,7 +119,7 @@ pub fn from_item(item: &Item<'_>) -> Target {
ItemKind::Union(..) => Target::Union,
ItemKind::Trait(..) => Target::Trait,
ItemKind::TraitAlias(..) => Target::TraitAlias,
- ItemKind::Impl { .. } => Target::Impl,
+ ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
}
}
@@ -141,7 +141,7 @@ pub fn from_def_kind(def_kind: DefKind) -> Target {
DefKind::Union => Target::Union,
DefKind::Trait => Target::Trait,
DefKind::TraitAlias => Target::TraitAlias,
- DefKind::Impl { .. } => Target::Impl,
+ DefKind::Impl { of_trait } => Target::Impl { of_trait },
_ => panic!("impossible case reached"),
}
}
@@ -169,11 +169,17 @@ pub fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target {
pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
match generic_param.kind {
- hir::GenericParamKind::Type { .. } => Target::GenericParam(GenericParamKind::Type),
+ hir::GenericParamKind::Type { default, .. } => Target::GenericParam {
+ kind: GenericParamKind::Type,
+ has_default: default.is_some(),
+ },
hir::GenericParamKind::Lifetime { .. } => {
- Target::GenericParam(GenericParamKind::Lifetime)
+ Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }
}
- hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const),
+ hir::GenericParamKind::Const { default, .. } => Target::GenericParam {
+ kind: GenericParamKind::Const,
+ has_default: default.is_some(),
+ },
}
}
@@ -196,7 +202,8 @@ pub fn name(self) -> &'static str {
Target::Union => "union",
Target::Trait => "trait",
Target::TraitAlias => "trait alias",
- Target::Impl => "implementation block",
+ Target::Impl { of_trait: false } => "inherent implementation block",
+ Target::Impl { of_trait: true } => "trait implementation block",
Target::Expression => "expression",
Target::Statement => "statement",
Target::Arm => "match arm",
@@ -210,7 +217,7 @@ pub fn name(self) -> &'static str {
Target::ForeignFn => "foreign function",
Target::ForeignStatic => "foreign static item",
Target::ForeignTy => "foreign type",
- Target::GenericParam(kind) => match kind {
+ Target::GenericParam { kind, has_default: _ } => match kind {
GenericParamKind::Type => "type parameter",
GenericParamKind::Lifetime => "lifetime parameter",
GenericParamKind::Const => "const parameter",
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index e38ca9e..2428c1a 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -371,9 +371,6 @@
*[other] parameters
} must be specified on the object type
-hir_analysis_multiple_relaxed_default_bounds =
- type parameter has more than one relaxed default bound, only one is supported
-
hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
hir_analysis_must_implement_not_function = not a function
@@ -448,8 +445,6 @@
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
.label = not allowed in type signatures
-hir_analysis_pointee_sized_trait_object = `PointeeSized` cannot be used with trait objects
-
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 87db80f..e24426f 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1173,7 +1173,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
bounds_span,
where_span,
})
- .emit_unless(delay);
+ .emit_unless_delay(delay);
Err(reported)
}
@@ -1481,7 +1481,7 @@ fn compare_self_type<'tcx>(
} else {
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
- return Err(err.emit_unless(delay));
+ return Err(err.emit_unless_delay(delay));
}
(true, false) => {
@@ -1502,7 +1502,7 @@ fn compare_self_type<'tcx>(
err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
- return Err(err.emit_unless(delay));
+ return Err(err.emit_unless_delay(delay));
}
}
@@ -1662,7 +1662,7 @@ fn compare_number_of_generics<'tcx>(
err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
}
- let reported = err.emit_unless(delay);
+ let reported = err.emit_unless_delay(delay);
err_occurred = Some(reported);
}
}
@@ -1745,7 +1745,7 @@ fn compare_number_of_method_arguments<'tcx>(
),
);
- return Err(err.emit_unless(delay));
+ return Err(err.emit_unless_delay(delay));
}
Ok(())
@@ -1872,7 +1872,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) -> Self::Result {
);
};
}
- error_found = Some(err.emit_unless(delay));
+ error_found = Some(err.emit_unless_delay(delay));
}
}
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
@@ -1974,7 +1974,7 @@ fn compare_generic_param_kinds<'tcx>(
err.span_label(impl_header_span, "");
err.span_label(param_impl_span, make_param_message("found", param_impl));
- let reported = err.emit_unless(delay);
+ let reported = err.emit_unless_delay(delay);
return Err(reported);
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index f2f1560d..cc53919 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -267,20 +267,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
match predicate.kind {
hir::WherePredicateKind::BoundPredicate(bound_pred) => {
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
-
let bound_vars = tcx.late_bound_vars(predicate.hir_id);
- // Keep the type around in a dummy predicate, in case of no bounds.
- // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
- // is still checked for WF.
+
+ // This is a `where Ty:` (sic!).
if bound_pred.bounds.is_empty() {
if let ty::Param(_) = ty.kind() {
- // This is a `where T:`, which can be in the HIR from the
- // transformation that moves `?Sized` to `T`'s declaration.
- // We can skip the predicate because type parameters are
- // trivially WF, but also we *should*, to avoid exposing
- // users who never wrote `where Type:,` themselves, to
- // compiler/tooling bugs from not handling WF predicates.
+ // We can skip the predicate because type parameters are trivially WF.
} else {
+ // Keep the type around in a dummy predicate. That way, it's not a complete
+ // noop (see #53696) and `Ty` is still checked for WF.
+
let span = bound_pred.bounded_ty.span;
let predicate = ty::Binder::bind_with_vars(
ty::ClauseKind::WellFormed(ty.into()),
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 77e63e3..eb3492f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -2495,7 +2495,7 @@ fn deny_non_region_late_bound(
format!("late-bound {what} parameter not allowed on {where_}"),
);
- let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
+ let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first);
first = false;
*arg = ResolvedArg::Error(guar);
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index fbd21f8..26a9872 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -280,13 +280,6 @@ pub(crate) struct CopyImplOnTypeWithDtor {
}
#[derive(Diagnostic)]
-#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)]
-pub(crate) struct MultipleRelaxedDefaultBounds {
- #[primary_span]
- pub spans: Vec<Span>,
-}
-
-#[derive(Diagnostic)]
#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)]
pub(crate) struct CopyImplOnNonAdt {
#[primary_span]
@@ -320,13 +313,6 @@ pub(crate) struct TraitObjectDeclaredWithNoTraits {
}
#[derive(Diagnostic)]
-#[diag(hir_analysis_pointee_sized_trait_object)]
-pub(crate) struct PointeeSizedTraitObject {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)]
pub(crate) struct AmbiguousLifetimeBound {
#[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 9a752ae..d7a827c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -6,7 +6,7 @@
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
-use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
+use rustc_hir::{AmbigArg, PolyTraitRef};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -85,17 +85,17 @@ fn search_bounds_for<'tcx>(
}
}
-fn collect_unbounds<'tcx>(
+fn collect_relaxed_bounds<'tcx>(
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
- let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
+ let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
- unbounds.push(ptr);
+ relaxed_bounds.push(ptr);
}
});
- unbounds
+ relaxed_bounds
}
fn collect_bounds<'a, 'tcx>(
@@ -124,13 +124,13 @@ fn collect_sizedness_bounds<'tcx>(
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
span: Span,
) -> CollectedSizednessBounds {
- let sized_did = tcx.require_lang_item(LangItem::Sized, span);
+ let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
- let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
+ let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
- let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
+ let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
CollectedSizednessBounds { sized, meta_sized, pointee_sized }
@@ -151,24 +151,6 @@ fn add_trait_bound<'tcx>(
}
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
- /// Skip `PointeeSized` bounds.
- ///
- /// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there
- /// is actually the absence of any bounds. This avoids limitations around non-global where
- /// clauses being preferred over item bounds (where `PointeeSized` bounds would be
- /// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is
- /// added to some items.
- pub(crate) fn should_skip_sizedness_bound<'hir>(
- &self,
- bound: &'hir hir::GenericBound<'tcx>,
- ) -> bool {
- bound
- .trait_ref()
- .and_then(|tr| tr.trait_def_id())
- .map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized))
- .unwrap_or(false)
- }
-
/// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
///
/// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
@@ -193,8 +175,8 @@ pub(crate) fn add_sizedness_bounds(
return;
}
- let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
- let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
+ let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
+ let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
// If adding sizedness bounds to a trait, then there are some relevant early exits
if let Some(trait_did) = trait_did {
@@ -209,9 +191,22 @@ pub(crate) fn add_sizedness_bounds(
return;
}
} else {
- // Report invalid unbounds on sizedness-bounded generic parameters.
- let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates);
- self.check_and_report_invalid_unbounds_on_param(unbounds);
+ // Report invalid relaxed bounds.
+ // FIXME: Since we only call this validation function here in this function, we only
+ // fully validate relaxed bounds in contexts where we perform
+ // "sized elaboration". In most cases that doesn't matter because we *usually*
+ // reject such relaxed bounds outright during AST lowering.
+ // However, this can easily get out of sync! Ideally, we would perform this step
+ // where we are guaranteed to catch *all* bounds like in
+ // `Self::lower_poly_trait_ref`. List of concrete issues:
+ // FIXME(more_maybe_bounds): We don't call this for e.g., trait object tys or
+ // supertrait bounds!
+ // FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
+ // AST lowering should reject them outright.
+ // FIXME(associated_type_bounds): We don't call this for them. However, AST
+ // lowering should reject them outright (#135229).
+ let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
+ self.check_and_report_invalid_relaxed_bounds(bounds);
}
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
@@ -231,7 +226,7 @@ pub(crate) fn add_sizedness_bounds(
} else {
// If there are no explicit sizedness bounds on a parameter then add a default
// `Sized` bound.
- let sized_did = tcx.require_lang_item(LangItem::Sized, span);
+ let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
}
}
@@ -463,10 +458,6 @@ pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<
'tcx: 'hir,
{
for hir_bound in hir_bounds {
- if self.should_skip_sizedness_bound(hir_bound) {
- continue;
- }
-
// In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
// we skip over any traits that don't define the given associated type.
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
@@ -482,12 +473,8 @@ pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<
match hir_bound {
hir::GenericBound::Trait(poly_trait_ref) => {
- let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
let _ = self.lower_poly_trait_ref(
- &poly_trait_ref.trait_ref,
- poly_trait_ref.span,
- constness,
- polarity,
+ poly_trait_ref,
param_ty,
bounds,
predicate_filter,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index 364ad38..76bb59e 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -2,7 +2,6 @@
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
-use rustc_hir::LangItem;
use rustc_hir::def::{DefKind, Res};
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
@@ -18,9 +17,7 @@
use super::HirTyLowerer;
use crate::errors::SelfInTypeAlias;
-use crate::hir_ty_lowering::{
- GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
-};
+use crate::hir_ty_lowering::{GenericArgCountMismatch, PredicateFilter, RegionInferReason};
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Lower a trait object type from the HIR to our internal notion of a type.
@@ -38,24 +35,15 @@ pub(super) fn lower_trait_object_ty(
let mut user_written_bounds = Vec::new();
let mut potential_assoc_types = Vec::new();
- for trait_bound in hir_bounds.iter() {
- if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
- continue;
- }
- if let GenericArgCountResult {
- correct:
- Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
- ..
- } = self.lower_poly_trait_ref(
- &trait_bound.trait_ref,
- trait_bound.span,
- trait_bound.modifiers.constness,
- hir::BoundPolarity::Positive,
+ for poly_trait_ref in hir_bounds.iter() {
+ let result = self.lower_poly_trait_ref(
+ poly_trait_ref,
dummy_self,
&mut user_written_bounds,
PredicateFilter::SelfOnly,
- ) {
- potential_assoc_types.extend(cur_potential_assoc_types);
+ );
+ if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
+ potential_assoc_types.extend(invalid_args);
}
}
@@ -81,13 +69,6 @@ pub(super) fn lower_trait_object_ty(
let guar = self.report_trait_object_addition_traits(®ular_traits);
return Ty::new_error(tcx, guar);
}
- // We don't support `PointeeSized` principals
- let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
- if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) {
- let guar = self.report_pointee_sized_trait_object(span);
- return Ty::new_error(tcx, guar);
- }
-
// Don't create a dyn trait if we have errors in the principal.
if let Err(guar) = regular_traits.error_reported() {
return Ty::new_error(tcx, guar);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 5d85a3f..287a553 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -8,7 +8,7 @@
};
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
+use rustc_hir::{self as hir, HirId, PolyTraitRef};
use rustc_middle::bug;
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -29,59 +29,54 @@
use super::InherentAssocCandidate;
use crate::errors::{
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
- ParenthesizedFnTraitExpansion, PointeeSizedTraitObject, TraitObjectDeclaredWithNoTraits,
+ ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
};
use crate::fluent_generated as fluent;
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
- /// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits.
- pub(crate) fn check_and_report_invalid_unbounds_on_param(
+ /// Check for duplicate relaxed bounds and relaxed bounds of non-default traits.
+ pub(crate) fn check_and_report_invalid_relaxed_bounds(
&self,
- unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
+ relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
) {
let tcx = self.tcx();
- let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
+ let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
- let mut unique_bounds = FxIndexSet::default();
- let mut seen_repeat = false;
- for unbound in &unbounds {
- if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
- seen_repeat |= !unique_bounds.insert(unbound_def_id);
+ for bound in &relaxed_bounds {
+ if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
+ grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
}
}
- if unbounds.len() > 1 {
- let err = errors::MultipleRelaxedDefaultBounds {
- spans: unbounds.iter().map(|ptr| ptr.span).collect(),
- };
-
- if seen_repeat {
- tcx.dcx().emit_err(err);
- } else if !tcx.features().more_maybe_bounds() {
- tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit();
- };
+ for (trait_def_id, spans) in grouped_bounds {
+ if spans.len() > 1 {
+ let name = tcx.item_name(trait_def_id);
+ self.dcx()
+ .struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
+ .with_code(E0203)
+ .emit();
+ }
}
- for unbound in unbounds {
- if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
- && ((did == sized_did) || tcx.is_default_trait(did))
+ let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP);
+
+ for bound in relaxed_bounds {
+ if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res
+ && (def_id == sized_def_id || tcx.is_default_trait(def_id))
{
continue;
}
-
- let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
- true => "`?Sized` and `experimental_default_bounds`",
- false => "`?Sized`",
- };
self.dcx().span_err(
- unbound.span,
- format!(
- "relaxing a default bound only does something for {}; all other traits are \
- not bound by default",
- unbound_traits
- ),
+ bound.span,
+ if tcx.sess.opts.unstable_opts.experimental_default_bounds
+ || tcx.features().more_maybe_bounds()
+ {
+ "bound modifier `?` can only be applied to default traits like `Sized`"
+ } else {
+ "bound modifier `?` can only be applied to `Sized`"
+ },
);
}
}
@@ -1410,10 +1405,6 @@ pub fn report_trait_object_with_no_traits(
self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
}
-
- pub(super) fn report_pointee_sized_trait_object(&self, span: Span) -> ErrorGuaranteed {
- self.dcx().emit_err(PointeeSizedTraitObject { span })
- }
}
/// Emit an error for the given associated item constraint.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 8c7c375..fc519c1 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -570,7 +570,7 @@ pub(crate) fn check_generic_arg_count(
gen_args,
def_id,
))
- .emit_unless(all_params_are_binded)
+ .emit_unless_delay(all_params_are_binded)
});
Err(reported)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index a5bd7c1..d768799 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -747,18 +747,46 @@ pub fn lower_impl_trait_ref(
/// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
/// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`.
/// The lowered poly-trait-ref will track this binder explicitly, however.
- #[instrument(level = "debug", skip(self, span, constness, bounds))]
+ #[instrument(level = "debug", skip(self, bounds))]
pub(crate) fn lower_poly_trait_ref(
&self,
- trait_ref: &hir::TraitRef<'tcx>,
- span: Span,
- constness: hir::BoundConstness,
- polarity: hir::BoundPolarity,
+ poly_trait_ref: &hir::PolyTraitRef<'tcx>,
self_ty: Ty<'tcx>,
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
predicate_filter: PredicateFilter,
) -> GenericArgCountResult {
+ let tcx = self.tcx();
+
+ // We use the *resolved* bound vars later instead of the HIR ones since the former
+ // also include the bound vars of the overarching predicate if applicable.
+ let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } =
+ *poly_trait_ref;
+ let hir::TraitBoundModifiers { constness, polarity } = modifiers;
+
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+
+ // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR
+ // as they denote the *absence* of a default bound. However, we can't bail out early here since
+ // we still need to perform several validation steps (see below). Instead, simply "pour" all
+ // resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.
+ let (polarity, bounds) = match polarity {
+ rustc_ast::BoundPolarity::Positive
+ if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
+ {
+ // To elaborate on the comment directly above, regarding `PointeeSized` specifically,
+ // we don't "reify" such bounds to avoid trait system limitations -- namely,
+ // non-global where-clauses being preferred over item bounds (where `PointeeSized`
+ // bounds would be proven) -- which can result in errors when a `PointeeSized`
+ // supertrait / bound / predicate is added to some items.
+ (ty::PredicatePolarity::Positive, &mut Vec::new())
+ }
+ rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
+ rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
+ rustc_ast::BoundPolarity::Maybe(_) => {
+ (ty::PredicatePolarity::Positive, &mut Vec::new())
+ }
+ };
+
let trait_segment = trait_ref.path.segments.last().unwrap();
let _ = self.prohibit_generic_args(
@@ -775,7 +803,6 @@ pub(crate) fn lower_poly_trait_ref(
Some(self_ty),
);
- let tcx = self.tcx();
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
debug!(?bound_vars);
@@ -786,27 +813,6 @@ pub(crate) fn lower_poly_trait_ref(
debug!(?poly_trait_ref);
- let polarity = match polarity {
- rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
- rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
- rustc_ast::BoundPolarity::Maybe(_) => {
- // Validate associated type at least. We may want to reject these
- // outright in the future...
- for constraint in trait_segment.args().constraints {
- let _ = self.lower_assoc_item_constraint(
- trait_ref.hir_ref_id,
- poly_trait_ref,
- constraint,
- &mut Default::default(),
- &mut Default::default(),
- constraint.span,
- predicate_filter,
- );
- }
- return arg_count;
- }
- };
-
// We deal with const conditions later.
match predicate_filter {
PredicateFilter::All
@@ -909,7 +915,7 @@ pub(crate) fn lower_poly_trait_ref(
// Don't register any associated item constraints for negative bounds,
// since we should have emitted an error for them earlier, and they
// would not be well-formed!
- if polarity != ty::PredicatePolarity::Positive {
+ if polarity == ty::PredicatePolarity::Negative {
self.dcx().span_delayed_bug(
constraint.span,
"negative trait bounds should not have assoc item constraints",
@@ -2489,6 +2495,14 @@ pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
ty::List::empty(),
PredicateFilter::All,
);
+ self.add_sizedness_bounds(
+ &mut bounds,
+ self_ty,
+ hir_bounds,
+ None,
+ None,
+ hir_ty.span,
+ );
self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
self_ty
}
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index b2a229a..6d67535 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1775,7 +1775,7 @@ pub(crate) fn coerce_inner<'a>(
);
}
- let reported = err.emit_unless(unsized_return);
+ let reported = err.emit_unless_delay(unsized_return);
self.final_ty = Some(Ty::new_error(fcx.tcx, reported));
}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 067ee0f..08e8164 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1549,7 +1549,7 @@ fn expr_assign_expected_bool_error(
// If the assignment expression itself is ill-formed, don't
// bother emitting another error
- err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error())
+ err.emit_unless_delay(lhs_ty.references_error() || rhs_ty.references_error())
}
pub(super) fn check_expr_let(
@@ -3865,7 +3865,7 @@ fn check_expr_offset_of(
self.dcx()
.create_err(NoVariantNamed { span: ident.span, ident, ty: container })
.with_span_label(field.span, "variant not found")
- .emit_unless(container.references_error());
+ .emit_unless_delay(container.references_error());
break;
};
let Some(&subfield) = fields.next() else {
@@ -3897,7 +3897,7 @@ fn check_expr_offset_of(
enum_span: field.span,
field_span: subident.span,
})
- .emit_unless(container.references_error());
+ .emit_unless_delay(container.references_error());
break;
};
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index a438cde..fb6897c 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1055,17 +1055,11 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
});
},
{
- sess.time("unused_lib_feature_checking", || {
- rustc_passes::stability::check_unused_or_stable_features(tcx)
- });
- },
- {
// We force these queries to run,
// since they might not otherwise get called.
// This marks the corresponding crate-level attributes
// as used, and ensures that their values are valid.
tcx.ensure_ok().limits(());
- tcx.ensure_ok().stability_index(());
}
);
});
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 826bce2..b2fa0fb 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -160,12 +160,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name {
sym::ptr_read
| sym::ptr_read_unaligned
- | sym::ptr_read_volatile
| sym::ptr_replace
| sym::ptr_write
| sym::ptr_write_bytes
- | sym::ptr_write_unaligned
- | sym::ptr_write_volatile => (&[0], true),
+ | sym::ptr_write_unaligned => (&[0], true),
sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false),
sym::ptr_copy
| sym::ptr_copy_nonoverlapping
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index cc33764..a2e4d73 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -396,7 +396,7 @@
bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray,
const char *SplitDwarfFile, const char *OutputObjFile,
const char *DebugInfoCompression, bool UseEmulatedTls,
- const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) {
+ const char *ArgsCstrBuff, size_t ArgsCstrBuffLen, bool UseWasmEH) {
auto OptLevel = fromRust(RustOptLevel);
auto RM = fromRust(RustReloc);
@@ -462,6 +462,9 @@
Options.ThreadModel = ThreadModel::Single;
}
+ if (UseWasmEH)
+ Options.ExceptionModel = ExceptionHandling::Wasm;
+
Options.EmitStackSizeSection = EmitStackSizeSection;
if (ArgsCstrBuff != nullptr) {
@@ -700,6 +703,10 @@
#ifdef ENZYME
extern "C" void registerEnzymeAndPassPipeline(llvm::PassBuilder &PB,
/* augmentPassBuilder */ bool);
+
+extern "C" {
+extern llvm::cl::opt<std::string> EnzymeFunctionToAnalyze;
+}
#endif
extern "C" LLVMRustResult LLVMRustOptimize(
@@ -1069,6 +1076,15 @@
return LLVMRustResult::Failure;
}
+ // Check if PrintTAFn was used and add type analysis pass if needed
+ if (!EnzymeFunctionToAnalyze.empty()) {
+ if (auto Err = PB.parsePassPipeline(MPM, "print-type-analysis")) {
+ std::string ErrMsg = toString(std::move(Err));
+ LLVMRustSetLastError(ErrMsg.c_str());
+ return LLVMRustResult::Failure;
+ }
+ }
+
if (PrintAfterEnzyme) {
// Handle the Rust flag `-Zautodiff=PrintModAfter`.
std::string Banner = "Module after EnzymeNewPM";
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e65c7a6..438eff3 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -12,7 +12,6 @@
use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard};
-use rustc_errors::DiagCtxtHandle;
use rustc_expand::base::SyntaxExtension;
use rustc_fs_util::try_canonicalize;
use rustc_hir as hir;
@@ -23,8 +22,10 @@
use rustc_middle::ty::data_structures::IndexSet;
use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
use rustc_proc_macro::bridge::client::ProcMacro;
+use rustc_session::Session;
use rustc_session::config::{
- CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers, TargetModifier,
+ CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers,
+ TargetModifier,
};
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
use rustc_session::lint::{self, BuiltinLintDiag};
@@ -70,6 +71,8 @@ pub struct CStore {
/// Unused externs of the crate
unused_externs: Vec<Symbol>,
+
+ used_extern_options: FxHashSet<Symbol>,
}
impl std::fmt::Debug for CStore {
@@ -78,28 +81,6 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
}
}
-pub struct CrateLoader<'a, 'tcx: 'a> {
- // Immutable configuration.
- tcx: TyCtxt<'tcx>,
- // Mutable output.
- cstore: &'a mut CStore,
- used_extern_options: &'a mut FxHashSet<Symbol>,
-}
-
-impl<'a, 'tcx> std::ops::Deref for CrateLoader<'a, 'tcx> {
- type Target = TyCtxt<'tcx>;
-
- fn deref(&self) -> &Self::Target {
- &self.tcx
- }
-}
-
-impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
- fn dcx(&self) -> DiagCtxtHandle<'tcx> {
- self.tcx.dcx()
- }
-}
-
pub enum LoadedMacro {
MacroDef {
def: MacroDef,
@@ -227,8 +208,8 @@ pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> FreezeWriteGuard<'_, CStore> {
fn intern_stable_crate_id<'tcx>(
&mut self,
- root: &CrateRoot,
tcx: TyCtxt<'tcx>,
+ root: &CrateRoot,
) -> Result<TyCtxtFeed<'tcx, CrateNum>, CrateError> {
assert_eq!(self.metas.len(), tcx.untracked().stable_crate_ids.read().len());
let num = tcx.create_crate_num(root.stable_crate_id()).map_err(|existing| {
@@ -495,21 +476,18 @@ pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
has_global_allocator: false,
has_alloc_error_handler: false,
unused_externs: Vec::new(),
+ used_extern_options: Default::default(),
}
}
-}
-impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
- pub fn new(
- tcx: TyCtxt<'tcx>,
- cstore: &'a mut CStore,
- used_extern_options: &'a mut FxHashSet<Symbol>,
- ) -> Self {
- CrateLoader { tcx, cstore, used_extern_options }
- }
-
- fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
- for (cnum, data) in self.cstore.iter_crate_data() {
+ fn existing_match(
+ &self,
+ externs: &Externs,
+ name: Symbol,
+ hash: Option<Svh>,
+ kind: PathKind,
+ ) -> Option<CrateNum> {
+ for (cnum, data) in self.iter_crate_data() {
if data.name() != name {
trace!("{} did not match {}", data.name(), name);
continue;
@@ -533,8 +511,8 @@ fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Opt
// We're also sure to compare *paths*, not actual byte slices. The
// `source` stores paths which are normalized which may be different
// from the strings on the command line.
- let source = self.cstore.get_crate_data(cnum).cdata.source();
- if let Some(entry) = self.sess.opts.externs.get(name.as_str()) {
+ let source = self.get_crate_data(cnum).cdata.source();
+ if let Some(entry) = externs.get(name.as_str()) {
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
if let Some(mut files) = entry.files() {
if files.any(|l| {
@@ -587,6 +565,7 @@ fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Opt
/// command parameter is set to `public-dependency`
fn is_private_dep(
&self,
+ externs: &Externs,
name: Symbol,
private_dep: Option<bool>,
origin: CrateOrigin<'_>,
@@ -595,7 +574,7 @@ fn is_private_dep(
return true;
}
- let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep);
+ let extern_private = externs.get(name.as_str()).map(|e| e.is_private_dep);
match (extern_private, private_dep) {
// Explicit non-private via `--extern`, explicit non-private from metadata, or
// unspecified with default to public.
@@ -605,8 +584,9 @@ fn is_private_dep(
}
}
- fn register_crate(
+ fn register_crate<'tcx>(
&mut self,
+ tcx: TyCtxt<'tcx>,
host_lib: Option<Library>,
origin: CrateOrigin<'_>,
lib: Library,
@@ -615,15 +595,15 @@ fn register_crate(
private_dep: Option<bool>,
) -> Result<CrateNum, CrateError> {
let _prof_timer =
- self.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str());
+ tcx.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str());
let Library { source, metadata } = lib;
let crate_root = metadata.get_root();
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
- let private_dep = self.is_private_dep(name, private_dep, origin);
+ let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin);
// Claim this crate number and cache it
- let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?;
+ let feed = self.intern_stable_crate_id(tcx, &crate_root)?;
let cnum = feed.key();
info!(
@@ -643,8 +623,15 @@ fn register_crate(
&crate_paths
};
- let cnum_map =
- self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind, private_dep)?;
+ let cnum_map = self.resolve_crate_deps(
+ tcx,
+ dep_root,
+ &crate_root,
+ &metadata,
+ cnum,
+ dep_kind,
+ private_dep,
+ )?;
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
let temp_root;
@@ -656,14 +643,14 @@ fn register_crate(
None => (&source, &crate_root),
};
let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
- Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
+ Some(self.dlsym_proc_macros(tcx.sess, &dlsym_dylib.0, dlsym_root.stable_crate_id())?)
} else {
None
};
let crate_metadata = CrateMetadata::new(
- self.sess,
- self.cstore,
+ tcx.sess,
+ self,
metadata,
crate_root,
raw_proc_macros,
@@ -675,13 +662,14 @@ fn register_crate(
host_hash,
);
- self.cstore.set_crate_data(cnum, crate_metadata);
+ self.set_crate_data(cnum, crate_metadata);
Ok(cnum)
}
- fn load_proc_macro<'b>(
+ fn load_proc_macro<'a, 'b>(
&self,
+ sess: &'a Session,
locator: &mut CrateLocator<'b>,
crate_rejections: &mut CrateRejections,
path_kind: PathKind,
@@ -690,13 +678,13 @@ fn load_proc_macro<'b>(
where
'a: 'b,
{
- if self.sess.opts.unstable_opts.dual_proc_macros {
+ if sess.opts.unstable_opts.dual_proc_macros {
// Use a new crate locator and crate rejections so trying to load a proc macro doesn't
// affect the error message we emit
let mut proc_macro_locator = locator.clone();
// Try to load a proc macro
- proc_macro_locator.for_target_proc_macro(self.sess, path_kind);
+ proc_macro_locator.for_target_proc_macro(sess, path_kind);
// Load the proc macro crate for the target
let target_result =
@@ -713,7 +701,7 @@ fn load_proc_macro<'b>(
*crate_rejections = CrateRejections::default();
// Load the proc macro crate for the host
- locator.for_proc_macro(self.sess, path_kind);
+ locator.for_proc_macro(sess, path_kind);
locator.hash = host_hash;
@@ -734,7 +722,7 @@ fn load_proc_macro<'b>(
let mut proc_macro_locator = locator.clone();
// Load the proc macro crate for the host
- proc_macro_locator.for_proc_macro(self.sess, path_kind);
+ proc_macro_locator.for_proc_macro(sess, path_kind);
let Some(host_result) =
self.load(&mut proc_macro_locator, &mut CrateRejections::default())?
@@ -746,32 +734,39 @@ fn load_proc_macro<'b>(
}
}
- fn resolve_crate(
+ fn resolve_crate<'tcx>(
&mut self,
+ tcx: TyCtxt<'tcx>,
name: Symbol,
span: Span,
dep_kind: CrateDepKind,
origin: CrateOrigin<'_>,
) -> Option<CrateNum> {
self.used_extern_options.insert(name);
- match self.maybe_resolve_crate(name, dep_kind, origin) {
+ match self.maybe_resolve_crate(tcx, name, dep_kind, origin) {
Ok(cnum) => {
- self.cstore.set_used_recursively(cnum);
+ self.set_used_recursively(cnum);
Some(cnum)
}
Err(err) => {
debug!("failed to resolve crate {} {:?}", name, dep_kind);
let missing_core = self
- .maybe_resolve_crate(sym::core, CrateDepKind::Explicit, CrateOrigin::Extern)
+ .maybe_resolve_crate(
+ tcx,
+ sym::core,
+ CrateDepKind::Explicit,
+ CrateOrigin::Extern,
+ )
.is_err();
- err.report(self.sess, span, missing_core);
+ err.report(tcx.sess, span, missing_core);
None
}
}
}
- fn maybe_resolve_crate<'b>(
+ fn maybe_resolve_crate<'b, 'tcx>(
&'b mut self,
+ tcx: TyCtxt<'tcx>,
name: Symbol,
mut dep_kind: CrateDepKind,
origin: CrateOrigin<'b>,
@@ -789,17 +784,19 @@ fn maybe_resolve_crate<'b>(
let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate };
let private_dep = origin.private_dep();
- let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
+ let result = if let Some(cnum) =
+ self.existing_match(&tcx.sess.opts.externs, name, hash, path_kind)
+ {
(LoadResult::Previous(cnum), None)
} else {
info!("falling back to a load");
let mut locator = CrateLocator::new(
- self.sess,
- &*self.cstore.metadata_loader,
+ tcx.sess,
+ &*self.metadata_loader,
name,
// The all loop is because `--crate-type=rlib --crate-type=rlib` is
// legal and produces both inside this type.
- self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
+ tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
hash,
extra_filename,
path_kind,
@@ -812,6 +809,7 @@ fn maybe_resolve_crate<'b>(
info!("falling back to loading proc_macro");
dep_kind = CrateDepKind::MacrosOnly;
match self.load_proc_macro(
+ tcx.sess,
&mut locator,
&mut crate_rejections,
path_kind,
@@ -831,8 +829,9 @@ fn maybe_resolve_crate<'b>(
// not specified by `--extern` on command line parameters, it may be
// `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
// `public-dependency` here.
- let private_dep = self.is_private_dep(name, private_dep, origin);
- let data = self.cstore.get_crate_data_mut(cnum);
+ let private_dep =
+ self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin);
+ let data = self.get_crate_data_mut(cnum);
if data.is_proc_macro_crate() {
dep_kind = CrateDepKind::MacrosOnly;
}
@@ -842,7 +841,7 @@ fn maybe_resolve_crate<'b>(
}
(LoadResult::Loaded(library), host_library) => {
info!("register newly loaded library for `{}`", name);
- self.register_crate(host_library, origin, library, dep_kind, name, private_dep)
+ self.register_crate(tcx, host_library, origin, library, dep_kind, name, private_dep)
}
_ => panic!(),
}
@@ -863,7 +862,7 @@ fn load(
// duplicates by just using the first crate.
let root = library.metadata.get_root();
let mut result = LoadResult::Loaded(library);
- for (cnum, data) in self.cstore.iter_crate_data() {
+ for (cnum, data) in self.iter_crate_data() {
if data.name() == root.name() && root.hash() == data.hash() {
assert!(locator.hash.is_none());
info!("load success, going to previous cnum: {}", cnum);
@@ -877,6 +876,7 @@ fn load(
/// Go through the crate metadata and load any crates that it references.
fn resolve_crate_deps(
&mut self,
+ tcx: TyCtxt<'_>,
dep_root: &CratePaths,
crate_root: &CrateRoot,
metadata: &MetadataBlob,
@@ -913,6 +913,7 @@ fn resolve_crate_deps(
_ => dep.kind,
};
let cnum = self.maybe_resolve_crate(
+ tcx,
dep.name,
dep_kind,
CrateOrigin::IndirectDependency {
@@ -930,10 +931,11 @@ fn resolve_crate_deps(
fn dlsym_proc_macros(
&self,
+ sess: &Session,
path: &Path,
stable_crate_id: StableCrateId,
) -> Result<&'static [ProcMacro], CrateError> {
- let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
+ let sym_name = sess.generate_proc_macro_decls_symbol(stable_crate_id);
debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name);
unsafe {
@@ -955,10 +957,10 @@ fn dlsym_proc_macros(
}
}
- fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
+ fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
// If we're only compiling an rlib, then there's no need to select a
// panic runtime, so we just skip this section entirely.
- let only_rlib = self.tcx.crate_types().iter().all(|ct| *ct == CrateType::Rlib);
+ let only_rlib = tcx.crate_types().iter().all(|ct| *ct == CrateType::Rlib);
if only_rlib {
info!("panic runtime injection skipped, only generating rlib");
return;
@@ -968,7 +970,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
// the same time we perform some general validation of the DAG we've got
// going such as ensuring everything has a compatible panic strategy.
let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime);
- for (_cnum, data) in self.cstore.iter_crate_data() {
+ for (_cnum, data) in self.iter_crate_data() {
needs_panic_runtime |= data.needs_panic_runtime();
}
@@ -987,7 +989,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
// Also note that we have yet to perform validation of the crate graph
// in terms of everyone has a compatible panic runtime format, that's
// performed later as part of the `dependency_format` module.
- let desired_strategy = self.sess.panic_strategy();
+ let desired_strategy = tcx.sess.panic_strategy();
let name = match desired_strategy {
PanicStrategy::Unwind => sym::panic_unwind,
PanicStrategy::Abort => sym::panic_abort,
@@ -995,64 +997,64 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
info!("panic runtime not found -- loading {}", name);
let Some(cnum) =
- self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected)
+ self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected)
else {
return;
};
- let data = self.cstore.get_crate_data(cnum);
+ let data = self.get_crate_data(cnum);
// Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was.
if !data.is_panic_runtime() {
- self.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name });
+ tcx.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name });
}
if data.required_panic_strategy() != Some(desired_strategy) {
- self.dcx()
+ tcx.dcx()
.emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy });
}
- self.cstore.injected_panic_runtime = Some(cnum);
+ self.injected_panic_runtime = Some(cnum);
}
- fn inject_profiler_runtime(&mut self) {
+ fn inject_profiler_runtime(&mut self, tcx: TyCtxt<'_>) {
let needs_profiler_runtime =
- self.sess.instrument_coverage() || self.sess.opts.cg.profile_generate.enabled();
- if !needs_profiler_runtime || self.sess.opts.unstable_opts.no_profiler_runtime {
+ tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled();
+ if !needs_profiler_runtime || tcx.sess.opts.unstable_opts.no_profiler_runtime {
return;
}
info!("loading profiler");
- let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
+ let name = Symbol::intern(&tcx.sess.opts.unstable_opts.profiler_runtime);
let Some(cnum) =
- self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected)
+ self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected)
else {
return;
};
- let data = self.cstore.get_crate_data(cnum);
+ let data = self.get_crate_data(cnum);
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime() {
- self.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name });
+ tcx.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name });
}
}
- fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
- self.cstore.has_global_allocator =
+ fn inject_allocator_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
+ self.has_global_allocator =
match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) {
[span1, span2, ..] => {
- self.dcx()
+ tcx.dcx()
.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
};
- self.cstore.has_alloc_error_handler = match &*fn_spans(
+ self.has_alloc_error_handler = match &*fn_spans(
krate,
Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)),
) {
[span1, span2, ..] => {
- self.dcx()
+ tcx.dcx()
.emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
true
}
@@ -1063,7 +1065,7 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
// about through the `#![needs_allocator]` attribute and is typically
// written down in liballoc.
if !attr::contains_name(&krate.attrs, sym::needs_allocator)
- && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator())
+ && !self.iter_crate_data().any(|(_, data)| data.needs_allocator())
{
return;
}
@@ -1071,7 +1073,7 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
// At this point we've determined that we need an allocator. Let's see
// if our compilation session actually needs an allocator based on what
// we're emitting.
- let all_rlib = self.tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
+ let all_rlib = tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
if all_rlib {
return;
}
@@ -1086,12 +1088,12 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
#[allow(rustc::symbol_intern_string_literal)]
let this_crate = Symbol::intern("this crate");
- let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate);
- for (_, data) in self.cstore.iter_crate_data() {
+ let mut global_allocator = self.has_global_allocator.then_some(this_crate);
+ for (_, data) in self.iter_crate_data() {
if data.has_global_allocator() {
match global_allocator {
Some(other_crate) => {
- self.dcx().emit_err(errors::ConflictingGlobalAlloc {
+ tcx.dcx().emit_err(errors::ConflictingGlobalAlloc {
crate_name: data.name(),
other_crate_name: other_crate,
});
@@ -1100,12 +1102,12 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
}
}
}
- let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate);
- for (_, data) in self.cstore.iter_crate_data() {
+ let mut alloc_error_handler = self.has_alloc_error_handler.then_some(this_crate);
+ for (_, data) in self.iter_crate_data() {
if data.has_alloc_error_handler() {
match alloc_error_handler {
Some(other_crate) => {
- self.dcx().emit_err(errors::ConflictingAllocErrorHandler {
+ tcx.dcx().emit_err(errors::ConflictingAllocErrorHandler {
crate_name: data.name(),
other_crate_name: other_crate,
});
@@ -1116,35 +1118,36 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
}
if global_allocator.is_some() {
- self.cstore.allocator_kind = Some(AllocatorKind::Global);
+ self.allocator_kind = Some(AllocatorKind::Global);
} else {
// Ok we haven't found a global allocator but we still need an
// allocator. At this point our allocator request is typically fulfilled
// by the standard library, denoted by the `#![default_lib_allocator]`
// attribute.
if !attr::contains_name(&krate.attrs, sym::default_lib_allocator)
- && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
+ && !self.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
- self.dcx().emit_err(errors::GlobalAllocRequired);
+ tcx.dcx().emit_err(errors::GlobalAllocRequired);
}
- self.cstore.allocator_kind = Some(AllocatorKind::Default);
+ self.allocator_kind = Some(AllocatorKind::Default);
}
if alloc_error_handler.is_some() {
- self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global);
+ self.alloc_error_handler_kind = Some(AllocatorKind::Global);
} else {
// The alloc crate provides a default allocation error handler if
// one isn't specified.
- self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
+ self.alloc_error_handler_kind = Some(AllocatorKind::Default);
}
}
- fn inject_forced_externs(&mut self) {
- for (name, entry) in self.sess.opts.externs.iter() {
+ fn inject_forced_externs(&mut self, tcx: TyCtxt<'_>) {
+ for (name, entry) in tcx.sess.opts.externs.iter() {
if entry.force {
let name_interned = Symbol::intern(name);
if !self.used_extern_options.contains(&name_interned) {
self.resolve_crate(
+ tcx,
name_interned,
DUMMY_SP,
CrateDepKind::Explicit,
@@ -1156,7 +1159,7 @@ fn inject_forced_externs(&mut self) {
}
/// Inject the `compiler_builtins` crate if it is not already in the graph.
- fn inject_compiler_builtins(&mut self, krate: &ast::Crate) {
+ fn inject_compiler_builtins(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
// `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates
if attr::contains_name(&krate.attrs, sym::compiler_builtins)
|| attr::contains_name(&krate.attrs, sym::no_core)
@@ -1167,7 +1170,7 @@ fn inject_compiler_builtins(&mut self, krate: &ast::Crate) {
// If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is
// the common case since usually it appears as a dependency of `std` or `alloc`.
- for (cnum, cmeta) in self.cstore.iter_crate_data() {
+ for (cnum, cmeta) in self.iter_crate_data() {
if cmeta.is_compiler_builtins() {
info!("`compiler_builtins` already exists (cnum = {cnum}); skipping injection");
return;
@@ -1176,6 +1179,7 @@ fn inject_compiler_builtins(&mut self, krate: &ast::Crate) {
// `compiler_builtins` is not yet in the graph; inject it. Error on resolution failure.
let Some(cnum) = self.resolve_crate(
+ tcx,
sym::compiler_builtins,
krate.spans.inner_span.shrink_to_lo(),
CrateDepKind::Explicit,
@@ -1186,17 +1190,17 @@ fn inject_compiler_builtins(&mut self, krate: &ast::Crate) {
};
// Sanity check that the loaded crate is `#![compiler_builtins]`
- let cmeta = self.cstore.get_crate_data(cnum);
+ let cmeta = self.get_crate_data(cnum);
if !cmeta.is_compiler_builtins() {
- self.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() });
+ tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() });
}
}
- fn report_unused_deps(&mut self, krate: &ast::Crate) {
+ fn report_unused_deps_in_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
// Make a point span rather than covering the whole file
let span = krate.spans.inner_span.shrink_to_lo();
// Complain about anything left over
- for (name, entry) in self.sess.opts.externs.iter() {
+ for (name, entry) in tcx.sess.opts.externs.iter() {
if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
// Don't worry about pathless `--extern foo` sysroot references
continue;
@@ -1211,25 +1215,25 @@ fn report_unused_deps(&mut self, krate: &ast::Crate) {
}
// Got a real unused --extern
- if self.sess.opts.json_unused_externs.is_enabled() {
- self.cstore.unused_externs.push(name_interned);
+ if tcx.sess.opts.json_unused_externs.is_enabled() {
+ self.unused_externs.push(name_interned);
continue;
}
- self.sess.psess.buffer_lint(
+ tcx.sess.psess.buffer_lint(
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
span,
ast::CRATE_NODE_ID,
BuiltinLintDiag::UnusedCrateDependency {
extern_crate: name_interned,
- local_crate: self.tcx.crate_name(LOCAL_CRATE),
+ local_crate: tcx.crate_name(LOCAL_CRATE),
},
);
}
}
- fn report_future_incompatible_deps(&self, krate: &ast::Crate) {
- let name = self.tcx.crate_name(LOCAL_CRATE);
+ fn report_future_incompatible_deps(&self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
+ let name = tcx.crate_name(LOCAL_CRATE);
if name.as_str() == "wasm_bindgen" {
let major = env::var("CARGO_PKG_VERSION_MAJOR")
@@ -1257,26 +1261,27 @@ fn report_future_incompatible_deps(&self, krate: &ast::Crate) {
// Make a point span rather than covering the whole file
let span = krate.spans.inner_span.shrink_to_lo();
- self.sess.dcx().emit_err(errors::WasmCAbi { span });
+ tcx.sess.dcx().emit_err(errors::WasmCAbi { span });
}
}
- pub fn postprocess(&mut self, krate: &ast::Crate) {
- self.inject_compiler_builtins(krate);
- self.inject_forced_externs();
- self.inject_profiler_runtime();
- self.inject_allocator_crate(krate);
- self.inject_panic_runtime(krate);
+ pub fn postprocess(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
+ self.inject_compiler_builtins(tcx, krate);
+ self.inject_forced_externs(tcx);
+ self.inject_profiler_runtime(tcx);
+ self.inject_allocator_crate(tcx, krate);
+ self.inject_panic_runtime(tcx, krate);
- self.report_unused_deps(krate);
- self.report_future_incompatible_deps(krate);
+ self.report_unused_deps_in_crate(tcx, krate);
+ self.report_future_incompatible_deps(tcx, krate);
- info!("{:?}", CrateDump(self.cstore));
+ info!("{:?}", CrateDump(self));
}
/// Process an `extern crate foo` AST node.
pub fn process_extern_crate(
&mut self,
+ tcx: TyCtxt<'_>,
item: &ast::Item,
def_id: LocalDefId,
definitions: &Definitions,
@@ -1286,7 +1291,7 @@ pub fn process_extern_crate(
debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name);
let name = match orig_name {
Some(orig_name) => {
- validate_crate_name(self.sess, orig_name, Some(item.span));
+ validate_crate_name(tcx.sess, orig_name, Some(item.span));
orig_name
}
None => ident.name,
@@ -1297,10 +1302,11 @@ pub fn process_extern_crate(
CrateDepKind::Explicit
};
- let cnum = self.resolve_crate(name, item.span, dep_kind, CrateOrigin::Extern)?;
+ let cnum =
+ self.resolve_crate(tcx, name, item.span, dep_kind, CrateOrigin::Extern)?;
let path_len = definitions.def_path(def_id).data.len();
- self.cstore.update_extern_crate(
+ self.update_extern_crate(
cnum,
ExternCrate {
src: ExternCrateSource::Extern(def_id.to_def_id()),
@@ -1315,10 +1321,16 @@ pub fn process_extern_crate(
}
}
- pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
- let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?;
+ pub fn process_path_extern(
+ &mut self,
+ tcx: TyCtxt<'_>,
+ name: Symbol,
+ span: Span,
+ ) -> Option<CrateNum> {
+ let cnum =
+ self.resolve_crate(tcx, name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?;
- self.cstore.update_extern_crate(
+ self.update_extern_crate(
cnum,
ExternCrate {
src: ExternCrateSource::Path,
@@ -1332,8 +1344,8 @@ pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateN
Some(cnum)
}
- pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
- self.maybe_resolve_crate(name, CrateDepKind::Explicit, CrateOrigin::Extern).ok()
+ pub fn maybe_process_path_extern(&mut self, tcx: TyCtxt<'_>, name: Symbol) -> Option<CrateNum> {
+ self.maybe_resolve_crate(tcx, name, CrateDepKind::Explicit, CrateOrigin::Extern).ok()
}
}
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 99faba7..dc93111 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -7,10 +7,9 @@
use rustc_attr_data_structures::{
self as attrs, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
};
-use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
use rustc_feature::GateIssue;
-use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, HirId};
use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
use rustc_session::Session;
@@ -65,48 +64,6 @@ pub fn same_origin(&self, other: &DeprecationEntry) -> bool {
}
}
-/// A stability index, giving the stability level for items and methods.
-#[derive(HashStable, Debug)]
-pub struct Index {
- /// This is mostly a cache, except the stabilities of local items
- /// are filled by the annotator.
- pub stab_map: LocalDefIdMap<Stability>,
- pub const_stab_map: LocalDefIdMap<ConstStability>,
- pub default_body_stab_map: LocalDefIdMap<DefaultBodyStability>,
- pub depr_map: LocalDefIdMap<DeprecationEntry>,
- /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
- /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
- /// exists, then this map will have a `impliee -> implier` entry.
- ///
- /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should
- /// specify their implications (both `implies` and `implied_by`). If only one of the two
- /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this
- /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is
- /// reported, only the `#[stable]` attribute information is available, so the map is necessary
- /// to know that the feature implies another feature. If it were reversed, and the `#[stable]`
- /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of
- /// unstable feature" error for a feature that was implied.
- pub implications: UnordMap<Symbol, Symbol>,
-}
-
-impl Index {
- pub fn local_stability(&self, def_id: LocalDefId) -> Option<Stability> {
- self.stab_map.get(&def_id).copied()
- }
-
- pub fn local_const_stability(&self, def_id: LocalDefId) -> Option<ConstStability> {
- self.const_stab_map.get(&def_id).copied()
- }
-
- pub fn local_default_body_stability(&self, def_id: LocalDefId) -> Option<DefaultBodyStability> {
- self.default_body_stab_map.get(&def_id).copied()
- }
-
- pub fn local_deprecation_entry(&self, def_id: LocalDefId) -> Option<DeprecationEntry> {
- self.depr_map.get(&def_id).cloned()
- }
-}
-
pub fn report_unstable(
sess: &Session,
feature: Symbol,
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 133111f..27ead51 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -702,8 +702,11 @@ pub fn read_scalar(
read_provenance: bool,
) -> AllocResult<Scalar<Prov>> {
// First and foremost, if anything is uninit, bail.
- if self.init_mask.is_range_initialized(range).is_err() {
- return Err(AllocError::InvalidUninitBytes(None));
+ if let Err(bad) = self.init_mask.is_range_initialized(range) {
+ return Err(AllocError::InvalidUninitBytes(Some(BadBytesAccess {
+ access: range,
+ bad,
+ })));
}
// Get the integer part of the result. We HAVE TO check provenance before returning this!
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d5c2b6d..ae8c825 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -112,7 +112,7 @@
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::EffectiveVisibilities;
use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
-use crate::middle::stability::{self, DeprecationEntry};
+use crate::middle::stability::DeprecationEntry;
use crate::mir::interpret::{
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
EvalToValTreeResult, GlobalId, LitToConstInput,
@@ -2171,6 +2171,18 @@
separate_provide_extern
arena_cache
}
+ /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
+ /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
+ /// exists, then this map will have a `impliee -> implier` entry.
+ ///
+ /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should
+ /// specify their implications (both `implies` and `implied_by`). If only one of the two
+ /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this
+ /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is
+ /// reported, only the `#[stable]` attribute information is available, so the map is necessary
+ /// to know that the feature implies another feature. If it were reversed, and the `#[stable]`
+ /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of
+ /// unstable feature" error for a feature that was implied.
query stability_implications(_: CrateNum) -> &'tcx UnordMap<Symbol, Symbol> {
arena_cache
desc { "calculating the implications between `#[unstable]` features defined in a crate" }
@@ -2277,11 +2289,6 @@
desc { "fetching potentially unused trait imports" }
}
- query stability_index(_: ()) -> &'tcx stability::Index {
- arena_cache
- eval_always
- desc { "calculating the stability index for the local crate" }
- }
/// All available crates in the graph, including those that should not be user-facing
/// (such as private crates).
query crates(_: ()) -> &'tcx [CrateNum] {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 81c13e5..7e6bcfe 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -65,7 +65,7 @@
use crate::lint::lint_level;
use crate::metadata::ModChild;
use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
-use crate::middle::{resolve_bound_vars, stability};
+use crate::middle::resolve_bound_vars;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::query::plumbing::QuerySystem;
@@ -1807,10 +1807,6 @@ pub fn coroutine_is_async_gen(self, def_id: DefId) -> bool {
)
}
- pub fn stability(self) -> &'tcx stability::Index {
- self.stability_index(())
- }
-
pub fn features(self) -> &'tcx rustc_feature::Features {
self.features_query(())
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2eb530f..9ee64df 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1210,30 +1210,6 @@ fn pretty_print_opaque_impl_type(
}
for (assoc_item_def_id, term) in assoc_items {
- // Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks,
- // unless we can find out what coroutine return type it comes from.
- let term = if let Some(ty) = term.skip_binder().as_type()
- && let ty::Alias(ty::Projection, proj) = ty.kind()
- && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
- && assoc
- .trait_container(tcx)
- .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
- && assoc.opt_name() == Some(rustc_span::sym::Return)
- {
- if let ty::Coroutine(_, args) = args.type_at(0).kind() {
- let return_ty = args.as_coroutine().return_ty();
- if !return_ty.is_ty_var() {
- return_ty.into()
- } else {
- continue;
- }
- } else {
- continue;
- }
- } else {
- term.skip_binder()
- };
-
if first {
p!("<");
first = false;
@@ -1243,7 +1219,7 @@ fn pretty_print_opaque_impl_type(
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
- match term.kind() {
+ match term.skip_binder().kind() {
TermKind::Ty(ty) => p!(print(ty)),
TermKind::Const(c) => p!(print(c)),
};
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 07717b7..6657f89 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -579,7 +579,7 @@ fn eval_to_const(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> {
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) => {
let src = self.evaluated[value].as_ref()?;
let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
- self.ecx.unsize_into(src, ty, &dest.clone().into()).discard_err()?;
+ self.ecx.unsize_into(src, ty, &dest).discard_err()?;
self.ecx
.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id())
.discard_err()?;
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 93a81f0..7f9234d 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -64,15 +64,15 @@ fn process<'tcx>(
typing_env: ty::TypingEnv<'tcx>,
caller: ty::Instance<'tcx>,
target: LocalDefId,
- seen: &mut FxHashSet<ty::Instance<'tcx>>,
+ seen: &mut FxHashMap<ty::Instance<'tcx>, bool>,
involved: &mut FxHashSet<LocalDefId>,
recursion_limiter: &mut FxHashMap<DefId, usize>,
recursion_limit: Limit,
) -> bool {
trace!(%caller);
- let mut cycle_found = false;
+ let mut reaches_root = false;
- for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
+ for &(callee_def_id, args) in tcx.mir_inliner_callees(caller.def) {
let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
tcx,
typing_env,
@@ -81,14 +81,17 @@ fn process<'tcx>(
trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping");
continue;
};
- let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else {
- trace!(?callee, "cannot resolve, skipping");
+ let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee_def_id, args)
+ else {
+ trace!(?callee_def_id, "cannot resolve, skipping");
continue;
};
// Found a path.
if callee.def_id() == target.to_def_id() {
- cycle_found = true;
+ reaches_root = true;
+ seen.insert(callee, true);
+ continue;
}
if tcx.is_constructor(callee.def_id()) {
@@ -101,10 +104,17 @@ fn process<'tcx>(
continue;
}
- if seen.insert(callee) {
+ let callee_reaches_root = if let Some(&c) = seen.get(&callee) {
+ // Even if we have seen this callee before, and thus don't need
+ // to recurse into it, we still need to propagate whether it reaches
+ // the root so that we can mark all the involved callers, in case we
+ // end up reaching that same recursive callee through some *other* cycle.
+ c
+ } else {
+ seen.insert(callee, false);
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
trace!(?callee, recursion = *recursion);
- let found_recursion = if recursion_limit.value_within_limit(*recursion) {
+ let callee_reaches_root = if recursion_limit.value_within_limit(*recursion) {
*recursion += 1;
ensure_sufficient_stack(|| {
process(
@@ -122,17 +132,19 @@ fn process<'tcx>(
// Pessimistically assume that there could be recursion.
true
};
- if found_recursion {
- if let Some(callee) = callee.def_id().as_local() {
- // Calling `optimized_mir` of a non-local definition cannot cycle.
- involved.insert(callee);
- }
- cycle_found = true;
+ seen.insert(callee, callee_reaches_root);
+ callee_reaches_root
+ };
+ if callee_reaches_root {
+ if let Some(callee_def_id) = callee.def_id().as_local() {
+ // Calling `optimized_mir` of a non-local definition cannot cycle.
+ involved.insert(callee_def_id);
}
+ reaches_root = true;
}
}
- cycle_found
+ reaches_root
}
#[instrument(level = "debug", skip(tcx), ret)]
@@ -166,7 +178,7 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>(
typing_env,
root_instance,
root,
- &mut FxHashSet::default(),
+ &mut FxHashMap::default(),
&mut involved,
&mut FxHashMap::default(),
recursion_limit,
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 098dc9d..650b85d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -1219,10 +1219,8 @@ fn disqualify_auto_trait_candidate_due_to_possible_impl(
// the type (even if after unification and processing nested goals
// it does not hold) will disqualify the built-in auto impl.
//
- // This differs from the current stable behavior and fixes #84857.
- // Due to breakage found via crater, we currently instead lint
- // patterns which can be used to exploit this unsoundness on stable,
- // see #93367 for more details.
+ // We've originally had a more permissive check here which resulted
+ // in unsoundness, see #84857.
ty::Bool
| ty::Char
| ty::Int(_)
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
index 0b97d4e..6de001f 100644
--- a/compiler/rustc_parse/src/lexer/diagnostics.rs
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -34,9 +34,12 @@ pub(super) fn same_indentation_level(sm: &SourceMap, open_sp: Span, close_sp: Sp
// When we get a `)` or `]` for `{`, we should emit help message here
// it's more friendly compared to report `unmatched error` in later phase
-fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[UnmatchedDelim]) -> bool {
+pub(super) fn report_missing_open_delim(
+ err: &mut Diag<'_>,
+ unmatched_delims: &mut Vec<UnmatchedDelim>,
+) -> bool {
let mut reported_missing_open = false;
- for unmatch_brace in unmatched_delims.iter() {
+ unmatched_delims.retain(|unmatch_brace| {
if let Some(delim) = unmatch_brace.found_delim
&& matches!(delim, Delimiter::Parenthesis | Delimiter::Bracket)
{
@@ -45,13 +48,20 @@ fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[UnmatchedDe
Delimiter::Bracket => "[",
_ => unreachable!(),
};
+
+ if let Some(unclosed_span) = unmatch_brace.unclosed_span {
+ err.span_label(unclosed_span, "the nearest open delimiter");
+ }
err.span_label(
unmatch_brace.found_span.shrink_to_lo(),
format!("missing open `{missed_open}` for this delimiter"),
);
reported_missing_open = true;
+ false
+ } else {
+ true
}
- }
+ });
reported_missing_open
}
@@ -61,10 +71,6 @@ pub(super) fn report_suspicious_mismatch_block(
sm: &SourceMap,
delim: Delimiter,
) {
- if report_missing_open_delim(err, &diag_info.unmatched_delims) {
- return;
- }
-
let mut matched_spans: Vec<(Span, bool)> = diag_info
.matching_block_spans
.iter()
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index fbea958..6474819 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -3,7 +3,9 @@
use rustc_ast_pretty::pprust::token_to_string;
use rustc_errors::Diag;
-use super::diagnostics::{report_suspicious_mismatch_block, same_indentation_level};
+use super::diagnostics::{
+ report_missing_open_delim, report_suspicious_mismatch_block, same_indentation_level,
+};
use super::{Lexer, UnmatchedDelim};
impl<'psess, 'src> Lexer<'psess, 'src> {
@@ -244,7 +246,16 @@ fn close_delim_err(&mut self, delim: Delimiter) -> Diag<'psess> {
let msg = format!("unexpected closing delimiter: `{token_str}`");
let mut err = self.dcx().struct_span_err(self.token.span, msg);
- report_suspicious_mismatch_block(&mut err, &self.diag_info, self.psess.source_map(), delim);
+ // if there is no missing open delim, report suspicious mismatch block
+ if !report_missing_open_delim(&mut err, &mut self.diag_info.unmatched_delims) {
+ report_suspicious_mismatch_block(
+ &mut err,
+ &self.diag_info,
+ self.psess.source_map(),
+ delim,
+ );
+ }
+
err.span_label(self.token.span, "unexpected closing delimiter");
err
}
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index d1b856c..51e23ed 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -560,7 +560,8 @@
`#[{$attr_name}]` only has an effect on {$target_name ->
[function] functions
[module] modules
- [implementation_block] implementation blocks
+ [trait_implementation_block] trait implementation blocks
+ [inherent_implementation_block] inherent implementation blocks
*[unspecified] (unspecified--this is a compiler bug)
}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2766b14..3ec6a11 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -11,11 +11,17 @@
use rustc_abi::{Align, ExternAbi, Size};
use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms};
-use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr};
+use rustc_attr_data_structures::{
+ AttributeKind, InlineAttr, PartialConstStability, ReprAttr, Stability, StabilityLevel,
+ find_attr,
+};
use rustc_attr_parsing::{AttributeParser, Late};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
-use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
+use rustc_feature::{
+ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
+ BuiltinAttribute,
+};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalModDefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -36,6 +42,7 @@
use rustc_session::lint::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
+ USELESS_DEPRECATED,
};
use rustc_session::parse::feature_err;
use rustc_span::edition::Edition;
@@ -161,12 +168,18 @@ fn check_attributes(
sym::automatically_derived,
*attr_span,
target,
- Target::Impl,
+ Target::Impl { of_trait: true },
),
Attribute::Parsed(
- AttributeKind::Stability { span, .. }
- | AttributeKind::ConstStability { span, .. },
- ) => self.check_stability_promotable(*span, target),
+ AttributeKind::Stability {
+ span: attr_span,
+ stability: Stability { level, feature },
+ }
+ | AttributeKind::ConstStability {
+ span: attr_span,
+ stability: PartialConstStability { level, feature, .. },
+ },
+ ) => self.check_stability(*attr_span, span, level, *feature, target),
Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
self.check_inline(hir_id, *attr_span, span, kind, target)
@@ -494,7 +507,7 @@ fn check_do_not_recommend(
attr: &Attribute,
item: Option<ItemLike<'_>>,
) {
- if !matches!(target, Target::Impl)
+ if !matches!(target, Target::Impl { .. })
|| matches!(
item,
Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl),.. }))
@@ -598,7 +611,7 @@ fn check_coverage(&self, attr_span: Span, target_span: Span, target: Target) {
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
- | Target::Impl
+ | Target::Impl { .. }
| Target::Mod => return,
// These are "functions", but they aren't allowed because they don't
@@ -987,9 +1000,9 @@ fn check_doc_alias_value(
let span = meta.span();
if let Some(location) = match target {
Target::AssocTy => {
- let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
- let containing_item = self.tcx.hir_expect_item(parent_def_id);
- if Target::from_item(containing_item) == Target::Impl {
+ if let DefKind::Impl { .. } =
+ self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id))
+ {
Some("type alias in implementation block")
} else {
None
@@ -1012,7 +1025,7 @@ fn check_doc_alias_value(
| Target::Arm
| Target::ForeignMod
| Target::Closure
- | Target::Impl
+ | Target::Impl { .. }
| Target::WherePredicate => Some(target.name()),
Target::ExternCrate
| Target::Use
@@ -1033,7 +1046,7 @@ fn check_doc_alias_value(
| Target::ForeignFn
| Target::ForeignStatic
| Target::ForeignTy
- | Target::GenericParam(..)
+ | Target::GenericParam { .. }
| Target::MacroDef
| Target::PatField
| Target::ExprField => None,
@@ -1590,7 +1603,7 @@ fn check_must_use(&self, hir_id: HirId, attr_span: Span, target: Target) {
let article = match target {
Target::ExternCrate
| Target::Enum
- | Target::Impl
+ | Target::Impl { .. }
| Target::Expression
| Target::Arm
| Target::AssocConst
@@ -2274,7 +2287,7 @@ fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Targ
match target {
// FIXME(staged_api): There's no reason we can't support more targets here. We're just
// being conservative to begin with.
- Target::Fn | Target::Impl => {}
+ Target::Fn | Target::Impl { .. } => {}
Target::ExternCrate
| Target::Use
| Target::Static
@@ -2300,7 +2313,7 @@ fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Targ
| Target::ForeignFn
| Target::ForeignStatic
| Target::ForeignTy
- | Target::GenericParam(_)
+ | Target::GenericParam { .. }
| Target::MacroDef
| Target::Param
| Target::PatField
@@ -2320,13 +2333,30 @@ fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: T
}
}
- fn check_stability_promotable(&self, span: Span, target: Target) {
+ fn check_stability(
+ &self,
+ attr_span: Span,
+ item_span: Span,
+ level: &StabilityLevel,
+ feature: Symbol,
+ target: Target,
+ ) {
match target {
Target::Expression => {
- self.dcx().emit_err(errors::StabilityPromotable { attr_span: span });
+ self.dcx().emit_err(errors::StabilityPromotable { attr_span });
}
_ => {}
}
+
+ // Stable *language* features shouldn't be used as unstable library features.
+ // (Not doing this for stable library features is checked by tidy.)
+ if level.is_unstable()
+ && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
+ {
+ self.tcx
+ .dcx()
+ .emit_err(errors::UnstableAttrForAlreadyStableFeature { attr_span, item_span });
+ }
}
fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) {
@@ -2354,6 +2384,28 @@ fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target:
errors::Deprecated,
);
}
+ Target::Impl { of_trait: true }
+ | Target::GenericParam { has_default: false, kind: _ } => {
+ self.tcx.emit_node_span_lint(
+ USELESS_DEPRECATED,
+ hir_id,
+ attr.span(),
+ errors::DeprecatedAnnotationHasNoEffect { span: attr.span() },
+ );
+ }
+ Target::AssocConst | Target::Method(..) | Target::AssocTy
+ if matches!(
+ self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id)),
+ DefKind::Impl { of_trait: true }
+ ) =>
+ {
+ self.tcx.emit_node_span_lint(
+ USELESS_DEPRECATED,
+ hir_id,
+ attr.span(),
+ errors::DeprecatedAnnotationHasNoEffect { span: attr.span() },
+ );
+ }
_ => {}
}
}
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 37330c0..c6ab6b0 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1373,9 +1373,9 @@ pub(crate) struct UnstableAttrForAlreadyStableFeature {
#[primary_span]
#[label]
#[help]
- pub span: Span,
+ pub attr_span: Span,
#[label(passes_item)]
- pub item_sp: Span,
+ pub item_span: Span,
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 3afed97..6fac018 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -287,7 +287,7 @@ fn visit_item(&mut self, i: &'ast ast::Item) {
ast::ItemKind::Union(..) => Target::Union,
ast::ItemKind::Trait(_) => Target::Trait,
ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
- ast::ItemKind::Impl(_) => Target::Impl,
+ ast::ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
ast::ItemKind::MacroDef(..) => Target::MacroDef,
ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
unreachable!("macros should have been expanded")
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 127e0df..35d2a65 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -44,7 +44,7 @@ fn extract(&self, attr: &Attribute) -> Option<(Symbol, FeatureStability, Span)>
StabilityLevel::Stable { since, .. } => FeatureStability::AcceptedSince(match since {
StableSince::Version(v) => Symbol::intern(&v.to_string()),
StableSince::Current => sym::env_CFG_RELEASE,
- StableSince::Err => return None,
+ StableSince::Err(_) => return None,
}),
};
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index e5530d5..40999d6 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1,37 +1,31 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-use std::mem::replace;
use std::num::NonZero;
use rustc_ast_lowering::stability::extern_abi_stability;
use rustc_attr_data_structures::{
- self as attrs, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability,
- Stability, StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr,
+ self as attrs, AttributeKind, ConstStability, DefaultBodyStability, DeprecatedSince, Stability,
+ StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr,
};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
-use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature};
+use rustc_feature::{EnabledLangFeature, EnabledLibFeature};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
-use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{self as hir, AmbigArg, FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::middle::privacy::EffectiveVisibilities;
-use rustc_middle::middle::stability::{
- AllowUnstable, Deprecated, DeprecationEntry, EvalResult, Index,
-};
-use rustc_middle::query::Providers;
+use rustc_middle::middle::stability::{AllowUnstable, Deprecated, DeprecationEntry, EvalResult};
+use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::lint;
-use rustc_session::lint::builtin::{
- DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED,
-};
+use rustc_session::lint::builtin::{DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL};
use rustc_span::{Span, Symbol, sym};
-use tracing::{debug, info};
+use tracing::instrument;
use crate::errors;
@@ -47,168 +41,372 @@ enum AnnotationKind {
Container,
}
-/// Whether to inherit deprecation flags for nested items. In most cases, we do want to inherit
-/// deprecation, because nested items rarely have individual deprecation attributes, and so
-/// should be treated as deprecated if their parent is. However, default generic parameters
-/// have separate deprecation attributes from their parents, so we do not wish to inherit
-/// deprecation in this case. For example, inheriting deprecation for `T` in `Foo<T>`
-/// would cause a duplicate warning arising from both `Foo` and `T` being deprecated.
-#[derive(Clone)]
-enum InheritDeprecation {
- Yes,
- No,
-}
-
-impl InheritDeprecation {
- fn yes(&self) -> bool {
- matches!(self, InheritDeprecation::Yes)
+fn inherit_deprecation(def_kind: DefKind) -> bool {
+ match def_kind {
+ DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => false,
+ _ => true,
}
}
-/// Whether to inherit const stability flags for nested items. In most cases, we do not want to
-/// inherit const stability: just because an enclosing `fn` is const-stable does not mean
-/// all `extern` imports declared in it should be const-stable! However, trait methods
-/// inherit const stability attributes from their parent and do not have their own.
-enum InheritConstStability {
- Yes,
- No,
-}
-
-impl InheritConstStability {
- fn yes(&self) -> bool {
- matches!(self, InheritConstStability::Yes)
+fn inherit_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ let def_kind = tcx.def_kind(def_id);
+ match def_kind {
+ DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
+ match tcx.def_kind(tcx.local_parent(def_id)) {
+ DefKind::Impl { of_trait: true } => true,
+ _ => false,
+ }
+ }
+ _ => false,
}
}
-enum InheritStability {
- Yes,
- No,
+fn annotation_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> AnnotationKind {
+ let def_kind = tcx.def_kind(def_id);
+ match def_kind {
+ // Inherent impls and foreign modules serve only as containers for other items,
+ // they don't have their own stability. They still can be annotated as unstable
+ // and propagate this unstability to children, but this annotation is completely
+ // optional. They inherit stability from their parents when unannotated.
+ DefKind::Impl { of_trait: false } | DefKind::ForeignMod => AnnotationKind::Container,
+ DefKind::Impl { of_trait: true } => AnnotationKind::DeprecationProhibited,
+
+ // Allow stability attributes on default generic arguments.
+ DefKind::TyParam | DefKind::ConstParam => {
+ match &tcx.hir_node_by_def_id(def_id).expect_generic_param().kind {
+ hir::GenericParamKind::Type { default: Some(_), .. }
+ | hir::GenericParamKind::Const { default: Some(_), .. } => {
+ AnnotationKind::Container
+ }
+ _ => AnnotationKind::Prohibited,
+ }
+ }
+
+ // Impl items in trait impls cannot have stability.
+ DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst => {
+ match tcx.def_kind(tcx.local_parent(def_id)) {
+ DefKind::Impl { of_trait: true } => AnnotationKind::Prohibited,
+ _ => AnnotationKind::Required,
+ }
+ }
+
+ _ => AnnotationKind::Required,
+ }
}
-impl InheritStability {
- fn yes(&self) -> bool {
- matches!(self, InheritStability::Yes)
+fn lookup_deprecation_entry(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DeprecationEntry> {
+ let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
+ let depr = attrs::find_attr!(attrs,
+ AttributeKind::Deprecation { deprecation, span: _ } => *deprecation
+ );
+
+ let Some(depr) = depr else {
+ if inherit_deprecation(tcx.def_kind(def_id)) {
+ let parent_id = tcx.opt_local_parent(def_id)?;
+ let parent_depr = tcx.lookup_deprecation_entry(parent_id)?;
+ return Some(parent_depr);
+ }
+
+ return None;
+ };
+
+ // `Deprecation` is just two pointers, no need to intern it
+ Some(DeprecationEntry::local(depr, def_id))
+}
+
+fn inherit_stability(def_kind: DefKind) -> bool {
+ match def_kind {
+ DefKind::Field | DefKind::Variant | DefKind::Ctor(..) => true,
+ _ => false,
}
}
+/// If the `-Z force-unstable-if-unmarked` flag is passed then we provide
+/// a parent stability annotation which indicates that this is private
+/// with the `rustc_private` feature. This is intended for use when
+/// compiling library and `rustc_*` crates themselves so we can leverage crates.io
+/// while maintaining the invariant that all sysroot crates are unstable
+/// by default and are unable to be used.
+const FORCE_UNSTABLE: Stability = Stability {
+ level: attrs::StabilityLevel::Unstable {
+ reason: UnstableReason::Default,
+ issue: NonZero::new(27812),
+ is_soft: false,
+ implied_by: None,
+ old_name: None,
+ },
+ feature: sym::rustc_private,
+};
+
+#[instrument(level = "debug", skip(tcx))]
+fn lookup_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Stability> {
+ // Propagate unstability. This can happen even for non-staged-api crates in case
+ // -Zforce-unstable-if-unmarked is set.
+ if !tcx.features().staged_api() {
+ if !tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
+ return None;
+ }
+
+ let Some(parent) = tcx.opt_local_parent(def_id) else { return Some(FORCE_UNSTABLE) };
+
+ if inherit_deprecation(tcx.def_kind(def_id)) {
+ let parent = tcx.lookup_stability(parent)?;
+ if parent.is_unstable() {
+ return Some(parent);
+ }
+ }
+
+ return None;
+ }
+
+ // # Regular stability
+ let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
+ let stab =
+ attrs::find_attr!(attrs, AttributeKind::Stability { stability, span: _ } => *stability);
+
+ if let Some(stab) = stab {
+ return Some(stab);
+ }
+
+ if inherit_deprecation(tcx.def_kind(def_id)) {
+ let Some(parent) = tcx.opt_local_parent(def_id) else {
+ return tcx
+ .sess
+ .opts
+ .unstable_opts
+ .force_unstable_if_unmarked
+ .then_some(FORCE_UNSTABLE);
+ };
+ let parent = tcx.lookup_stability(parent)?;
+ if parent.is_unstable() || inherit_stability(tcx.def_kind(def_id)) {
+ return Some(parent);
+ }
+ }
+
+ None
+}
+
+#[instrument(level = "debug", skip(tcx))]
+fn lookup_default_body_stability(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+) -> Option<DefaultBodyStability> {
+ if !tcx.features().staged_api() {
+ return None;
+ }
+
+ let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
+ // FIXME: check that this item can have body stability
+ attrs::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability)
+}
+
+#[instrument(level = "debug", skip(tcx))]
+fn lookup_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ConstStability> {
+ if !tcx.features().staged_api() {
+ // Propagate unstability. This can happen even for non-staged-api crates in case
+ // -Zforce-unstable-if-unmarked is set.
+ if inherit_deprecation(tcx.def_kind(def_id)) {
+ let parent = tcx.opt_local_parent(def_id)?;
+ let parent_stab = tcx.lookup_stability(parent)?;
+ if parent_stab.is_unstable()
+ && let Some(fn_sig) = tcx.hir_node_by_def_id(def_id).fn_sig()
+ && fn_sig.header.is_const()
+ {
+ let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
+ let const_stability_indirect =
+ find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
+ return Some(ConstStability::unmarked(const_stability_indirect, parent_stab));
+ }
+ }
+
+ return None;
+ }
+
+ let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
+ let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
+ let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability { stability, span: _ } => *stability);
+
+ // After checking the immediate attributes, get rid of the span and compute implied
+ // const stability: inherit feature gate from regular stability.
+ let mut const_stab = const_stab
+ .map(|const_stab| ConstStability::from_partial(const_stab, const_stability_indirect));
+
+ // If this is a const fn but not annotated with stability markers, see if we can inherit
+ // regular stability.
+ if let Some(fn_sig) = tcx.hir_node_by_def_id(def_id).fn_sig()
+ && fn_sig.header.is_const()
+ && const_stab.is_none()
+ // We only ever inherit unstable features.
+ && let Some(inherit_regular_stab) = tcx.lookup_stability(def_id)
+ && inherit_regular_stab.is_unstable()
+ {
+ const_stab = Some(ConstStability {
+ // We subject these implicitly-const functions to recursive const stability.
+ const_stable_indirect: true,
+ promotable: false,
+ level: inherit_regular_stab.level,
+ feature: inherit_regular_stab.feature,
+ });
+ }
+
+ if let Some(const_stab) = const_stab {
+ return Some(const_stab);
+ }
+
+ // `impl const Trait for Type` items forward their const stability to their immediate children.
+ // FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
+ // Currently, once that is set, we do not inherit anything from the parent any more.
+ if inherit_const_stability(tcx, def_id) {
+ let parent = tcx.opt_local_parent(def_id)?;
+ let parent = tcx.lookup_const_stability(parent)?;
+ if parent.is_const_unstable() {
+ return Some(parent);
+ }
+ }
+
+ None
+}
+
/// A private tree-walker for producing an `Index`.
-struct Annotator<'a, 'tcx> {
+struct Annotator<'tcx> {
tcx: TyCtxt<'tcx>,
- index: &'a mut Index,
- parent_stab: Option<Stability>,
- parent_const_stab: Option<ConstStability>,
- parent_depr: Option<DeprecationEntry>,
- in_trait_impl: bool,
+ implications: UnordMap<Symbol, Symbol>,
}
-impl<'a, 'tcx> Annotator<'a, 'tcx> {
+impl<'tcx> Annotator<'tcx> {
/// Determine the stability for a node based on its attributes and inherited stability. The
/// stability is recorded in the index and used as the parent. If the node is a function,
/// `fn_sig` is its signature.
- fn annotate<F>(
- &mut self,
- def_id: LocalDefId,
- item_sp: Span,
- fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
- kind: AnnotationKind,
- inherit_deprecation: InheritDeprecation,
- inherit_const_stability: InheritConstStability,
- inherit_from_parent: InheritStability,
- visit_children: F,
- ) where
- F: FnOnce(&mut Self),
- {
- let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
- debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
-
- let depr = attrs::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
- let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
-
- let mut is_deprecated = false;
- if let Some((depr, span)) = &depr {
- is_deprecated = true;
-
- if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
- let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
- self.tcx.emit_node_span_lint(
- USELESS_DEPRECATED,
- hir_id,
- *span,
- errors::DeprecatedAnnotationHasNoEffect { span: *span },
- );
- }
-
- // `Deprecation` is just two pointers, no need to intern it
- let depr_entry = DeprecationEntry::local(*depr, def_id);
- self.index.depr_map.insert(def_id, depr_entry);
- } else if let Some(parent_depr) = self.parent_depr {
- if inherit_deprecation.yes() {
- is_deprecated = true;
- info!("tagging child {:?} as deprecated from parent", def_id);
- self.index.depr_map.insert(def_id, parent_depr);
- }
- }
-
+ #[instrument(level = "trace", skip(self))]
+ fn annotate(&mut self, def_id: LocalDefId) {
if !self.tcx.features().staged_api() {
- // Propagate unstability. This can happen even for non-staged-api crates in case
- // -Zforce-unstable-if-unmarked is set.
- if let Some(stab) = self.parent_stab {
- if inherit_deprecation.yes() && stab.is_unstable() {
- self.index.stab_map.insert(def_id, stab);
- if fn_sig.is_some_and(|s| s.header.is_const()) {
- self.index.const_stab_map.insert(
- def_id,
- ConstStability::unmarked(const_stability_indirect, stab),
- );
- }
- }
- }
-
- self.recurse_with_stability_attrs(
- depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
- None,
- None,
- visit_children,
- );
return;
}
- // # Regular and body stability
- let stab = attrs::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span));
- let body_stab =
- attrs::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability);
-
- if let Some((depr, span)) = &depr
- && depr.is_since_rustc_version()
- && stab.is_none()
+ if let Some(stability) = self.tcx.lookup_stability(def_id)
+ && let StabilityLevel::Unstable { implied_by: Some(implied_by), .. } = stability.level
{
- self.tcx.dcx().emit_err(errors::DeprecatedAttribute { span: *span });
+ self.implications.insert(implied_by, stability.feature);
}
- if let Some(body_stab) = body_stab {
- // FIXME: check that this item can have body stability
-
- self.index.default_body_stab_map.insert(def_id, body_stab);
- debug!(?self.index.default_body_stab_map);
+ if let Some(stability) = self.tcx.lookup_const_stability(def_id)
+ && let StabilityLevel::Unstable { implied_by: Some(implied_by), .. } = stability.level
+ {
+ self.implications.insert(implied_by, stability.feature);
}
+ }
+}
- let stab = stab.map(|(stab, span)| {
- // Error if prohibited, or can't inherit anything from a container.
- if kind == AnnotationKind::Prohibited
- || (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
- {
- self.tcx.dcx().emit_err(errors::UselessStability { span, item_sp });
+impl<'tcx> Visitor<'tcx> for Annotator<'tcx> {
+ /// Because stability levels are scoped lexically, we want to walk
+ /// nested items in the context of the outer item, so enable
+ /// deep-walking.
+ type NestedFilter = nested_filter::All;
+
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
+ }
+
+ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
+ match i.kind {
+ hir::ItemKind::Struct(_, _, ref sd) => {
+ if let Some(ctor_def_id) = sd.ctor_def_id() {
+ self.annotate(ctor_def_id);
+ }
}
+ _ => {}
+ }
- debug!("annotate: found {:?}", stab);
+ self.annotate(i.owner_id.def_id);
+ intravisit::walk_item(self, i)
+ }
+
+ fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
+ self.annotate(ti.owner_id.def_id);
+ intravisit::walk_trait_item(self, ti);
+ }
+
+ fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
+ self.annotate(ii.owner_id.def_id);
+ intravisit::walk_impl_item(self, ii);
+ }
+
+ fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
+ self.annotate(var.def_id);
+ if let Some(ctor_def_id) = var.data.ctor_def_id() {
+ self.annotate(ctor_def_id);
+ }
+
+ intravisit::walk_variant(self, var)
+ }
+
+ fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
+ self.annotate(s.def_id);
+ intravisit::walk_field_def(self, s);
+ }
+
+ fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
+ self.annotate(i.owner_id.def_id);
+ intravisit::walk_foreign_item(self, i);
+ }
+
+ fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
+ self.annotate(p.def_id);
+ intravisit::walk_generic_param(self, p);
+ }
+}
+
+struct MissingStabilityAnnotations<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ effective_visibilities: &'tcx EffectiveVisibilities,
+}
+
+impl<'tcx> MissingStabilityAnnotations<'tcx> {
+ /// Verify that deprecation and stability attributes make sense with one another.
+ #[instrument(level = "trace", skip(self))]
+ fn check_compatible_stability(&self, def_id: LocalDefId) {
+ if !self.tcx.features().staged_api() {
+ return;
+ }
+
+ let depr = self.tcx.lookup_deprecation_entry(def_id);
+ let stab = self.tcx.lookup_stability(def_id);
+ let const_stab = self.tcx.lookup_const_stability(def_id);
+
+ macro_rules! find_attr_span {
+ ($name:ident) => {{
+ let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
+ attrs::find_attr!(attrs, AttributeKind::$name { span, .. } => *span)
+ }}
+ }
+
+ if stab.is_none()
+ && depr.map_or(false, |d| d.attr.is_since_rustc_version())
+ && let Some(span) = find_attr_span!(Deprecation)
+ {
+ self.tcx.dcx().emit_err(errors::DeprecatedAttribute { span });
+ }
+
+ if let Some(stab) = stab {
+ // Error if prohibited, or can't inherit anything from a container.
+ let kind = annotation_kind(self.tcx, def_id);
+ if kind == AnnotationKind::Prohibited
+ || (kind == AnnotationKind::Container && stab.level.is_stable() && depr.is_some())
+ {
+ if let Some(span) = find_attr_span!(Stability) {
+ let item_sp = self.tcx.def_span(def_id);
+ self.tcx.dcx().emit_err(errors::UselessStability { span, item_sp });
+ }
+ }
// Check if deprecated_since < stable_since. If it is,
// this is *almost surely* an accident.
- if let (
- &Some(DeprecatedSince::RustcVersion(dep_since)),
- &attrs::StabilityLevel::Stable { since: stab_since, .. },
- ) = (&depr.as_ref().map(|(d, _)| d.since), &stab.level)
+ if let Some(depr) = depr
+ && let DeprecatedSince::RustcVersion(dep_since) = depr.attr.since
+ && let attrs::StabilityLevel::Stable { since: stab_since, .. } = stab.level
+ && let Some(span) = find_attr_span!(Stability)
{
+ let item_sp = self.tcx.def_span(def_id);
match stab_since {
StableSince::Current => {
self.tcx
@@ -222,393 +420,61 @@ fn annotate<F>(
.emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
}
}
- StableSince::Err => {
+ StableSince::Err(_) => {
// An error already reported. Assume the unparseable stabilization
// version is older than the deprecation version.
}
}
}
-
- // Stable *language* features shouldn't be used as unstable library features.
- // (Not doing this for stable library features is checked by tidy.)
- if let Stability { level: StabilityLevel::Unstable { .. }, feature } = stab {
- if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
- self.tcx
- .dcx()
- .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp });
- }
- }
- if let Stability {
- level: StabilityLevel::Unstable { implied_by: Some(implied_by), .. },
- feature,
- } = stab
- {
- self.index.implications.insert(implied_by, feature);
- }
-
- self.index.stab_map.insert(def_id, stab);
- stab
- });
-
- if stab.is_none() {
- debug!("annotate: stab not found, parent = {:?}", self.parent_stab);
- if let Some(stab) = self.parent_stab {
- if inherit_deprecation.yes() && stab.is_unstable() || inherit_from_parent.yes() {
- self.index.stab_map.insert(def_id, stab);
- }
- }
}
- let final_stab = self.index.stab_map.get(&def_id);
-
- // # Const stability
-
- let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span));
-
// If the current node is a function with const stability attributes (directly given or
// implied), check if the function/method is const or the parent impl block is const.
+ let fn_sig = self.tcx.hir_node_by_def_id(def_id).fn_sig();
if let Some(fn_sig) = fn_sig
&& !fn_sig.header.is_const()
&& const_stab.is_some()
+ && find_attr_span!(ConstStability).is_some()
{
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
}
// If this is marked const *stable*, it must also be regular-stable.
- if let Some((const_stab, const_span)) = const_stab
+ if let Some(const_stab) = const_stab
&& let Some(fn_sig) = fn_sig
&& const_stab.is_const_stable()
&& !stab.is_some_and(|s| s.is_stable())
+ && let Some(const_span) = find_attr_span!(ConstStability)
{
self.tcx
.dcx()
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
}
- // Stable *language* features shouldn't be used as unstable library features.
- // (Not doing this for stable library features is checked by tidy.)
- if let Some((
- PartialConstStability { level: StabilityLevel::Unstable { .. }, feature, .. },
- const_span,
- )) = const_stab
- {
- if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
- self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
- span: const_span,
- item_sp,
- });
- }
- }
-
- if let Some((stab, span)) = &const_stab
+ if let Some(stab) = &const_stab
&& stab.is_const_stable()
- && const_stability_indirect
+ && stab.const_stable_indirect
+ && let Some(span) = find_attr_span!(ConstStability)
{
- self.tcx.dcx().emit_err(errors::RustcConstStableIndirectPairing { span: *span });
- }
-
- // After checking the immediate attributes, get rid of the span and compute implied
- // const stability: inherit feature gate from regular stability.
- let mut const_stab = const_stab
- .map(|(stab, _span)| ConstStability::from_partial(stab, const_stability_indirect));
-
- // If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
- if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
- // We only ever inherit unstable features.
- let Some(inherit_regular_stab) =
- final_stab.filter(|s| s.is_unstable())
- {
- const_stab = Some(ConstStability {
- // We subject these implicitly-const functions to recursive const stability.
- const_stable_indirect: true,
- promotable: false,
- level: inherit_regular_stab.level,
- feature: inherit_regular_stab.feature,
- });
- }
-
- // Now that everything is computed, insert it into the table.
- const_stab.inspect(|const_stab| {
- self.index.const_stab_map.insert(def_id, *const_stab);
- });
-
- if let Some(ConstStability {
- level: StabilityLevel::Unstable { implied_by: Some(implied_by), .. },
- feature,
- ..
- }) = const_stab
- {
- self.index.implications.insert(implied_by, feature);
- }
-
- // `impl const Trait for Type` items forward their const stability to their
- // immediate children.
- // FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
- // Currently, once that is set, we do not inherit anything from the parent any more.
- if const_stab.is_none() {
- debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
- if let Some(parent) = self.parent_const_stab {
- if parent.is_const_unstable() {
- self.index.const_stab_map.insert(def_id, parent);
- }
- }
- }
-
- self.recurse_with_stability_attrs(
- depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
- stab,
- inherit_const_stability.yes().then_some(const_stab).flatten(),
- visit_children,
- );
- }
-
- fn recurse_with_stability_attrs(
- &mut self,
- depr: Option<DeprecationEntry>,
- stab: Option<Stability>,
- const_stab: Option<ConstStability>,
- f: impl FnOnce(&mut Self),
- ) {
- // These will be `Some` if this item changes the corresponding stability attribute.
- let mut replaced_parent_depr = None;
- let mut replaced_parent_stab = None;
- let mut replaced_parent_const_stab = None;
-
- if let Some(depr) = depr {
- replaced_parent_depr = Some(replace(&mut self.parent_depr, Some(depr)));
- }
- if let Some(stab) = stab {
- replaced_parent_stab = Some(replace(&mut self.parent_stab, Some(stab)));
- }
- if let Some(const_stab) = const_stab {
- replaced_parent_const_stab =
- Some(replace(&mut self.parent_const_stab, Some(const_stab)));
- }
-
- f(self);
-
- if let Some(orig_parent_depr) = replaced_parent_depr {
- self.parent_depr = orig_parent_depr;
- }
- if let Some(orig_parent_stab) = replaced_parent_stab {
- self.parent_stab = orig_parent_stab;
- }
- if let Some(orig_parent_const_stab) = replaced_parent_const_stab {
- self.parent_const_stab = orig_parent_const_stab;
+ self.tcx.dcx().emit_err(errors::RustcConstStableIndirectPairing { span });
}
}
-}
-impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
- /// Because stability levels are scoped lexically, we want to walk
- /// nested items in the context of the outer item, so enable
- /// deep-walking.
- type NestedFilter = nested_filter::All;
-
- fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
- self.tcx
- }
-
- fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
- let orig_in_trait_impl = self.in_trait_impl;
- let mut kind = AnnotationKind::Required;
- let mut const_stab_inherit = InheritConstStability::No;
- let mut fn_sig = None;
-
- match i.kind {
- // Inherent impls and foreign modules serve only as containers for other items,
- // they don't have their own stability. They still can be annotated as unstable
- // and propagate this instability to children, but this annotation is completely
- // optional. They inherit stability from their parents when unannotated.
- hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
- | hir::ItemKind::ForeignMod { .. } => {
- self.in_trait_impl = false;
- kind = AnnotationKind::Container;
- }
- hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
- self.in_trait_impl = true;
- kind = AnnotationKind::DeprecationProhibited;
- const_stab_inherit = InheritConstStability::Yes;
- }
- hir::ItemKind::Struct(_, _, ref sd) => {
- if let Some(ctor_def_id) = sd.ctor_def_id() {
- self.annotate(
- ctor_def_id,
- i.span,
- None,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::Yes,
- |_| {},
- )
- }
- }
- hir::ItemKind::Fn { sig: ref item_fn_sig, .. } => {
- fn_sig = Some(item_fn_sig);
- }
- _ => {}
- }
-
- self.annotate(
- i.owner_id.def_id,
- i.span,
- fn_sig,
- kind,
- InheritDeprecation::Yes,
- const_stab_inherit,
- InheritStability::No,
- |v| intravisit::walk_item(v, i),
- );
- self.in_trait_impl = orig_in_trait_impl;
- }
-
- fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
- let fn_sig = match ti.kind {
- hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
- _ => None,
- };
-
- self.annotate(
- ti.owner_id.def_id,
- ti.span,
- fn_sig,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::No,
- |v| {
- intravisit::walk_trait_item(v, ti);
- },
- );
- }
-
- fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
- let kind =
- if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
-
- let fn_sig = match ii.kind {
- hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
- _ => None,
- };
-
- self.annotate(
- ii.owner_id.def_id,
- ii.span,
- fn_sig,
- kind,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::No,
- |v| {
- intravisit::walk_impl_item(v, ii);
- },
- );
- }
-
- fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
- self.annotate(
- var.def_id,
- var.span,
- None,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::Yes,
- |v| {
- if let Some(ctor_def_id) = var.data.ctor_def_id() {
- v.annotate(
- ctor_def_id,
- var.span,
- None,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::Yes,
- |_| {},
- );
- }
-
- intravisit::walk_variant(v, var)
- },
- )
- }
-
- fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
- self.annotate(
- s.def_id,
- s.span,
- None,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::Yes,
- |v| {
- intravisit::walk_field_def(v, s);
- },
- );
- }
-
- fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
- let fn_sig = match &i.kind {
- rustc_hir::ForeignItemKind::Fn(fn_sig, ..) => Some(fn_sig),
- _ => None,
- };
- self.annotate(
- i.owner_id.def_id,
- i.span,
- fn_sig,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::No,
- |v| {
- intravisit::walk_foreign_item(v, i);
- },
- );
- }
-
- fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
- let kind = match &p.kind {
- // Allow stability attributes on default generic arguments.
- hir::GenericParamKind::Type { default: Some(_), .. }
- | hir::GenericParamKind::Const { default: Some(_), .. } => AnnotationKind::Container,
- _ => AnnotationKind::Prohibited,
- };
-
- self.annotate(
- p.def_id,
- p.span,
- None,
- kind,
- InheritDeprecation::No,
- InheritConstStability::No,
- InheritStability::No,
- |v| {
- intravisit::walk_generic_param(v, p);
- },
- );
- }
-}
-
-struct MissingStabilityAnnotations<'tcx> {
- tcx: TyCtxt<'tcx>,
- effective_visibilities: &'tcx EffectiveVisibilities,
-}
-
-impl<'tcx> MissingStabilityAnnotations<'tcx> {
- fn check_missing_stability(&self, def_id: LocalDefId, span: Span) {
- let stab = self.tcx.stability().local_stability(def_id);
+ #[instrument(level = "debug", skip(self))]
+ fn check_missing_stability(&self, def_id: LocalDefId) {
+ let stab = self.tcx.lookup_stability(def_id);
+ self.tcx.ensure_ok().lookup_const_stability(def_id);
if !self.tcx.sess.is_test_crate()
&& stab.is_none()
&& self.effective_visibilities.is_reachable(def_id)
{
let descr = self.tcx.def_descr(def_id.to_def_id());
+ let span = self.tcx.def_span(def_id);
self.tcx.dcx().emit_err(errors::MissingStabilityAttr { span, descr });
}
}
- fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
+ fn check_missing_const_stability(&self, def_id: LocalDefId) {
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
|| (self.tcx.def_kind(def_id.to_def_id()) == DefKind::Trait
&& self.tcx.is_const_trait(def_id.to_def_id()));
@@ -618,6 +484,7 @@ fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
&& self.effective_visibilities.is_reachable(def_id)
&& self.tcx.lookup_const_stability(def_id).is_none()
{
+ let span = self.tcx.def_span(def_id);
let descr = self.tcx.def_descr(def_id.to_def_id());
self.tcx.dcx().emit_err(errors::MissingConstStabAttr { span, descr });
}
@@ -632,6 +499,8 @@ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
}
fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
+ self.check_compatible_stability(i.owner_id.def_id);
+
// Inherent impls and foreign modules serve only as containers for other items,
// they don't have their own stability. They still can be annotated as unstable
// and propagate this instability to children, but this annotation is completely
@@ -641,119 +510,97 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
| hir::ItemKind::ForeignMod { .. }
) {
- self.check_missing_stability(i.owner_id.def_id, i.span);
+ self.check_missing_stability(i.owner_id.def_id);
}
// Ensure stable `const fn` have a const stability attribute.
- self.check_missing_const_stability(i.owner_id.def_id, i.span);
+ self.check_missing_const_stability(i.owner_id.def_id);
intravisit::walk_item(self, i)
}
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
- self.check_missing_stability(ti.owner_id.def_id, ti.span);
+ self.check_compatible_stability(ti.owner_id.def_id);
+ self.check_missing_stability(ti.owner_id.def_id);
intravisit::walk_trait_item(self, ti);
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
+ self.check_compatible_stability(ii.owner_id.def_id);
let impl_def_id = self.tcx.hir_get_parent_item(ii.hir_id());
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
- self.check_missing_stability(ii.owner_id.def_id, ii.span);
- self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
+ self.check_missing_stability(ii.owner_id.def_id);
+ self.check_missing_const_stability(ii.owner_id.def_id);
}
intravisit::walk_impl_item(self, ii);
}
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
- self.check_missing_stability(var.def_id, var.span);
+ self.check_compatible_stability(var.def_id);
+ self.check_missing_stability(var.def_id);
if let Some(ctor_def_id) = var.data.ctor_def_id() {
- self.check_missing_stability(ctor_def_id, var.span);
+ self.check_missing_stability(ctor_def_id);
}
intravisit::walk_variant(self, var);
}
fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
- self.check_missing_stability(s.def_id, s.span);
+ self.check_compatible_stability(s.def_id);
+ self.check_missing_stability(s.def_id);
intravisit::walk_field_def(self, s);
}
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
- self.check_missing_stability(i.owner_id.def_id, i.span);
+ self.check_compatible_stability(i.owner_id.def_id);
+ self.check_missing_stability(i.owner_id.def_id);
intravisit::walk_foreign_item(self, i);
}
- // Note that we don't need to `check_missing_stability` for default generic parameters,
- // as we assume that any default generic parameters without attributes are automatically
- // stable (assuming they have not inherited instability from their parent).
+
+ fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
+ self.check_compatible_stability(p.def_id);
+ // Note that we don't need to `check_missing_stability` for default generic parameters,
+ // as we assume that any default generic parameters without attributes are automatically
+ // stable (assuming they have not inherited instability from their parent).
+ intravisit::walk_generic_param(self, p);
+ }
}
-fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
- let mut index = Index {
- stab_map: Default::default(),
- const_stab_map: Default::default(),
- default_body_stab_map: Default::default(),
- depr_map: Default::default(),
- implications: Default::default(),
- };
-
- {
- let mut annotator = Annotator {
- tcx,
- index: &mut index,
- parent_stab: None,
- parent_const_stab: None,
- parent_depr: None,
- in_trait_impl: false,
- };
-
- // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
- // a parent stability annotation which indicates that this is private
- // with the `rustc_private` feature. This is intended for use when
- // compiling `librustc_*` crates themselves so we can leverage crates.io
- // while maintaining the invariant that all sysroot crates are unstable
- // by default and are unable to be used.
- if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
- let stability = Stability {
- level: attrs::StabilityLevel::Unstable {
- reason: UnstableReason::Default,
- issue: NonZero::new(27812),
- is_soft: false,
- implied_by: None,
- old_name: None,
- },
- feature: sym::rustc_private,
- };
- annotator.parent_stab = Some(stability);
- }
-
- annotator.annotate(
- CRATE_DEF_ID,
- tcx.hir_span(CRATE_HIR_ID),
- None,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::No,
- |v| tcx.hir_walk_toplevel_module(v),
- );
- }
- index
+fn stability_implications(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> UnordMap<Symbol, Symbol> {
+ let mut annotator = Annotator { tcx, implications: Default::default() };
+ annotator.annotate(CRATE_DEF_ID);
+ tcx.hir_walk_toplevel_module(&mut annotator);
+ annotator.implications
}
/// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors.
fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
tcx.hir_visit_item_likes_in_module(module_def_id, &mut Checker { tcx });
+
+ let is_staged_api =
+ tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api();
+ if is_staged_api {
+ let effective_visibilities = &tcx.effective_visibilities(());
+ let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
+ if module_def_id.is_top_level_module() {
+ missing.check_missing_stability(CRATE_DEF_ID);
+ }
+ tcx.hir_visit_item_likes_in_module(module_def_id, &mut missing);
+ }
+
+ if module_def_id.is_top_level_module() {
+ check_unused_or_stable_features(tcx)
+ }
}
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
check_mod_unstable_api_usage,
- stability_index,
- stability_implications: |tcx, _| tcx.stability().implications.clone(),
- lookup_stability: |tcx, id| tcx.stability().local_stability(id),
- lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id),
- lookup_default_body_stability: |tcx, id| tcx.stability().local_default_body_stability(id),
- lookup_deprecation_entry: |tcx, id| tcx.stability().local_deprecation_entry(id),
+ stability_implications,
+ lookup_stability,
+ lookup_const_stability,
+ lookup_default_body_stability,
+ lookup_deprecation_entry,
..*providers
};
}
@@ -1058,7 +905,7 @@ fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
};
let def_id = owner.def_id;
- let Some(stab) = tcx.stability().local_stability(def_id) else {
+ let Some(stab) = tcx.lookup_stability(def_id) else {
return false;
};
@@ -1127,16 +974,9 @@ fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
/// Given the list of enabled features that were not language features (i.e., that
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
+// This is `pub` for rustdoc. rustc should call it through `check_mod_unstable_api_usage`.
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
- let is_staged_api =
- tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api();
- if is_staged_api {
- let effective_visibilities = &tcx.effective_visibilities(());
- let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
- missing.check_missing_stability(CRATE_DEF_ID, tcx.hir_span(CRATE_HIR_ID));
- tcx.hir_walk_toplevel_module(&mut missing);
- tcx.hir_visit_all_item_likes_in_crate(&mut missing);
- }
+ let _prof_timer = tcx.sess.timer("unused_lib_feature_checking");
let enabled_lang_features = tcx.features().enabled_lang_features();
let mut lang_features = UnordSet::default();
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 80c13e4..9dd80bc 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1624,6 +1624,10 @@ fn check_item(&mut self, id: ItemId) {
self.check(def_id, item_visibility, effective_vis).generics().predicates();
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
+ if assoc_item.is_impl_trait_in_trait() {
+ continue;
+ }
+
self.check_assoc_item(assoc_item, item_visibility, effective_vis);
if assoc_item.is_type() {
@@ -1736,6 +1740,10 @@ fn check_item(&mut self, id: ItemId) {
check.ty().trait_ref();
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
+ if assoc_item.is_impl_trait_in_trait() {
+ continue;
+ }
+
let impl_item_vis = if !of_trait {
min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
} else {
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 675ea9d..737577b 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -49,7 +49,8 @@ pub(crate) fn define_binding(
ns: Namespace,
binding: NameBinding<'ra>,
) {
- if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) {
+ let key = self.new_disambiguated_key(ident, ns);
+ if let Err(old_binding) = self.try_define(parent, key, binding, false) {
self.report_conflict(parent, ident, ns, old_binding, binding);
}
}
@@ -441,18 +442,16 @@ fn add_import(
self.r.indeterminate_imports.push(import);
match import.kind {
+ // Don't add unresolved underscore imports to modules
+ ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
ImportKind::Single { target, type_ns_only, .. } => {
- // Don't add underscore imports to `single_imports`
- // because they cannot define any usable names.
- if target.name != kw::Underscore {
- self.r.per_ns(|this, ns| {
- if !type_ns_only || ns == TypeNS {
- let key = BindingKey::new(target, ns);
- let mut resolution = this.resolution(current_module, key).borrow_mut();
- resolution.single_imports.insert(import);
- }
- });
- }
+ self.r.per_ns(|this, ns| {
+ if !type_ns_only || ns == TypeNS {
+ let key = BindingKey::new(target, ns);
+ let mut resolution = this.resolution(current_module, key).borrow_mut();
+ resolution.single_imports.insert(import);
+ }
+ });
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
// which are not relevant to import resolution.
@@ -898,9 +897,12 @@ fn build_reduced_graph_for_extern_crate(
Some(self.r.graph_root)
} else {
let tcx = self.r.tcx;
- let crate_id = self.r.crate_loader(|c| {
- c.process_extern_crate(item, local_def_id, &tcx.definitions_untracked())
- });
+ let crate_id = self.r.cstore_mut().process_extern_crate(
+ self.r.tcx,
+ item,
+ local_def_id,
+ &tcx.definitions_untracked(),
+ );
crate_id.map(|crate_id| {
self.r.extern_crate_map.insert(local_def_id, crate_id);
self.r.expect_module(crate_id.as_def_id())
@@ -1406,12 +1408,9 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
let parent = self.parent_scope.module;
let expansion = self.parent_scope.expansion;
self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
- } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
- && ident.name != kw::Underscore
- {
- // Don't add underscore names, they cannot be looked up anyway.
+ } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
let impl_def_id = self.r.tcx.local_parent(local_def_id);
- let key = BindingKey::new(ident, ns);
+ let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index f6f45ad..d72fbc1 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1425,7 +1425,8 @@ pub(crate) fn lookup_import_candidates<FilterFn>(
// otherwise cause duplicate suggestions.
continue;
}
- let Some(crate_id) = self.crate_loader(|c| c.maybe_process_path_extern(ident.name))
+ let Some(crate_id) =
+ self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
else {
continue;
};
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index b4c15ed..0a4c25b 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -25,7 +25,7 @@
use smallvec::SmallVec;
use tracing::debug;
-use crate::Namespace::{self, *};
+use crate::Namespace::*;
use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
use crate::errors::{
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
@@ -338,20 +338,13 @@ pub(crate) fn import(
pub(crate) fn try_define(
&mut self,
module: Module<'ra>,
- ident: Ident,
- ns: Namespace,
+ key: BindingKey,
binding: NameBinding<'ra>,
warn_ambiguity: bool,
) -> Result<(), NameBinding<'ra>> {
let res = binding.res();
- self.check_reserved_macro_name(ident, res);
+ self.check_reserved_macro_name(key.ident, res);
self.set_binding_parent_module(binding, module);
- // Even if underscore names cannot be looked up, we still need to add them to modules,
- // because they can be fetched by glob imports from those modules, and bring traits
- // into scope both directly and through glob imports.
- let key = BindingKey::new_disambiguated(ident, ns, || {
- (module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap()
- });
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
if let Some(old_binding) = resolution.best_binding() {
if res == Res::Err && old_binding.res() != Res::Err {
@@ -390,7 +383,7 @@ pub(crate) fn try_define(
(old_glob @ true, false) | (old_glob @ false, true) => {
let (glob_binding, non_glob_binding) =
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
- if ns == MacroNS
+ if key.ns == MacroNS
&& non_glob_binding.expansion != LocalExpnId::ROOT
&& glob_binding.res() != non_glob_binding.res()
{
@@ -496,10 +489,10 @@ fn update_resolution<T, F>(
};
if self.is_accessible_from(binding.vis, scope) {
let imported_binding = self.import(binding, *import);
+ let key = BindingKey { ident, ..key };
let _ = self.try_define(
import.parent_scope.module,
- ident,
- key.ns,
+ key,
imported_binding,
warn_ambiguity,
);
@@ -521,15 +514,11 @@ fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool)
let dummy_binding = self.dummy_binding;
let dummy_binding = self.import(dummy_binding, import);
self.per_ns(|this, ns| {
- let module = import.parent_scope.module;
- let _ = this.try_define(module, target, ns, dummy_binding, false);
- // Don't remove underscores from `single_imports`, they were never added.
- if target.name != kw::Underscore {
- let key = BindingKey::new(target, ns);
- this.update_resolution(module, key, false, |_, resolution| {
- resolution.single_imports.swap_remove(&import);
- })
- }
+ let key = BindingKey::new(target, ns);
+ let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
+ this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
+ resolution.single_imports.swap_remove(&import);
+ })
});
self.record_use(target, dummy_binding, Used::Other);
} else if import.imported_module.get().is_none() {
@@ -906,7 +895,7 @@ fn resolve_import(&mut self, import: Import<'ra>) -> usize {
PendingBinding::Ready(Some(imported_binding))
}
Err(Determinacy::Determined) => {
- // Don't remove underscores from `single_imports`, they were never added.
+ // Don't update the resolution for underscores, because it was never added.
if target.name != kw::Underscore {
let key = BindingKey::new(target, ns);
this.update_resolution(parent, key, false, |_, resolution| {
@@ -1521,8 +1510,7 @@ fn resolve_glob_import(&mut self, import: Import<'ra>) {
.is_some_and(|binding| binding.warn_ambiguity_recursive());
let _ = self.try_define(
import.parent_scope.module,
- key.ident,
- key.ns,
+ key,
imported_binding,
warn_ambiguity,
);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 93cec8d..a3a7705 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2913,7 +2913,7 @@ fn with_generic_param_rib<'c, F>(
self.r
.dcx()
.create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span })
- .emit_unless(is_raw_underscore_lifetime);
+ .emit_unless_delay(is_raw_underscore_lifetime);
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
continue;
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index ee462d9..6909594 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2485,7 +2485,8 @@ fn lookup_typo_candidate(
let extern_prelude = self.r.extern_prelude.clone();
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
self.r
- .crate_loader(|c| c.maybe_process_path_extern(ident.name))
+ .cstore_mut()
+ .maybe_process_path_extern(self.r.tcx, ident.name)
.and_then(|crate_id| {
let crate_mod =
Res::Def(DefKind::Mod, crate_id.as_def_id());
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index f38fee8..0d41a82 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -45,7 +45,7 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::FreezeReadGuard;
+use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed};
use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind};
@@ -58,7 +58,7 @@
use rustc_hir::definitions::DisambiguatorState;
use rustc_hir::{PrimTy, TraitCandidate};
use rustc_index::bit_set::DenseBitSet;
-use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_metadata::creader::CStore;
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::query::Providers;
@@ -532,26 +532,15 @@ struct BindingKey {
/// identifier.
ident: Ident,
ns: Namespace,
- /// When we add an underscore binding (with ident `_`) to some module, this field has
- /// a non-zero value that uniquely identifies this binding in that module.
- /// For non-underscore bindings this field is zero.
- /// When a key is constructed for name lookup (as opposed to name definition), this field is
- /// also zero, even for underscore names, so for underscores the lookup will never succeed.
+ /// 0 if ident is not `_`, otherwise a value that's unique to the specific
+ /// `_` in the expanded AST that introduced this binding.
disambiguator: u32,
}
impl BindingKey {
fn new(ident: Ident, ns: Namespace) -> Self {
- BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 }
- }
-
- fn new_disambiguated(
- ident: Ident,
- ns: Namespace,
- disambiguator: impl FnOnce() -> u32,
- ) -> BindingKey {
- let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 };
- BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator }
+ let ident = ident.normalize_to_macros_2_0();
+ BindingKey { ident, ns, disambiguator: 0 }
}
}
@@ -1098,6 +1087,8 @@ pub struct Resolver<'ra, 'tcx> {
extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
+ underscore_disambiguator: u32,
+
/// Maps glob imports to the names of items actually imported.
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
glob_error: Option<ErrorGuaranteed>,
@@ -1119,7 +1110,6 @@ pub struct Resolver<'ra, 'tcx> {
builtin_types_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
builtin_attrs_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
registered_tool_bindings: FxHashMap<Ident, NameBinding<'ra>>,
- used_extern_options: FxHashSet<Symbol>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Symbol, SyntaxExtensionKind>,
registered_tools: &'tcx RegisteredTools,
@@ -1510,6 +1500,7 @@ pub fn new(
extern_crate_map: Default::default(),
module_children: Default::default(),
trait_map: NodeMap::default(),
+ underscore_disambiguator: 0,
empty_module,
local_module_map,
extern_module_map: Default::default(),
@@ -1554,7 +1545,6 @@ pub fn new(
(*ident, binding)
})
.collect(),
- used_extern_options: Default::default(),
macro_names: FxHashSet::default(),
builtin_macros: Default::default(),
registered_tools,
@@ -1741,18 +1731,14 @@ fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
StableHashingContext::new(self.tcx.sess, self.tcx.untracked())
}
- fn crate_loader<T>(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T {
- f(&mut CrateLoader::new(
- self.tcx,
- &mut CStore::from_tcx_mut(self.tcx),
- &mut self.used_extern_options,
- ))
- }
-
fn cstore(&self) -> FreezeReadGuard<'_, CStore> {
CStore::from_tcx(self.tcx)
}
+ fn cstore_mut(&self) -> FreezeWriteGuard<'_, CStore> {
+ CStore::from_tcx_mut(self.tcx)
+ }
+
fn dummy_ext(&self, macro_kind: MacroKind) -> Arc<SyntaxExtension> {
match macro_kind {
MacroKind::Bang => Arc::clone(&self.dummy_ext_bang),
@@ -1798,7 +1784,7 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate));
self.tcx
.sess
- .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate)));
+ .time("resolve_postprocess", || self.cstore_mut().postprocess(self.tcx, krate));
});
// Make sure we don't mutate the cstore from here on.
@@ -1895,6 +1881,17 @@ fn find_transitive_imports(
import_ids
}
+ fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
+ let ident = ident.normalize_to_macros_2_0();
+ let disambiguator = if ident.name == kw::Underscore {
+ self.underscore_disambiguator += 1;
+ self.underscore_disambiguator
+ } else {
+ 0
+ };
+ BindingKey { ident, ns, disambiguator }
+ }
+
fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
if module.populate_on_access.get() {
module.populate_on_access.set(false);
@@ -2153,7 +2150,7 @@ fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBin
Some(if let Some(binding) = entry.binding {
if finalize {
if !entry.is_import() {
- self.crate_loader(|c| c.process_path_extern(ident.name, ident.span));
+ self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
} else if entry.introduced_by_item {
self.record_use(ident, binding, Used::Other);
}
@@ -2162,13 +2159,13 @@ fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBin
} else {
let crate_id = if finalize {
let Some(crate_id) =
- self.crate_loader(|c| c.process_path_extern(ident.name, ident.span))
+ self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
else {
return Some(self.dummy_binding);
};
crate_id
} else {
- self.crate_loader(|c| c.maybe_process_path_extern(ident.name))?
+ self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)?
};
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT)
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 0e8904a..77ef7f5 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -530,7 +530,7 @@ fn glob_delegation_suffixes(
target_trait.for_each_child(self, |this, ident, ns, _binding| {
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
- && overriding_keys.contains(&BindingKey::new(ident, ns))
+ && overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
{
// The name is overridden, do not produce it from the glob delegation.
} else {
diff --git a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
index f20782c..0d6c619 100644
--- a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
+++ b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
@@ -3,7 +3,7 @@
pub(crate) fn target() -> Target {
Target {
arch: "amdgpu".into(),
- data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
+ data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
llvm_target: "amdgcn-amd-amdhsa".into(),
metadata: TargetMetadata {
description: Some("AMD GPU".into()),
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 39cdf6e..3839337 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -783,7 +783,7 @@ fn as_u128(self) -> u128 {
// This is a provenance-stripping memcpy.
for (i, chunk) in self.data.iter().copied().enumerate() {
- let chunk = chunk.expose_provenance().to_ne_bytes();
+ let chunk = chunk.addr().to_ne_bytes();
let start = i * chunk.len();
bytes[start..(start + chunk.len())].copy_from_slice(&chunk);
}
diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs
index 069c50c..c21c083 100644
--- a/library/core/src/async_iter/async_iter.rs
+++ b/library/core/src/async_iter/async_iter.rs
@@ -28,15 +28,15 @@ pub trait AsyncIterator {
/// async iterator state:
///
/// - `Poll::Pending` means that this async iterator's next value is not ready
- /// yet. Implementations will ensure that the current task will be notified
- /// when the next value may be ready.
+ /// yet. Implementations will ensure that the current task will be notified
+ /// when the next value may be ready.
///
/// - `Poll::Ready(Some(val))` means that the async iterator has successfully
- /// produced a value, `val`, and may produce further values on subsequent
- /// `poll_next` calls.
+ /// produced a value, `val`, and may produce further values on subsequent
+ /// `poll_next` calls.
///
/// - `Poll::Ready(None)` means that the async iterator has terminated, and
- /// `poll_next` should not be invoked again.
+ /// `poll_next` should not be invoked again.
///
/// # Panics
///
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 6419ae9..1b9af10 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -1482,13 +1482,14 @@ fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> {
}
}
-fn default_chaining_impl<T: PointeeSized, U: PointeeSized>(
+fn default_chaining_impl<T, U>(
lhs: &T,
rhs: &U,
p: impl FnOnce(Ordering) -> bool,
) -> ControlFlow<bool>
where
- T: PartialOrd<U>,
+ T: PartialOrd<U> + PointeeSized,
+ U: PointeeSized,
{
// It's important that this only call `partial_cmp` once, not call `eq` then
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 228a331..8ac29e5 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -854,7 +854,6 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
/// }";
/// assert_eq!(format!("The origin is: {origin:#?}"), expected);
/// ```
-
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index f90e685..106cc72 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1379,6 +1379,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f16::floor`](../../std/primitive.f16.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf16(x: f16) -> f16;
@@ -1386,6 +1387,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f32::floor`](../../std/primitive.f32.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf32(x: f32) -> f32;
@@ -1393,6 +1395,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f64::floor`](../../std/primitive.f64.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf64(x: f64) -> f64;
@@ -1400,6 +1403,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f128::floor`](../../std/primitive.f128.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf128(x: f128) -> f128;
@@ -1408,6 +1412,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf16(x: f16) -> f16;
@@ -1415,6 +1420,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf32(x: f32) -> f32;
@@ -1422,6 +1428,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf64(x: f64) -> f64;
@@ -1429,6 +1436,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf128(x: f128) -> f128;
@@ -1437,6 +1445,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf16(x: f16) -> f16;
@@ -1444,6 +1453,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf32(x: f32) -> f32;
@@ -1451,6 +1461,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf64(x: f64) -> f64;
@@ -1458,6 +1469,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf128(x: f128) -> f128;
@@ -1467,6 +1479,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f16(x: f16) -> f16;
@@ -1476,6 +1489,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f32(x: f32) -> f32;
@@ -1485,6 +1499,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f64(x: f64) -> f64;
@@ -1494,6 +1509,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f128(x: f128) -> f128;
@@ -1502,6 +1518,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f16::round`](../../std/primitive.f16.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf16(x: f16) -> f16;
@@ -1509,6 +1526,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f32::round`](../../std/primitive.f32.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf32(x: f32) -> f32;
@@ -1516,6 +1534,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f64::round`](../../std/primitive.f64.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf64(x: f64) -> f64;
@@ -1523,6 +1542,7 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
///
/// The stabilized version of this intrinsic is
/// [`f128::round`](../../std/primitive.f128.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf128(x: f128) -> f128;
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 8090c98..c5e199c 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -18,7 +18,6 @@ pub struct Zip<A, B> {
// index, len and a_len are only used by the specialized version of zip
index: usize,
len: usize,
- a_len: usize,
}
impl<A: Iterator, B: Iterator> Zip<A, B> {
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
@@ -158,7 +157,6 @@ macro_rules! zip_impl_general_defaults {
b,
index: 0, // unused
len: 0, // unused
- a_len: 0, // unused
}
}
@@ -299,9 +297,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
B: TrustedRandomAccess + Iterator,
{
fn new(a: A, b: B) -> Self {
- let a_len = a.size();
- let len = cmp::min(a_len, b.size());
- Zip { a, b, index: 0, len, a_len }
+ let len = cmp::min(a.size(), b.size());
+ Zip { a, b, index: 0, len }
}
#[inline]
@@ -315,17 +312,6 @@ fn next(&mut self) -> Option<(A::Item, B::Item)> {
unsafe {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
- } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
- let i = self.index;
- // as above, increment before executing code that may panic
- self.index += 1;
- self.len += 1;
- // match the base implementation's potential side effects
- // SAFETY: we just checked that `i` < `self.a.len()`
- unsafe {
- self.a.__iterator_get_unchecked(i);
- }
- None
} else {
None
}
@@ -371,36 +357,42 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator,
{
- if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
- let sz_a = self.a.size();
- let sz_b = self.b.size();
- // Adjust a, b to equal length, make sure that only the first call
- // of `next_back` does this, otherwise we will break the restriction
- // on calls to `self.next_back()` after calling `get_unchecked()`.
- if sz_a != sz_b {
+ // No effects when the iterator is exhausted, to reduce the number of
+ // cases the unsafe code has to handle.
+ // See #137255 for a case where where too many epicycles lead to unsoundness.
+ if self.index < self.len {
+ let old_len = self.len;
+
+ // since get_unchecked and the side-effecting code can execute user code
+ // which can panic we decrement the counter beforehand
+ // so that the same index won't be accessed twice, as required by TrustedRandomAccess.
+ // Additionally this will ensure that the side-effects code won't run a second time.
+ self.len -= 1;
+
+ // Adjust a, b to equal length if we're iterating backwards.
+ if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
+ // note if some forward-iteration already happened then these aren't the real
+ // remaining lengths of the inner iterators, so we have to relate them to
+ // Zip's internal length-tracking.
let sz_a = self.a.size();
- if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
- for _ in 0..sz_a - self.len {
- // since next_back() may panic we increment the counters beforehand
- // to keep Zip's state in sync with the underlying iterator source
- self.a_len -= 1;
- self.a.next_back();
- }
- debug_assert_eq!(self.a_len, self.len);
- }
let sz_b = self.b.size();
- if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
- for _ in 0..sz_b - self.len {
- self.b.next_back();
+ // This condition can and must only be true on the first `next_back` call,
+ // otherwise we will break the restriction on calls to `self.next_back()`
+ // after calling `get_unchecked()`.
+ if sz_a != sz_b && (old_len == sz_a || old_len == sz_b) {
+ if A::MAY_HAVE_SIDE_EFFECT && sz_a > old_len {
+ for _ in 0..sz_a - old_len {
+ self.a.next_back();
+ }
}
+ if B::MAY_HAVE_SIDE_EFFECT && sz_b > old_len {
+ for _ in 0..sz_b - old_len {
+ self.b.next_back();
+ }
+ }
+ debug_assert_eq!(self.a.size(), self.b.size());
}
}
- }
- if self.index < self.len {
- // since get_unchecked executes code which can panic we increment the counters beforehand
- // so that the same index won't be accessed twice, as required by TrustedRandomAccess
- self.len -= 1;
- self.a_len -= 1;
let i = self.len;
// SAFETY: `i` is smaller than the previous value of `self.len`,
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 3bc9cff..ab27650 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -436,7 +436,6 @@ fn extend_reserve(&mut self, additional: usize) {
/// **For implementors:** For a collection to unsafely rely on this method's safety precondition (that is,
/// invoke UB if they are violated), it must implement `extend_reserve` correctly. In other words,
/// callers may assume that if they `extend_reserve`ed enough space they can call this method.
-
// This method is for internal usage only. It is only on the trait because of specialization's limitations.
#[unstable(feature = "extend_one_unchecked", issue = "none")]
#[doc(hidden)]
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index f296792..10f9d46 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3414,10 +3414,10 @@ fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
/// ```
#[stable(feature = "iter_copied", since = "1.36.0")]
#[rustc_diagnostic_item = "iter_copied"]
- fn copied<'a, T: 'a>(self) -> Copied<Self>
+ fn copied<'a, T>(self) -> Copied<Self>
where
+ T: Copy + 'a,
Self: Sized + Iterator<Item = &'a T>,
- T: Copy,
{
Copied::new(self)
}
@@ -3462,10 +3462,10 @@ fn copied<'a, T: 'a>(self) -> Copied<Self>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "iter_cloned"]
- fn cloned<'a, T: 'a>(self) -> Cloned<Self>
+ fn cloned<'a, T>(self) -> Cloned<Self>
where
+ T: Clone + 'a,
Self: Sized + Iterator<Item = &'a T>,
- T: Clone,
{
Cloned::new(self)
}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 729de5f..3c33f4b 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -39,9 +39,9 @@
//! return. You should mark your implementation using `#[panic_handler]`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
-//! compiler. This is often mapped to GCC's personality function, but crates
-//! which do not trigger a panic can be assured that this function is never
-//! called. The `lang` attribute is called `eh_personality`.
+//! compiler. This is often mapped to GCC's personality function, but crates
+//! which do not trigger a panic can be assured that this function is never
+//! called. The `lang` attribute is called `eh_personality`.
#![stable(feature = "core", since = "1.6.0")]
#![doc(
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index fc35e54..34d8370 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -1005,28 +1005,6 @@ pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
}
}
- /// Deprecated version of [`slice::assume_init_ref`].
- #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
- #[deprecated(
- note = "replaced by inherent assume_init_ref method; will eventually be removed",
- since = "1.83.0"
- )]
- pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
- // SAFETY: Same for both methods.
- unsafe { slice.assume_init_ref() }
- }
-
- /// Deprecated version of [`slice::assume_init_mut`].
- #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
- #[deprecated(
- note = "replaced by inherent assume_init_mut method; will eventually be removed",
- since = "1.83.0"
- )]
- pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
- // SAFETY: Same for both methods.
- unsafe { slice.assume_init_mut() }
- }
-
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
@@ -1040,94 +1018,6 @@ pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
this.as_mut_ptr() as *mut T
}
-
- /// Deprecated version of [`slice::write_copy_of_slice`].
- #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
- #[deprecated(
- note = "replaced by inherent write_copy_of_slice method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
- where
- T: Copy,
- {
- this.write_copy_of_slice(src)
- }
-
- /// Deprecated version of [`slice::write_clone_of_slice`].
- #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
- #[deprecated(
- note = "replaced by inherent write_clone_of_slice method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
- where
- T: Clone,
- {
- this.write_clone_of_slice(src)
- }
-
- /// Deprecated version of [`slice::write_filled`].
- #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
- #[deprecated(
- note = "replaced by inherent write_filled method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T]
- where
- T: Clone,
- {
- this.write_filled(value)
- }
-
- /// Deprecated version of [`slice::write_with`].
- #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
- #[deprecated(
- note = "replaced by inherent write_with method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T]
- where
- F: FnMut() -> T,
- {
- this.write_with(|_| f())
- }
-
- /// Deprecated version of [`slice::write_iter`].
- #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
- #[deprecated(
- note = "replaced by inherent write_iter method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn fill_from<'a, I>(
- this: &'a mut [MaybeUninit<T>],
- it: I,
- ) -> (&'a mut [T], &'a mut [MaybeUninit<T>])
- where
- I: IntoIterator<Item = T>,
- {
- this.write_iter(it)
- }
-
- /// Deprecated version of [`slice::as_bytes`].
- #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
- #[deprecated(
- note = "replaced by inherent as_bytes method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
- this.as_bytes()
- }
-
- /// Deprecated version of [`slice::as_bytes_mut`].
- #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
- #[deprecated(
- note = "replaced by inherent as_bytes_mut method; will eventually be removed",
- since = "1.83.0"
- )]
- pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
- this.as_bytes_mut()
- }
}
impl<T> [MaybeUninit<T>] {
@@ -1304,7 +1194,7 @@ pub fn write_filled(&mut self, value: T) -> &mut [T]
/// Fills a slice with elements returned by calling a closure for each index.
///
/// This method uses a closure to create new values. If you'd rather `Clone` a given value, use
- /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can
+ /// [slice::write_filled]. If you want to use the `Default` trait to generate values, you can
/// pass [`|_| Default::default()`][Default::default] as the argument.
///
/// # Panics
@@ -1463,7 +1353,7 @@ pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] {
/// use std::mem::MaybeUninit;
///
/// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
- /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
+ /// let uninit_bytes = uninit.as_bytes_mut();
/// uninit_bytes.write_copy_of_slice(&[0x12, 0x34, 0x56, 0x78]);
/// let vals = unsafe { uninit.assume_init_ref() };
/// if cfg!(target_endian = "little") {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 1bd12d8..2198d09 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -36,7 +36,7 @@
/// * If you want to leak memory, see [`Box::leak`].
/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`].
/// * If you want to dispose of a value properly, running its destructor, see
-/// [`mem::drop`].
+/// [`mem::drop`].
///
/// # Safety
///
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index aaa68e8..49a7ae5 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -787,7 +787,6 @@ pub const fn is_link_local(&self) -> bool {
/// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
/// [unspecified address]: Ipv4Addr::UNSPECIFIED
/// [broadcast address]: Ipv4Addr::BROADCAST
-
///
/// # Examples
///
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 4c09c93..69e6c10 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -1448,7 +1448,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@@ -1478,7 +1477,6 @@ pub const fn floor(self) -> f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn ceil(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@@ -1514,7 +1512,6 @@ pub const fn ceil(self) -> f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@@ -1548,7 +1545,6 @@ pub const fn round(self) -> f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round_ties_even(self) -> f128 {
intrinsics::round_ties_even_f128(self)
@@ -1580,7 +1576,6 @@ pub const fn round_ties_even(self) -> f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn trunc(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@@ -1611,7 +1606,6 @@ pub const fn trunc(self) -> f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(self) -> f128 {
self - self.trunc()
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 1d98a48..b66cef0 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -1424,7 +1424,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@@ -1454,7 +1453,6 @@ pub const fn floor(self) -> f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn ceil(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@@ -1490,7 +1488,6 @@ pub const fn ceil(self) -> f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@@ -1524,7 +1521,6 @@ pub const fn round(self) -> f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round_ties_even(self) -> f16 {
intrinsics::round_ties_even_f16(self)
@@ -1556,7 +1552,6 @@ pub const fn round_ties_even(self) -> f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn trunc(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@@ -1587,7 +1582,6 @@ pub const fn trunc(self) -> f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
- // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(self) -> f16 {
self - self.trunc()
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index b460c7d..f8344da 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1591,7 +1591,6 @@ pub mod math {
/// [`f32::floor`]: ../../../std/primitive.f32.html#method.floor
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
@@ -1622,7 +1621,6 @@ pub const fn floor(x: f32) -> f32 {
#[doc(alias = "ceiling")]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn ceil(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
unsafe { intrinsics::ceilf32(x) }
@@ -1657,7 +1655,6 @@ pub const fn ceil(x: f32) -> f32 {
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[must_use = "method returns a new number and does not mutate the original value"]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn round(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
unsafe { intrinsics::roundf32(x) }
@@ -1691,7 +1688,6 @@ pub const fn round(x: f32) -> f32 {
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[must_use = "method returns a new number and does not mutate the original value"]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn round_ties_even(x: f32) -> f32 {
intrinsics::round_ties_even_f32(x)
}
@@ -1722,7 +1718,6 @@ pub const fn round_ties_even(x: f32) -> f32 {
#[doc(alias = "truncate")]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn trunc(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
unsafe { intrinsics::truncf32(x) }
@@ -1752,7 +1747,6 @@ pub const fn trunc(x: f32) -> f32 {
/// [`f32::fract`]: ../../../std/primitive.f32.html#method.fract
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(x: f32) -> f32 {
x - trunc(x)
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 3cd079b..93da63c 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1589,7 +1589,6 @@ pub mod math {
/// [`f64::floor`]: ../../../std/primitive.f64.html#method.floor
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@@ -1619,7 +1618,6 @@ pub const fn floor(x: f64) -> f64 {
#[inline]
#[doc(alias = "ceiling")]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn ceil(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@@ -1654,7 +1652,6 @@ pub const fn ceil(x: f64) -> f64 {
/// [`f64::round`]: ../../../std/primitive.f64.html#method.round
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@@ -1688,7 +1685,6 @@ pub const fn round(x: f64) -> f64 {
/// [`f64::round_ties_even`]: ../../../std/primitive.f64.html#method.round_ties_even
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round_ties_even(x: f64) -> f64 {
intrinsics::round_ties_even_f64(x)
@@ -1719,7 +1715,6 @@ pub const fn round_ties_even(x: f64) -> f64 {
#[inline]
#[doc(alias = "truncate")]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn trunc(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@@ -1750,7 +1745,6 @@ pub const fn trunc(x: f64) -> f64 {
/// [`f64::fract`]: ../../../std/primitive.f64.html#method.fract
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(x: f64) -> f64 {
x - trunc(x)
diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs
index 28a3f5d..649a736 100644
--- a/library/core/src/num/int_log10.rs
+++ b/library/core/src/num/int_log10.rs
@@ -1,5 +1,5 @@
-/// These functions compute the integer logarithm of their type, assuming
-/// that someone has already checked that the value is strictly positive.
+//! These functions compute the integer logarithm of their type, assuming
+//! that someone has already checked that the value is strictly positive.
// 0 < val <= u8::MAX
#[inline]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index ab68232..584cd60 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -556,7 +556,7 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
pub const fn strict_add(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_add(rhs);
if b { overflow_panic::add() } else { a }
- }
+ }
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
/// cannot occur.
@@ -653,7 +653,7 @@ pub const fn checked_add_signed(self, rhs: $SignedT) -> Option<Self> {
pub const fn strict_add_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_add_signed(rhs);
if b { overflow_panic::add() } else { a }
- }
+ }
/// Checked integer subtraction. Computes `self - rhs`, returning
/// `None` if overflow occurred.
@@ -713,7 +713,7 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
pub const fn strict_sub(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_sub(rhs);
if b { overflow_panic::sub() } else { a }
- }
+ }
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
/// cannot occur.
@@ -805,6 +805,43 @@ pub const fn checked_sub_signed(self, rhs: $SignedT) -> Option<Self> {
}
}
+ /// Strict subtraction with a signed integer. Computes `self - rhs`,
+ /// panicking if overflow occurred.
+ ///
+ /// # Panics
+ ///
+ /// ## Overflow behavior
+ ///
+ /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(strict_overflow_ops)]
+ #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".strict_sub_signed(2), 1);")]
+ /// ```
+ ///
+ /// The following panic because of overflow:
+ ///
+ /// ```should_panic
+ /// #![feature(strict_overflow_ops)]
+ #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_sub_signed(2);")]
+ /// ```
+ ///
+ /// ```should_panic
+ /// #![feature(strict_overflow_ops)]
+ #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")]
+ /// ```
+ #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self {
+ let (a, b) = self.overflowing_sub_signed(rhs);
+ if b { overflow_panic::sub() } else { a }
+ }
+
#[doc = concat!(
"Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
stringify!($SignedT), "`], returning `None` if overflow occurred."
@@ -913,7 +950,7 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
pub const fn strict_mul(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_mul(rhs);
if b { overflow_panic::mul() } else { a }
- }
+ }
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
/// cannot occur.
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 5bd8014..9a1ba7d 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1363,7 +1363,6 @@ mod prim_f16 {}
/// x = a + b + c + d; // As written
/// x = (a + c) + (b + d); // Reordered to shorten critical path and enable vectorization
/// ```
-
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_f32 {}
diff --git a/library/core/src/ptr/docs/as_uninit_slice.md b/library/core/src/ptr/docs/as_uninit_slice.md
index c80c040..1113f47 100644
--- a/library/core/src/ptr/docs/as_uninit_slice.md
+++ b/library/core/src/ptr/docs/as_uninit_slice.md
@@ -10,24 +10,24 @@
all of the following is true:
* The pointer must be [valid] for reads for `ptr.len() * size_of::<T>()` many bytes,
-and it must be properly aligned. This means in particular:
+ and it must be properly aligned. This means in particular:
* The entire memory range of this slice must be contained within a single [allocation]!
-Slices can never span across multiple allocations.
+ Slices can never span across multiple allocations.
* The pointer must be aligned even for zero-length slices. One
-reason for this is that enum layout optimizations may rely on references
-(including slices of any length) being aligned and non-null to distinguish
-them from other data. You can obtain a pointer that is usable as `data`
-for zero-length slices using [`NonNull::dangling()`].
+ reason for this is that enum layout optimizations may rely on references
+ (including slices of any length) being aligned and non-null to distinguish
+ them from other data. You can obtain a pointer that is usable as `data`
+ for zero-length slices using [`NonNull::dangling()`].
* The total size `ptr.len() * size_of::<T>()` of the slice must be no larger than `isize::MAX`.
-See the safety documentation of [`pointer::offset`].
+ See the safety documentation of [`pointer::offset`].
* You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
-arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-In particular, while this reference exists, the memory the pointer points to must
-not get mutated (except inside `UnsafeCell`).
+ arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+ In particular, while this reference exists, the memory the pointer points to must
+ not get mutated (except inside `UnsafeCell`).
This applies even if the result of this method is unused!
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index fe8c6f8..dbe3999 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -28,7 +28,8 @@
//! undefined behavior to perform two concurrent accesses to the same location from different
//! threads unless both accesses only read from memory. Notice that this explicitly
//! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
-//! be used for inter-thread synchronization.
+//! be used for inter-thread synchronization, regardless of whether they are acting on
+//! Rust memory or not.
//! * The result of casting a reference to a pointer is valid for as long as the
//! underlying allocation is live and no reference (just raw pointers) is used to
//! access the same memory. That is, reference and pointer accesses cannot be
@@ -114,6 +115,10 @@
//! fully contiguous (i.e., has no "holes"), there is no guarantee that this
//! will not change in the future.
//!
+//! Allocations must behave like "normal" memory: in particular, reads must not have
+//! side-effects, and writes must become visible to other threads using the usual synchronization
+//! primitives.
+//!
//! For any allocation with `base` address, `size`, and a set of
//! `addresses`, the following are guaranteed:
//! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base +
@@ -2021,54 +2026,61 @@ macro_rules! swap_prefix {
}
}
-/// Performs a volatile read of the value from `src` without moving it. This
-/// leaves the memory in `src` unchanged.
+/// Performs a volatile read of the value from `src` without moving it.
///
-/// Volatile operations are intended to act on I/O memory, and are guaranteed
-/// to not be elided or reordered by the compiler across other volatile
-/// operations.
+/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
+/// observable events (just like syscalls, but less opaque), and are guaranteed to not be elided or
+/// reordered by the compiler across other externally observable events. With this in mind, there
+/// are two cases of usage that need to be distinguished:
///
-/// # Notes
+/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
+/// [`read`], except for the additional guarantee that it won't be elided or reordered (see
+/// above). This implies that the operation will actually access memory and not e.g. be lowered to
+/// reusing data from a previous read. Other than that, all the usual rules for memory accesses
+/// apply (including provenance). In particular, just like in C, whether an operation is volatile
+/// has no bearing whatsoever on questions involving concurrent accesses from multiple threads.
+/// Volatile accesses behave exactly like non-atomic accesses in that regard.
///
-/// Rust does not currently have a rigorously and formally defined memory model,
-/// so the precise semantics of what "volatile" means here is subject to change
-/// over time. That being said, the semantics will almost always end up pretty
-/// similar to [C11's definition of volatile][c11].
+/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust
+/// allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is
+/// typically used for CPU and peripheral registers that must be accessed via an I/O memory
+/// mapping, most commonly at fixed addresses reserved by the hardware. These often have special
+/// semantics associated to their manipulation, and cannot be used as general purpose memory.
+/// Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics
+/// of such a read are well-defined by the target hardware. The provenance of the pointer is
+/// irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It
+/// can cause side-effects, but those must not affect Rust-allocated memory in any way. This
+/// access is still not considered [atomic], and as such it cannot be used for inter-thread
+/// synchronization.
///
-/// The compiler shouldn't change the relative order or number of volatile
-/// memory operations. However, volatile memory operations on zero-sized types
-/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops
-/// and may be ignored.
+/// Note that volatile memory operations where T is a zero-sized type are noops and may be ignored.
///
-/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+/// [allocation]: crate::ptr#allocated-object
+/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses
///
/// # Safety
///
+/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of whether `T` is
+/// [`Copy`]. If `T` is not [`Copy`], using both the returned value and the value at `*src` can
+/// [violate memory safety][read-ownership]. However, storing non-[`Copy`] types in volatile memory
+/// is almost certainly incorrect.
+///
/// Behavior is undefined if any of the following conditions are violated:
///
-/// * `src` must be [valid] for reads.
+/// * `src` must be either [valid] for reads, or it must point to memory outside of all Rust
+/// allocations and reading from that memory must:
+/// - not trap, and
+/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `src` must be properly aligned.
///
-/// * `src` must point to a properly initialized value of type `T`.
-///
-/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
-/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
-/// value and the value at `*src` can [violate memory safety][read-ownership].
-/// However, storing non-[`Copy`] types in volatile memory is almost certainly
-/// incorrect.
+/// * Reading from `src` must produce a properly initialized value of type `T`.
///
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// [valid]: self#safety
/// [read-ownership]: read#ownership-of-the-returned-value
///
-/// Just like in C, whether an operation is volatile has no bearing whatsoever
-/// on questions involving concurrent access from multiple threads. Volatile
-/// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `read_volatile` and any write operation to the same location
-/// is undefined behavior.
-///
/// # Examples
///
/// Basic usage:
@@ -2090,50 +2102,63 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
unsafe {
ub_checks::assert_unsafe_precondition!(
check_language_ub,
- "ptr::read_volatile requires that the pointer argument is aligned and non-null",
+ "ptr::read_volatile requires that the pointer argument is aligned",
(
addr: *const () = src as *const (),
align: usize = align_of::<T>(),
- is_zst: bool = T::IS_ZST,
- ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
+ ) => ub_checks::maybe_is_aligned(addr, align)
);
intrinsics::volatile_load(src)
}
}
-/// Performs a volatile write of a memory location with the given value without
-/// reading or dropping the old value.
+/// Performs a volatile write of a memory location with the given value without reading or dropping
+/// the old value.
///
-/// Volatile operations are intended to act on I/O memory, and are guaranteed
-/// to not be elided or reordered by the compiler across other volatile
-/// operations.
+/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
+/// observable events (just like syscalls), and are guaranteed to not be elided or reordered by the
+/// compiler across other externally observable events. With this in mind, there are two cases of
+/// usage that need to be distinguished:
///
-/// `write_volatile` does not drop the contents of `dst`. This is safe, but it
-/// could leak allocations or resources, so care should be taken not to overwrite
-/// an object that should be dropped.
+/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
+/// [`write`][write()], except for the additional guarantee that it won't be elided or reordered
+/// (see above). This implies that the operation will actually access memory and not e.g. be
+/// lowered to a register access. Other than that, all the usual rules for memory accesses apply
+/// (including provenance). In particular, just like in C, whether an operation is volatile has no
+/// bearing whatsoever on questions involving concurrent access from multiple threads. Volatile
+/// accesses behave exactly like non-atomic accesses in that regard.
///
-/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
-/// location pointed to by `dst`.
+/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust
+/// allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is
+/// typically used for CPU and peripheral registers that must be accessed via an I/O memory
+/// mapping, most commonly at fixed addresses reserved by the hardware. These often have special
+/// semantics associated to their manipulation, and cannot be used as general purpose memory.
+/// Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics
+/// of such a write are well-defined by the target hardware. The provenance of the pointer is
+/// irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It
+/// can cause side-effects, but those must not affect Rust-allocated memory in any way. This
+/// access is still not considered [atomic], and as such it cannot be used for inter-thread
+/// synchronization.
///
-/// # Notes
+/// Note that volatile memory operations on zero-sized types (e.g., if a zero-sized type is passed
+/// to `write_volatile`) are noops and may be ignored.
///
-/// Rust does not currently have a rigorously and formally defined memory model,
-/// so the precise semantics of what "volatile" means here is subject to change
-/// over time. That being said, the semantics will almost always end up pretty
-/// similar to [C11's definition of volatile][c11].
+/// `write_volatile` does not drop the contents of `dst`. This is safe, but it could leak
+/// allocations or resources, so care should be taken not to overwrite an object that should be
+/// dropped when operating on Rust memory. Additionally, it does not drop `src`. Semantically, `src`
+/// is moved into the location pointed to by `dst`.
///
-/// The compiler shouldn't change the relative order or number of volatile
-/// memory operations. However, volatile memory operations on zero-sized types
-/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops
-/// and may be ignored.
-///
-/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+/// [allocation]: crate::ptr#allocated-object
+/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
-/// * `dst` must be [valid] for writes.
+/// * `dst` must be either [valid] for writes, or it must point to memory outside of all Rust
+/// allocations and writing to that memory must:
+/// - not trap, and
+/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `dst` must be properly aligned.
///
@@ -2141,12 +2166,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
///
/// [valid]: self#safety
///
-/// Just like in C, whether an operation is volatile has no bearing whatsoever
-/// on questions involving concurrent access from multiple threads. Volatile
-/// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `write_volatile` and any other operation (reading or writing)
-/// on the same location is undefined behavior.
-///
/// # Examples
///
/// Basic usage:
@@ -2170,12 +2189,11 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
unsafe {
ub_checks::assert_unsafe_precondition!(
check_language_ub,
- "ptr::write_volatile requires that the pointer argument is aligned and non-null",
+ "ptr::write_volatile requires that the pointer argument is aligned",
(
addr: *mut () = dst as *mut (),
align: usize = align_of::<T>(),
- is_zst: bool = T::IS_ZST,
- ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
+ ) => ub_checks::maybe_is_aligned(addr, align)
);
intrinsics::volatile_store(dst, src);
}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 3241902..6fe5aff 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -971,7 +971,7 @@ pub const fn swap(&mut self, a: usize, b: usize) {
/// assert!(v == [3, 2, 1]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_slice_reverse", issue = "135120")]
+ #[rustc_const_stable(feature = "const_slice_reverse", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn reverse(&mut self) {
let half_len = self.len() / 2;
@@ -1004,6 +1004,7 @@ const fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
// this check tells LLVM that the indexing below is
// in-bounds. Then after inlining -- once the actual
// lengths of the slices are known -- it's removed.
+ // FIXME(const_trait_impl) replace with let (a, b) = (&mut a[..n], &mut b[..n]);
let (a, _) = a.split_at_mut(n);
let (b, _) = b.split_at_mut(n);
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 18a516c..029abf1 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2651,7 +2651,6 @@ pub fn trim_right_matches<P: Pattern>(&self, pat: P) -> &str
/// you're trying to parse into.
///
/// `parse` can parse into any type that implements the [`FromStr`] trait.
-
///
/// # Errors
///
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index a7caaeb..b809294 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -121,12 +121,24 @@ pub(crate) const fn maybe_is_aligned_and_not_null(
is_zst: bool,
) -> bool {
// This is just for safety checks so we can const_eval_select.
+ maybe_is_aligned(ptr, align) && (is_zst || !ptr.is_null())
+}
+
+/// Checks whether `ptr` is properly aligned with respect to the given alignment.
+///
+/// In `const` this is approximate and can fail spuriously. It is primarily intended
+/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
+/// check is anyway not executed in `const`.
+#[inline]
+#[rustc_allow_const_fn_unstable(const_eval_select)]
+pub(crate) const fn maybe_is_aligned(ptr: *const (), align: usize) -> bool {
+ // This is just for safety checks so we can const_eval_select.
const_eval_select!(
- @capture { ptr: *const (), align: usize, is_zst: bool } -> bool:
+ @capture { ptr: *const (), align: usize } -> bool:
if const {
- is_zst || !ptr.is_null()
+ true
} else {
- ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
+ ptr.is_aligned_to(align)
}
)
}
diff --git a/library/coretests/tests/iter/adapters/cloned.rs b/library/coretests/tests/iter/adapters/cloned.rs
index 78babb7..0a3dd1c 100644
--- a/library/coretests/tests/iter/adapters/cloned.rs
+++ b/library/coretests/tests/iter/adapters/cloned.rs
@@ -31,7 +31,8 @@ fn test_cloned_side_effects() {
.zip(&[1]);
for _ in iter {}
}
- assert_eq!(count, 2);
+ // Zip documentation provides some leeway about side-effects
+ assert!([1, 2].iter().any(|v| *v == count));
}
#[test]
diff --git a/library/coretests/tests/iter/adapters/zip.rs b/library/coretests/tests/iter/adapters/zip.rs
index 70392dc..063e226 100644
--- a/library/coretests/tests/iter/adapters/zip.rs
+++ b/library/coretests/tests/iter/adapters/zip.rs
@@ -107,9 +107,19 @@ fn test_zip_next_back_side_effects_exhausted() {
iter.next();
iter.next();
iter.next();
- iter.next();
+ assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
- assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
+
+ assert!(a.starts_with(&[1, 2, 3]));
+ let a_len = a.len();
+ // Tail-side-effects of forward-iteration are "at most one" per next().
+ // And for reverse iteration we don't guarantee much either.
+ // But we can put some bounds on the possible behaviors.
+ assert!(a_len <= 6);
+ assert!(a_len >= 3);
+ a.sort();
+ assert_eq!(a, &[1, 2, 3, 4, 5, 6][..a.len()]);
+
assert_eq!(b, vec![200, 300, 400]);
}
@@ -120,7 +130,8 @@ fn test_zip_cloned_sideffectful() {
for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}
- assert_eq!(&xs, &[1, 1, 1, 0][..]);
+ // Zip documentation permits either case.
+ assert!([&[1, 1, 1, 0], &[1, 1, 0, 0]].iter().any(|v| &xs == *v));
assert_eq!(&ys, &[1, 1][..]);
let xs = [CountClone::new(), CountClone::new()];
@@ -139,7 +150,8 @@ fn test_zip_map_sideffectful() {
for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}
- assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
+ // Zip documentation permits either case.
+ assert!([&[1, 1, 1, 1, 1, 0], &[1, 1, 1, 1, 0, 0]].iter().any(|v| &xs == *v));
assert_eq!(&ys, &[1, 1, 1, 1]);
let mut xs = [0; 4];
@@ -168,7 +180,8 @@ fn test_zip_map_rev_sideffectful() {
{
let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
- (&mut it).take(5).count();
+ // the current impl only trims the tails if the iterator isn't exhausted
+ (&mut it).take(3).count();
it.next_back();
}
assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]);
@@ -211,9 +224,18 @@ fn test_zip_nth_back_side_effects_exhausted() {
iter.next();
iter.next();
iter.next();
- iter.next();
+ assert_eq!(iter.next(), None);
assert_eq!(iter.nth_back(0), None);
- assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
+ assert!(a.starts_with(&[1, 2, 3]));
+ let a_len = a.len();
+ // Tail-side-effects of forward-iteration are "at most one" per next().
+ // And for reverse iteration we don't guarantee much either.
+ // But we can put some bounds on the possible behaviors.
+ assert!(a_len <= 6);
+ assert!(a_len >= 3);
+ a.sort();
+ assert_eq!(a, &[1, 2, 3, 4, 5, 6][..a.len()]);
+
assert_eq!(b, vec![200, 300, 400]);
}
@@ -238,32 +260,6 @@ fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
}
#[test]
-#[cfg(panic = "unwind")]
-fn test_zip_trusted_random_access_next_back_drop() {
- use std::panic::{AssertUnwindSafe, catch_unwind};
-
- let mut counter = 0;
-
- let it = [42].iter().map(|e| {
- let c = counter;
- counter += 1;
- if c == 0 {
- panic!("bomb");
- }
-
- e
- });
- let it2 = [(); 0].iter();
- let mut zip = it.zip(it2);
- catch_unwind(AssertUnwindSafe(|| {
- zip.next_back();
- }))
- .unwrap_err();
- assert!(zip.next().is_none());
- assert_eq!(counter, 1);
-}
-
-#[test]
fn test_double_ended_zip() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
@@ -276,6 +272,63 @@ fn test_double_ended_zip() {
}
#[test]
+#[cfg(panic = "unwind")]
+/// Regression test for #137255
+/// A previous implementation of Zip TrustedRandomAccess specializations tried to do a lot of work
+/// to preserve side-effects of equalizing the iterator lengths during backwards iteration.
+/// This lead to several cases of unsoundness, twice due to being left in an inconsistent state
+/// after panics.
+/// The new implementation does not try as hard, but we still need panic-safety.
+fn test_nested_zip_panic_safety() {
+ use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
+ use std::sync::atomic::{AtomicUsize, Ordering};
+
+ let mut panic = true;
+ // keeps track of how often element get visited, must be at most once each
+ let witness = [8, 9, 10, 11, 12].map(|i| (i, AtomicUsize::new(0)));
+ let a = witness.as_slice().iter().map(|e| {
+ e.1.fetch_add(1, Ordering::Relaxed);
+ if panic {
+ panic = false;
+ resume_unwind(Box::new(()))
+ }
+ e.0
+ });
+ // shorter than `a`, so `a` will get trimmed
+ let b = [1, 2, 3, 4].as_slice().iter().copied();
+ // shorter still, so `ab` will get trimmed.`
+ let c = [5, 6, 7].as_slice().iter().copied();
+
+ // This will panic during backwards trimming.
+ let ab = zip(a, b);
+ // This being Zip + TrustedRandomAccess means it will only call `next_back``
+ // during trimming and otherwise do calls `__iterator_get_unchecked` on `ab`.
+ let mut abc = zip(ab, c);
+
+ assert_eq!(abc.len(), 3);
+ // This will first trigger backwards trimming before it would normally obtain the
+ // actual element if it weren't for the panic.
+ // This used to corrupt the internal state of `abc`, which then lead to
+ // TrustedRandomAccess safety contract violations in calls to `ab`,
+ // which ultimately lead to UB.
+ catch_unwind(AssertUnwindSafe(|| abc.next_back())).ok();
+ // check for sane outward behavior after the panic, which indicates a sane internal state.
+ // Technically these outcomes are not required because a panic frees us from correctness obligations.
+ assert_eq!(abc.len(), 2);
+ assert_eq!(abc.next(), Some(((8, 1), 5)));
+ assert_eq!(abc.next_back(), Some(((9, 2), 6)));
+ for (i, (_, w)) in witness.iter().enumerate() {
+ let v = w.load(Ordering::Relaxed);
+ // required by TRA contract
+ assert!(v <= 1, "expected idx {i} to be visited at most once, actual: {v}");
+ }
+ // Trimming panicked and should only run once, so this one won't be visited.
+ // Implementation detail, but not trying to run it again is what keeps
+ // things simple.
+ assert_eq!(witness[3].1.load(Ordering::Relaxed), 0);
+}
+
+#[test]
fn test_issue_82282() {
fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
static UNIT_EMPTY_ARR: [(); 0] = [];
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index e2249bd..4cfac9e 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -19,7 +19,6 @@
#![feature(const_deref)]
#![feature(const_destruct)]
#![feature(const_eval_select)]
-#![feature(const_float_round_methods)]
#![feature(const_ops)]
#![feature(const_ref_cell)]
#![feature(const_trait_impl)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 311b2cb..323742a 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -329,7 +329,6 @@
#![feature(bstr_internals)]
#![feature(char_internals)]
#![feature(clone_to_uninit)]
-#![feature(const_float_round_methods)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]
#![feature(duration_constants)]
diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs
index e79ec2a..2bff73a 100644
--- a/library/std/src/num/f32.rs
+++ b/library/std/src/num/f32.rs
@@ -44,7 +44,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn floor(self) -> f32 {
core::f32::math::floor(self)
@@ -67,7 +67,7 @@ pub const fn floor(self) -> f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn ceil(self) -> f32 {
core::f32::math::ceil(self)
@@ -96,7 +96,7 @@ pub const fn ceil(self) -> f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round(self) -> f32 {
core::f32::math::round(self)
@@ -123,7 +123,7 @@ pub const fn round(self) -> f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "round_ties_even", since = "1.77.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round_ties_even(self) -> f32 {
core::f32::math::round_ties_even(self)
@@ -149,7 +149,7 @@ pub const fn round_ties_even(self) -> f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn trunc(self) -> f32 {
core::f32::math::trunc(self)
@@ -173,7 +173,7 @@ pub const fn trunc(self) -> f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn fract(self) -> f32 {
core::f32::math::fract(self)
diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs
index 8534178..b71e319 100644
--- a/library/std/src/num/f64.rs
+++ b/library/std/src/num/f64.rs
@@ -44,7 +44,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn floor(self) -> f64 {
core::f64::math::floor(self)
@@ -67,7 +67,7 @@ pub const fn floor(self) -> f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn ceil(self) -> f64 {
core::f64::math::ceil(self)
@@ -96,7 +96,7 @@ pub const fn ceil(self) -> f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round(self) -> f64 {
core::f64::math::round(self)
@@ -123,7 +123,7 @@ pub const fn round(self) -> f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "round_ties_even", since = "1.77.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round_ties_even(self) -> f64 {
core::f64::math::round_ties_even(self)
@@ -149,7 +149,7 @@ pub const fn round_ties_even(self) -> f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn trunc(self) -> f64 {
core::f64::math::trunc(self)
@@ -173,7 +173,7 @@ pub const fn trunc(self) -> f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+ #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn fract(self) -> f64 {
core::f64::math::fract(self)
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 6ce4c6d..2965174 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -105,7 +105,7 @@
debuginfo/
...
- # Bootstrap host tools (which are always compiled with the stage0 compiler)
+ # Host tools (which are always compiled with the stage0 compiler)
# are stored here.
bootstrap-tools/
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d8c6be7..40e0836 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -8,6 +8,7 @@
import shutil
import subprocess
import sys
+import sysconfig
import tarfile
import tempfile
@@ -333,7 +334,11 @@
if ostype == "Android":
kernel = "linux-android"
else:
- kernel = "unknown-linux-gnu"
+ python_soabi = sysconfig.get_config_var("SOABI")
+ if python_soabi is not None and "musl" in python_soabi:
+ kernel = "unknown-linux-musl"
+ else:
+ kernel = "unknown-linux-gnu"
elif kernel == "SunOS":
kernel = "pc-solaris"
# On Solaris, uname -m will return a machine classification instead
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 3278b55..f0acb7f 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -4,7 +4,10 @@
add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
};
use crate::core::build_steps::tool;
-use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo};
+use crate::core::build_steps::tool::{
+ COMPILETEST_ALLOW_FEATURES, SourceType, ToolTargetBuildMode, get_tool_target_compiler,
+ prepare_tool_cargo,
+};
use crate::core::builder::{
self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
};
@@ -252,8 +255,10 @@ fn prepare_compiler_for_check(
mode: Mode,
) -> Compiler {
let host = builder.host_target;
+
match mode {
Mode::ToolBootstrap => builder.compiler(0, host),
+ Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
Mode::ToolStd => {
if builder.config.compile_time_deps {
// When --compile-time-deps is passed, we can't use any rustc
@@ -350,7 +355,7 @@ fn run(self, builder: &Builder<'_>) {
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
- rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage);
+ rustc_cargo_env(builder, &mut cargo, target);
let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 09bb2e3..c7e7b01 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -19,7 +19,7 @@
use tracing::{instrument, span};
use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
-use crate::core::build_steps::tool::SourceType;
+use crate::core::build_steps::tool::{SourceType, copy_lld_artifacts};
use crate::core::build_steps::{dist, llvm};
use crate::core::builder;
use crate::core::builder::{
@@ -1316,15 +1316,10 @@ pub fn rustc_cargo(
cargo.env("RUSTC_WRAPPER", ccache);
}
- rustc_cargo_env(builder, cargo, target, build_compiler.stage);
+ rustc_cargo_env(builder, cargo, target);
}
-pub fn rustc_cargo_env(
- builder: &Builder<'_>,
- cargo: &mut Cargo,
- target: TargetSelection,
- build_stage: u32,
-) {
+pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
// Set some configuration variables picked up by build scripts and
// the compiler alike
cargo
@@ -1379,18 +1374,24 @@ pub fn rustc_cargo_env(
cargo.rustflag("--cfg=llvm_enzyme");
}
- // Note that this is disabled if LLVM itself is disabled or we're in a check
- // build. If we are in a check build we still go ahead here presuming we've
- // detected that LLVM is already built and good to go which helps prevent
- // busting caches (e.g. like #71152).
+ // These conditionals represent a tension between three forces:
+ // - For non-check builds, we need to define some LLVM-related environment
+ // variables, requiring LLVM to have been built.
+ // - For check builds, we want to avoid building LLVM if possible.
+ // - Check builds and non-check builds should have the same environment if
+ // possible, to avoid unnecessary rebuilds due to cache-busting.
+ //
+ // Therefore we try to avoid building LLVM for check builds, but only if
+ // building LLVM would be expensive. If "building" LLVM is cheap
+ // (i.e. it's already built or is downloadable), we prefer to maintain a
+ // consistent environment between check and non-check builds.
if builder.config.llvm_enabled(target) {
- let building_is_expensive =
+ let building_llvm_is_expensive =
crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
.should_build();
- // `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler
- let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
- let should_skip_build = building_is_expensive && can_skip_build;
- if !should_skip_build {
+
+ let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
+ if !skip_llvm {
rustc_llvm_env(builder, cargo, target)
}
}
@@ -1407,6 +1408,9 @@ pub fn rustc_cargo_env(
/// Pass down configuration from the LLVM build into the build of
/// rustc_llvm and rustc_codegen_llvm.
+///
+/// Note that this has the side-effect of _building LLVM_, which is sometimes
+/// unwanted (e.g. for check builds).
fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
if builder.config.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
@@ -1665,7 +1669,7 @@ fn run(self, builder: &Builder<'_>) {
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
- rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+ rustc_cargo_env(builder, &mut cargo, target);
// Ideally, we'd have a separate step for the individual codegen backends,
// like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.
@@ -2050,19 +2054,20 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
}
}
- let maybe_install_llvm_bitcode_linker = |compiler| {
+ let maybe_install_llvm_bitcode_linker = || {
if builder.config.llvm_bitcode_linker_enabled {
trace!("llvm-bitcode-linker enabled, installing");
- let llvm_bitcode_linker =
- builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
- build_compiler: compiler,
- target: target_compiler.host,
- });
+ let llvm_bitcode_linker = builder.ensure(
+ crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
+ builder,
+ target_compiler,
+ ),
+ );
// Copy the llvm-bitcode-linker to the self-contained binary directory
let bindir_self_contained = builder
- .sysroot(compiler)
- .join(format!("lib/rustlib/{}/bin/self-contained", compiler.host));
+ .sysroot(target_compiler)
+ .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
t!(fs::create_dir_all(&bindir_self_contained));
@@ -2089,9 +2094,9 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
}
- let mut precompiled_compiler = target_compiler;
- precompiled_compiler.forced_compiler(true);
- maybe_install_llvm_bitcode_linker(precompiled_compiler);
+ // FIXME: this is incomplete, we do not copy a bunch of other stuff to the downloaded
+ // sysroot...
+ maybe_install_llvm_bitcode_linker();
return target_compiler;
}
@@ -2256,10 +2261,12 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
if builder.config.lld_enabled {
- builder.ensure(crate::core::build_steps::tool::LldWrapper {
- build_compiler,
- target_compiler,
- });
+ let lld_wrapper =
+ builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
+ builder,
+ target_compiler,
+ ));
+ copy_lld_artifacts(builder, lld_wrapper, target_compiler);
}
if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
@@ -2284,15 +2291,14 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
}
// In addition to `rust-lld` also install `wasm-component-ld` when
- // LLD is enabled. This is a relatively small binary that primarily
- // delegates to the `rust-lld` binary for linking and then runs
- // logic to create the final binary. This is used by the
- // `wasm32-wasip2` target of Rust.
+ // is enabled. This is used by the `wasm32-wasip2` target of Rust.
if builder.tool_enabled("wasm-component-ld") {
- let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
- compiler: build_compiler,
- target: target_compiler.host,
- });
+ let wasm_component = builder.ensure(
+ crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
+ builder,
+ target_compiler,
+ ),
+ );
builder.copy_link(
&wasm_component.tool_path,
&libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
@@ -2300,7 +2306,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
);
}
- maybe_install_llvm_bitcode_linker(target_compiler);
+ maybe_install_llvm_bitcode_linker();
// Ensure that `libLLVM.so` ends up in the newly build compiler directory,
// so that it can be found when the newly built `rustc` is run.
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 8b2d65a..39e4fb2 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1575,7 +1575,10 @@ macro_rules! add_component {
compiler: builder.compiler(stage, target),
backend: "cranelift".to_string(),
});
- add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {compiler, target});
+ add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
+ build_compiler: compiler,
+ target
+ });
let etc = builder.src.join("src/etc/installer");
@@ -2341,9 +2344,13 @@ fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
}
}
+/// Distributes the `llvm-bitcode-linker` tool so that it can be used by a compiler whose host
+/// is `target`.
#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
pub struct LlvmBitcodeLinker {
- pub compiler: Compiler,
+ /// The linker will be compiled by this compiler.
+ pub build_compiler: Compiler,
+ /// The linker will by usable by rustc on this host.
pub target: TargetSelection,
}
@@ -2359,9 +2366,8 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(LlvmBitcodeLinker {
- compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
+ build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
+ run.builder,
run.target,
),
target: run.target,
@@ -2369,13 +2375,10 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let compiler = self.compiler;
let target = self.target;
- builder.ensure(compile::Rustc::new(compiler, target));
-
- let llbc_linker =
- builder.ensure(tool::LlvmBitcodeLinker { build_compiler: compiler, target });
+ let llbc_linker = builder
+ .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 4434d66..4156b49 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -287,7 +287,7 @@ fn run($sel, $builder: &Builder<'_>) {
}
};
LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), only_hosts: true, {
- if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { compiler: self.compiler, target: self.target }) {
+ if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.compiler, target: self.target }) {
install_sh(builder, "llvm-bitcode-linker", self.compiler.stage, Some(self.target), &tarball);
} else {
builder.info(
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 9e7ea5c..7652ea1 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1757,6 +1757,10 @@ fn run(self, builder: &Builder<'_>) {
cmd.arg("--host").arg(&*compiler.host.triple);
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
+ if let Some(codegen_backend) = builder.config.default_codegen_backend(compiler.host) {
+ cmd.arg("--codegen-backend").arg(&codegen_backend);
+ }
+
if builder.build.config.llvm_enzyme {
cmd.arg("--has-enzyme");
}
@@ -1810,7 +1814,24 @@ fn run(self, builder: &Builder<'_>) {
}
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
- flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
+ flags.push(format!(
+ "-Cdebuginfo={}",
+ if suite == "codegen" {
+ // codegen tests typically check LLVM IR and are sensitive to additional debuginfo.
+ // So do not apply `rust.debuginfo-level-tests` for codegen tests.
+ if builder.config.rust_debuginfo_level_tests
+ != crate::core::config::DebuginfoLevel::None
+ {
+ println!(
+ "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
+ builder.config.rust_debuginfo_level_tests
+ );
+ }
+ crate::core::config::DebuginfoLevel::None
+ } else {
+ builder.config.rust_debuginfo_level_tests
+ }
+ ));
flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
if suite != "mir-opt" {
@@ -2945,7 +2966,8 @@ fn run(self, builder: &Builder<'_>) {
builder.info(&format!("REMOTE copy libs to emulator ({target})"));
- let remote_test_server = builder.ensure(tool::RemoteTestServer { compiler, target });
+ let remote_test_server =
+ builder.ensure(tool::RemoteTestServer { build_compiler: compiler, target });
// Spawn the emulator and wait for it to come online
let tool = builder.tool_exe(Tool::RemoteTestClient);
@@ -3386,7 +3408,7 @@ fn run(self, builder: &Builder<'_>) {
cargo
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
- compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+ compile::rustc_cargo_env(builder, &mut cargo, target);
// Avoid incremental cache issues when changing rustc
cargo.env("CARGO_BUILD_INCREMENTAL", "false");
@@ -3518,7 +3540,7 @@ fn run(self, builder: &Builder<'_>) {
cargo
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
- compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+ compile::rustc_cargo_env(builder, &mut cargo, target);
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
// Avoid incremental cache issues when changing rustc
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 1c994b0..f5fa33b 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -42,7 +42,8 @@ pub enum ToolArtifactKind {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
- compiler: Compiler,
+ /// Compiler that will build this tool.
+ build_compiler: Compiler,
target: TargetSelection,
tool: &'static str,
path: &'static str,
@@ -112,34 +113,34 @@ fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult {
let mut tool = self.tool;
let path = self.path;
- let target_compiler = self.compiler;
- self.compiler = if self.mode == Mode::ToolRustc {
- get_tool_rustc_compiler(builder, self.compiler)
+ let target_compiler = self.build_compiler;
+ self.build_compiler = if self.mode == Mode::ToolRustc {
+ get_tool_rustc_compiler(builder, self.build_compiler)
} else {
- self.compiler
+ self.build_compiler
};
match self.mode {
Mode::ToolRustc => {
// If compiler was forced, its artifacts should have been prepared earlier.
- if !self.compiler.is_forced_compiler() {
- builder.std(self.compiler, self.compiler.host);
- builder.ensure(compile::Rustc::new(self.compiler, target));
+ if !self.build_compiler.is_forced_compiler() {
+ builder.std(self.build_compiler, self.build_compiler.host);
+ builder.ensure(compile::Rustc::new(self.build_compiler, target));
}
}
Mode::ToolStd => {
// If compiler was forced, its artifacts should have been prepared earlier.
- if !self.compiler.is_forced_compiler() {
- builder.std(self.compiler, target)
+ if !self.build_compiler.is_forced_compiler() {
+ builder.std(self.build_compiler, target);
}
}
- Mode::ToolBootstrap => {} // uses downloaded stage0 compiler libs
+ Mode::ToolBootstrap | Mode::ToolTarget => {} // uses downloaded stage0 compiler libs
_ => panic!("unexpected Mode for tool build"),
}
let mut cargo = prepare_tool_cargo(
builder,
- self.compiler,
+ self.build_compiler,
self.mode,
target,
Kind::Build,
@@ -161,7 +162,7 @@ fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult {
// Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer)
// could use the additional optimizations.
- if self.mode == Mode::ToolRustc && is_lto_stage(&self.compiler) {
+ if self.mode == Mode::ToolRustc && is_lto_stage(&self.build_compiler) {
let lto = match builder.config.rust_lto {
RustcLto::Off => Some("off"),
RustcLto::Thin => Some("thin"),
@@ -183,8 +184,9 @@ fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult {
Kind::Build,
self.mode,
self.tool,
- self.compiler.stage,
- &self.compiler.host,
+ // A stage N tool is built with the stage N-1 compiler.
+ self.build_compiler.stage + 1,
+ &self.build_compiler.host,
&self.target,
);
@@ -207,14 +209,14 @@ fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult {
}
let tool_path = match self.artifact_kind {
ToolArtifactKind::Binary => {
- copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool)
+ copy_link_tool_bin(builder, self.build_compiler, self.target, self.mode, tool)
}
ToolArtifactKind::Library => builder
- .cargo_out(self.compiler, self.mode, self.target)
+ .cargo_out(self.build_compiler, self.mode, self.target)
.join(format!("lib{tool}.rlib")),
};
- ToolBuildResult { tool_path, build_compiler: self.compiler, target_compiler }
+ ToolBuildResult { tool_path, build_compiler: self.build_compiler, target_compiler }
}
}
}
@@ -365,6 +367,47 @@ pub(crate) fn get_tool_rustc_compiler(
builder.compiler(target_compiler.stage.saturating_sub(1), builder.config.host_target)
}
+/// Determines how to build a `ToolTarget`, i.e. which compiler should be used to compile it.
+/// The compiler stage is automatically bumped if we need to cross-compile a stage 1 tool.
+pub enum ToolTargetBuildMode {
+ /// Build the tool using rustc that corresponds to the selected CLI stage.
+ Build(TargetSelection),
+ /// Build the tool so that it can be attached to the sysroot of the passed compiler.
+ /// Since we always dist stage 2+, the compiler that builds the tool in this case has to be
+ /// stage 1+.
+ Dist(Compiler),
+}
+
+/// Returns compiler that is able to compile a `ToolTarget` tool with the given `mode`.
+pub(crate) fn get_tool_target_compiler(
+ builder: &Builder<'_>,
+ mode: ToolTargetBuildMode,
+) -> Compiler {
+ let (target, build_compiler_stage) = match mode {
+ ToolTargetBuildMode::Build(target) => {
+ assert!(builder.top_stage > 0);
+ // If we want to build a stage N tool, we need to compile it with stage N-1 rustc
+ (target, builder.top_stage - 1)
+ }
+ ToolTargetBuildMode::Dist(target_compiler) => {
+ assert!(target_compiler.stage > 0);
+ // If we want to dist a stage N rustc, we want to attach stage N tool to it.
+ // And to build that tool, we need to compile it with stage N-1 rustc
+ (target_compiler.host, target_compiler.stage - 1)
+ }
+ };
+
+ let compiler = if builder.host_target == target {
+ builder.compiler(build_compiler_stage, builder.host_target)
+ } else {
+ // If we are cross-compiling a stage 1 tool, we cannot do that with a stage 0 compiler,
+ // so we auto-bump the tool's stage to 2, which means we need a stage 1 compiler.
+ builder.compiler(build_compiler_stage.max(1), builder.host_target)
+ };
+ builder.std(compiler, target);
+ compiler
+}
+
/// Links a built tool binary with the given `name` from the build directory to the
/// tools directory.
fn copy_link_tool_bin(
@@ -451,7 +494,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
let compiletest_wants_stage0 = $tool_name == "compiletest" && builder.config.compiletest_use_stage0_libtest;
builder.ensure(ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.compiler,
target: self.target,
tool: $tool_name,
mode: if is_unstable && !compiletest_wants_stage0 {
@@ -521,7 +564,6 @@ fn metadata(&self) -> Option<StepMetadata> {
// rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features.
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
CoverageDump, "src/tools/coverage-dump", "coverage-dump";
- WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
@@ -560,7 +602,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.require_submodule("src/tools/rustc-perf", None);
let tool = ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.compiler,
target: self.target,
tool: "collector",
mode: Mode::ToolBootstrap,
@@ -576,7 +618,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
let res = builder.ensure(tool.clone());
// We also need to symlink the `rustc-fake` binary to the corresponding directory,
// because `collector` expects it in the same directory.
- copy_link_tool_bin(builder, tool.compiler, tool.target, tool.mode, "rustc-fake");
+ copy_link_tool_bin(builder, tool.build_compiler, tool.target, tool.mode, "rustc-fake");
res
}
@@ -620,7 +662,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.ensure(ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.compiler,
target: self.compiler.host,
tool: "error_index_generator",
mode: Mode::ToolRustc,
@@ -636,7 +678,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
- pub compiler: Compiler,
+ pub build_compiler: Compiler,
pub target: TargetSelection,
}
@@ -649,17 +691,20 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(RemoteTestServer {
- compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
+ build_compiler: get_tool_target_compiler(
+ run.builder,
+ ToolTargetBuildMode::Build(run.target),
+ ),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.ensure(ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.build_compiler,
target: self.target,
tool: "remote-test-server",
- mode: Mode::ToolStd,
+ mode: Mode::ToolTarget,
path: "src/tools/remote-test-server",
source_type: SourceType::InTree,
extra_features: Vec::new(),
@@ -668,6 +713,10 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
artifact_kind: ToolArtifactKind::Binary,
})
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::build("remote-test-server", self.target).built_by(self.build_compiler))
+ }
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
@@ -757,7 +806,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
let ToolBuildResult { tool_path, build_compiler, target_compiler } =
builder.ensure(ToolBuild {
- compiler: target_compiler,
+ build_compiler: target_compiler,
target,
// Cargo adds a number of paths to the dylib search path on windows, which results in
// the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
@@ -825,7 +874,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.build.require_submodule("src/tools/cargo", None);
builder.ensure(ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.compiler,
target: self.target,
tool: "cargo",
mode: Mode::ToolRustc,
@@ -839,17 +888,50 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
}
}
+/// Represents a built LldWrapper, the `lld-wrapper` tool itself, and a directory
+/// containing a build of LLD.
+#[derive(Clone)]
+pub struct BuiltLldWrapper {
+ tool: ToolBuildResult,
+ lld_dir: PathBuf,
+}
+
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct LldWrapper {
pub build_compiler: Compiler,
- pub target_compiler: Compiler,
+ pub target: TargetSelection,
+}
+
+impl LldWrapper {
+ /// Returns `LldWrapper` that should be **used** by the passed compiler.
+ pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+ Self {
+ build_compiler: get_tool_target_compiler(
+ builder,
+ ToolTargetBuildMode::Dist(target_compiler),
+ ),
+ target: target_compiler.host,
+ }
+ }
}
impl Step for LldWrapper {
- type Output = ToolBuildResult;
+ type Output = BuiltLldWrapper;
+
+ const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.never()
+ run.path("src/tools/lld-wrapper")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(LldWrapper {
+ build_compiler: get_tool_target_compiler(
+ run.builder,
+ ToolTargetBuildMode::Build(run.target),
+ ),
+ target: run.target,
+ });
}
#[cfg_attr(
@@ -858,25 +940,16 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
level = "debug",
name = "LldWrapper::run",
skip_all,
- fields(build_compiler = ?self.build_compiler, target_compiler = ?self.target_compiler),
+ fields(build_compiler = ?self.build_compiler),
),
)]
- fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
- if builder.config.dry_run() {
- return ToolBuildResult {
- tool_path: Default::default(),
- build_compiler: self.build_compiler,
- target_compiler: self.target_compiler,
- };
- }
-
- let target = self.target_compiler.host;
-
- let tool_result = builder.ensure(ToolBuild {
- compiler: self.build_compiler,
- target,
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let lld_dir = builder.ensure(llvm::Lld { target: self.target });
+ let tool = builder.ensure(ToolBuild {
+ build_compiler: self.build_compiler,
+ target: self.target,
tool: "lld-wrapper",
- mode: Mode::ToolStd,
+ mode: Mode::ToolTarget,
path: "src/tools/lld-wrapper",
source_type: SourceType::InTree,
extra_features: Vec::new(),
@@ -884,38 +957,110 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
cargo_args: Vec::new(),
artifact_kind: ToolArtifactKind::Binary,
});
-
- let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target);
- t!(fs::create_dir_all(&libdir_bin));
-
- let lld_install = builder.ensure(llvm::Lld { target });
- let src_exe = exe("lld", target);
- let dst_exe = exe("rust-lld", target);
-
- builder.copy_link(
- &lld_install.join("bin").join(src_exe),
- &libdir_bin.join(dst_exe),
- FileType::Executable,
- );
- let self_contained_lld_dir = libdir_bin.join("gcc-ld");
- t!(fs::create_dir_all(&self_contained_lld_dir));
-
- for name in crate::LLD_FILE_NAMES {
- builder.copy_link(
- &tool_result.tool_path,
- &self_contained_lld_dir.join(exe(name, target)),
- FileType::Executable,
- );
- }
-
- tool_result
+ BuiltLldWrapper { tool, lld_dir }
}
fn metadata(&self) -> Option<StepMetadata> {
- Some(
- StepMetadata::build("LldWrapper", self.target_compiler.host)
- .built_by(self.build_compiler),
- )
+ Some(StepMetadata::build("LldWrapper", self.target).built_by(self.build_compiler))
+ }
+}
+
+pub(crate) fn copy_lld_artifacts(
+ builder: &Builder<'_>,
+ lld_wrapper: BuiltLldWrapper,
+ target_compiler: Compiler,
+) {
+ let target = target_compiler.host;
+
+ let libdir_bin = builder.sysroot_target_bindir(target_compiler, target);
+ t!(fs::create_dir_all(&libdir_bin));
+
+ let src_exe = exe("lld", target);
+ let dst_exe = exe("rust-lld", target);
+
+ builder.copy_link(
+ &lld_wrapper.lld_dir.join("bin").join(src_exe),
+ &libdir_bin.join(dst_exe),
+ FileType::Executable,
+ );
+ let self_contained_lld_dir = libdir_bin.join("gcc-ld");
+ t!(fs::create_dir_all(&self_contained_lld_dir));
+
+ for name in crate::LLD_FILE_NAMES {
+ builder.copy_link(
+ &lld_wrapper.tool.tool_path,
+ &self_contained_lld_dir.join(exe(name, target)),
+ FileType::Executable,
+ );
+ }
+}
+
+/// Builds the `wasm-component-ld` linker wrapper, which is shipped with rustc to be executed on the
+/// host platform where rustc runs.
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct WasmComponentLd {
+ build_compiler: Compiler,
+ target: TargetSelection,
+}
+
+impl WasmComponentLd {
+ /// Returns `WasmComponentLd` that should be **used** by the passed compiler.
+ pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+ Self {
+ build_compiler: get_tool_target_compiler(
+ builder,
+ ToolTargetBuildMode::Dist(target_compiler),
+ ),
+ target: target_compiler.host,
+ }
+ }
+}
+
+impl Step for WasmComponentLd {
+ type Output = ToolBuildResult;
+
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/wasm-component-ld")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(WasmComponentLd {
+ build_compiler: get_tool_target_compiler(
+ run.builder,
+ ToolTargetBuildMode::Build(run.target),
+ ),
+ target: run.target,
+ });
+ }
+
+ #[cfg_attr(
+ feature = "tracing",
+ instrument(
+ level = "debug",
+ name = "WasmComponentLd::run",
+ skip_all,
+ fields(build_compiler = ?self.build_compiler),
+ ),
+ )]
+ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
+ builder.ensure(ToolBuild {
+ build_compiler: self.build_compiler,
+ target: self.target,
+ tool: "wasm-component-ld",
+ mode: Mode::ToolTarget,
+ path: "src/tools/wasm-component-ld",
+ source_type: SourceType::InTree,
+ extra_features: vec![],
+ allow_features: "",
+ cargo_args: vec![],
+ artifact_kind: ToolArtifactKind::Binary,
+ })
+ }
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::build("WasmComponentLd", self.target).built_by(self.build_compiler))
}
}
@@ -948,7 +1093,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.ensure(ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.compiler,
target: self.target,
tool: "rust-analyzer",
mode: Mode::ToolRustc,
@@ -993,7 +1138,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> Option<ToolBuildResult> {
let tool_result = builder.ensure(ToolBuild {
- compiler: self.compiler,
+ build_compiler: self.compiler,
target: self.target,
tool: "rust-analyzer-proc-macro-srv",
mode: Mode::ToolRustc,
@@ -1021,8 +1166,35 @@ fn run(self, builder: &Builder<'_>) -> Option<ToolBuildResult> {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct LlvmBitcodeLinker {
- pub build_compiler: Compiler,
- pub target: TargetSelection,
+ build_compiler: Compiler,
+ target: TargetSelection,
+}
+
+impl LlvmBitcodeLinker {
+ /// Returns `LlvmBitcodeLinker` that will be **compiled** by the passed compiler, for the given
+ /// `target`.
+ pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
+ Self { build_compiler, target }
+ }
+
+ /// Returns `LlvmBitcodeLinker` that should be **used** by the passed compiler.
+ pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+ Self {
+ build_compiler: get_tool_target_compiler(
+ builder,
+ ToolTargetBuildMode::Dist(target_compiler),
+ ),
+ target: target_compiler.host,
+ }
+ }
+
+ /// Return a compiler that is able to build this tool for the given `target`.
+ pub fn get_build_compiler_for_target(
+ builder: &Builder<'_>,
+ target: TargetSelection,
+ ) -> Compiler {
+ get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target))
+ }
}
impl Step for LlvmBitcodeLinker {
@@ -1038,9 +1210,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(LlvmBitcodeLinker {
- build_compiler: run
- .builder
- .compiler(run.builder.top_stage, run.builder.config.host_target),
+ build_compiler: Self::get_build_compiler_for_target(run.builder, run.target),
target: run.target,
});
}
@@ -1051,10 +1221,10 @@ fn make_run(run: RunConfig<'_>) {
)]
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.ensure(ToolBuild {
- compiler: self.build_compiler,
+ build_compiler: self.build_compiler,
target: self.target,
tool: "llvm-bitcode-linker",
- mode: Mode::ToolRustc,
+ mode: Mode::ToolTarget,
path: "src/tools/llvm-bitcode-linker",
source_type: SourceType::InTree,
extra_features: vec![],
@@ -1239,7 +1409,7 @@ fn run_tool_build_step(
let ToolBuildResult { tool_path, build_compiler, target_compiler } =
builder.ensure(ToolBuild {
- compiler,
+ build_compiler: compiler,
target,
tool: tool_name,
mode: Mode::ToolRustc,
@@ -1338,7 +1508,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
let compiler = builder.compiler(builder.top_stage, bootstrap_host);
builder.ensure(ToolBuild {
- compiler,
+ build_compiler: compiler,
target: bootstrap_host,
tool: "test-float-parse",
mode: Mode::ToolStd,
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index a3b471c..badd5f2 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -537,7 +537,7 @@ fn cargo(
}
}
- let stage = if compiler.stage == 0 && self.local_rebuild {
+ let build_compiler_stage = if compiler.stage == 0 && self.local_rebuild {
// Assume the local-rebuild rustc already has stage1 features.
1
} else {
@@ -545,15 +545,17 @@ fn cargo(
};
// We synthetically interpret a stage0 compiler used to build tools as a
- // "raw" compiler in that it's the exact snapshot we download. Normally
- // the stage0 build means it uses libraries build by the stage0
- // compiler, but for tools we just use the precompiled libraries that
- // we've downloaded
- let use_snapshot = mode == Mode::ToolBootstrap;
- assert!(!use_snapshot || stage == 0 || self.local_rebuild);
+ // "raw" compiler in that it's the exact snapshot we download. For things like
+ // ToolRustc, we would have to use the artificial stage0-sysroot compiler instead.
+ let use_snapshot =
+ mode == Mode::ToolBootstrap || (mode == Mode::ToolTarget && build_compiler_stage == 0);
+ assert!(!use_snapshot || build_compiler_stage == 0 || self.local_rebuild);
- let maybe_sysroot = self.sysroot(compiler);
- let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot };
+ let sysroot = if use_snapshot {
+ self.rustc_snapshot_sysroot().to_path_buf()
+ } else {
+ self.sysroot(compiler)
+ };
let libdir = self.rustc_libdir(compiler);
let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
@@ -562,7 +564,7 @@ fn cargo(
}
let mut rustflags = Rustflags::new(target);
- if stage != 0 {
+ if build_compiler_stage != 0 {
if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") {
cargo.args(s.split_whitespace());
}
@@ -604,7 +606,7 @@ fn cargo(
// sysroot. Passing this cfg enables raw-dylib support instead, which makes the native
// library unnecessary. This can be removed when windows-rs enables raw-dylib
// unconditionally.
- if let Mode::Rustc | Mode::ToolRustc | Mode::ToolBootstrap = mode {
+ if let Mode::Rustc | Mode::ToolRustc | Mode::ToolBootstrap | Mode::ToolTarget = mode {
rustflags.arg("--cfg=windows_raw_dylib");
}
@@ -657,7 +659,7 @@ fn cargo(
// FIXME(rust-lang/cargo#5754) we shouldn't be using special command arguments
// to the host invocation here, but rather Cargo should know what flags to pass rustc
// itself.
- if stage == 0 {
+ if build_compiler_stage == 0 {
hostflags.arg("--cfg=bootstrap");
}
@@ -666,7 +668,7 @@ fn cargo(
// #71458.
let mut rustdocflags = rustflags.clone();
rustdocflags.propagate_cargo_env("RUSTDOCFLAGS");
- if stage == 0 {
+ if build_compiler_stage == 0 {
rustdocflags.env("RUSTDOCFLAGS_BOOTSTRAP");
} else {
rustdocflags.env("RUSTDOCFLAGS_NOT_BOOTSTRAP");
@@ -677,7 +679,7 @@ fn cargo(
}
match mode {
- Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
+ Mode::Std | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTarget => {}
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
// Build proc macros both for the host and the target unless proc-macros are not
// supported by the target.
@@ -719,7 +721,7 @@ fn cargo(
// feature on the rustc side.
cargo.arg("-Zbinary-dep-depinfo");
let allow_features = match mode {
- Mode::ToolBootstrap | Mode::ToolStd => {
+ Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTarget => {
// Restrict the allowed features so we don't depend on nightly
// accidentally.
//
@@ -833,7 +835,7 @@ fn cargo(
cargo
.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target))
.env("RUSTC_REAL", self.rustc(compiler))
- .env("RUSTC_STAGE", stage.to_string())
+ .env("RUSTC_STAGE", build_compiler_stage.to_string())
.env("RUSTC_SYSROOT", sysroot)
.env("RUSTC_LIBDIR", libdir)
.env("RUSTDOC", self.bootstrap_out.join("rustdoc"))
@@ -878,7 +880,7 @@ fn cargo(
let debuginfo_level = match mode {
Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc,
Mode::Std => self.config.rust_debuginfo_level_std,
- Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc => {
+ Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc | Mode::ToolTarget => {
self.config.rust_debuginfo_level_tools
}
};
@@ -890,11 +892,10 @@ fn cargo(
profile_var("DEBUG_ASSERTIONS"),
match mode {
Mode::Std => self.config.std_debug_assertions,
- Mode::Rustc => self.config.rustc_debug_assertions,
- Mode::Codegen => self.config.rustc_debug_assertions,
- Mode::ToolBootstrap => self.config.tools_debug_assertions,
- Mode::ToolStd => self.config.tools_debug_assertions,
- Mode::ToolRustc => self.config.tools_debug_assertions,
+ Mode::Rustc | Mode::Codegen => self.config.rustc_debug_assertions,
+ Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc | Mode::ToolTarget => {
+ self.config.tools_debug_assertions
+ }
}
.to_string(),
);
@@ -965,7 +966,11 @@ fn cargo(
cargo.env("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR", map_to);
}
}
- Mode::Std | Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => {
+ Mode::Std
+ | Mode::ToolBootstrap
+ | Mode::ToolRustc
+ | Mode::ToolStd
+ | Mode::ToolTarget => {
if let Some(ref map_to) =
self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::NonCompiler)
{
@@ -1280,7 +1285,7 @@ fn cargo(
};
if let Some(limit) = limit
- && (stage == 0
+ && (build_compiler_stage == 0
|| self.config.default_codegen_backend(target).unwrap_or_default() == "llvm")
{
rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 1b75d00..d73e2bc 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -963,6 +963,7 @@ macro_rules! describe {
tool::RemoteTestServer,
tool::RemoteTestClient,
tool::RustInstaller,
+ tool::FeaturesStatusDump,
tool::Cargo,
tool::RustAnalyzer,
tool::RustAnalyzerProcMacroSrv,
@@ -984,6 +985,8 @@ macro_rules! describe {
tool::CoverageDump,
tool::LlvmBitcodeLinker,
tool::RustcPerf,
+ tool::WasmComponentLd,
+ tool::LldWrapper
),
Kind::Clippy => describe!(
clippy::Std,
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 51a9064..e60a115 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -712,7 +712,11 @@ fn build_compiler_no_explicit_stage() {
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
");
+ }
+ #[test]
+ fn build_rustc_no_explicit_stage() {
+ let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx.config("build")
.path("rustc")
@@ -769,11 +773,11 @@ fn build_compiler_tools() {
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 0 <host> -> LldWrapper 1 <host>
- [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
+ [build] rustc 0 <host> -> LlvmBitcodeLinker 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 1 <host> -> rustc 2 <host>
[build] rustc 1 <host> -> LldWrapper 2 <host>
- [build] rustc 2 <host> -> LlvmBitcodeLinker 3 <host>
+ [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
[build] rustc 2 <host> -> std 2 <host>
[build] rustdoc 1 <host>
"
@@ -793,17 +797,17 @@ fn build_compiler_tools_cross() {
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 0 <host> -> LldWrapper 1 <host>
- [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
+ [build] rustc 0 <host> -> LlvmBitcodeLinker 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 1 <host> -> rustc 2 <host>
[build] rustc 1 <host> -> LldWrapper 2 <host>
- [build] rustc 2 <host> -> LlvmBitcodeLinker 3 <host>
+ [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
[build] rustc 1 <host> -> std 1 <target1>
[build] rustc 2 <host> -> std 2 <target1>
[build] llvm <target1>
[build] rustc 1 <host> -> rustc 2 <target1>
[build] rustc 1 <host> -> LldWrapper 2 <target1>
- [build] rustc 2 <target1> -> LlvmBitcodeLinker 3 <target1>
+ [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
[build] rustdoc 1 <target1>
"
);
@@ -1062,18 +1066,28 @@ fn dist_baseline() {
fn dist_extended() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
- ctx
- .config("dist")
- .args(&["--set", "build.extended=true"])
- .render_steps(), @r"
+ ctx.config("dist")
+ .args(&[
+ "--set",
+ "build.extended=true",
+ "--set",
+ "rust.llvm-bitcode-linker=true",
+ "--set",
+ "rust.lld=true",
+ ])
+ .render_steps(), @r"
[build] rustc 0 <host> -> UnstableBookGen 1 <host>
[build] rustc 0 <host> -> Rustbook 1 <host>
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 0 <host> -> LldWrapper 1 <host>
[build] rustc 0 <host> -> WasmComponentLd 1 <host>
+ [build] rustc 0 <host> -> LlvmBitcodeLinker 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 1 <host> -> rustc 2 <host>
+ [build] rustc 1 <host> -> LldWrapper 2 <host>
[build] rustc 1 <host> -> WasmComponentLd 2 <host>
+ [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
[build] rustdoc 1 <host>
[doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
[build] rustc 2 <host> -> std 2 <host>
@@ -1092,7 +1106,6 @@ fn dist_extended() {
[build] rustc 0 <host> -> cargo-clippy 1 <host>
[build] rustc 0 <host> -> miri 1 <host>
[build] rustc 0 <host> -> cargo-miri 1 <host>
- [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
");
}
@@ -1294,17 +1307,19 @@ fn check_compiler_no_explicit_stage() {
ctx.config("check")
.path("compiler")
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
");
+ }
+ #[test]
+ fn check_rustc_no_explicit_stage() {
+ let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx.config("check")
.path("rustc")
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
");
}
@@ -1324,7 +1339,6 @@ fn check_compiler_stage_1() {
.path("compiler")
.stage(1)
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@@ -1456,7 +1470,6 @@ fn check_library_skip_without_download_rustc() {
.paths(&["library", "compiler"])
.args(&args)
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@@ -1470,7 +1483,6 @@ fn check_miri_no_explicit_stage() {
ctx.config("check")
.path("miri")
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> Miri 1 <host>
");
@@ -1491,7 +1503,6 @@ fn check_miri_stage_1() {
.path("miri")
.stage(1)
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> Miri 1 <host>
");
@@ -1544,7 +1555,6 @@ fn check_codegen() {
ctx.config("check")
.path("rustc_codegen_cranelift")
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@@ -1558,7 +1568,6 @@ fn check_rust_analyzer() {
ctx.config("check")
.path("rust-analyzer")
.render_steps(), @r"
- [build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> rust-analyzer 1 <host>
");
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 44be518..63aab4d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -253,12 +253,24 @@ pub enum Mode {
/// These tools are intended to be only executed on the host system that
/// invokes bootstrap, and they thus cannot be cross-compiled.
///
- /// They are always built using the stage0 compiler, and typically they
+ /// They are always built using the stage0 compiler, and they
/// can be compiled with stable Rust.
///
/// These tools also essentially do not participate in staging.
ToolBootstrap,
+ /// Build a cross-compilable helper tool. These tools do not depend on unstable features or
+ /// compiler internals, but they might be cross-compilable (so we cannot build them using the
+ /// stage0 compiler, unlike `ToolBootstrap`).
+ ///
+ /// Some of these tools are also shipped in our `dist` archives.
+ /// While we could compile them using the stage0 compiler when not cross-compiling, we instead
+ /// use the in-tree compiler (and std) to build them, so that we can ship e.g. std security
+ /// fixes and avoid depending fully on stage0 for the artifacts that we ship.
+ ///
+ /// This mode is used e.g. for linkers and linker tools invoked by rustc on its host target.
+ ToolTarget,
+
/// Build a tool which uses the locally built std, placing output in the
/// "stageN-tools" directory. Its usage is quite rare, mainly used by
/// compiletest which needs libtest.
@@ -273,11 +285,21 @@ pub enum Mode {
impl Mode {
pub fn is_tool(&self) -> bool {
- matches!(self, Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd)
+ match self {
+ Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd | Mode::ToolTarget => true,
+ Mode::Std | Mode::Codegen | Mode::Rustc => false,
+ }
}
pub fn must_support_dlopen(&self) -> bool {
- matches!(self, Mode::Std | Mode::Codegen)
+ match self {
+ Mode::Std | Mode::Codegen => true,
+ Mode::ToolBootstrap
+ | Mode::ToolRustc
+ | Mode::ToolStd
+ | Mode::ToolTarget
+ | Mode::Rustc => false,
+ }
}
}
@@ -802,17 +824,39 @@ fn tools_dir(&self, compiler: Compiler) -> PathBuf {
/// stage when running with a particular host compiler.
///
/// The mode indicates what the root directory is for.
- fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
- let suffix = match mode {
- Mode::Std => "-std",
- Mode::Rustc => "-rustc",
- Mode::Codegen => "-codegen",
- Mode::ToolBootstrap => {
- return self.out.join(compiler.host).join("bootstrap-tools");
+ fn stage_out(&self, build_compiler: Compiler, mode: Mode) -> PathBuf {
+ use std::fmt::Write;
+
+ fn bootstrap_tool() -> (Option<u32>, &'static str) {
+ (None, "bootstrap-tools")
+ }
+ fn staged_tool(build_compiler: Compiler) -> (Option<u32>, &'static str) {
+ (Some(build_compiler.stage), "tools")
+ }
+
+ let (stage, suffix) = match mode {
+ Mode::Std => (Some(build_compiler.stage), "std"),
+ Mode::Rustc => (Some(build_compiler.stage), "rustc"),
+ Mode::Codegen => (Some(build_compiler.stage), "codegen"),
+ Mode::ToolBootstrap => bootstrap_tool(),
+ Mode::ToolStd | Mode::ToolRustc => (Some(build_compiler.stage), "tools"),
+ Mode::ToolTarget => {
+ // If we're not cross-compiling (the common case), share the target directory with
+ // bootstrap tools to reuse the build cache.
+ if build_compiler.stage == 0 {
+ bootstrap_tool()
+ } else {
+ staged_tool(build_compiler)
+ }
}
- Mode::ToolStd | Mode::ToolRustc => "-tools",
};
- self.out.join(compiler.host).join(format!("stage{}{}", compiler.stage, suffix))
+ let path = self.out.join(build_compiler.host);
+ let mut dir_name = String::new();
+ if let Some(stage) = stage {
+ write!(dir_name, "stage{stage}-").unwrap();
+ }
+ dir_name.push_str(suffix);
+ path.join(dir_name)
}
/// Returns the root output directory for all Cargo output in a given stage,
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index f0c52fe..0a6ebe4 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -172,9 +172,9 @@
optional:
# This job is used just to test optional jobs.
# It will be replaced by tier 2 and tier 3 jobs in the future.
- - name: optional-mingw-check-1
+ - name: optional-pr-check-1
env:
- IMAGE: mingw-check-1
+ IMAGE: pr-check-1
<<: *job-linux-4c
# Main CI jobs that have to be green to merge a commit into master
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index ad85207..ed87628 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -43,4 +43,9 @@
curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
7z x -y mingw.7z > /dev/null
ciCommandAddPath "$(cygpath -m "$(pwd)/${mingw_dir}/bin")"
+
+ # Initialize mingw for the user.
+ # This should be done by github but isn't for some reason.
+ # (see https://github.com/actions/runner-images/issues/12600)
+ /c/msys64/usr/bin/bash -lc ' '
fi
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 63aa08c..5c3ae35 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -75,8 +75,10 @@
| `check-fail` | Building (no codegen) should fail | `ui`, `crashes` | N/A |
| `build-pass` | Building should pass | `ui`, `crashes`, `codegen`, `incremental` | N/A |
| `build-fail` | Building should fail | `ui`, `crashes` | N/A |
-| `run-pass` | Running the test binary should pass | `ui`, `crashes`, `incremental` | N/A |
-| `run-fail` | Running the test binary should fail | `ui`, `crashes` | N/A |
+| `run-pass` | Program must exit with code `0` | `ui`, `crashes`, `incremental` | N/A |
+| `run-fail` | Program must exit with code `1..=127` | `ui`, `crashes` | N/A |
+| `run-crash` | Program must crash | `ui` | N/A |
+| `run-fail-or-crash` | Program must `run-fail` or `run-crash` | `ui` | N/A |
| `ignore-pass` | Ignore `--pass` flag | `ui`, `crashes`, `codegen`, `incremental` | N/A |
| `dont-check-failure-status` | Don't check exact failure status (i.e. `1`) | `ui`, `incremental` | N/A |
| `failure-status` | Check | `ui`, `crashes` | Any `u16` |
@@ -203,6 +205,8 @@
on `wasm32-unknown-unknown` target because the target does not support the
`proc-macro` crate type.
- `needs-target-std` — ignores if target platform does not have std support.
+- `ignore-backends` — ignores the listed backends, separated by whitespace characters.
+- `needs-backends` — only runs the test if current codegen backend is listed.
The following directives will check LLVM support:
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 4fce583..9bfc60e 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -448,7 +448,7 @@
- `//@ build-pass` — compilation and linking should succeed but do
not run the resulting binary.
- `//@ run-pass` — compilation should succeed and running the resulting
- binary should also succeed.
+ binary should make it exit with code 0 which indicates success.
- Fail directives:
- `//@ check-fail` — compilation should fail (the codegen phase is skipped).
This is the default for UI tests.
@@ -457,10 +457,20 @@
- First time is to ensure that the compile succeeds without the codegen phase
- Second time is to ensure that the full compile fails
- `//@ run-fail` — compilation should succeed, but running the resulting
- binary should fail.
+ binary should make it exit with a code in the range `1..=127` which
+ indicates regular failure. On targets without unwind support, crashes
+ are also accepted.
+ - `//@ run-crash` — compilation should succeed, but running the resulting
+ binary should fail with a crash. Crashing is defined as "not exiting with
+ a code in the range `0..=127`". Example on Linux: Termination by `SIGABRT`
+ or `SIGSEGV`. Example on Windows: Exiting with the code for
+ `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`).
+ - `//@ run-fail-or-crash` — compilation should succeed, but running the
+ resulting binary should either `run-fail` or `run-crash`. Useful if a test
+ crashes on some targets but just fails on others.
-For `run-pass` and `run-fail` tests, by default the output of the program itself
-is not checked.
+For `run-pass`. `run-fail`, `run-crash` and `run-fail-or-crash` tests, by
+default the output of the program itself is not checked.
If you want to check the output of running the program, include the
`check-run-results` directive. This will check for a `.run.stderr` and
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index f8bafe0..c80d7d8 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -54,17 +54,17 @@
programs for the Linux operating system on the AMD64 architecture and
equivalent.
-| Exploit mitigation | Supported and enabled by default | Since |
-| - | - | - |
-| Position-independent executable | Yes | 0.12.0 (2014-10-09) |
-| Integer overflow checks | Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) | 1.1.0 (2015-06-25) |
-| Non-executable memory regions | Yes | 1.8.0 (2016-04-14) |
-| Stack clashing protection | Yes | 1.20.0 (2017-08-31) |
-| Read-only relocations and immediate binding | Yes | 1.21.0 (2017-10-12) |
-| Heap corruption protection | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) |
-| Stack smashing protection | Yes | Nightly |
-| Forward-edge control flow protection | Yes | Nightly |
-| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | Nightly |
+| Exploit mitigation | Supported | Enabled by default | Since |
+| - | - | - | - |
+| Position-independent executable | Yes | Yes | 0.12.0 (2014-10-09) |
+| Integer overflow checks | Yes | (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) | 1.1.0 (2015-06-25) |
+| Non-executable memory regions | Yes | Yes | 1.8.0 (2016-04-14) |
+| Stack clashing protection | Yes | Yes | 1.20.0 (2017-08-31) |
+| Read-only relocations and immediate binding | Yes | Yes | 1.21.0 (2017-10-12) |
+| Heap corruption protection | Yes | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) |
+| Stack smashing protection | Yes | No, `-Z stack-protector` | Nightly |
+| Forward-edge control flow protection | Yes | No, `-Z sanitizer=cfi` | Nightly |
+| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | No, `-Z sanitizer=shadow-call-stack,safestack` | Nightly |
[^all-targets]: See <https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec>
for a list of targets and their default options.
diff --git a/src/doc/rustc/src/platform-support/xtensa.md b/src/doc/rustc/src/platform-support/xtensa.md
index 994b3ad..8592ce7 100644
--- a/src/doc/rustc/src/platform-support/xtensa.md
+++ b/src/doc/rustc/src/platform-support/xtensa.md
@@ -24,4 +24,4 @@
## Building the targets
-The targets can be built by installing the [Xtensa enabled Rust channel](https://github.com/esp-rs/rust/). See instructions in the [RISC-V and Xtensa Targets section of The Rust on ESP Book](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html).
+The targets can be built by installing the [Xtensa enabled Rust channel](https://github.com/esp-rs/rust/). See instructions in the [RISC-V and Xtensa Targets section of The Rust on ESP Book](https://docs.espressif.com/projects/rust/book/installation/index.html).
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0964749..5ac5da2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1677,7 +1677,7 @@ pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
}
}
- pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
+ pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
match self {
Type::Path { path, .. } => path.generics(),
_ => None,
@@ -2227,7 +2227,7 @@ pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
self.segments.last().map(|seg| &seg.args)
}
- pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
+ pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
self.segments.last().and_then(|seg| {
if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
Some(args.iter().filter_map(|arg| match arg {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index fd1b17b..813fdee 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -343,13 +343,11 @@ fn print_pat(pat: &Pat<'_>, wild: bool) -> impl Display {
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
- let s = if let Some(def) = def.as_local() {
+ if let Some(def) = def.as_local() {
rendered_const(cx.tcx, cx.tcx.hir_body_owned_by(def), def)
} else {
inline::print_inlined_const(cx.tcx, def)
- };
-
- s
+ }
}
// array lengths are obviously usize
ty::ConstKind::Value(cv) if *cv.ty.kind() == ty::Uint(ty::UintTy::Usize) => {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 9b4d253..38ba6b4 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -632,7 +632,7 @@ fn run_test(
// the user to exploit nightly-only features on stable
runner_compiler.env("RUSTC_BOOTSTRAP", "1");
runner_compiler.args(compiler_args);
- runner_compiler.args(&["--crate-type=bin", "-o"]).arg(&output_file);
+ runner_compiler.args(["--crate-type=bin", "-o"]).arg(&output_file);
let mut extern_path = std::ffi::OsString::from(format!(
"--extern=doctest_bundle_{edition}=",
edition = doctest.edition
@@ -657,7 +657,7 @@ fn run_test(
extern_path.push(&output_bundle_file);
runner_compiler.arg(extern_path);
runner_compiler.arg(&runner_input_file);
- if std::fs::write(&runner_input_file, &merged_test_code).is_err() {
+ if std::fs::write(&runner_input_file, merged_test_code).is_err() {
// If we cannot write this file for any reason, we leave. All combined tests will be
// tested as standalone tests.
return Err(TestFailure::CompileError);
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 9697510..f5ec828 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -140,7 +140,7 @@ fn visit_testable<F: FnOnce(&mut Self)>(
.iter()
.filter(|a| a.has_name(sym::attr))
.flat_map(|a| a.meta_item_list().unwrap_or_default())
- .map(|i| pprust::meta_list_item_to_string(i))
+ .map(pprust::meta_list_item_to_string)
{
// Add the additional attributes to the global_crate_attrs vector
self.collector.global_crate_attrs.push(attr);
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 79ff1fa..aa4be4d 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -81,7 +81,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
let _timer =
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
- cx.mod_item_in(&item)?;
+ cx.mod_item_in(item)?;
let (clean::StrippedItem(box clean::ModuleItem(ref module))
| clean::ModuleItem(ref module)) = item.inner.kind
else {
@@ -99,7 +99,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
} else if let Some(item_name) = item.name
&& !item.is_extern_crate()
{
- prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(&item))?;
+ prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
}
Ok(())
}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b164851..be8a2d5 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -114,9 +114,9 @@ pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
let real_params =
fmt::from_fn(|f| real_params.clone().map(|g| g.print(cx)).joined(", ", f));
if f.alternate() {
- write!(f, "<{:#}>", real_params)
+ write!(f, "<{real_params:#}>")
} else {
- write!(f, "<{}>", real_params)
+ write!(f, "<{real_params}>")
}
})
}
@@ -594,7 +594,7 @@ pub(crate) fn href_with_root_path(
}
}
};
- let url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
+ let url_parts = make_href(root_path, shortty, url_parts, fqp, is_remote);
Ok((url_parts, shortty, fqp.clone()))
}
@@ -1115,7 +1115,7 @@ pub(crate) fn print(&self, use_absolute: bool, cx: &Context<'_>) -> impl Display
{
let last = ty.last();
if f.alternate() {
- write!(f, "{}<", last)?;
+ write!(f, "{last}<")?;
self.print_type(inner_type, f, use_absolute, cx)?;
write!(f, ">")?;
} else {
@@ -1219,7 +1219,7 @@ pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> imp
.map(|param| {
fmt::from_fn(|f| {
if let Some(name) = param.name {
- write!(f, "{}: ", name)?;
+ write!(f, "{name}: ")?;
}
param.type_.print(cx).fmt(f)
})
@@ -1341,7 +1341,7 @@ fn inner_full_print(
write!(f, "const ")?;
}
if let Some(name) = param.name {
- write!(f, "{}: ", name)?;
+ write!(f, "{name}: ")?;
}
param.type_.print(cx).fmt(f)?;
}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index b2feee3..272180f 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -547,7 +547,7 @@ fn next(&mut self) -> Option<(TokenKind, &'a str)> {
fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class> {
let ignore: &[&str] =
if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] };
- if ignore.iter().any(|k| *k == text) {
+ if ignore.contains(&text) {
return None;
}
Some(match text {
@@ -1159,7 +1159,7 @@ fn string_without_closing_tag<T: Display>(
return Some("</a>");
}
if !open_tag {
- write!(out, "{}", text_s).unwrap();
+ out.write_str(&text_s).unwrap();
return None;
}
let klass_s = klass.as_html();
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 50320cb..1f92c52 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -132,6 +132,5 @@ pub(crate) fn redirect(url: &str) -> String {
<script>location.replace("{url}" + location.search + location.hash);</script>
</body>
</html>"##,
- url = url,
)
}
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index e41435d..4addf2c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -251,7 +251,7 @@ fn next(&mut self) -> Option<Self::Item> {
if !parse_result.rust {
let added_classes = parse_result.added_classes;
let lang_string = if let Some(lang) = parse_result.unknown.first() {
- format!("language-{}", lang)
+ format!("language-{lang}")
} else {
String::new()
};
@@ -999,7 +999,7 @@ fn parse_key_value(&mut self, c: char, start: usize) -> Option<LangStringToken<'
if let Some((_, c)) = self.inner.next() {
if c != '=' {
- self.emit_error(format!("expected `=`, found `{}`", c));
+ self.emit_error(format!("expected `=`, found `{c}`"));
return None;
}
} else {
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 7b81470..5ceb1fc 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -193,14 +193,12 @@ fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
if it.is_stripped()
&& let Some(def_id) = it.def_id()
&& def_id.is_local()
+ && (self.info.is_inside_inlined_module
+ || self.shared.cache.inlined_items.contains(&def_id))
{
- if self.info.is_inside_inlined_module
- || self.shared.cache.inlined_items.contains(&def_id)
- {
- // For now we're forced to generate a redirect page for stripped items until
- // `record_extern_fqn` correctly points to external items.
- render_redirect_pages = true;
- }
+ // For now we're forced to generate a redirect page for stripped items until
+ // `record_extern_fqn` correctly points to external items.
+ render_redirect_pages = true;
}
let mut title = String::new();
if !is_module {
@@ -254,40 +252,36 @@ fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
&self.shared.style_files,
)
} else {
- if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
- if self.current.len() + 1 != names.len()
- || self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
- {
- // We checked that the redirection isn't pointing to the current file,
- // preventing an infinite redirection loop in the generated
- // documentation.
+ if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id())
+ && (self.current.len() + 1 != names.len()
+ || self.current.iter().zip(names.iter()).any(|(a, b)| a != b))
+ {
+ // We checked that the redirection isn't pointing to the current file,
+ // preventing an infinite redirection loop in the generated
+ // documentation.
- let path = fmt::from_fn(|f| {
- for name in &names[..names.len() - 1] {
- write!(f, "{name}/")?;
+ let path = fmt::from_fn(|f| {
+ for name in &names[..names.len() - 1] {
+ write!(f, "{name}/")?;
+ }
+ write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
+ });
+ match self.shared.redirections {
+ Some(ref redirections) => {
+ let mut current_path = String::new();
+ for name in &self.current {
+ current_path.push_str(name.as_str());
+ current_path.push('/');
}
- write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
- });
- match self.shared.redirections {
- Some(ref redirections) => {
- let mut current_path = String::new();
- for name in &self.current {
- current_path.push_str(name.as_str());
- current_path.push('/');
- }
- let _ = write!(
- current_path,
- "{}",
- print_item_path(ty, names.last().unwrap().as_str())
- );
- redirections.borrow_mut().insert(current_path, path.to_string());
- }
- None => {
- return layout::redirect(&format!(
- "{root}{path}",
- root = self.root_path()
- ));
- }
+ let _ = write!(
+ current_path,
+ "{}",
+ print_item_path(ty, names.last().unwrap().as_str())
+ );
+ redirections.borrow_mut().insert(current_path, path.to_string());
+ }
+ None => {
+ return layout::redirect(&format!("{root}{path}", root = self.root_path()));
}
}
}
@@ -762,11 +756,7 @@ fn after_krate(mut self) -> Result<(), Error> {
// Flush pending errors.
self.shared.fs.close();
let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
- if nb_errors > 0 {
- Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
- } else {
- Ok(())
- }
+ if nb_errors > 0 { Err(Error::new(io::Error::other("I/O error"), "")) } else { Ok(()) }
}
fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
@@ -842,7 +832,7 @@ fn item(&mut self, item: &clean::Item) -> Result<(), Error> {
self.info.render_redirect_pages = item.is_stripped();
}
- let buf = self.render_item(&item, false);
+ let buf = self.render_item(item, false);
// buf will be empty if the item is stripped and there is no redirect for it
if !buf.is_empty() {
let name = item.name.as_ref().unwrap();
@@ -853,7 +843,7 @@ fn item(&mut self, item: &clean::Item) -> Result<(), Error> {
self.shared.fs.write(joint_dst, buf)?;
if !self.info.render_redirect_pages {
- self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
+ self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
}
// If the item is a macro, redirect from the old macro URL (with !)
// to the new one (without).
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index d8c3713..872dbbc 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1110,7 +1110,7 @@ fn since_to_string(since: &StableSince) -> Option<String> {
match since {
StableSince::Version(since) => Some(since.to_string()),
StableSince::Current => Some(RustcVersion::CURRENT.to_string()),
- StableSince::Err => None,
+ StableSince::Err(_) => None,
}
}
@@ -1483,10 +1483,10 @@ fn render_deref_methods(
}
}
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
- } else if let Some(prim) = target.primitive_type() {
- if let Some(&did) = cache.primitive_locations.get(&prim) {
- render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
- }
+ } else if let Some(prim) = target.primitive_type()
+ && let Some(&did) = cache.primitive_locations.get(&prim)
+ {
+ render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
}
}
@@ -2058,21 +2058,20 @@ fn render_default_items(
// default items which weren't overridden in the implementation block.
// We don't emit documentation for default items if they appear in the
// Implementations on Foreign Types or Implementors sections.
- if rendering_params.show_default_items {
- if let Some(t) = trait_
- && !impl_.is_negative_trait_impl()
- {
- render_default_items(
- &mut default_impl_items,
- &mut impl_items,
- cx,
- t,
- impl_,
- &i.impl_item,
- render_mode,
- rendering_params,
- )?;
- }
+ if rendering_params.show_default_items
+ && let Some(t) = trait_
+ && !impl_.is_negative_trait_impl()
+ {
+ render_default_items(
+ &mut default_impl_items,
+ &mut impl_items,
+ cx,
+ t,
+ impl_,
+ &i.impl_item,
+ render_mode,
+ rendering_params,
+ )?;
}
if render_mode == RenderMode::Normal {
let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
@@ -2570,7 +2569,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String>
match ty {
clean::Type::Path { path } => process_path(path.def_id()),
clean::Type::Tuple(tys) => {
- work.extend(tys.into_iter());
+ work.extend(tys.iter());
}
clean::Type::Slice(ty) => {
work.push_back(ty);
diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs
index d1dddfe..be51dad 100644
--- a/src/librustdoc/html/render/ordered_json.rs
+++ b/src/librustdoc/html/render/ordered_json.rs
@@ -25,7 +25,7 @@ pub(crate) fn array_sorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I)
.into_iter()
.sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow()))
.format_with(",", |item, f| f(item.borrow()));
- Self(format!("[{}]", items))
+ Self(format!("[{items}]"))
}
pub(crate) fn array_unsorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 5fbda47..02ee34a 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1451,7 +1451,7 @@ struct ItemUnion<'a, 'cx> {
impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
fn render_union(&self) -> impl Display {
- render_union(self.it, Some(&self.generics), &self.fields, self.cx)
+ render_union(self.it, Some(self.generics), self.fields, self.cx)
}
fn document_field(&self, field: &'a clean::Item) -> impl Display {
@@ -1982,16 +1982,14 @@ fn item_constant(
w.write_str(";")?;
}
- if !is_literal {
- if let Some(value) = &value {
- let value_lowercase = value.to_lowercase();
- let expr_lowercase = expr.to_lowercase();
+ if !is_literal && let Some(value) = &value {
+ let value_lowercase = value.to_lowercase();
+ let expr_lowercase = expr.to_lowercase();
- if value_lowercase != expr_lowercase
- && value_lowercase.trim_end_matches("i32") != expr_lowercase
- {
- write!(w, " // {value}", value = Escape(value))?;
- }
+ if value_lowercase != expr_lowercase
+ && value_lowercase.trim_end_matches("i32") != expr_lowercase
+ {
+ write!(w, " // {value}", value = Escape(value))?;
}
}
Ok::<(), fmt::Error>(())
@@ -2071,41 +2069,39 @@ fn item_fields(
_ => None,
})
.peekable();
- if let None | Some(CtorKind::Fn) = ctor_kind {
- if fields.peek().is_some() {
- let title = format!(
- "{}{}",
- if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
- document_non_exhaustive_header(it),
- );
+ if let None | Some(CtorKind::Fn) = ctor_kind
+ && fields.peek().is_some()
+ {
+ let title = format!(
+ "{}{}",
+ if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
+ document_non_exhaustive_header(it),
+ );
+ write!(
+ w,
+ "{}",
+ write_section_heading(
+ &title,
+ "fields",
+ Some("fields"),
+ document_non_exhaustive(it)
+ )
+ )?;
+ for (index, (field, ty)) in fields.enumerate() {
+ let field_name =
+ field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
+ let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
write!(
w,
- "{}",
- write_section_heading(
- &title,
- "fields",
- Some("fields"),
- document_non_exhaustive(it)
- )
+ "<span id=\"{id}\" class=\"{item_type} section-header\">\
+ <a href=\"#{id}\" class=\"anchor field\">§</a>\
+ <code>{field_name}: {ty}</code>\
+ </span>\
+ {doc}",
+ item_type = ItemType::StructField,
+ ty = ty.print(cx),
+ doc = document(cx, field, Some(it), HeadingOffset::H3),
)?;
- for (index, (field, ty)) in fields.enumerate() {
- let field_name = field
- .name
- .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
- let id =
- cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
- write!(
- w,
- "<span id=\"{id}\" class=\"{item_type} section-header\">\
- <a href=\"#{id}\" class=\"anchor field\">§</a>\
- <code>{field_name}: {ty}</code>\
- </span>\
- {doc}",
- item_type = ItemType::StructField,
- ty = ty.print(cx),
- doc = document(cx, field, Some(it), HeadingOffset::H3),
- )?;
- }
}
}
Ok(())
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 80a59fa..3c9be29 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -116,7 +116,7 @@ pub(crate) fn build_index(
// Set up alias indexes.
for (i, item) in cache.search_index.iter().enumerate() {
for alias in &item.aliases[..] {
- aliases.entry(alias.as_str().to_lowercase()).or_default().push(i);
+ aliases.entry(alias.to_string()).or_default().push(i);
}
}
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 91540e06..b9f5ada 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -541,7 +541,7 @@ fn sidebar_deref_methods<'a>(
.iter()
.filter(|i| {
i.inner_impl().trait_.is_none()
- && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c)
+ && real_target.is_doc_subtype_of(&i.inner_impl().for_, c)
})
.flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
.collect::<Vec<_>>();
diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs
index a7b954a..659c5e6 100644
--- a/src/librustdoc/html/render/sorted_template.rs
+++ b/src/librustdoc/html/render/sorted_template.rs
@@ -63,7 +63,8 @@ fn fmt(&self, mut f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (p, fragment) in self.fragments.iter().with_position() {
let mut f = DeltaWriter { inner: &mut f, delta: 0 };
let sep = if matches!(p, Position::First | Position::Only) { "" } else { F::SEPARATOR };
- write!(f, "{}{}", sep, fragment)?;
+ f.write_str(sep)?;
+ f.write_str(fragment)?;
fragment_lengths.push(f.delta);
}
let offset = Offset { start: self.before.len(), fragment_lengths };
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index ca2512e..a958976 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -219,6 +219,8 @@
crate: string,
descShard: SearchDescShard,
id: number,
+ // This is the name of the item. For doc aliases, if you want the name of the aliased
+ // item, take a look at `Row.original.name`.
name: string,
normalizedName: string,
word: string,
@@ -227,6 +229,11 @@
path: string,
ty: number,
type: FunctionSearchType | null,
+ descIndex: number,
+ bitIndex: number,
+ implDisambiguator: String | null,
+ is_alias?: boolean,
+ original?: Row,
}
/**
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 15cad31..2caf214 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -830,7 +830,7 @@
*/
function makePrimitiveElement(name, extra) {
return Object.assign({
- name: name,
+ name,
id: null,
fullPath: [name],
pathWithoutLast: [],
@@ -1483,6 +1483,7 @@
*/
this.assocTypeIdNameMap = new Map();
this.ALIASES = new Map();
+ this.FOUND_ALIASES = new Set();
this.rootPath = rootPath;
this.searchState = searchState;
@@ -2030,6 +2031,8 @@
// normalized names, type signature objects and fingerprints, and aliases.
id = 0;
+ /** @type {Array<[string, { [key: string]: Array<number> }, number]>} */
+ const allAliases = [];
for (const [crate, crateCorpus] of rawSearchIndex) {
// a string representing the lengths of each description shard
// a string representing the list of function types
@@ -2178,10 +2181,10 @@
paths[i] = { ty, name, path, exactPath, unboxFlag };
}
- // convert `item*` into an object form, and construct word indices.
+ // Convert `item*` into an object form, and construct word indices.
//
- // before any analysis is performed lets gather the search terms to
- // search against apart from the rest of the data. This is a quick
+ // Before any analysis is performed, let's gather the search terms to
+ // search against apart from the rest of the data. This is a quick
// operation that is cached for the life of the page state so that
// all other search operations have access to this cached data for
// faster analysis operations
@@ -2269,29 +2272,58 @@
}
if (aliases) {
- const currentCrateAliases = new Map();
- this.ALIASES.set(crate, currentCrateAliases);
- for (const alias_name in aliases) {
- if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
- continue;
- }
-
- /** @type{number[]} */
- let currentNameAliases;
- if (currentCrateAliases.has(alias_name)) {
- currentNameAliases = currentCrateAliases.get(alias_name);
- } else {
- currentNameAliases = [];
- currentCrateAliases.set(alias_name, currentNameAliases);
- }
- for (const local_alias of aliases[alias_name]) {
- currentNameAliases.push(local_alias + currentIndex);
- }
- }
+ // We need to add the aliases in `searchIndex` after we finished filling it
+ // to not mess up indexes.
+ allAliases.push([crate, aliases, currentIndex]);
}
currentIndex += itemTypes.length;
this.searchState.descShards.set(crate, descShardList);
}
+
+ for (const [crate, aliases, index] of allAliases) {
+ for (const [alias_name, alias_refs] of Object.entries(aliases)) {
+ if (!this.ALIASES.has(crate)) {
+ this.ALIASES.set(crate, new Map());
+ }
+ const word = alias_name.toLowerCase();
+ const crate_alias_map = this.ALIASES.get(crate);
+ if (!crate_alias_map.has(word)) {
+ crate_alias_map.set(word, []);
+ }
+ const aliases_map = crate_alias_map.get(word);
+
+ const normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, "");
+ for (const alias of alias_refs) {
+ const originalIndex = alias + index;
+ const original = searchIndex[originalIndex];
+ /** @type {rustdoc.Row} */
+ const row = {
+ crate,
+ name: alias_name,
+ normalizedName,
+ is_alias: true,
+ ty: original.ty,
+ type: original.type,
+ paramNames: [],
+ word,
+ id,
+ parent: undefined,
+ original,
+ path: "",
+ implDisambiguator: original.implDisambiguator,
+ // Needed to load the description of the original item.
+ // @ts-ignore
+ descShard: original.descShard,
+ descIndex: original.descIndex,
+ bitIndex: original.bitIndex,
+ };
+ aliases_map.push(row);
+ this.nameTrie.insert(normalizedName, id, this.tailTable);
+ id += 1;
+ searchIndex.push(row);
+ }
+ }
+ }
// Drop the (rather large) hash table used for reusing function items
this.TYPES_POOL = new Map();
return searchIndex;
@@ -2536,6 +2568,8 @@
parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) +
parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0);
const maxEditDistance = Math.floor(queryLen / 3);
+ // We reinitialize the `FOUND_ALIASES` map.
+ this.FOUND_ALIASES.clear();
/**
* @type {Map<string, number>}
@@ -2695,6 +2729,10 @@
const buildHrefAndPath = item => {
let displayPath;
let href;
+ if (item.is_alias) {
+ this.FOUND_ALIASES.add(item.word);
+ item = item.original;
+ }
const type = itemTypes[item.ty];
const name = item.name;
let path = item.path;
@@ -3198,8 +3236,7 @@
result.item = this.searchIndex[result.id];
result.word = this.searchIndex[result.id].word;
if (isReturnTypeQuery) {
- // we are doing a return-type based search,
- // deprioritize "clone-like" results,
+ // We are doing a return-type based search, deprioritize "clone-like" results,
// ie. functions that also take the queried type as an argument.
const resultItemType = result.item && result.item.type;
if (!resultItemType) {
@@ -4259,28 +4296,13 @@
return false;
}
- // this does not yet have a type in `rustdoc.d.ts`.
- // @ts-expect-error
- function createAliasFromItem(item) {
- return {
- crate: item.crate,
- name: item.name,
- path: item.path,
- descShard: item.descShard,
- descIndex: item.descIndex,
- exactPath: item.exactPath,
- ty: item.ty,
- parent: item.parent,
- type: item.type,
- is_alias: true,
- bitIndex: item.bitIndex,
- implDisambiguator: item.implDisambiguator,
- };
- }
-
// @ts-expect-error
const handleAliases = async(ret, query, filterCrates, currentCrate) => {
const lowerQuery = query.toLowerCase();
+ if (this.FOUND_ALIASES.has(lowerQuery)) {
+ return;
+ }
+ this.FOUND_ALIASES.add(lowerQuery);
// We separate aliases and crate aliases because we want to have current crate
// aliases to be before the others in the displayed results.
// @ts-expect-error
@@ -4292,7 +4314,7 @@
&& this.ALIASES.get(filterCrates).has(lowerQuery)) {
const query_aliases = this.ALIASES.get(filterCrates).get(lowerQuery);
for (const alias of query_aliases) {
- aliases.push(createAliasFromItem(this.searchIndex[alias]));
+ aliases.push(alias);
}
}
} else {
@@ -4302,7 +4324,7 @@
const pushTo = crate === currentCrate ? crateAliases : aliases;
const query_aliases = crateAliasesIndex.get(lowerQuery);
for (const alias of query_aliases) {
- pushTo.push(createAliasFromItem(this.searchIndex[alias]));
+ pushTo.push(alias);
}
}
}
@@ -4310,9 +4332,9 @@
// @ts-expect-error
const sortFunc = (aaa, bbb) => {
- if (aaa.path < bbb.path) {
+ if (aaa.original.path < bbb.original.path) {
return 1;
- } else if (aaa.path === bbb.path) {
+ } else if (aaa.original.path === bbb.original.path) {
return 0;
}
return -1;
@@ -4322,20 +4344,9 @@
aliases.sort(sortFunc);
// @ts-expect-error
- const fetchDesc = alias => {
- // @ts-expect-error
- return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ?
- "" : this.searchState.loadDesc(alias);
- };
- const [crateDescs, descs] = await Promise.all([
- // @ts-expect-error
- Promise.all(crateAliases.map(fetchDesc)),
- Promise.all(aliases.map(fetchDesc)),
- ]);
-
- // @ts-expect-error
const pushFunc = alias => {
- alias.alias = query;
+ // Cloning `alias` to prevent its fields to be updated.
+ alias = {...alias};
const res = buildHrefAndPath(alias);
alias.displayPath = pathSplitter(res[0]);
alias.fullPath = alias.displayPath + alias.name;
@@ -4347,16 +4358,8 @@
}
};
- aliases.forEach((alias, i) => {
- // @ts-expect-error
- alias.desc = descs[i];
- });
aliases.forEach(pushFunc);
// @ts-expect-error
- crateAliases.forEach((alias, i) => {
- alias.desc = crateDescs[i];
- });
- // @ts-expect-error
crateAliases.forEach(pushFunc);
};
@@ -4802,7 +4805,7 @@
output.className = "search-results " + extraClass;
const lis = Promise.all(array.map(async item => {
- const name = item.name;
+ const name = item.is_alias ? item.original.name : item.name;
const type = itemTypes[item.ty];
const longType = longItemTypes[item.ty];
const typeName = longType.length !== 0 ? `${longType}` : "?";
@@ -4822,7 +4825,7 @@
let alias = " ";
if (item.is_alias) {
alias = ` <div class="alias">\
-<b>${item.alias}</b><i class="grey"> - see </i>\
+<b>${item.name}</b><i class="grey"> - see </i>\
</div>`;
}
resultName.insertAdjacentHTML(
@@ -5201,6 +5204,7 @@
if (searchState.input.value.length === 0) {
searchState.hideResults();
} else {
+ // @ts-ignore
searchState.timeout = setTimeout(search, 500);
}
};
@@ -5842,8 +5846,8 @@
// be called ONLY when the whole file has been parsed and loaded.
// @ts-expect-error
-function initSearch(searchIndx) {
- rawSearchIndex = searchIndx;
+function initSearch(searchIndex) {
+ rawSearchIndex = searchIndex;
if (typeof window !== "undefined") {
// @ts-expect-error
docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState);
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 0a84d8c..08bc0bb 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -50,7 +50,7 @@ pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
let span = item.span(self.tcx);
let visibility = item.visibility(self.tcx);
let clean::ItemInner { name, item_id, .. } = *item.inner;
- let id = self.id_from_item(&item);
+ let id = self.id_from_item(item);
let inner = match item.kind {
clean::KeywordItem => return None,
clean::StrippedItem(ref inner) => {
@@ -86,14 +86,14 @@ fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
items
.iter()
.filter(|i| !i.is_stripped() && !i.is_keyword())
- .map(|i| self.id_from_item(&i))
+ .map(|i| self.id_from_item(i))
.collect()
}
fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
items
.iter()
- .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i)))
+ .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(i)))
.collect()
}
}
@@ -358,12 +358,12 @@ fn from_clean(struct_: &clean::Struct, renderer: &JsonRenderer<'_>) -> Self {
let clean::Struct { ctor_kind, generics, fields } = struct_;
let kind = match ctor_kind {
- Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(&fields)),
+ Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)),
Some(CtorKind::Const) => {
assert!(fields.is_empty());
StructKind::Unit
}
- None => StructKind::Plain { fields: renderer.ids(&fields), has_stripped_fields },
+ None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields },
};
Struct {
@@ -381,7 +381,7 @@ fn from_clean(union_: &clean::Union, renderer: &JsonRenderer<'_>) -> Self {
Union {
generics: generics.into_json(renderer),
has_stripped_fields,
- fields: renderer.ids(&fields),
+ fields: renderer.ids(fields),
impls: Vec::new(), // Added in JsonRenderer::item
}
}
@@ -659,7 +659,7 @@ fn from_clean(decl: &clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self {
let clean::FnDecl { inputs, output, c_variadic } = decl;
FunctionSignature {
inputs: inputs
- .into_iter()
+ .iter()
.map(|param| {
// `_` is the most sensible name for missing param names.
let name = param.name.unwrap_or(kw::Underscore).to_string();
@@ -684,7 +684,7 @@ fn from_clean(trait_: &clean::Trait, renderer: &JsonRenderer<'_>) -> Self {
is_auto,
is_unsafe,
is_dyn_compatible,
- items: renderer.ids(&items),
+ items: renderer.ids(items),
generics: generics.into_json(renderer),
bounds: bounds.into_json(renderer),
implementations: Vec::new(), // Added in JsonRenderer::item
@@ -727,7 +727,7 @@ fn from_clean(impl_: &clean::Impl, renderer: &JsonRenderer<'_>) -> Self {
.collect(),
trait_: trait_.into_json(renderer),
for_: for_.into_json(renderer),
- items: renderer.ids(&items),
+ items: renderer.ids(items),
is_negative,
is_synthetic,
blanket_impl: blanket_impl.map(|x| x.into_json(renderer)),
@@ -770,7 +770,7 @@ fn from_clean(variant: &clean::Variant, renderer: &JsonRenderer<'_>) -> Self {
let kind = match &variant.kind {
CLike => VariantKind::Plain,
- Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(&fields)),
+ Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)),
Struct(s) => VariantKind::Struct {
has_stripped_fields: s.has_stripped_entries(),
fields: renderer.ids(&s.fields),
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 600a4b4..760e48b 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -133,7 +133,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
let feature_stability: FxHashMap<&str, Stability> = sess
.target
.rust_target_features()
- .into_iter()
+ .iter()
.copied()
.map(|(name, stability, _)| (name, stability))
.collect();
@@ -143,7 +143,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
target_features: sess
.target
.rust_target_features()
- .into_iter()
+ .iter()
.copied()
.filter(|(_, stability, _)| {
// Describe only target features which the user can toggle
@@ -157,7 +157,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
_ => None,
},
implies_features: implied_features
- .into_iter()
+ .iter()
.copied()
.filter(|name| {
// Imply only target features which the user can toggle
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ca6f67e..5a9aa2a 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -274,7 +274,7 @@ fn from(f: DiagnosticInfo<'_>) -> Self {
}
impl OwnedDiagnosticInfo {
- pub(crate) fn into_info(&self) -> DiagnosticInfo<'_> {
+ pub(crate) fn as_info(&self) -> DiagnosticInfo<'_> {
DiagnosticInfo {
item: &self.item,
ori_link: &self.ori_link,
@@ -1177,7 +1177,7 @@ pub(crate) fn resolve_ambiguities(&mut self) {
// Primitive types are always valid.
Res::Primitive(_) => true,
});
- let diag_info = info.diag_info.into_info();
+ let diag_info = info.diag_info.as_info();
match info.resolved.len() {
1 => {
let (res, fragment) = info.resolved.pop().unwrap();
@@ -1243,17 +1243,16 @@ fn compute_link(
disambiguator,
None | Some(Disambiguator::Namespace(Namespace::TypeNS) | Disambiguator::Primitive)
) && !matches!(res, Res::Primitive(_))
+ && let Some(prim) = resolve_primitive(path_str, TypeNS)
{
- if let Some(prim) = resolve_primitive(path_str, TypeNS) {
- // `prim@char`
- if matches!(disambiguator, Some(Disambiguator::Primitive)) {
- res = prim;
- } else {
- // `[char]` when a `char` module is in scope
- let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
- ambiguity_error(self.cx, &diag_info, path_str, candidates, true);
- return None;
- }
+ // `prim@char`
+ if matches!(disambiguator, Some(Disambiguator::Primitive)) {
+ res = prim;
+ } else {
+ // `[char]` when a `char` module is in scope
+ let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
+ ambiguity_error(self.cx, &diag_info, path_str, candidates, true);
+ return None;
}
}
@@ -2233,7 +2232,7 @@ fn ambiguity_error(
// 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 is_proc_macro_crate = cx.tcx.crate_types() == [CrateType::ProcMacro];
let mut kinds = candidates
.iter()
.map(|(res, def_id)| {
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 5757b6a..e69cf87 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -93,14 +93,14 @@ fn check_redundant_explicit_link<'md>(
if let Event::Start(Tag::Link { link_type, dest_url, .. }) = event {
let link_data = collect_link_data(&mut offset_iter);
- if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
- if &link_data.display_link.replace('`', "") != resolvable_link {
- // Skips if display link does not match to actual
- // resolvable link, usually happens if display link
- // has several segments, e.g.
- // [this is just an `Option`](Option)
- continue;
- }
+ if let Some(resolvable_link) = link_data.resolvable_link.as_ref()
+ && &link_data.display_link.replace('`', "") != resolvable_link
+ {
+ // Skips if display link does not match to actual
+ // resolvable link, usually happens if display link
+ // has several segments, e.g.
+ // [this is just an `Option`](Option)
+ continue;
}
let explicit_link = dest_url.to_string();
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
index b53e3b4..bb13308 100644
--- a/src/librustdoc/passes/strip_aliased_non_local.rs
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -47,13 +47,11 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
// FIXME(#125009): Not-local should probably consider same Cargo workspace
if let Some(def_id) = i.def_id()
&& !def_id.is_local()
- {
- if i.is_doc_hidden()
+ && (i.is_doc_hidden()
// Default to *not* stripping items with inherited visibility.
- || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public)
- {
- return Some(strip_item(i));
- }
+ || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public))
+ {
+ return Some(strip_item(i));
}
Some(self.fold_item_recur(i))
diff --git a/src/llvm-project b/src/llvm-project
index d3c793b..e8a2ffc 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit d3c793b025645a4565ac59aceb30d2d116ff1a41
+Subproject commit e8a2ffcf322f45b8dce82c65ab27a3e2430a6b51
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index cf70e88..216f168 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -249,7 +249,7 @@ fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: Msrv) -> bool {
let stable = match since {
StableSince::Version(v) => msrv.meets(cx, v),
StableSince::Current => msrv.current(cx).is_none(),
- StableSince::Err => false,
+ StableSince::Err(_) => false,
};
if !stable {
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 942c71a..b335645 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -432,7 +432,7 @@ pub fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bo
let const_stab_rust_version = match since {
StableSince::Version(version) => version,
StableSince::Current => RustcVersion::CURRENT,
- StableSince::Err => return false,
+ StableSince::Err(_) => return false,
};
msrv.meets(cx, const_stab_rust_version)
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 33da1a2..12084fa 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -88,11 +88,37 @@ pub enum PassMode {
}
}
+string_enum! {
+ #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ pub enum RunResult {
+ Pass => "run-pass",
+ Fail => "run-fail",
+ Crash => "run-crash",
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
+pub enum RunFailMode {
+ /// Running the program must make it exit with a regular failure exit code
+ /// in the range `1..=127`. If the program is terminated by e.g. a signal
+ /// the test will fail.
+ Fail,
+ /// Running the program must result in a crash, e.g. by `SIGABRT` or
+ /// `SIGSEGV` on Unix or on Windows by having an appropriate NTSTATUS high
+ /// bit in the exit code.
+ Crash,
+ /// Running the program must either fail or crash. Useful for e.g. sanitizer
+ /// tests since some sanitizer implementations exit the process with code 1
+ /// to in the face of memory errors while others abort (crash) the process
+ /// in the face of memory errors.
+ FailOrCrash,
+}
+
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum FailMode {
Check,
Build,
- Run,
+ Run(RunFailMode),
}
string_enum! {
@@ -149,6 +175,36 @@ pub enum Sanitizer {
Hwaddress,
}
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum CodegenBackend {
+ Cranelift,
+ Gcc,
+ Llvm,
+}
+
+impl<'a> TryFrom<&'a str> for CodegenBackend {
+ type Error = &'static str;
+
+ fn try_from(value: &'a str) -> Result<Self, Self::Error> {
+ match value.to_lowercase().as_str() {
+ "cranelift" => Ok(Self::Cranelift),
+ "gcc" => Ok(Self::Gcc),
+ "llvm" => Ok(Self::Llvm),
+ _ => Err("unknown backend"),
+ }
+ }
+}
+
+impl CodegenBackend {
+ pub fn as_str(self) -> &'static str {
+ match self {
+ Self::Cranelift => "cranelift",
+ Self::Gcc => "gcc",
+ Self::Llvm => "llvm",
+ }
+ }
+}
+
/// Configuration for `compiletest` *per invocation*.
///
/// In terms of `bootstrap`, this means that `./x test tests/ui tests/run-make` actually correspond
@@ -625,6 +681,9 @@ pub struct Config {
/// need `core` stubs in cross-compilation scenarios that do not otherwise want/need to
/// `-Zbuild-std`. Used in e.g. ABI tests.
pub minicore_path: Utf8PathBuf,
+
+ /// Current codegen backend used.
+ pub codegen_backend: CodegenBackend,
}
impl Config {
@@ -727,6 +786,7 @@ pub fn incomplete_for_rustdoc_gui_test() -> Config {
profiler_runtime: Default::default(),
diff_command: Default::default(),
minicore_path: Default::default(),
+ codegen_backend: CodegenBackend::Llvm,
}
}
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 93133ea..1397c87 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -9,7 +9,7 @@
use semver::Version;
use tracing::*;
-use crate::common::{Config, Debugger, FailMode, PassMode, TestMode};
+use crate::common::{CodegenBackend, Config, Debugger, FailMode, PassMode, RunFailMode, TestMode};
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
use crate::directives::auxiliary::{AuxProps, parse_and_update_aux};
use crate::directives::needs::CachedNeedsConditions;
@@ -654,7 +654,13 @@ fn update_fail_mode(&mut self, ln: &str, config: &Config) {
Some(FailMode::Build)
} else if config.parse_name_directive(ln, "run-fail") {
check_ui("run");
- Some(FailMode::Run)
+ Some(FailMode::Run(RunFailMode::Fail))
+ } else if config.parse_name_directive(ln, "run-crash") {
+ check_ui("run");
+ Some(FailMode::Run(RunFailMode::Crash))
+ } else if config.parse_name_directive(ln, "run-fail-or-crash") {
+ check_ui("run");
+ Some(FailMode::Run(RunFailMode::FailOrCrash))
} else {
None
};
@@ -812,6 +818,7 @@ fn line_directive<'line>(
"ignore-arm-unknown-linux-musleabihf",
"ignore-auxiliary",
"ignore-avr",
+ "ignore-backends",
"ignore-beta",
"ignore-cdb",
"ignore-compare-mode-next-solver",
@@ -901,6 +908,7 @@ fn line_directive<'line>(
"min-llvm-version",
"min-system-llvm-version",
"needs-asm-support",
+ "needs-backends",
"needs-crate-type",
"needs-deterministic-layouts",
"needs-dlltool",
@@ -1007,7 +1015,9 @@ fn line_directive<'line>(
"regex-error-pattern",
"remap-src-base",
"revisions",
+ "run-crash",
"run-fail",
+ "run-fail-or-crash",
"run-flags",
"run-pass",
"run-rustfix",
@@ -1661,6 +1671,8 @@ macro_rules! decision {
decision!(cfg::handle_only(config, ln));
decision!(needs::handle_needs(&cache.needs, config, ln));
decision!(ignore_llvm(config, path, ln));
+ decision!(ignore_backends(config, path, ln));
+ decision!(needs_backends(config, path, ln));
decision!(ignore_cdb(config, ln));
decision!(ignore_gdb(config, ln));
decision!(ignore_lldb(config, ln));
@@ -1787,6 +1799,49 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
IgnoreDecision::Continue
}
+fn ignore_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
+ if let Some(backends_to_ignore) = config.parse_name_value_directive(line, "ignore-backends") {
+ for backend in backends_to_ignore.split_whitespace().map(|backend| {
+ match CodegenBackend::try_from(backend) {
+ Ok(backend) => backend,
+ Err(error) => {
+ panic!("Invalid ignore-backends value `{backend}` in `{path}`: {error}")
+ }
+ }
+ }) {
+ if config.codegen_backend == backend {
+ return IgnoreDecision::Ignore {
+ reason: format!("{} backend is marked as ignore", backend.as_str()),
+ };
+ }
+ }
+ }
+ IgnoreDecision::Continue
+}
+
+fn needs_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
+ if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends") {
+ if !needed_backends
+ .split_whitespace()
+ .map(|backend| match CodegenBackend::try_from(backend) {
+ Ok(backend) => backend,
+ Err(error) => {
+ panic!("Invalid needs-backends value `{backend}` in `{path}`: {error}")
+ }
+ })
+ .any(|backend| config.codegen_backend == backend)
+ {
+ return IgnoreDecision::Ignore {
+ reason: format!(
+ "{} backend is not part of required backends",
+ config.codegen_backend.as_str()
+ ),
+ };
+ }
+ }
+ IgnoreDecision::Continue
+}
+
fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index f3b3605..41bed8e 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -39,7 +39,7 @@
use self::directives::{EarlyProps, make_test_description};
use crate::common::{
- CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
+ CodegenBackend, CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
expected_output_path, output_base_dir, output_relative_path,
};
use crate::directives::DirectivesCache;
@@ -203,6 +203,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
"debugger",
"only test a specific debugger in debuginfo tests",
"gdb | lldb | cdb",
+ )
+ .optopt(
+ "",
+ "codegen-backend",
+ "the codegen backend currently used",
+ "CODEGEN BACKEND NAME",
);
let (argv0, args_) = args.split_first().unwrap();
@@ -264,6 +270,15 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
|| directives::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
);
+ let codegen_backend = match matches.opt_str("codegen-backend").as_deref() {
+ Some(backend) => match CodegenBackend::try_from(backend) {
+ Ok(backend) => backend,
+ Err(error) => panic!("invalid value `{backend}` for `--codegen-backend`: {error}"),
+ },
+ // By default, it's always llvm.
+ None => CodegenBackend::Llvm,
+ };
+
let run_ignored = matches.opt_present("ignored");
let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
@@ -449,6 +464,8 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
diff_command: matches.opt_str("compiletest-diff-tool"),
minicore_path: opt_path(matches, "minicore-path"),
+
+ codegen_backend,
}
}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index cb8f593..f66d4f9 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -16,8 +16,8 @@
use tracing::*;
use crate::common::{
- CompareMode, Config, Debugger, FailMode, PassMode, TestMode, TestPaths, TestSuite,
- UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG,
+ CompareMode, Config, Debugger, FailMode, PassMode, RunFailMode, RunResult, TestMode, TestPaths,
+ TestSuite, UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG,
UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name,
output_testname_unique,
};
@@ -282,7 +282,8 @@ fn pass_mode(&self) -> Option<PassMode> {
fn should_run(&self, pm: Option<PassMode>) -> WillExecute {
let test_should_run = match self.config.mode {
TestMode::Ui
- if pm == Some(PassMode::Run) || self.props.fail_mode == Some(FailMode::Run) =>
+ if pm == Some(PassMode::Run)
+ || matches!(self.props.fail_mode, Some(FailMode::Run(_))) =>
{
true
}
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index f6bc85c..0507c26 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -6,8 +6,8 @@
use tracing::debug;
use super::{
- AllowUnused, Emit, FailMode, LinkToAux, PassMode, TargetLocation, TestCx, TestOutput,
- Truncated, UI_FIXED, WillExecute,
+ AllowUnused, Emit, FailMode, LinkToAux, PassMode, RunFailMode, RunResult, TargetLocation,
+ TestCx, TestOutput, Truncated, UI_FIXED, WillExecute,
};
use crate::json;
@@ -140,12 +140,53 @@ pub(super) fn run_ui_test(&self) {
&proc_res,
);
}
+ let code = proc_res.status.code();
+ let run_result = if proc_res.status.success() {
+ RunResult::Pass
+ } else if code.is_some_and(|c| c >= 1 && c <= 127) {
+ RunResult::Fail
+ } else {
+ RunResult::Crash
+ };
+ // Help users understand why the test failed by including the actual
+ // exit code and actual run result in the failure message.
+ let pass_hint = format!("code={code:?} so test would pass with `{run_result}`");
if self.should_run_successfully(pm) {
- if !proc_res.status.success() {
- self.fatal_proc_rec("test run failed!", &proc_res);
+ if run_result != RunResult::Pass {
+ self.fatal_proc_rec(
+ &format!("test did not exit with success! {pass_hint}"),
+ &proc_res,
+ );
}
- } else if proc_res.status.success() {
- self.fatal_proc_rec("test run succeeded!", &proc_res);
+ } else if self.props.fail_mode == Some(FailMode::Run(RunFailMode::Fail)) {
+ // If the test is marked as `run-fail` but do not support
+ // unwinding we allow it to crash, since a panic will trigger an
+ // abort (crash) instead of unwind (exit with code 101).
+ let crash_ok = !self.config.can_unwind();
+ if run_result != RunResult::Fail && !(crash_ok && run_result == RunResult::Crash) {
+ let err = if crash_ok {
+ format!(
+ "test did not exit with failure or crash (`{}` can't unwind)! {pass_hint}",
+ self.config.target
+ )
+ } else {
+ format!("test did not exit with failure! {pass_hint}")
+ };
+ self.fatal_proc_rec(&err, &proc_res);
+ }
+ } else if self.props.fail_mode == Some(FailMode::Run(RunFailMode::Crash)) {
+ if run_result != RunResult::Crash {
+ self.fatal_proc_rec(&format!("test did not crash! {pass_hint}"), &proc_res);
+ }
+ } else if self.props.fail_mode == Some(FailMode::Run(RunFailMode::FailOrCrash)) {
+ if run_result != RunResult::Fail && run_result != RunResult::Crash {
+ self.fatal_proc_rec(
+ &format!("test did not exit with failure or crash! {pass_hint}"),
+ &proc_res,
+ );
+ }
+ } else {
+ unreachable!("run_ui_test() must not be called if the test should not run");
}
self.get_output(&proc_res)
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 3cc38fa..1033992 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -157,7 +157,7 @@ fn addr_from_alloc_id_uncached(
this.get_alloc_bytes_unchecked_raw(alloc_id)?
}
}
- AllocKind::Function | AllocKind::VTable => {
+ AllocKind::Function | AllocKind::Virtual => {
// Allocate some dummy memory to get a unique address for this function/vtable.
let alloc_bytes = MiriAllocBytes::from_bytes(
&[0u8; 1],
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 834a4b4..e834fdf 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -650,7 +650,7 @@ fn sb_reborrow(
dcx.log_protector();
}
},
- AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+ AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
// No stacked borrows on these allocations.
}
}
@@ -1021,7 +1021,7 @@ fn sb_expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}");
alloc_extra.borrow_tracker_sb().borrow_mut().exposed_tags.insert(tag);
}
- AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+ AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
// No stacked borrows on these allocations.
}
}
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index c157c69..aa92f8a 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -673,7 +673,7 @@ fn tb_expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
trace!("Tree Borrows tag {tag:?} exposed in {alloc_id:?}");
alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag);
}
- AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+ AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
// No tree borrows on these allocations.
}
}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs
index 047fe07..5778765 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs
@@ -1,4 +1,6 @@
//@ignore-target: windows # No pthreads on Windows
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
/// Test that destroying a pthread_cond twice fails, even without a check for number validity
@@ -15,6 +17,6 @@ fn main() {
libc::pthread_cond_destroy(cond.as_mut_ptr());
libc::pthread_cond_destroy(cond.as_mut_ptr());
- //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/
}
}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr
index 7abdfa8..6156070 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC
|
LL | libc::pthread_cond_destroy(cond.as_mut_ptr());
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs
index 90e33d5..9116966 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs
@@ -1,5 +1,7 @@
//@ignore-target: windows # No pthreads on Windows
//@ignore-target: apple # Our macOS condattr don't have any fields so we do not notice this.
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
/// Test that destroying a pthread_condattr twice fails, even without a check for number validity
@@ -13,6 +15,6 @@ fn main() {
libc::pthread_condattr_destroy(attr.as_mut_ptr());
libc::pthread_condattr_destroy(attr.as_mut_ptr());
- //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/
}
}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr
index 28a6625..da64970 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC
|
LL | libc::pthread_condattr_destroy(attr.as_mut_ptr());
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs
index 1792c22..f04fe8b 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs
@@ -1,4 +1,6 @@
//@ignore-target: windows # No pthreads on Windows
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
/// Test that destroying a pthread_mutex twice fails, even without a check for number validity
@@ -16,6 +18,6 @@ fn main() {
libc::pthread_mutex_destroy(mutex.as_mut_ptr());
libc::pthread_mutex_destroy(mutex.as_mut_ptr());
- //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/
}
}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr
index e7a6dee..05db823 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC
|
LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr());
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs
index 3711c1f..d9daf52 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs
@@ -1,4 +1,6 @@
//@ignore-target: windows # No pthreads on Windows
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
/// Test that destroying a pthread_mutexattr twice fails, even without a check for number validity
@@ -12,6 +14,6 @@ fn main() {
libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
- //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/
}
}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr
index 0c9ee71..ee3883d 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC
|
LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs
index 6a31e97..720ba71 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs
@@ -1,4 +1,6 @@
//@ignore-target: windows # No pthreads on Windows
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
/// Test that destroying a pthread_rwlock twice fails, even without a check for number validity
@@ -9,6 +11,6 @@ fn main() {
libc::pthread_rwlock_destroy(&mut lock);
libc::pthread_rwlock_destroy(&mut lock);
- //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/
}
}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr
index 836f0d0..430398d 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC
|
LL | libc::pthread_rwlock_destroy(&mut lock);
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr
index 6a7d9a4..3252368 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/arg_inplace_observe_after.rs:LL:CC
|
LL | _observe = non_copy.0;
@@ -9,6 +9,11 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/function_calls/arg_inplace_observe_after.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
+ALLOC (stack variable, size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
index 0fc634b..09a5b9a 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC
|
LL | unsafe { ptr.read() };
@@ -14,6 +14,11 @@
LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
+ALLOC (stack variable, size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr
index 746ab2e..2409154 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
LL | unsafe { ptr.read() };
@@ -14,6 +14,11 @@
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
+ALLOC (stack variable, size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
index 7747a75..93720ca 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr
@@ -3,7 +3,7 @@
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC
|
LL | dbg!(x.0);
@@ -15,6 +15,19 @@
= note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
+ALLOC (stack variable, size: 132, align: 4) {
+ 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x30 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x40 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x50 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x60 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x70 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░
+ 0x80 │ __ __ __ __ │ ░░░░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs
index 0c305ee..c03e468 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs
@@ -1,4 +1,7 @@
//@compile-flags: -Zmiri-disable-validation
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
#![feature(core_intrinsics, custom_mir)]
use std::intrinsics::mir::*;
@@ -9,7 +12,7 @@
pub unsafe fn deref_meta(p: *const *const [i32]) -> usize {
mir! {
{
- RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
+ RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .* but memory is uninitialized/
Return()
}
}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr
index 1c22876..1e7f500 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs:LL:CC
|
LL | RET = PtrMetadata(*p);
@@ -14,6 +14,9 @@
LL | let _meta = deref_meta(p.as_ptr().cast());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs
index a2ffdc9..7053c0f 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs
@@ -1,4 +1,7 @@
//@compile-flags: -Zmiri-disable-validation
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]"
+
#![feature(core_intrinsics, custom_mir)]
use std::intrinsics::mir::*;
@@ -9,7 +12,7 @@
pub unsafe fn deref_meta(p: *const *const [i32]) -> usize {
mir! {
{
- RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
+ RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .* but memory is uninitialized/
Return()
}
}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
index 00e63b1..80b4c8b 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
@@ -12,7 +12,7 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs:LL:CC
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs:LL:CC
|
LL | RET = PtrMetadata(*p);
@@ -28,6 +28,9 @@
LL | let _meta = deref_meta(p.as_ptr().cast());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error; 1 warning emitted
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs
index e5a5128..3ba2984 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs
@@ -1,4 +1,7 @@
//@compile-flags: -Zmiri-disable-validation
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
#![feature(core_intrinsics, custom_mir)]
use std::intrinsics::mir::*;
@@ -9,7 +12,7 @@
pub unsafe fn deref_meta(p: *const *const i32) -> () {
mir! {
{
- RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
+ RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .*, but memory is uninitialized/
Return()
}
}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr
index 2406695..7a1f3d6 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/intrinsics/ptr_metadata_uninit_thin.rs:LL:CC
|
LL | RET = PtrMetadata(*p);
@@ -14,6 +14,9 @@
LL | let _meta = deref_meta(p.as_ptr());
| ^^^^^^^^^^^^^^^^^^^^^^
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/read_from_trivial_switch.rs b/src/tools/miri/tests/fail/read_from_trivial_switch.rs
index d34b1cd..2696c42 100644
--- a/src/tools/miri/tests/fail/read_from_trivial_switch.rs
+++ b/src/tools/miri/tests/fail/read_from_trivial_switch.rs
@@ -4,11 +4,14 @@
//
// See <https://github.com/rust-lang/miri/issues/4237>.
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
use std::mem::MaybeUninit;
fn main() {
let uninit: MaybeUninit<i32> = MaybeUninit::uninit();
let bad_ref: &i32 = unsafe { uninit.assume_init_ref() };
let &(0 | _) = bad_ref;
- //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: /Undefined Behavior: .*, but memory is uninitialized .* requires initialized memory/
}
diff --git a/src/tools/miri/tests/fail/read_from_trivial_switch.stderr b/src/tools/miri/tests/fail/read_from_trivial_switch.stderr
index 923d836..1dcc341b 100644
--- a/src/tools/miri/tests/fail/read_from_trivial_switch.stderr
+++ b/src/tools/miri/tests/fail/read_from_trivial_switch.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/read_from_trivial_switch.rs:LL:CC
|
LL | let &(0 | _) = bad_ref;
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/read_from_trivial_switch.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs
index e1a16be..606fa21 100644
--- a/src/tools/miri/tests/fail/uninit/padding-enum.rs
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs
@@ -1,3 +1,6 @@
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
use std::mem;
// We have three fields to avoid the ScalarPair optimization.
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
index a9a5568..64229ac 100644
--- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/uninit/padding-enum.rs:LL:CC
|
LL | let _val = *c.add(padding_offset);
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/uninit/padding-enum.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.rs b/src/tools/miri/tests/fail/uninit/padding-pair.rs
index c8c00b3..70ae48f 100644
--- a/src/tools/miri/tests/fail/uninit/padding-pair.rs
+++ b/src/tools/miri/tests/fail/uninit/padding-pair.rs
@@ -1,3 +1,6 @@
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
#![feature(core_intrinsics)]
use std::mem::{self, MaybeUninit};
diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr
index d281a35..2e7a577 100644
--- a/src/tools/miri/tests/fail/uninit/padding-pair.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/uninit/padding-pair.rs:LL:CC
|
LL | let v = unsafe { *z.offset(first_undef) };
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/uninit/padding-pair.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr
index 3298f6a..05d7546 100644
--- a/src/tools/miri/tests/fail/uninit/padding-struct.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x1..0x2], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
--> tests/fail/uninit/padding-struct.rs:LL:CC
|
LL | let _val = *c.add(1);
@@ -9,6 +9,11 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/uninit/padding-struct.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0x1..0x2], in this allocation:
+ALLOC (stack variable, size: 4, align: 2) {
+ 00 __ 00 00 │ .░..
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
index 4e363db..549785e 100644
--- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
+++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
@@ -1,3 +1,6 @@
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
use std::mem;
// If this is `None`, the metadata becomes padding.
diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
index d92d05a..ce11320 100644
--- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/uninit/padding-wide-ptr.rs:LL:CC
|
LL | let _val = *c.add(mem::size_of::<*const u8>());
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/uninit/padding-wide-ptr.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
index 0ba5520..c1d284c 100644
--- a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
+++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
@@ -1,3 +1,6 @@
+//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
+//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
+
#![feature(core_intrinsics)]
use std::mem::{self, MaybeUninit};
diff --git a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
index 0ae0ce5..eb049dd 100644
--- a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
+++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory
--> tests/fail/uninit/transmute-pair-uninit.rs:LL:CC
|
LL | let v = unsafe { *z.offset(first_undef) };
@@ -9,6 +9,9 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/uninit/transmute-pair-uninit.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation:
+ALLOC DUMP
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr
index d2a5a2d..5a5aa12 100644
--- a/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr
+++ b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x5..0x6], but memory is uninitialized at [0x5..0x6], and this operation requires initialized memory
--> tests/fail/uninit/uninit_byte_read.rs:LL:CC
|
LL | let undef = unsafe { *v.as_ptr().add(5) };
@@ -9,6 +9,11 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/uninit/uninit_byte_read.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0x5..0x6], in this allocation:
+ALLOC (Rust heap, size: 10, align: 1) {
+ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/validity/invalid_int_op.stderr b/src/tools/miri/tests/fail/validity/invalid_int_op.stderr
index 6e24cad..0b19156 100644
--- a/src/tools/miri/tests/fail/validity/invalid_int_op.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_int_op.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> tests/fail/validity/invalid_int_op.rs:LL:CC
|
LL | let i = unsafe { std::mem::MaybeUninit::<i32>::uninit().assume_init() };
@@ -9,6 +9,11 @@
= note: BACKTRACE:
= note: inside `main` at tests/fail/validity/invalid_int_op.rs:LL:CC
+Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
+ALLOC (stack variable, size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs
index e267f82..7ab1607 100644
--- a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs
+++ b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs
@@ -20,6 +20,6 @@ fn partial_init() {
assert!(*slice_ptr == 0);
assert!(*slice_ptr.offset(1) == 0);
// Reading the third is UB!
- let _val = *slice_ptr.offset(2); //~ ERROR: Undefined Behavior: using uninitialized data
+ let _val = *slice_ptr.offset(2); //~ ERROR: /Undefined Behavior: reading memory.*, but memory is uninitialized/
}
}
diff --git a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr
index 84fd913..74a599e 100644
--- a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr
+++ b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr
@@ -17,7 +17,7 @@
LL | partial_init();
| ^^^^^^^^^^^^^^
-error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+error: Undefined Behavior: reading memory at ALLOC[0x2..0x3], but memory is uninitialized at [0x2..0x3], and this operation requires initialized memory
--> tests/native-lib/fail/tracing/partial_init.rs:LL:CC
|
LL | let _val = *slice_ptr.offset(2);
@@ -33,6 +33,11 @@
LL | partial_init();
| ^^^^^^^^^^^^^^
+Uninitialized memory occurred at ALLOC[0x2..0x3], in this allocation:
+ALLOC (stack variable, size: 3, align: 1) {
+ ╾00[wildcard] (1 ptr byte)╼ ╾00[wildcard] (1 ptr byte)╼ __ │ ━━░
+}
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error; 1 warning emitted
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-time.rs b/src/tools/miri/tests/pass-dep/libc/libc-time.rs
index e895784..9e9fadf 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-time.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-time.rs
@@ -336,7 +336,7 @@ fn test_nanosleep() {
let remainder = ptr::null_mut::<libc::timespec>();
let is_error = unsafe { libc::nanosleep(&duration_zero, remainder) };
assert_eq!(is_error, 0);
- assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
+ assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
let start_test_sleep = Instant::now();
let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 };
@@ -390,7 +390,7 @@ pub fn absolute() {
)
};
assert_eq!(error, 0);
- assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
+ assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
let start_test_sleep = Instant::now();
let hunderd_millis_after_start = add_100_millis(timespec_now(libc::CLOCK_MONOTONIC));
@@ -417,7 +417,7 @@ pub fn relative() {
libc::clock_nanosleep(libc::CLOCK_MONOTONIC, NO_FLAGS, &duration_zero, remainder)
};
assert_eq!(error, 0);
- assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
+ assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
let start_test_sleep = Instant::now();
let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 };
diff --git a/src/tools/miri/tests/pass/intrinsics/type-id.rs b/src/tools/miri/tests/pass/intrinsics/type-id.rs
new file mode 100644
index 0000000..123fdbd
--- /dev/null
+++ b/src/tools/miri/tests/pass/intrinsics/type-id.rs
@@ -0,0 +1,19 @@
+use std::any::{Any, TypeId};
+
+fn main() {
+ let t1 = TypeId::of::<u64>();
+ let t2 = TypeId::of::<u64>();
+ assert_eq!(t1, t2);
+ let t3 = TypeId::of::<usize>();
+ assert_ne!(t1, t3);
+
+ let _ = format!("{t1:?}"); // test that we can debug-print
+
+ let b = Box::new(0u64) as Box<dyn Any>;
+ assert_eq!(*b.downcast_ref::<u64>().unwrap(), 0);
+ assert!(b.downcast_ref::<usize>().is_none());
+
+ // Get the first pointer chunk and try to make it a ZST ref.
+ // This used to trigger an error because TypeId allocs got misclassified as "LiveData".
+ let _raw_chunk = unsafe { (&raw const t1).cast::<&()>().read() };
+}
diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs
index 946e926..d41dc80 100644
--- a/src/tools/opt-dist/src/environment.rs
+++ b/src/tools/opt-dist/src/environment.rs
@@ -27,6 +27,7 @@ pub struct Environment {
shared_llvm: bool,
run_tests: bool,
fast_try_build: bool,
+ build_llvm: bool,
}
impl Environment {
@@ -111,6 +112,10 @@ pub fn run_tests(&self) -> bool {
pub fn is_fast_try_build(&self) -> bool {
self.fast_try_build
}
+
+ pub fn build_llvm(&self) -> bool {
+ self.build_llvm
+ }
}
/// What is the extension of binary executables on this platform?
diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs
index 0dc6e56..56eff2c 100644
--- a/src/tools/opt-dist/src/exec.rs
+++ b/src/tools/opt-dist/src/exec.rs
@@ -139,8 +139,10 @@ pub fn llvm_pgo_instrument(mut self, profile_dir: &Utf8Path) -> Self {
self
}
- pub fn llvm_pgo_optimize(mut self, profile: &LlvmPGOProfile) -> Self {
- self.cmd = self.cmd.arg("--llvm-profile-use").arg(profile.0.as_str());
+ pub fn llvm_pgo_optimize(mut self, profile: Option<&LlvmPGOProfile>) -> Self {
+ if let Some(prof) = profile {
+ self.cmd = self.cmd.arg("--llvm-profile-use").arg(prof.0.as_str());
+ }
self
}
@@ -174,8 +176,10 @@ pub fn with_rustc_bolt_ldflags(mut self) -> Self {
self
}
- pub fn with_bolt_profile(mut self, profile: BoltProfile) -> Self {
- self.cmd = self.cmd.arg("--reproducible-artifact").arg(profile.0.as_str());
+ pub fn with_bolt_profile(mut self, profile: Option<BoltProfile>) -> Self {
+ if let Some(prof) = profile {
+ self.cmd = self.cmd.arg("--reproducible-artifact").arg(prof.0.as_str());
+ }
self
}
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index 9c8a663..7857f19 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -98,6 +98,10 @@ enum EnvironmentCmd {
/// Perform tests after final build if it's not a fast try build
#[arg(long)]
run_tests: bool,
+
+ /// Will be LLVM built during the run?
+ #[arg(long, default_value_t = true, action(clap::ArgAction::Set))]
+ build_llvm: bool,
},
/// Perform an optimized build on Linux CI, from inside Docker.
LinuxCi {
@@ -133,6 +137,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
benchmark_cargo_config,
shared,
run_tests,
+ build_llvm,
} => {
let env = EnvironmentBuilder::default()
.host_tuple(target_triple)
@@ -148,6 +153,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
.benchmark_cargo_config(benchmark_cargo_config)
.run_tests(run_tests)
.fast_try_build(is_fast_try_build)
+ .build_llvm(build_llvm)
.build()?;
(env, shared.build_args)
@@ -172,6 +178,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
.skipped_tests(vec![])
.run_tests(true)
.fast_try_build(is_fast_try_build)
+ .build_llvm(true)
.build()?;
(env, shared.build_args)
@@ -193,6 +200,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
.skipped_tests(vec![])
.run_tests(true)
.fast_try_build(is_fast_try_build)
+ .build_llvm(true)
.build()?;
(env, shared.build_args)
@@ -255,30 +263,35 @@ fn execute_pipeline(
// Stage 2: Gather LLVM PGO profiles
// Here we build a PGO instrumented LLVM, reusing the previously PGO optimized rustc.
// Then we use the instrumented LLVM to gather LLVM PGO profiles.
- let llvm_pgo_profile = timer.section("Stage 2 (LLVM PGO)", |stage| {
- // Remove the previous, uninstrumented build of LLVM.
- clear_llvm_files(env)?;
+ let llvm_pgo_profile = if env.build_llvm() {
+ timer.section("Stage 2 (LLVM PGO)", |stage| {
+ // Remove the previous, uninstrumented build of LLVM.
+ clear_llvm_files(env)?;
- let llvm_profile_dir_root = env.artifact_dir().join("llvm-pgo");
+ let llvm_profile_dir_root = env.artifact_dir().join("llvm-pgo");
- stage.section("Build PGO instrumented LLVM", |section| {
- Bootstrap::build(env)
- .llvm_pgo_instrument(&llvm_profile_dir_root)
- .avoid_rustc_rebuild()
- .run(section)
- })?;
+ stage.section("Build PGO instrumented LLVM", |section| {
+ Bootstrap::build(env)
+ .llvm_pgo_instrument(&llvm_profile_dir_root)
+ .avoid_rustc_rebuild()
+ .run(section)
+ })?;
- let profile = stage
- .section("Gather profiles", |_| gather_llvm_profiles(env, &llvm_profile_dir_root))?;
+ let profile = stage.section("Gather profiles", |_| {
+ gather_llvm_profiles(env, &llvm_profile_dir_root)
+ })?;
- print_free_disk_space()?;
+ print_free_disk_space()?;
- // Proactively delete the instrumented artifacts, to avoid using them by accident in
- // follow-up stages.
- clear_llvm_files(env)?;
+ // Proactively delete the instrumented artifacts, to avoid using them by accident in
+ // follow-up stages.
+ clear_llvm_files(env)?;
- Ok(profile)
- })?;
+ Ok(Some(profile))
+ })?
+ } else {
+ None
+ };
let bolt_profiles = if env.use_bolt() {
// Stage 3: Build BOLT instrumented LLVM
@@ -286,37 +299,43 @@ fn execute_pipeline(
// Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build.
// BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc,
// therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused.
+ let libdir = env.build_artifacts().join("stage2").join("lib");
timer.section("Stage 3 (BOLT)", |stage| {
- stage.section("Build PGO optimized LLVM", |stage| {
- Bootstrap::build(env)
- .with_llvm_bolt_ldflags()
- .llvm_pgo_optimize(&llvm_pgo_profile)
- .avoid_rustc_rebuild()
- .run(stage)
- })?;
+ let llvm_profile = if env.build_llvm() {
+ stage.section("Build PGO optimized LLVM", |stage| {
+ Bootstrap::build(env)
+ .with_llvm_bolt_ldflags()
+ .llvm_pgo_optimize(llvm_pgo_profile.as_ref())
+ .avoid_rustc_rebuild()
+ .run(stage)
+ })?;
- let libdir = env.build_artifacts().join("stage2").join("lib");
- // The actual name will be something like libLLVM.so.18.1-rust-dev.
- let llvm_lib = io::find_file_in_dir(&libdir, "libLLVM.so", "")?;
+ // The actual name will be something like libLLVM.so.18.1-rust-dev.
+ let llvm_lib = io::find_file_in_dir(&libdir, "libLLVM.so", "")?;
- log::info!("Optimizing {llvm_lib} with BOLT");
+ log::info!("Optimizing {llvm_lib} with BOLT");
- // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc
- // Instrument the libraries and gather profiles
- let llvm_profile = with_bolt_instrumented(&llvm_lib, |llvm_profile_dir| {
- stage.section("Gather profiles", |_| {
- gather_bolt_profiles(env, "LLVM", llvm_benchmarks(env), llvm_profile_dir)
- })
- })?;
- print_free_disk_space()?;
+ // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc
+ // Instrument the libraries and gather profiles
+ let llvm_profile = with_bolt_instrumented(&llvm_lib, |llvm_profile_dir| {
+ stage.section("Gather profiles", |_| {
+ gather_bolt_profiles(env, "LLVM", llvm_benchmarks(env), llvm_profile_dir)
+ })
+ })?;
+ print_free_disk_space()?;
- // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked
- // from several places, and this specific path (`llvm_lib`) will *not* be packaged into
- // the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
- // therefore it will actually optimize all the hard links, which means that the final
- // packaged `libLLVM.so` file *will* be BOLT optimized.
- bolt_optimize(&llvm_lib, &llvm_profile, env)
- .context("Could not optimize LLVM with BOLT")?;
+ // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked
+ // from several places, and this specific path (`llvm_lib`) will *not* be packaged into
+ // the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
+ // therefore it will actually optimize all the hard links, which means that the final
+ // packaged `libLLVM.so` file *will* be BOLT optimized.
+ bolt_optimize(&llvm_lib, &llvm_profile, env)
+ .context("Could not optimize LLVM with BOLT")?;
+
+ Some(llvm_profile)
+ } else {
+ None
+ };
let rustc_lib = io::find_file_in_dir(&libdir, "librustc_driver", ".so")?;
@@ -334,15 +353,16 @@ fn execute_pipeline(
bolt_optimize(&rustc_lib, &rustc_profile, env)
.context("Could not optimize rustc with BOLT")?;
- // LLVM is not being cleared here, we want to use the BOLT-optimized LLVM
- Ok(vec![llvm_profile, rustc_profile])
+ // LLVM is not being cleared here. Either we built it and we want to use the BOLT-optimized LLVM, or we
+ // didn't build it, so we don't want to remove it.
+ Ok(vec![llvm_profile, Some(rustc_profile)])
})?
} else {
vec![]
};
let mut dist = Bootstrap::dist(env, &dist_args)
- .llvm_pgo_optimize(&llvm_pgo_profile)
+ .llvm_pgo_optimize(llvm_pgo_profile.as_ref())
.rustc_pgo_optimize(&rustc_pgo_profile)
.avoid_rustc_rebuild();
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 36a7d6a..ae062d5 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -163,7 +163,9 @@ pub fn gather_rustc_profiles(
let merged_profile = env.artifact_dir().join("rustc-pgo.profdata");
log::info!("Merging Rustc PGO profiles to {merged_profile}");
- merge_llvm_profiles(env, &merged_profile, profile_root, LlvmProfdata::Target)?;
+ let llvm_profdata = if env.build_llvm() { LlvmProfdata::Target } else { LlvmProfdata::Host };
+
+ merge_llvm_profiles(env, &merged_profile, profile_root, llvm_profdata)?;
log_profile_stats("Rustc", &merged_profile, profile_root)?;
// We don't need the individual .profraw files now that they have been merged
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index f70fc91..0baa179 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -28,7 +28,14 @@
}
function contentToDiffLine(key, value) {
- return `"${key}": "${value}",`;
+ if (typeof value === "object" && !Array.isArray(value) && value !== null) {
+ const out = Object.entries(value)
+ .filter(([subKey, _]) => ["path", "name"].includes(subKey))
+ .map(([subKey, subValue]) => `"${subKey}": ${JSON.stringify(subValue)}`)
+ .join(", ");
+ return `"${key}": ${out},`;
+ }
+ return `"${key}": ${JSON.stringify(value)},`;
}
function shouldIgnoreField(fieldName) {
@@ -37,47 +44,61 @@
fieldName === "proposeCorrectionTo";
}
+function valueMapper(key, testOutput) {
+ const isAlias = testOutput["is_alias"];
+ let value = testOutput[key];
+ // To make our life easier, if there is a "parent" type, we add it to the path.
+ if (key === "path") {
+ if (testOutput["parent"] !== undefined) {
+ if (value.length > 0) {
+ value += "::" + testOutput["parent"]["name"];
+ } else {
+ value = testOutput["parent"]["name"];
+ }
+ } else if (testOutput["is_alias"]) {
+ value = valueMapper(key, testOutput["original"]);
+ }
+ } else if (isAlias && key === "alias") {
+ value = testOutput["name"];
+ } else if (isAlias && ["name"].includes(key)) {
+ value = testOutput["original"][key];
+ }
+ return value;
+}
+
// This function is only called when no matching result was found and therefore will only display
// the diff between the two items.
-function betterLookingDiff(entry, data) {
+function betterLookingDiff(expected, testOutput) {
let output = " {\n";
- const spaces = " ";
- for (const key in entry) {
- if (!Object.prototype.hasOwnProperty.call(entry, key)) {
+ const spaces = " ";
+ for (const key in expected) {
+ if (!Object.prototype.hasOwnProperty.call(expected, key)) {
continue;
}
- if (!data || !Object.prototype.hasOwnProperty.call(data, key)) {
- output += "-" + spaces + contentToDiffLine(key, entry[key]) + "\n";
+ if (!testOutput || !Object.prototype.hasOwnProperty.call(testOutput, key)) {
+ output += "-" + spaces + contentToDiffLine(key, expected[key]) + "\n";
continue;
}
- const value = data[key];
- if (value !== entry[key]) {
- output += "-" + spaces + contentToDiffLine(key, entry[key]) + "\n";
+ const value = valueMapper(key, testOutput);
+ if (value !== expected[key]) {
+ output += "-" + spaces + contentToDiffLine(key, expected[key]) + "\n";
output += "+" + spaces + contentToDiffLine(key, value) + "\n";
} else {
- output += spaces + contentToDiffLine(key, value) + "\n";
+ output += spaces + " " + contentToDiffLine(key, value) + "\n";
}
}
return output + " }";
}
-function lookForEntry(entry, data) {
- return data.findIndex(data_entry => {
+function lookForEntry(expected, testOutput) {
+ return testOutput.findIndex(testOutputEntry => {
let allGood = true;
- for (const key in entry) {
- if (!Object.prototype.hasOwnProperty.call(entry, key)) {
+ for (const key in expected) {
+ if (!Object.prototype.hasOwnProperty.call(expected, key)) {
continue;
}
- let value = data_entry[key];
- // To make our life easier, if there is a "parent" type, we add it to the path.
- if (key === "path" && data_entry["parent"] !== undefined) {
- if (value.length > 0) {
- value += "::" + data_entry["parent"]["name"];
- } else {
- value = data_entry["parent"]["name"];
- }
- }
- if (value !== entry[key]) {
+ const value = valueMapper(key, testOutputEntry);
+ if (value !== expected[key]) {
allGood = false;
break;
}
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index e83b47e..fb00b3a 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -331,11 +331,9 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba
continue;
}
- if in_feature_group {
- if let Some(doc_comment) = line.strip_prefix("///") {
- doc_comments.push(doc_comment.trim().to_string());
- continue;
- }
+ if in_feature_group && let Some(doc_comment) = line.strip_prefix("///") {
+ doc_comments.push(doc_comment.trim().to_string());
+ continue;
}
let mut parts = line.split(',');
@@ -465,19 +463,20 @@ fn get_and_check_lib_features(
map_lib_features(base_src_path, &mut |res, file, line| match res {
Ok((name, f)) => {
let mut check_features = |f: &Feature, list: &Features, display: &str| {
- if let Some(s) = list.get(name) {
- if f.tracking_issue != s.tracking_issue && f.level != Status::Accepted {
- tidy_error!(
- bad,
- "{}:{}: feature gate {} has inconsistent `issue`: \"{}\" mismatches the {} `issue` of \"{}\"",
- file.display(),
- line,
- name,
- f.tracking_issue_display(),
- display,
- s.tracking_issue_display(),
- );
- }
+ if let Some(s) = list.get(name)
+ && f.tracking_issue != s.tracking_issue
+ && f.level != Status::Accepted
+ {
+ tidy_error!(
+ bad,
+ "{}:{}: feature gate {} has inconsistent `issue`: \"{}\" mismatches the {} `issue` of \"{}\"",
+ file.display(),
+ line,
+ name,
+ f.tracking_issue_display(),
+ display,
+ s.tracking_issue_display(),
+ );
}
};
check_features(&f, lang_features, "corresponding lang feature");
diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs
index 85c1ef6..836b569 100644
--- a/src/tools/tidy/src/fluent_period.rs
+++ b/src/tools/tidy/src/fluent_period.rs
@@ -33,14 +33,14 @@ fn check_period(filename: &str, contents: &str, bad: &mut bool) {
continue;
}
- if let Some(pat) = &m.value {
- if let Some(PatternElement::TextElement { value }) = pat.elements.last() {
- // We don't care about ellipses.
- if value.ends_with(".") && !value.ends_with("...") {
- let ll = find_line(contents, value);
- let name = m.id.name;
- tidy_error!(bad, "{filename}:{ll}: message `{name}` ends in a period");
- }
+ if let Some(pat) = &m.value
+ && let Some(PatternElement::TextElement { value }) = pat.elements.last()
+ {
+ // We don't care about ellipses.
+ if value.ends_with(".") && !value.ends_with("...") {
+ let ll = find_line(contents, value);
+ let name = m.id.name;
+ tidy_error!(bad, "{filename}:{ll}: message `{name}` ends in a period");
}
}
@@ -50,12 +50,13 @@ fn check_period(filename: &str, contents: &str, bad: &mut bool) {
continue;
}
- if let Some(PatternElement::TextElement { value }) = attr.value.elements.last() {
- if value.ends_with(".") && !value.ends_with("...") {
- let ll = find_line(contents, value);
- let name = attr.id.name;
- tidy_error!(bad, "{filename}:{ll}: attr `{name}` ends in a period");
- }
+ if let Some(PatternElement::TextElement { value }) = attr.value.elements.last()
+ && value.ends_with(".")
+ && !value.ends_with("...")
+ {
+ let ll = find_line(contents, value);
+ let name = attr.id.name;
+ tidy_error!(bad, "{filename}:{ll}: attr `{name}` ends in a period");
}
}
}
diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs
index 12fafd9..909bf48 100644
--- a/src/tools/tidy/src/fluent_used.rs
+++ b/src/tools/tidy/src/fluent_used.rs
@@ -12,7 +12,7 @@ fn filter_used_messages(
) {
// we don't just check messages never appear in Rust files,
// because messages can be used as parts of other fluent messages in Fluent files,
- // so we do checking messages appear only once in all Rust and Fluent files.
+ // so we check messages appear only once in all Rust and Fluent files.
let matches = static_regex!(r"\w+").find_iter(contents);
for name in matches {
if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) {
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index ade4055b..cb87550 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -13,8 +13,9 @@
macro_rules! static_regex {
($re:literal) => {{
- static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
- RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
+ static RE: ::std::sync::LazyLock<::regex::Regex> =
+ ::std::sync::LazyLock::new(|| ::regex::Regex::new($re).unwrap());
+ &*RE
}};
}
@@ -134,7 +135,7 @@ pub fn files_modified(ci_info: &CiInfo, pred: impl Fn(&str) -> bool) -> bool {
eprintln!("No base commit, assuming all files are modified");
return true;
};
- match crate::git_diff(&base_commit, "--name-status") {
+ match crate::git_diff(base_commit, "--name-status") {
Some(output) => {
let modified_files = output.lines().filter_map(|ln| {
let (status, name) = ln
diff --git a/src/tools/tidy/src/mir_opt_tests.rs b/src/tools/tidy/src/mir_opt_tests.rs
index 1efe71b..6119eb5 100644
--- a/src/tools/tidy/src/mir_opt_tests.rs
+++ b/src/tools/tidy/src/mir_opt_tests.rs
@@ -55,22 +55,21 @@ fn check_dash_files(path: &Path, bless: bool, bad: &mut bool) {
.filter(|e| e.file_type().is_file())
{
let path = file.path();
- if path.extension() == Some("rs".as_ref()) {
- if let Some(name) = path.file_name().and_then(|s| s.to_str()) {
- if name.contains('-') {
- if !bless {
- tidy_error!(
- bad,
- "mir-opt test files should not have dashes in them: {}",
- path.display()
- );
- } else {
- let new_name = name.replace('-', "_");
- let mut new_path = path.to_owned();
- new_path.set_file_name(new_name);
- let _ = std::fs::rename(path, new_path);
- }
- }
+ if path.extension() == Some("rs".as_ref())
+ && let Some(name) = path.file_name().and_then(|s| s.to_str())
+ && name.contains('-')
+ {
+ if !bless {
+ tidy_error!(
+ bad,
+ "mir-opt test files should not have dashes in them: {}",
+ path.display()
+ );
+ } else {
+ let new_name = name.replace('-', "_");
+ let mut new_path = path.to_owned();
+ new_path.set_file_name(new_name);
+ let _ = std::fs::rename(path, new_path);
}
}
}
diff --git a/src/tools/tidy/src/rustdoc_templates.rs b/src/tools/tidy/src/rustdoc_templates.rs
index dca3e8d..597290a 100644
--- a/src/tools/tidy/src/rustdoc_templates.rs
+++ b/src/tools/tidy/src/rustdoc_templates.rs
@@ -26,7 +26,7 @@ pub fn check(librustdoc_path: &Path, bad: &mut bool) {
None
// Then we check if this a comment tag.
} else if *tag != "{#" {
- return Some(false);
+ Some(false)
// And finally we check if the comment is empty (ie, only there to strip
// extra whitespace characters).
} else if let Some(start_pos) = line.rfind(tag) {
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 8dde461..35ed61e 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -417,10 +417,10 @@ fn skip(path: &Path, is_dir: bool) -> bool {
return;
}
// Shell completions are automatically generated
- if let Some(p) = file.parent() {
- if p.ends_with(Path::new("src/etc/completions")) {
- return;
- }
+ if let Some(p) = file.parent()
+ && p.ends_with(Path::new("src/etc/completions"))
+ {
+ return;
}
let [
mut skip_cr,
@@ -604,25 +604,25 @@ fn skip(path: &Path, is_dir: bool) -> bool {
backtick_count += comment_text.chars().filter(|ch| *ch == '`').count();
}
comment_block = Some((start_line, backtick_count));
- } else if let Some((start_line, backtick_count)) = comment_block.take() {
- if backtick_count % 2 == 1 {
- let mut err = |msg: &str| {
- tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
- };
- let block_len = (i + 1) - start_line;
- if block_len == 1 {
- suppressible_tidy_err!(
- err,
- skip_odd_backticks,
- "comment with odd number of backticks"
- );
- } else {
- suppressible_tidy_err!(
- err,
- skip_odd_backticks,
- "{block_len}-line comment block with odd number of backticks"
- );
- }
+ } else if let Some((start_line, backtick_count)) = comment_block.take()
+ && backtick_count % 2 == 1
+ {
+ let mut err = |msg: &str| {
+ tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
+ };
+ let block_len = (i + 1) - start_line;
+ if block_len == 1 {
+ suppressible_tidy_err!(
+ err,
+ skip_odd_backticks,
+ "comment with odd number of backticks"
+ );
+ } else {
+ suppressible_tidy_err!(
+ err,
+ skip_odd_backticks,
+ "{block_len}-line comment block with odd number of backticks"
+ );
}
}
}
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index 1a6fd3e..f4a6783 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -30,17 +30,17 @@ pub fn check(tests_path: &Path, bad: &mut bool) {
comp_vec.push(component);
}
}
- } else if let Some(compile_flags) = directive.strip_prefix(COMPILE_FLAGS_HEADER) {
- if let Some((_, v)) = compile_flags.split_once("--target") {
- let v = v.trim_start_matches([' ', '=']);
- let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") };
- if let Some((arch, _)) = v {
- let info = header_map.entry(revision).or_insert(RevisionInfo::default());
- info.target_arch.replace(arch);
- } else {
- eprintln!("{file}: seems to have a malformed --target value");
- *bad = true;
- }
+ } else if let Some(compile_flags) = directive.strip_prefix(COMPILE_FLAGS_HEADER)
+ && let Some((_, v)) = compile_flags.split_once("--target")
+ {
+ let v = v.trim_start_matches([' ', '=']);
+ let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") };
+ if let Some((arch, _)) = v {
+ let info = header_map.entry(revision).or_insert(RevisionInfo::default());
+ info.target_arch.replace(arch);
+ } else {
+ eprintln!("{file}: seems to have a malformed --target value");
+ *bad = true;
}
}
});
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 7e29573..b9d22ec 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -161,31 +161,30 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) {
tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
}
- if let Ok(metadata) = fs::metadata(file_path) {
- if metadata.len() == 0 {
- tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
- }
+ if let Ok(metadata) = fs::metadata(file_path)
+ && metadata.len() == 0
+ {
+ tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
}
}
- if ext == "rs" {
- if let Some(test_name) = static_regex!(r"^issues?[-_]?(\d{3,})").captures(testname)
- {
- // these paths are always relative to the passed `path` and always UTF8
- let stripped_path = file_path
- .strip_prefix(path)
- .unwrap()
- .to_str()
- .unwrap()
- .replace(std::path::MAIN_SEPARATOR_STR, "/");
+ if ext == "rs"
+ && let Some(test_name) = static_regex!(r"^issues?[-_]?(\d{3,})").captures(testname)
+ {
+ // these paths are always relative to the passed `path` and always UTF8
+ let stripped_path = file_path
+ .strip_prefix(path)
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .replace(std::path::MAIN_SEPARATOR_STR, "/");
- if !remaining_issue_names.remove(stripped_path.as_str()) {
- tidy_error!(
- bad,
- "file `tests/{stripped_path}` must begin with a descriptive name, consider `{{reason}}-issue-{issue_n}.rs`",
- issue_n = &test_name[1],
- );
- }
+ if !remaining_issue_names.remove(stripped_path.as_str()) {
+ tidy_error!(
+ bad,
+ "file `tests/{stripped_path}` must begin with a descriptive name, consider `{{reason}}-issue-{issue_n}.rs`",
+ issue_n = &test_name[1],
+ );
}
}
}
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
index 6a5e9ec..9f7f43c 100644
--- a/src/tools/tidy/src/x_version.rs
+++ b/src/tools/tidy/src/x_version.rs
@@ -25,12 +25,12 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
if let Some(version) = iter.next() {
// Check this is the rust-lang/rust x tool installation since it should be
// installed at a path containing `src/tools/x`.
- if let Some(path) = iter.next() {
- if path.contains("src/tools/x") {
- let version = version.strip_prefix("v").unwrap();
- installed = Some(Version::parse(version).unwrap());
- break;
- }
+ if let Some(path) = iter.next()
+ && path.contains("src/tools/x")
+ {
+ let version = version.strip_prefix("v").unwrap();
+ installed = Some(Version::parse(version).unwrap());
+ break;
};
}
} else {
diff --git a/src/tools/unicode-table-generator/Cargo.toml b/src/tools/unicode-table-generator/Cargo.toml
index f8a5009..3ca6e9e 100644
--- a/src/tools/unicode-table-generator/Cargo.toml
+++ b/src/tools/unicode-table-generator/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "unicode-table-generator"
version = "0.1.0"
-edition = "2021"
+edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs
index 1eb35e8..78a7bba 100644
--- a/src/tools/unicode-table-generator/src/cascading_map.rs
+++ b/src/tools/unicode-table-generator/src/cascading_map.rs
@@ -21,7 +21,7 @@ pub fn emit_cascading_map(&mut self, ranges: &[Range<u32>]) -> bool {
let points = ranges
.iter()
- .flat_map(|r| (r.start..r.end).into_iter().collect::<Vec<u32>>())
+ .flat_map(|r| (r.start..r.end).collect::<Vec<u32>>())
.collect::<Vec<u32>>();
println!("there are {} points", points.len());
@@ -32,21 +32,20 @@ pub fn emit_cascading_map(&mut self, ranges: &[Range<u32>]) -> bool {
// assert that there is no whitespace over the 0x3000 range.
assert!(point <= 0x3000, "the highest unicode whitespace value has changed");
let high_bytes = point as usize >> 8;
- let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_insert_with(Vec::new);
+ let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_default();
codepoints.push(point);
}
let mut bit_for_high_byte = 1u8;
let mut arms = Vec::<String>::new();
- let mut high_bytes: Vec<usize> =
- codepoints_by_high_bytes.keys().map(|k| k.clone()).collect();
+ let mut high_bytes: Vec<usize> = codepoints_by_high_bytes.keys().copied().collect();
high_bytes.sort();
for high_byte in high_bytes {
let codepoints = codepoints_by_high_bytes.get_mut(&high_byte).unwrap();
if codepoints.len() == 1 {
let ch = codepoints.pop().unwrap();
- arms.push(format!("{} => c as u32 == {:#04x}", high_byte, ch));
+ arms.push(format!("{high_byte} => c as u32 == {ch:#04x}"));
continue;
}
// more than 1 codepoint in this arm
@@ -54,8 +53,7 @@ pub fn emit_cascading_map(&mut self, ranges: &[Range<u32>]) -> bool {
map[(*codepoint & 0xff) as usize] |= bit_for_high_byte;
}
arms.push(format!(
- "{} => WHITESPACE_MAP[c as usize & 0xff] & {} != 0",
- high_byte, bit_for_high_byte
+ "{high_byte} => WHITESPACE_MAP[c as usize & 0xff] & {bit_for_high_byte} != 0"
));
bit_for_high_byte <<= 1;
}
@@ -68,7 +66,7 @@ pub fn emit_cascading_map(&mut self, ranges: &[Range<u32>]) -> bool {
writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap();
for arm in arms {
- writeln!(&mut self.file, " {},", arm).unwrap();
+ writeln!(&mut self.file, " {arm},").unwrap();
}
writeln!(&mut self.file, " _ => false,").unwrap();
writeln!(&mut self.file, " }}").unwrap();
diff --git a/src/tools/unicode-table-generator/src/case_mapping.rs b/src/tools/unicode-table-generator/src/case_mapping.rs
index 00241b7..9c64544 100644
--- a/src/tools/unicode-table-generator/src/case_mapping.rs
+++ b/src/tools/unicode-table-generator/src/case_mapping.rs
@@ -9,7 +9,7 @@
pub(crate) fn generate_case_mapping(data: &UnicodeData) -> String {
let mut file = String::new();
- write!(file, "const INDEX_MASK: u32 = 0x{:x};", INDEX_MASK).unwrap();
+ write!(file, "const INDEX_MASK: u32 = 0x{INDEX_MASK:x};").unwrap();
file.push_str("\n\n");
file.push_str(HEADER.trim_start());
file.push('\n');
diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs
index 415db2c..6cdb82a 100644
--- a/src/tools/unicode-table-generator/src/main.rs
+++ b/src/tools/unicode-table-generator/src/main.rs
@@ -160,15 +160,15 @@ fn load_data() -> UnicodeData {
.push(Codepoints::Single(row.codepoint));
}
- if let Some(mapped) = row.simple_lowercase_mapping {
- if mapped != row.codepoint {
- to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
- }
+ if let Some(mapped) = row.simple_lowercase_mapping
+ && mapped != row.codepoint
+ {
+ to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
}
- if let Some(mapped) = row.simple_uppercase_mapping {
- if mapped != row.codepoint {
- to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
- }
+ if let Some(mapped) = row.simple_uppercase_mapping
+ && mapped != row.codepoint
+ {
+ to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
}
}
@@ -196,12 +196,12 @@ fn load_data() -> UnicodeData {
.flat_map(|codepoints| match codepoints {
Codepoints::Single(c) => c
.scalar()
- .map(|ch| (ch as u32..ch as u32 + 1))
+ .map(|ch| ch as u32..ch as u32 + 1)
.into_iter()
.collect::<Vec<_>>(),
Codepoints::Range(c) => c
.into_iter()
- .flat_map(|c| c.scalar().map(|ch| (ch as u32..ch as u32 + 1)))
+ .flat_map(|c| c.scalar().map(|ch| ch as u32..ch as u32 + 1))
.collect::<Vec<_>>(),
})
.collect::<Vec<Range<u32>>>(),
@@ -236,7 +236,7 @@ fn main() {
let ranges_by_property = &unicode_data.ranges;
if let Some(path) = test_path {
- std::fs::write(&path, generate_tests(&write_location, &ranges_by_property)).unwrap();
+ std::fs::write(&path, generate_tests(&write_location, ranges_by_property)).unwrap();
}
let mut total_bytes = 0;
@@ -246,9 +246,9 @@ fn main() {
let mut emitter = RawEmitter::new();
if property == &"White_Space" {
- emit_whitespace(&mut emitter, &ranges);
+ emit_whitespace(&mut emitter, ranges);
} else {
- emit_codepoints(&mut emitter, &ranges);
+ emit_codepoints(&mut emitter, ranges);
}
modules.push((property.to_lowercase().to_string(), emitter.file));
@@ -288,7 +288,7 @@ fn main() {
for line in contents.lines() {
if !line.trim().is_empty() {
table_file.push_str(" ");
- table_file.push_str(&line);
+ table_file.push_str(line);
}
table_file.push('\n');
}
@@ -312,7 +312,7 @@ fn version() -> String {
let start = readme.find(prefix).unwrap() + prefix.len();
let end = readme.find(" of the Unicode Standard.").unwrap();
let version =
- readme[start..end].split('.').map(|v| v.parse::<u32>().expect(&v)).collect::<Vec<_>>();
+ readme[start..end].split('.').map(|v| v.parse::<u32>().expect(v)).collect::<Vec<_>>();
let [major, minor, micro] = [version[0], version[1], version[2]];
out.push_str(&format!("({major}, {minor}, {micro});\n"));
@@ -320,7 +320,7 @@ fn version() -> String {
}
fn fmt_list<V: std::fmt::Debug>(values: impl IntoIterator<Item = V>) -> String {
- let pieces = values.into_iter().map(|b| format!("{:?}, ", b)).collect::<Vec<_>>();
+ let pieces = values.into_iter().map(|b| format!("{b:?}, ")).collect::<Vec<_>>();
let mut out = String::new();
let mut line = String::from("\n ");
for piece in pieces {
@@ -348,7 +348,7 @@ fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String
s.push_str("\nfn main() {\n");
for (property, ranges) in ranges {
- s.push_str(&format!(r#" println!("Testing {}");"#, property));
+ s.push_str(&format!(r#" println!("Testing {property}");"#));
s.push('\n');
s.push_str(&format!(" {}_true();\n", property.to_lowercase()));
s.push_str(&format!(" {}_false();\n", property.to_lowercase()));
@@ -373,7 +373,7 @@ fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String
s.push_str(" }\n\n");
}
- s.push_str("}");
+ s.push('}');
s
}
@@ -388,7 +388,7 @@ fn generate_asserts(s: &mut String, property: &str, points: &[u32], truthy: bool
range.start,
));
} else {
- s.push_str(&format!(" for chn in {:?}u32 {{\n", range));
+ s.push_str(&format!(" for chn in {range:?}u32 {{\n"));
s.push_str(&format!(
" assert!({}unicode_data::{}::lookup(std::char::from_u32(chn).unwrap()), \"{{:?}}\", chn);\n",
if truthy { "" } else { "!" },
@@ -439,7 +439,7 @@ fn merge_ranges(ranges: &mut Vec<Range<u32>>) {
let mut last_end = None;
for range in ranges {
if let Some(last) = last_end {
- assert!(range.start > last, "{:?}", range);
+ assert!(range.start > last, "{range:?}");
}
last_end = Some(range.end);
}
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index ee94d3c..e9e0efc 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -156,10 +156,10 @@ pub fn emit_codepoints(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
emitter.blank_line();
let mut bitset = emitter.clone();
- let bitset_ok = bitset.emit_bitset(&ranges).is_ok();
+ let bitset_ok = bitset.emit_bitset(ranges).is_ok();
let mut skiplist = emitter.clone();
- skiplist.emit_skiplist(&ranges);
+ skiplist.emit_skiplist(ranges);
if bitset_ok && bitset.bytes_used <= skiplist.bytes_used {
*emitter = bitset;
@@ -174,7 +174,7 @@ pub fn emit_whitespace(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
emitter.blank_line();
let mut cascading = emitter.clone();
- cascading.emit_cascading_map(&ranges);
+ cascading.emit_cascading_map(ranges);
*emitter = cascading;
emitter.desc = String::from("cascading");
}
@@ -272,7 +272,7 @@ enum UniqueMapping {
// for canonical when possible.
while let Some((&to, _)) = mappings
.iter()
- .find(|(&to, _)| to == 0)
+ .find(|&(&to, _)| to == 0)
.or_else(|| mappings.iter().max_by_key(|m| m.1.len()))
{
// Get the mapping with the most entries. Currently, no mapping can
@@ -311,10 +311,9 @@ enum UniqueMapping {
}
}
}
- assert!(
- unique_mapping
- .insert(to, UniqueMapping::Canonical(canonical_words.len()))
- .is_none()
+ assert_eq!(
+ unique_mapping.insert(to, UniqueMapping::Canonical(canonical_words.len())),
+ None
);
canonical_words.push(to);
@@ -340,14 +339,10 @@ enum UniqueMapping {
// We'll probably always have some slack though so this loop will still
// be needed.
for &w in unique_words {
- if !unique_mapping.contains_key(&w) {
- assert!(
- unique_mapping
- .insert(w, UniqueMapping::Canonical(canonical_words.len()))
- .is_none()
- );
+ unique_mapping.entry(w).or_insert_with(|| {
canonical_words.push(w);
- }
+ UniqueMapping::Canonical(canonical_words.len())
+ });
}
assert_eq!(canonicalized_words.len() + canonical_words.len(), unique_words.len());
assert_eq!(unique_mapping.len(), unique_words.len());
diff --git a/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs b/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
index b3b623b5..f9966a2 100644
--- a/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
+++ b/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
@@ -8,6 +8,14 @@
//@ min-llvm-version: 21.0.0
#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+
+unsafe extern "C" {
+ safe fn add(x: i32, y: i32) -> i32;
+}
pub fn add_one(x: i32) -> i32 {
// CHECK-LABEL: __cfi__{{.*}}7add_one{{.*}}:
@@ -23,7 +31,7 @@ pub fn add_one(x: i32) -> i32 {
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-NEXT: mov ecx, 2628068948
- x + 1
+ add(x, 1)
}
pub fn add_two(x: i32, _y: i32) -> i32 {
@@ -40,7 +48,7 @@ pub fn add_two(x: i32, _y: i32) -> i32 {
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-NEXT: mov edx, 2505940310
- x + 2
+ add(x, 2)
}
pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
@@ -57,5 +65,5 @@ pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-NEXT: mov edx, 653723426
- f(arg) + f(arg)
+ add(f(arg), f(arg))
}
diff --git a/tests/assembly/wasm_exceptions.rs b/tests/assembly/wasm_exceptions.rs
index f05ccfa..704e802 100644
--- a/tests/assembly/wasm_exceptions.rs
+++ b/tests/assembly/wasm_exceptions.rs
@@ -2,7 +2,6 @@
//@ assembly-output: emit-asm
//@ compile-flags: -C target-feature=+exception-handling
//@ compile-flags: -C panic=unwind
-//@ compile-flags: -C llvm-args=-wasm-enable-eh
#![crate_type = "lib"]
#![feature(core_intrinsics)]
diff --git a/tests/codegen/enum/enum-discriminant-eq.rs b/tests/codegen/enum/enum-discriminant-eq.rs
new file mode 100644
index 0000000..0494c5f
--- /dev/null
+++ b/tests/codegen/enum/enum-discriminant-eq.rs
@@ -0,0 +1,223 @@
+//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
+//@ min-llvm-version: 20
+//@ only-64bit
+
+// The `derive(PartialEq)` on enums with field-less variants compares discriminants,
+// so make sure we emit that in some reasonable way.
+
+#![crate_type = "lib"]
+#![feature(ascii_char)]
+#![feature(core_intrinsics)]
+#![feature(repr128)]
+
+use std::ascii::Char as AC;
+use std::cmp::Ordering;
+use std::intrinsics::discriminant_value;
+use std::num::NonZero;
+
+// A type that's bigger than `isize`, unlike the usual cases that have small tags.
+#[repr(u128)]
+pub enum Giant {
+ Two = 2,
+ Three = 3,
+ Four = 4,
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_bool_eq_discr(a: Option<bool>, b: Option<bool>) -> bool {
+ // CHECK-LABEL: @opt_bool_eq_discr(
+ // CHECK: %[[A:.+]] = icmp ne i8 %a, 2
+ // CHECK: %[[B:.+]] = icmp eq i8 %b, 2
+ // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+ // CHECK: ret i1 %[[R]]
+
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_ord_eq_discr(a: Option<Ordering>, b: Option<Ordering>) -> bool {
+ // CHECK-LABEL: @opt_ord_eq_discr(
+ // CHECK: %[[A:.+]] = icmp ne i8 %a, 2
+ // CHECK: %[[B:.+]] = icmp eq i8 %b, 2
+ // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+ // CHECK: ret i1 %[[R]]
+
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_nz32_eq_discr(a: Option<NonZero<u32>>, b: Option<NonZero<u32>>) -> bool {
+ // CHECK-LABEL: @opt_nz32_eq_discr(
+ // CHECK: %[[A:.+]] = icmp ne i32 %a, 0
+ // CHECK: %[[B:.+]] = icmp eq i32 %b, 0
+ // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+ // CHECK: ret i1 %[[R]]
+
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_ac_eq_discr(a: Option<AC>, b: Option<AC>) -> bool {
+ // CHECK-LABEL: @opt_ac_eq_discr(
+ // CHECK: %[[A:.+]] = icmp ne i8 %a, -128
+ // CHECK: %[[B:.+]] = icmp eq i8 %b, -128
+ // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+ // CHECK: ret i1 %[[R]]
+
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_giant_eq_discr(a: Option<Giant>, b: Option<Giant>) -> bool {
+ // CHECK-LABEL: @opt_giant_eq_discr(
+ // CHECK: %[[A:.+]] = icmp ne i128 %a, 1
+ // CHECK: %[[B:.+]] = icmp eq i128 %b, 1
+ // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+ // CHECK: ret i1 %[[R]]
+
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+pub enum Mid<T> {
+ Before,
+ Thing(T),
+ After,
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_bool_eq_discr(a: Mid<bool>, b: Mid<bool>) -> bool {
+ // CHECK-LABEL: @mid_bool_eq_discr(
+
+ // CHECK: %[[A_REL_DISCR:.+]] = add nsw i8 %a, -2
+ // CHECK: %[[A_IS_NICHE:.+]] = icmp samesign ugt i8 %a, 1
+ // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %[[A_REL_DISCR]], 1
+ // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+ // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1
+
+ // CHECK: %[[B_REL_DISCR:.+]] = add nsw i8 %b, -2
+ // CHECK: %[[B_IS_NICHE:.+]] = icmp samesign ugt i8 %b, 1
+ // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %[[B_REL_DISCR]], 1
+ // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+ // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1
+
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ord_eq_discr(a: Mid<Ordering>, b: Mid<Ordering>) -> bool {
+ // CHECK-LABEL: @mid_ord_eq_discr(
+
+ // CHECK: %[[A_REL_DISCR:.+]] = add nsw i8 %a, -2
+ // CHECK: %[[A_IS_NICHE:.+]] = icmp sgt i8 %a, 1
+ // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %[[A_REL_DISCR]], 1
+ // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+ // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1
+
+ // CHECK: %[[B_REL_DISCR:.+]] = add nsw i8 %b, -2
+ // CHECK: %[[B_IS_NICHE:.+]] = icmp sgt i8 %b, 1
+ // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %[[B_REL_DISCR]], 1
+ // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+ // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1
+
+ // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]]
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_nz32_eq_discr(a: Mid<NonZero<u32>>, b: Mid<NonZero<u32>>) -> bool {
+ // CHECK-LABEL: @mid_nz32_eq_discr(
+ // CHECK: %[[R:.+]] = icmp eq i32 %a.0, %b.0
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ac_eq_discr(a: Mid<AC>, b: Mid<AC>) -> bool {
+ // CHECK-LABEL: @mid_ac_eq_discr(
+
+ // CHECK: %[[A_REL_DISCR:.+]] = xor i8 %a, -128
+ // CHECK: %[[A_IS_NICHE:.+]] = icmp slt i8 %a, 0
+ // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %a, -127
+ // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+ // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1
+
+ // CHECK: %[[B_REL_DISCR:.+]] = xor i8 %b, -128
+ // CHECK: %[[B_IS_NICHE:.+]] = icmp slt i8 %b, 0
+ // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %b, -127
+ // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+ // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1
+
+ // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]]
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+// FIXME: This should be improved once our LLVM fork picks up the fix for
+// <https://github.com/llvm/llvm-project/issues/134024>
+#[unsafe(no_mangle)]
+pub fn mid_giant_eq_discr(a: Mid<Giant>, b: Mid<Giant>) -> bool {
+ // CHECK-LABEL: @mid_giant_eq_discr(
+
+ // CHECK: %[[A_TRUNC:.+]] = trunc nuw nsw i128 %a to i64
+ // CHECK: %[[A_REL_DISCR:.+]] = add nsw i64 %[[A_TRUNC]], -5
+ // CHECK: %[[A_IS_NICHE:.+]] = icmp samesign ugt i128 %a, 4
+ // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i64 %[[A_REL_DISCR]], 1
+ // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+ // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i64 %[[A_REL_DISCR]], i64 1
+
+ // CHECK: %[[B_TRUNC:.+]] = trunc nuw nsw i128 %b to i64
+ // CHECK: %[[B_REL_DISCR:.+]] = add nsw i64 %[[B_TRUNC]], -5
+ // CHECK: %[[B_IS_NICHE:.+]] = icmp samesign ugt i128 %b, 4
+ // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i64 %[[B_REL_DISCR]], 1
+ // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+ // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i64 %[[B_REL_DISCR]], i64 1
+
+ // CHECK: %[[R:.+]] = icmp eq i64 %[[A_DISCR]], %[[B_DISCR]]
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == discriminant_value(&b)
+}
+
+// In niche-encoded enums, testing for the untagged variant should optimize to a
+// straight-forward comparison looking for the natural range of the payload value.
+
+#[unsafe(no_mangle)]
+pub fn mid_bool_is_thing(a: Mid<bool>) -> bool {
+ // CHECK-LABEL: @mid_bool_is_thing(
+ // CHECK: %[[R:.+]] = icmp samesign ult i8 %a, 2
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ord_is_thing(a: Mid<Ordering>) -> bool {
+ // CHECK-LABEL: @mid_ord_is_thing(
+ // CHECK: %[[R:.+]] = icmp slt i8 %a, 2
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_nz32_is_thing(a: Mid<NonZero<u32>>) -> bool {
+ // CHECK-LABEL: @mid_nz32_is_thing(
+ // CHECK: %[[R:.+]] = icmp eq i32 %a.0, 1
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ac_is_thing(a: Mid<AC>) -> bool {
+ // CHECK-LABEL: @mid_ac_is_thing(
+ // CHECK: %[[R:.+]] = icmp sgt i8 %a, -1
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_giant_is_thing(a: Mid<Giant>) -> bool {
+ // CHECK-LABEL: @mid_giant_is_thing(
+ // CHECK: %[[R:.+]] = icmp samesign ult i128 %a, 5
+ // CHECK: ret i1 %[[R]]
+ discriminant_value(&a) == 1
+}
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index 9863500..57db44e 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -41,7 +41,7 @@ pub enum Enum1 {
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
-// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 2
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp{{( samesign)?}} ugt i8 %0, 1
// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1
// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0
// CHECK-NEXT: switch i64 %[[DISCR]]
@@ -148,10 +148,10 @@ pub enum MiddleNiche {
// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
-// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5
// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
-// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[REL_VAR]], i8 2
+// CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp{{( samesign)?}} ult i8 %0, 2
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[NOT_NICHE]], i8 2, i8 %[[REL_VAR]]
// CHECK-NEXT: switch i8 %[[DISCR]]
#[no_mangle]
pub fn match4(e: MiddleNiche) -> u8 {
@@ -167,11 +167,10 @@ pub fn match4(e: MiddleNiche) -> u8 {
// CHECK-LABEL: define{{.+}}i1 @match4_is_c(i8{{.+}}%e)
// CHECK-NEXT: start
-// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %e, -2
-// CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp ugt i8 %[[REL_VAR]], 4
-// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %e, 4
// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
-// CHECK-NEXT: ret i1 %[[NOT_NICHE]]
+// CHECK-NEXT: %[[IS_C:.+]] = icmp{{( samesign)?}} ult i8 %e, 2
+// CHECK-NEXT: ret i1 %[[IS_C]]
#[no_mangle]
pub fn match4_is_c(e: MiddleNiche) -> bool {
// Before #139098, this couldn't optimize out the `select` because it looked
@@ -453,10 +452,10 @@ pub enum HugeVariantIndex {
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
-// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 3
-// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 1
-// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp{{( samesign)?}} ugt i8 %0, 1
// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 257
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i64 %[[NICHE_DISCR]], 258
+// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 258
// CHECK-NEXT: switch i64 %[[DISCR]],
// CHECK-NEXT: i64 257,
@@ -471,3 +470,310 @@ pub fn match5(e: HugeVariantIndex) -> u8 {
Possible259 => 100,
}
}
+
+// Make an enum where the niche tags wrap both as signed and as unsigned, to hit
+// the most-fallback case where there's just nothing smart to do.
+
+pub enum E10Through65 {
+ D10 = 10,
+ D11 = 11,
+ D12 = 12,
+ D13 = 13,
+ D14 = 14,
+ D15 = 15,
+ D16 = 16,
+ D17 = 17,
+ D18 = 18,
+ D19 = 19,
+ D20 = 20,
+ D21 = 21,
+ D22 = 22,
+ D23 = 23,
+ D24 = 24,
+ D25 = 25,
+ D26 = 26,
+ D27 = 27,
+ D28 = 28,
+ D29 = 29,
+ D30 = 30,
+ D31 = 31,
+ D32 = 32,
+ D33 = 33,
+ D34 = 34,
+ D35 = 35,
+ D36 = 36,
+ D37 = 37,
+ D38 = 38,
+ D39 = 39,
+ D40 = 40,
+ D41 = 41,
+ D42 = 42,
+ D43 = 43,
+ D44 = 44,
+ D45 = 45,
+ D46 = 46,
+ D47 = 47,
+ D48 = 48,
+ D49 = 49,
+ D50 = 50,
+ D51 = 51,
+ D52 = 52,
+ D53 = 53,
+ D54 = 54,
+ D55 = 55,
+ D56 = 56,
+ D57 = 57,
+ D58 = 58,
+ D59 = 59,
+ D60 = 60,
+ D61 = 61,
+ D62 = 62,
+ D63 = 63,
+ D64 = 64,
+ D65 = 65,
+}
+
+pub enum Tricky {
+ Untagged(E10Through65),
+ V001,
+ V002,
+ V003,
+ V004,
+ V005,
+ V006,
+ V007,
+ V008,
+ V009,
+ V010,
+ V011,
+ V012,
+ V013,
+ V014,
+ V015,
+ V016,
+ V017,
+ V018,
+ V019,
+ V020,
+ V021,
+ V022,
+ V023,
+ V024,
+ V025,
+ V026,
+ V027,
+ V028,
+ V029,
+ V030,
+ V031,
+ V032,
+ V033,
+ V034,
+ V035,
+ V036,
+ V037,
+ V038,
+ V039,
+ V040,
+ V041,
+ V042,
+ V043,
+ V044,
+ V045,
+ V046,
+ V047,
+ V048,
+ V049,
+ V050,
+ V051,
+ V052,
+ V053,
+ V054,
+ V055,
+ V056,
+ V057,
+ V058,
+ V059,
+ V060,
+ V061,
+ V062,
+ V063,
+ V064,
+ V065,
+ V066,
+ V067,
+ V068,
+ V069,
+ V070,
+ V071,
+ V072,
+ V073,
+ V074,
+ V075,
+ V076,
+ V077,
+ V078,
+ V079,
+ V080,
+ V081,
+ V082,
+ V083,
+ V084,
+ V085,
+ V086,
+ V087,
+ V088,
+ V089,
+ V090,
+ V091,
+ V092,
+ V093,
+ V094,
+ V095,
+ V096,
+ V097,
+ V098,
+ V099,
+ V100,
+ V101,
+ V102,
+ V103,
+ V104,
+ V105,
+ V106,
+ V107,
+ V108,
+ V109,
+ V110,
+ V111,
+ V112,
+ V113,
+ V114,
+ V115,
+ V116,
+ V117,
+ V118,
+ V119,
+ V120,
+ V121,
+ V122,
+ V123,
+ V124,
+ V125,
+ V126,
+ V127,
+ V128,
+ V129,
+ V130,
+ V131,
+ V132,
+ V133,
+ V134,
+ V135,
+ V136,
+ V137,
+ V138,
+ V139,
+ V140,
+ V141,
+ V142,
+ V143,
+ V144,
+ V145,
+ V146,
+ V147,
+ V148,
+ V149,
+ V150,
+ V151,
+ V152,
+ V153,
+ V154,
+ V155,
+ V156,
+ V157,
+ V158,
+ V159,
+ V160,
+ V161,
+ V162,
+ V163,
+ V164,
+ V165,
+ V166,
+ V167,
+ V168,
+ V169,
+ V170,
+ V171,
+ V172,
+ V173,
+ V174,
+ V175,
+ V176,
+ V177,
+ V178,
+ V179,
+ V180,
+ V181,
+ V182,
+ V183,
+ V184,
+ V185,
+ V186,
+ V187,
+ V188,
+ V189,
+ V190,
+ V191,
+ V192,
+ V193,
+ V194,
+ V195,
+ V196,
+ V197,
+ V198,
+ V199,
+ V200,
+}
+
+const _: () = assert!(std::intrinsics::discriminant_value(&Tricky::V100) == 100);
+
+// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @discriminant6(i8 noundef %e)
+// CHECK-NEXT: start:
+// CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %e, -66
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], -56
+// CHECK-NEXT: %[[TAGGED_DISCR:.+]] = add i8 %e, -65
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[TAGGED_DISCR]], i8 0
+// CHECK-NEXT: ret i8 %[[DISCR]]
+#[no_mangle]
+pub fn discriminant6(e: Tricky) -> u8 {
+ std::intrinsics::discriminant_value(&e) as _
+}
+
+// Case from <https://github.com/rust-lang/rust/issues/104519>,
+// where sign-extension is important.
+
+pub enum OpenResult {
+ Ok(()),
+ Err(()),
+ TransportErr(TransportErr),
+}
+
+#[repr(i32)]
+pub enum TransportErr {
+ UnknownMethod = -2,
+}
+
+#[no_mangle]
+pub fn match7(result: OpenResult) -> u8 {
+ // CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match7(i32{{.+}}%result)
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: %[[NOT_OK:.+]] = icmp ne i32 %result, -1
+ // CHECK-NEXT: %[[RET:.+]] = zext i1 %[[NOT_OK]] to i8
+ // CHECK-NEXT: ret i8 %[[RET]]
+ match result {
+ OpenResult::Ok(()) => 0,
+ _ => 1,
+ }
+}
diff --git a/tests/codegen/repeat-operand-zero-len.rs b/tests/codegen/repeat-operand-zero-len.rs
new file mode 100644
index 0000000..b4cec42
--- /dev/null
+++ b/tests/codegen/repeat-operand-zero-len.rs
@@ -0,0 +1,28 @@
+//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
+
+// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
+// It only applies when the resulting array is a ZST, so the test is written in
+// such a way as to keep MIR optimizations from seeing that fact and removing
+// the local and statement altogether. (At the time of writing, no other codegen
+// test hit that code path, nor did a stage 2 build of the compiler.)
+
+#![crate_type = "lib"]
+
+#[repr(transparent)]
+pub struct Wrapper<T, const N: usize>([T; N]);
+
+// CHECK-LABEL: define {{.+}}do_repeat{{.+}}(i32 noundef %x)
+// CHECK-NEXT: start:
+// CHECK-NOT: alloca
+// CHECK-NEXT: ret void
+#[inline(never)]
+pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
+ Wrapper([x; N])
+}
+
+// CHECK-LABEL: @trigger_repeat_zero_len
+#[no_mangle]
+pub fn trigger_repeat_zero_len() -> Wrapper<u32, 0> {
+ // CHECK: call void {{.+}}do_repeat{{.+}}(i32 noundef 4)
+ do_repeat(4)
+}
diff --git a/tests/codegen/repeat-operand-zst-elem.rs b/tests/codegen/repeat-operand-zst-elem.rs
new file mode 100644
index 0000000..c363775
--- /dev/null
+++ b/tests/codegen/repeat-operand-zst-elem.rs
@@ -0,0 +1,28 @@
+//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
+
+// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
+// It only applies when the resulting array is a ZST, so the test is written in
+// such a way as to keep MIR optimizations from seeing that fact and removing
+// the local and statement altogether. (At the time of writing, no other codegen
+// test hit that code path, nor did a stage 2 build of the compiler.)
+
+#![crate_type = "lib"]
+
+#[repr(transparent)]
+pub struct Wrapper<T, const N: usize>([T; N]);
+
+// CHECK-LABEL: define {{.+}}do_repeat{{.+}}()
+// CHECK-NEXT: start:
+// CHECK-NOT: alloca
+// CHECK-NEXT: ret void
+#[inline(never)]
+pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
+ Wrapper([x; N])
+}
+
+// CHECK-LABEL: @trigger_repeat_zst_elem
+#[no_mangle]
+pub fn trigger_repeat_zst_elem() -> Wrapper<(), 8> {
+ // CHECK: call void {{.+}}do_repeat{{.+}}()
+ do_repeat(())
+}
diff --git a/tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff b/tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff
new file mode 100644
index 0000000..90a4a50
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `a` before Inline
++ // MIR for `a` after Inline
+
+ fn a() -> () {
+ let mut _0: ();
+ let _1: ();
+ let mut _2: ();
+ let _3: ();
+ let mut _4: ();
++ let mut _5: fn() {a};
++ let mut _6: fn() {b};
++ scope 1 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++ }
++ scope 2 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++ }
+
+ bb0: {
+ StorageLive(_1);
+ StorageLive(_2);
+ _2 = ();
+- _1 = <fn() {a} as FnOnce<()>>::call_once(a, move _2) -> [return: bb1, unwind unreachable];
++ StorageLive(_5);
++ _5 = a;
++ _1 = move _5() -> [return: bb1, unwind unreachable];
+ }
+
+ bb1: {
++ StorageDead(_5);
+ StorageDead(_2);
+ StorageDead(_1);
+ StorageLive(_3);
+ StorageLive(_4);
+ _4 = ();
+- _3 = <fn() {b} as FnOnce<()>>::call_once(b, move _4) -> [return: bb2, unwind unreachable];
++ StorageLive(_6);
++ _6 = b;
++ _3 = move _6() -> [return: bb2, unwind unreachable];
+ }
+
+ bb2: {
++ StorageDead(_6);
+ StorageDead(_4);
+ StorageDead(_3);
+ _0 = const ();
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff b/tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff
new file mode 100644
index 0000000..55da685
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `a` before Inline
++ // MIR for `a` after Inline
+
+ fn a() -> () {
+ let mut _0: ();
+ let _1: ();
+ let mut _2: ();
+ let _3: ();
+ let mut _4: ();
++ let mut _5: fn() {a};
++ let mut _6: fn() {b};
++ scope 1 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++ }
++ scope 2 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++ }
+
+ bb0: {
+ StorageLive(_1);
+ StorageLive(_2);
+ _2 = ();
+- _1 = <fn() {a} as FnOnce<()>>::call_once(a, move _2) -> [return: bb1, unwind continue];
++ StorageLive(_5);
++ _5 = a;
++ _1 = move _5() -> [return: bb1, unwind continue];
+ }
+
+ bb1: {
++ StorageDead(_5);
+ StorageDead(_2);
+ StorageDead(_1);
+ StorageLive(_3);
+ StorageLive(_4);
+ _4 = ();
+- _3 = <fn() {b} as FnOnce<()>>::call_once(b, move _4) -> [return: bb2, unwind continue];
++ StorageLive(_6);
++ _6 = b;
++ _3 = move _6() -> [return: bb2, unwind continue];
+ }
+
+ bb2: {
++ StorageDead(_6);
+ StorageDead(_4);
+ StorageDead(_3);
+ _0 = const ();
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff b/tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff
new file mode 100644
index 0000000..2090411
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `b` before Inline
++ // MIR for `b` after Inline
+
+ fn b() -> () {
+ let mut _0: ();
+ let _1: ();
+ let mut _2: ();
+ let _3: ();
+ let mut _4: ();
++ let mut _5: fn() {b};
++ let mut _6: fn() {a};
++ scope 1 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++ }
++ scope 2 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++ }
+
+ bb0: {
+ StorageLive(_1);
+ StorageLive(_2);
+ _2 = ();
+- _1 = <fn() {b} as FnOnce<()>>::call_once(b, move _2) -> [return: bb1, unwind unreachable];
++ StorageLive(_5);
++ _5 = b;
++ _1 = move _5() -> [return: bb1, unwind unreachable];
+ }
+
+ bb1: {
++ StorageDead(_5);
+ StorageDead(_2);
+ StorageDead(_1);
+ StorageLive(_3);
+ StorageLive(_4);
+ _4 = ();
+- _3 = <fn() {a} as FnOnce<()>>::call_once(a, move _4) -> [return: bb2, unwind unreachable];
++ StorageLive(_6);
++ _6 = a;
++ _3 = move _6() -> [return: bb2, unwind unreachable];
+ }
+
+ bb2: {
++ StorageDead(_6);
+ StorageDead(_4);
+ StorageDead(_3);
+ _0 = const ();
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff b/tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff
new file mode 100644
index 0000000..9e6eef1
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `b` before Inline
++ // MIR for `b` after Inline
+
+ fn b() -> () {
+ let mut _0: ();
+ let _1: ();
+ let mut _2: ();
+ let _3: ();
+ let mut _4: ();
++ let mut _5: fn() {b};
++ let mut _6: fn() {a};
++ scope 1 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++ }
++ scope 2 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++ }
+
+ bb0: {
+ StorageLive(_1);
+ StorageLive(_2);
+ _2 = ();
+- _1 = <fn() {b} as FnOnce<()>>::call_once(b, move _2) -> [return: bb1, unwind continue];
++ StorageLive(_5);
++ _5 = b;
++ _1 = move _5() -> [return: bb1, unwind continue];
+ }
+
+ bb1: {
++ StorageDead(_5);
+ StorageDead(_2);
+ StorageDead(_1);
+ StorageLive(_3);
+ StorageLive(_4);
+ _4 = ();
+- _3 = <fn() {a} as FnOnce<()>>::call_once(a, move _4) -> [return: bb2, unwind continue];
++ StorageLive(_6);
++ _6 = a;
++ _3 = move _6() -> [return: bb2, unwind continue];
+ }
+
+ bb2: {
++ StorageDead(_6);
+ StorageDead(_4);
+ StorageDead(_3);
+ _0 = const ();
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/inline_double_cycle.rs b/tests/mir-opt/inline_double_cycle.rs
new file mode 100644
index 0000000..cf3b87c
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.rs
@@ -0,0 +1,22 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// skip-filecheck
+//@ test-mir-pass: Inline
+//@ edition: 2021
+//@ compile-flags: -Zinline-mir --crate-type=lib
+
+// EMIT_MIR inline_double_cycle.a.Inline.diff
+// EMIT_MIR inline_double_cycle.b.Inline.diff
+
+#![feature(fn_traits)]
+
+#[inline]
+pub fn a() {
+ FnOnce::call_once(a, ());
+ FnOnce::call_once(b, ());
+}
+
+#[inline]
+pub fn b() {
+ FnOnce::call_once(b, ());
+ FnOnce::call_once(a, ());
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/README.md b/tests/run-make/autodiff/type-trees/type-analysis/README.md
new file mode 100644
index 0000000..c712edf
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/README.md
@@ -0,0 +1,13 @@
+# Autodiff Type-Trees Type Analysis Tests
+
+This directory contains run-make tests for the autodiff type-trees type analysis functionality. These tests verify that the autodiff compiler correctly analyzes and tracks type information for different Rust types during automatic differentiation.
+
+## What These Tests Do
+
+Each test compiles a simple Rust function with the `#[autodiff_reverse]` attribute and verifies that the compiler:
+
+1. **Correctly identifies type information** in the generated LLVM IR
+2. **Tracks type annotations** for variables and operations
+3. **Preserves type context** through the autodiff transformation process
+
+The tests capture the stdout from the autodiff compiler (which contains type analysis information) and verify it matches expected patterns using FileCheck.
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array/array.check b/tests/run-make/autodiff/type-trees/type-analysis/array/array.check
new file mode 100644
index 0000000..6e41976
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array/array.check
@@ -0,0 +1,26 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 4, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 4, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array/array.rs b/tests/run-make/autodiff/type-trees/type-analysis/array/array.rs
new file mode 100644
index 0000000..9a85941
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array/array.rs
@@ -0,0 +1,20 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &[f32; 3]) -> f32 {
+ x[0] * x[0] + x[1] * x[1] + x[2] * x[2]
+}
+
+fn main() {
+ let x = [1.0f32, 2.0, 3.0];
+ let mut df_dx = [0.0f32; 3];
+ let out = callee(&x);
+ let out_ = d_square(&x, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(2.0, df_dx[0]);
+ assert_eq!(4.0, df_dx[1]);
+ assert_eq!(6.0, df_dx[2]);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs
new file mode 100644
index 0000000..d68ab46
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("array.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("array.stdout", stdout);
+ rfs::write("array.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("array.check").stdin_buf(rfs::read("array.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check
new file mode 100644
index 0000000..ed81ad4
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check
@@ -0,0 +1,54 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ 0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x [2 x float]], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x float], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ 0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x [2 x float]], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x float], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs
new file mode 100644
index 0000000..a95111a
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs
@@ -0,0 +1,32 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &[[[f32; 2]; 2]; 2]) -> f32 {
+ let mut sum = 0.0;
+ for i in 0..2 {
+ for j in 0..2 {
+ for k in 0..2 {
+ sum += x[i][j][k] * x[i][j][k];
+ }
+ }
+ }
+ sum
+}
+
+fn main() {
+ let x = [[[1.0f32, 2.0], [3.0, 4.0]], [[5.0, 6.0], [7.0, 8.0]]];
+ let mut df_dx = [[[0.0f32; 2]; 2]; 2];
+ let out = callee(&x);
+ let out_ = d_square(&x, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ for i in 0..2 {
+ for j in 0..2 {
+ for k in 0..2 {
+ assert_eq!(df_dx[i][j][k], 2.0 * x[i][j][k]);
+ }
+ }
+ }
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs
new file mode 100644
index 0000000..8e75c21
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("array3d.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("array3d.stdout", stdout);
+ rfs::write("array3d.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("array3d.check").stdin_buf(rfs::read("array3d.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/box/box.check b/tests/run-make/autodiff/type-trees/type-analysis/box/box.check
new file mode 100644
index 0000000..1911e18
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/box/box.check
@@ -0,0 +1,12 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/box/box.rs b/tests/run-make/autodiff/type-trees/type-analysis/box/box.rs
new file mode 100644
index 0000000..658ccff
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/box/box.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &Box<f32>) -> f32 {
+ **x * **x
+}
+
+fn main() {
+ let x = Box::new(7.0f32);
+ let mut df_dx = Box::new(0.0f32);
+ let out = callee(&x);
+ let out_ = d_square(&x, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(14.0, *df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs
new file mode 100644
index 0000000..1e8c8f9
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("box.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("box.stdout", stdout);
+ rfs::write("box.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("box.check").stdin_buf(rfs::read("box.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check
new file mode 100644
index 0000000..e750345
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs
new file mode 100644
index 0000000..8c877bf
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: *const f32) -> f32 {
+ unsafe { *x * *x }
+}
+
+fn main() {
+ let x: f32 = 7.0;
+ let out = callee(&x as *const f32);
+ let mut df_dx: f32 = 0.0;
+ let out_ = d_square(&x as *const f32, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs
new file mode 100644
index 0000000..ce38c6b
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs
@@ -0,0 +1,31 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("const_pointer.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("const_pointer.stdout", stdout);
+ rfs::write("const_pointer.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck()
+ .patterns("const_pointer.check")
+ .stdin_buf(rfs::read("const_pointer.stdout"))
+ .run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check
new file mode 100644
index 0000000..0cc0ffd
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check
@@ -0,0 +1,12 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs
new file mode 100644
index 0000000..b945821
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs
@@ -0,0 +1,19 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &f32) -> f32 {
+ *x * *x
+}
+
+fn main() {
+ let x: f32 = 7.0;
+ let mut df_dx: f32 = 0.0;
+ let out = callee(&x);
+ let out_ = d_square(&x, &mut df_dx, 1.0);
+
+ assert_eq!(out, out_);
+ assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs
new file mode 100644
index 0000000..d7e4921
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("f32.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("f32.stdout", stdout);
+ rfs::write("f32.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("f32.check").stdin_buf(rfs::read("f32.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check
new file mode 100644
index 0000000..efc49da
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@double} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = load double, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = fmul double %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: ret double %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@double} |{[-1]:Pointer, [-1,0]:Float@double}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = load double, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = fmul double %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: ret double %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs
new file mode 100644
index 0000000..9b47569
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs
@@ -0,0 +1,20 @@
+#![feature(autodiff)]
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_callee, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &f64) -> f64 {
+ x * x
+}
+
+fn main() {
+ let x = std::hint::black_box(3.0);
+
+ let output = callee(&x);
+ assert_eq!(9.0, output);
+
+ let mut df_dx = 0.0;
+ let output_ = d_callee(&x, &mut df_dx, 1.0);
+ assert_eq!(output, output_);
+ assert_eq!(6.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs
new file mode 100644
index 0000000..8bf92b8
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("f64.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("f64.stdout", stdout);
+ rfs::write("f64.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("f64.check").stdin_buf(rfs::read("f64.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check
new file mode 100644
index 0000000..31a0721
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs
new file mode 100644
index 0000000..19dfbbb
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i128) -> i128 {
+ *x * *x
+}
+
+fn main() {
+ let x: i128 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs
new file mode 100644
index 0000000..21e8698
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("i128.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("i128.stdout", stdout);
+ rfs::write("i128.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("i128.check").stdin_buf(rfs::read("i128.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check
new file mode 100644
index 0000000..8cc2995
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs
new file mode 100644
index 0000000..8209919
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i16) -> i16 {
+ *x * *x
+}
+
+fn main() {
+ let x: i16 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs
new file mode 100644
index 0000000..a2875a8
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("i16.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("i16.stdout", stdout);
+ rfs::write("i16.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("i16.check").stdin_buf(rfs::read("i16.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check
new file mode 100644
index 0000000..4df9828
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs
new file mode 100644
index 0000000..e95068d
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i32) -> i32 {
+ *x * *x
+}
+
+fn main() {
+ let x: i32 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs
new file mode 100644
index 0000000..857017f
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("i32.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("i32.stdout", stdout);
+ rfs::write("i32.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("i32.check").stdin_buf(rfs::read("i32.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check
new file mode 100644
index 0000000..651a208
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs
new file mode 100644
index 0000000..afc0cad
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i8) -> i8 {
+ *x * *x
+}
+
+fn main() {
+ let x: i8 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs
new file mode 100644
index 0000000..6551e2d
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("i8.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("i8.stdout", stdout);
+ rfs::write("i8.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("i8.check").stdin_buf(rfs::read("i8.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check
new file mode 100644
index 0000000..40ee6ed
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs
new file mode 100644
index 0000000..dd16098
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &isize) -> isize {
+ *x * *x
+}
+
+fn main() {
+ let x: isize = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs
new file mode 100644
index 0000000..09277f6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("isize.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("isize.stdout", stdout);
+ rfs::write("isize.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("isize.check").stdin_buf(rfs::read("isize.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check
new file mode 100644
index 0000000..e750345
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs
new file mode 100644
index 0000000..2b672f6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: *mut f32) -> f32 {
+ unsafe { *x * *x }
+}
+
+fn main() {
+ let mut x: f32 = 7.0;
+ let out = callee(&mut x as *mut f32);
+ let mut df_dx: f32 = 0.0;
+ let out_ = d_square(&mut x as *mut f32, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs
new file mode 100644
index 0000000..4d5a504
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("mut_pointer.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("mut_pointer.stdout", stdout);
+ rfs::write("mut_pointer.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("mut_pointer.check").stdin_buf(rfs::read("mut_pointer.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check
new file mode 100644
index 0000000..e750345
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs
new file mode 100644
index 0000000..7019e3f
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &mut f32) -> f32 {
+ *x * *x
+}
+
+fn main() {
+ let mut x: f32 = 7.0;
+ let mut df_dx: f32 = 0.0;
+ let out = callee(&mut x);
+ let out_ = d_square(&mut x, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs
new file mode 100644
index 0000000..13668c5
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("mut_ref.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("mut_ref.stdout", stdout);
+ rfs::write("mut_ref.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("mut_ref.check").stdin_buf(rfs::read("mut_ref.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check
new file mode 100644
index 0000000..e750345
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs
new file mode 100644
index 0000000..3ced164
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &f32) -> f32 {
+ *x * *x
+}
+
+fn main() {
+ let x: f32 = 7.0;
+ let mut df_dx: f32 = 0.0;
+ let out = callee(&x);
+ let out_ = d_square(&x, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs
new file mode 100644
index 0000000..b68e4e5
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("ref.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("ref.stdout", stdout);
+ rfs::write("ref.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("ref.check").stdin_buf(rfs::read("ref.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs
new file mode 100644
index 0000000..4073f75
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("struct.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("struct.stdout", stdout);
+ rfs::write("struct.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("struct.check").stdin_buf(rfs::read("struct.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check
new file mode 100644
index 0000000..e750345
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs
new file mode 100644
index 0000000..52cb6a9
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs
@@ -0,0 +1,23 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[derive(Copy, Clone)]
+struct MyStruct {
+ f: f32,
+}
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &MyStruct) -> f32 {
+ x.f * x.f
+}
+
+fn main() {
+ let x = MyStruct { f: 7.0 };
+ let mut df_dx = MyStruct { f: 0.0 };
+ let out = callee(&x);
+ let out_ = d_square(&x, &mut df_dx, 1.0);
+ assert_eq!(out, out_);
+ assert_eq!(14.0, df_dx.f);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs
new file mode 100644
index 0000000..3f605d4
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("u128.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("u128.stdout", stdout);
+ rfs::write("u128.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("u128.check").stdin_buf(rfs::read("u128.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check
new file mode 100644
index 0000000..31a0721
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs
new file mode 100644
index 0000000..d19d2fa
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u128) -> u128 {
+ *x * *x
+}
+
+fn main() {
+ let x: u128 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs
new file mode 100644
index 0000000..0051f6f
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("u16.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("u16.stdout", stdout);
+ rfs::write("u16.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("u16.check").stdin_buf(rfs::read("u16.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check
new file mode 100644
index 0000000..8cc2995
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs
new file mode 100644
index 0000000..f5f5b50
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u16) -> u16 {
+ *x * *x
+}
+
+fn main() {
+ let x: u16 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs
new file mode 100644
index 0000000..0882230
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("u32.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("u32.stdout", stdout);
+ rfs::write("u32.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("u32.check").stdin_buf(rfs::read("u32.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check
new file mode 100644
index 0000000..4df9828
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs
new file mode 100644
index 0000000..66b4c22
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u32) -> u32 {
+ *x * *x
+}
+
+fn main() {
+ let x: u32 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs
new file mode 100644
index 0000000..100b4f4
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("u8.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("u8.stdout", stdout);
+ rfs::write("u8.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("u8.check").stdin_buf(rfs::read("u8.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check
new file mode 100644
index 0000000..651a208
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs
new file mode 100644
index 0000000..de9cdeb
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u8) -> u8 {
+ *x * *x
+}
+
+fn main() {
+ let x: u8 = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs
new file mode 100644
index 0000000..67f0fe1
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("union.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("union.stdout", stdout);
+ rfs::write("union.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("union.check").stdin_buf(rfs::read("union.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/union/union.check b/tests/run-make/autodiff/type-trees/type-analysis/union/union.check
new file mode 100644
index 0000000..e750345
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/union/union.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/union/union.rs b/tests/run-make/autodiff/type-trees/type-analysis/union/union.rs
new file mode 100644
index 0000000..8d997f8
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/union/union.rs
@@ -0,0 +1,20 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[allow(dead_code)]
+union MyUnion {
+ f: f32,
+ i: i32,
+}
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &MyUnion) -> f32 {
+ unsafe { x.f * x.f }
+}
+
+fn main() {
+ let x = MyUnion { f: 7.0 };
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs
new file mode 100644
index 0000000..d5cfd70
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("usize.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("usize.stdout", stdout);
+ rfs::write("usize.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("usize.check").stdin_buf(rfs::read("usize.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check
new file mode 100644
index 0000000..40ee6ed
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs
new file mode 100644
index 0000000..8e758be
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &usize) -> usize {
+ *x * *x
+}
+
+fn main() {
+ let x: usize = 7;
+ let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs
new file mode 100644
index 0000000..94491fa
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ // Compile the Rust file with the required flags, capturing both stdout and stderr
+ let output = rustc()
+ .input("vec.rs")
+ .arg("-Zautodiff=Enable,PrintTAFn=callee")
+ .arg("-Zautodiff=NoPostopt")
+ .opt_level("3")
+ .arg("-Clto=fat")
+ .arg("-g")
+ .run();
+
+ let stdout = output.stdout_utf8();
+ let stderr = output.stderr_utf8();
+
+ // Write the outputs to files
+ rfs::write("vec.stdout", stdout);
+ rfs::write("vec.stderr", stderr);
+
+ // Run FileCheck on the stdout using the check file
+ llvm_filecheck().patterns("vec.check").stdin_buf(rfs::read("vec.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check
new file mode 100644
index 0000000..dcf9508
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check
@@ -0,0 +1,18 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer}
+// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !102, !noundef !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 16, !dbg !{{[0-9]+}}: {[-1]:Pointer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, 0, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ -0.000000e+00, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = add nuw i64 %{{[0-9]+}}, 1, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ -0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs
new file mode 100644
index 0000000..b60c2a8
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(arg: &std::vec::Vec<f32>) -> f32 {
+ arg.iter().sum()
+}
+
+fn main() {
+ let v = vec![1.0f32, 2.0, 3.0];
+ let _ = callee(&v);
+}
diff --git a/tests/run-make/link-eh-frame-terminator/rmake.rs b/tests/run-make/link-eh-frame-terminator/rmake.rs
index 6bfae38..06b77f0 100644
--- a/tests/run-make/link-eh-frame-terminator/rmake.rs
+++ b/tests/run-make/link-eh-frame-terminator/rmake.rs
@@ -9,6 +9,7 @@
//@ ignore-32bit
// Reason: the usage of a large array in the test causes an out-of-memory
// error on 32 bit systems.
+//@ ignore-cross-compile
use run_make_support::{bin_name, llvm_objdump, run, rustc};
diff --git a/tests/rustdoc-js-std/alias-lev.js b/tests/rustdoc-js-std/alias-lev.js
new file mode 100644
index 0000000..17f3dc2
--- /dev/null
+++ b/tests/rustdoc-js-std/alias-lev.js
@@ -0,0 +1,11 @@
+// This test ensures that aliases are also allowed to be partially matched.
+
+// ignore-order
+
+const EXPECTED = {
+ // The full alias name is `getcwd`.
+ 'query': 'getcw',
+ 'others': [
+ { 'path': 'std::env', 'name': 'current_dir', 'alias': 'getcwd' },
+ ],
+};
diff --git a/tests/rustdoc-js/non-english-identifier.js b/tests/rustdoc-js/non-english-identifier.js
index f2180b4..3d50bd3 100644
--- a/tests/rustdoc-js/non-english-identifier.js
+++ b/tests/rustdoc-js/non-english-identifier.js
@@ -115,11 +115,10 @@
query: '加法',
others: [
{
- name: "add",
+ name: "加法",
path: "non_english_identifier",
- is_alias: true,
- alias: "加法",
- href: "../non_english_identifier/macro.add.html"
+ href: "../non_english_identifier/trait.加法.html",
+ desc: "Add"
},
{
name: "add",
@@ -129,11 +128,13 @@
href: "../non_english_identifier/fn.add.html"
},
{
- name: "加法",
+ name: "add",
path: "non_english_identifier",
- href: "../non_english_identifier/trait.加法.html",
- desc: "Add"
- }],
+ is_alias: true,
+ alias: "加法",
+ href: "../non_english_identifier/macro.add.html"
+ },
+ ],
in_args: [{
name: "加上",
path: "non_english_identifier::加法",
diff --git a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr
index 85c9516..9d3ce5e 100644
--- a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr
+++ b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr
@@ -4,13 +4,13 @@
LL | #[doc(alias = "foo")]
| ^^^^^^^^^^^^^
-error: `#[doc(alias = "...")]` isn't allowed on implementation block
+error: `#[doc(alias = "...")]` isn't allowed on inherent implementation block
--> $DIR/check-doc-alias-attr-location.rs:10:7
|
LL | #[doc(alias = "bar")]
| ^^^^^^^^^^^^^
-error: `#[doc(alias = "...")]` isn't allowed on implementation block
+error: `#[doc(alias = "...")]` isn't allowed on trait implementation block
--> $DIR/check-doc-alias-attr-location.rs:16:7
|
LL | #[doc(alias = "foobar")]
diff --git a/tests/rustdoc/reexport/auxiliary/reexports-attrs.rs b/tests/rustdoc/reexport/auxiliary/reexports-attrs.rs
new file mode 100644
index 0000000..96fa820
--- /dev/null
+++ b/tests/rustdoc/reexport/auxiliary/reexports-attrs.rs
@@ -0,0 +1,14 @@
+#[unsafe(no_mangle)]
+pub fn f0() {}
+
+#[unsafe(link_section = ".here")]
+pub fn f1() {}
+
+#[unsafe(export_name = "f2export")]
+pub fn f2() {}
+
+#[repr(u8)]
+pub enum T0 { V1 }
+
+#[non_exhaustive]
+pub enum T1 {}
diff --git a/tests/rustdoc/reexport/reexport-attrs.rs b/tests/rustdoc/reexport/reexport-attrs.rs
new file mode 100644
index 0000000..0ec6458
--- /dev/null
+++ b/tests/rustdoc/reexport/reexport-attrs.rs
@@ -0,0 +1,20 @@
+//@ aux-build: reexports-attrs.rs
+
+#![crate_name = "foo"]
+
+extern crate reexports_attrs;
+
+//@ has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' '#[no_mangle]'
+pub use reexports_attrs::f0;
+
+//@ has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' '#[link_section = ".here"]'
+pub use reexports_attrs::f1;
+
+//@ has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' '#[export_name = "f2export"]'
+pub use reexports_attrs::f2;
+
+//@ has 'foo/enum.T0.html' '//pre[@class="rust item-decl"]' '#[repr(u8)]'
+pub use reexports_attrs::T0;
+
+//@ has 'foo/enum.T1.html' '//pre[@class="rust item-decl"]' '#[non_exhaustive]'
+pub use reexports_attrs::T1;
diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs
index b90bb9e..029ce7d 100644
--- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs
+++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs
@@ -1,8 +1,7 @@
// Regression test for <https://github.com/rust-lang/rust/issues/137554>.
fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
- //~^ ERROR `?Trait` is not permitted in trait object types
- //~| ERROR expected trait, found associated function `Iterator::advance_by`
- //~| ERROR the value of the associated type `Item` in `Iterator` must be specified
+ //~^ ERROR expected trait, found associated function `Iterator::advance_by`
+ //~| ERROR relaxed bounds are not permitted in trait object types
todo!()
}
diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr
index 7f0fbc8..ffe0b14 100644
--- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr
+++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr
@@ -1,25 +1,15 @@
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29
- |
-LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
error[E0404]: expected trait, found associated function `Iterator::advance_by`
--> $DIR/missing-associated_item_or_field_def_ids.rs:3:30
|
LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait
-error[E0191]: the value of the associated type `Item` in `Iterator` must be specified
- --> $DIR/missing-associated_item_or_field_def_ids.rs:3:18
+error: relaxed bounds are not permitted in trait object types
+ --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29
|
LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) {
- | ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0191, E0404, E0658.
-For more information about an error, try `rustc --explain E0191`.
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs
index f6b749a..bac4e60 100644
--- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs
+++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs
@@ -6,7 +6,6 @@ trait Tr {
fn main() {
let _: dyn Tr + ?Foo<Assoc = ()>;
- //~^ ERROR: `?Trait` is not permitted in trait object types
- //~| ERROR: cannot find trait `Foo` in this scope
- //~| ERROR: the value of the associated type `Item` in `Tr` must be specified
+ //~^ ERROR: cannot find trait `Foo` in this scope
+ //~| ERROR: relaxed bounds are not permitted in trait object types
}
diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr
index f31a1de..3660fce 100644
--- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr
+++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr
@@ -1,28 +1,15 @@
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21
- |
-LL | let _: dyn Tr + ?Foo<Assoc = ()>;
- | ^^^^^^^^^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
error[E0405]: cannot find trait `Foo` in this scope
--> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:22
|
LL | let _: dyn Tr + ?Foo<Assoc = ()>;
| ^^^ not found in this scope
-error[E0191]: the value of the associated type `Item` in `Tr` must be specified
- --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:16
+error: relaxed bounds are not permitted in trait object types
+ --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21
|
-LL | type Item;
- | --------- `Item` defined here
-...
LL | let _: dyn Tr + ?Foo<Assoc = ()>;
- | ^^ help: specify the associated type: `Tr<Item = Type>`
+ | ^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0191, E0405, E0658.
-For more information about an error, try `rustc --explain E0191`.
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/attributes/positions/used.stderr b/tests/ui/attributes/positions/used.stderr
index 96dd43a..64460c1 100644
--- a/tests/ui/attributes/positions/used.stderr
+++ b/tests/ui/attributes/positions/used.stderr
@@ -28,7 +28,7 @@
LL | #[used]
| ^^^^^^^
LL | impl Bar for Foo {}
- | ------------------- but this is a implementation block
+ | ------------------- but this is a trait implementation block
error: attribute must be applied to a `static` variable
--> $DIR/used.rs:21:5
diff --git a/tests/ui/cfg/crt-static-with-target-features-works.rs b/tests/ui/cfg/crt-static-with-target-features-works.rs
new file mode 100644
index 0000000..bce0222
--- /dev/null
+++ b/tests/ui/cfg/crt-static-with-target-features-works.rs
@@ -0,0 +1,24 @@
+// Test to ensure that specifying a value for crt-static in target features
+// does not result in skipping the features following it.
+// This is a regression test for #144143
+
+//@ add-core-stubs
+//@ needs-llvm-components: x86
+//@ compile-flags: --target=x86_64-unknown-linux-gnu
+//@ compile-flags: -Ctarget-feature=+crt-static,+avx2
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[rustc_builtin_macro]
+macro_rules! compile_error {
+ () => {};
+}
+
+#[cfg(target_feature = "avx2")]
+compile_error!("+avx2");
+//~^ ERROR: +avx2
diff --git a/tests/ui/cfg/crt-static-with-target-features-works.stderr b/tests/ui/cfg/crt-static-with-target-features-works.stderr
new file mode 100644
index 0000000..6f265c6
--- /dev/null
+++ b/tests/ui/cfg/crt-static-with-target-features-works.stderr
@@ -0,0 +1,8 @@
+error: +avx2
+ --> $DIR/crt-static-with-target-features-works.rs:23:1
+ |
+LL | compile_error!("+avx2");
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr
index 92b226f..0c57edd 100644
--- a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr
+++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr
@@ -1,8 +1,12 @@
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:40:32
|
LL | get_flag::<false, { unsafe { char_raw.character } }>();
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#7}` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ ff __ __ __ │ .░░░
+ }
error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
--> $DIR/invalid-patterns.rs:42:14
@@ -26,11 +30,15 @@
42 │ B
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:44:58
|
LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#11}` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ ff __ __ __ │ .░░░
+ }
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:31:21
diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr
index 92b226f..0c57edd 100644
--- a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr
+++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr
@@ -1,8 +1,12 @@
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:40:32
|
LL | get_flag::<false, { unsafe { char_raw.character } }>();
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#7}` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ ff __ __ __ │ .░░░
+ }
error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
--> $DIR/invalid-patterns.rs:42:14
@@ -26,11 +30,15 @@
42 │ B
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:44:58
|
LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
| ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#11}` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ ff __ __ __ │ .░░░
+ }
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:31:21
diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr
index c1706a8..770a55c 100644
--- a/tests/ui/consts/const-compare-bytes-ub.stderr
+++ b/tests/ui/consts/const-compare-bytes-ub.stderr
@@ -33,12 +33,20 @@
|
LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::LHS_UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: 1, align: 1) {
+ __ │ ░
+ }
error[E0080]: reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
--> $DIR/const-compare-bytes-ub.rs:33:9
|
LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::RHS_UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: 1, align: 1) {
+ __ │ ░
+ }
error[E0080]: unable to turn pointer into integer
--> $DIR/const-compare-bytes-ub.rs:37:9
diff --git a/tests/ui/consts/const-err-enum-discriminant.32bit.stderr b/tests/ui/consts/const-err-enum-discriminant.32bit.stderr
new file mode 100644
index 0000000..cc78610
--- /dev/null
+++ b/tests/ui/consts/const-err-enum-discriminant.32bit.stderr
@@ -0,0 +1,13 @@
+error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
+ --> $DIR/const-err-enum-discriminant.rs:10:21
+ |
+LL | Boo = [unsafe { Foo { b: () }.a }; 4][3],
+ | ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+ }
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-err-enum-discriminant.64bit.stderr b/tests/ui/consts/const-err-enum-discriminant.64bit.stderr
new file mode 100644
index 0000000..1d32851
--- /dev/null
+++ b/tests/ui/consts/const-err-enum-discriminant.64bit.stderr
@@ -0,0 +1,13 @@
+error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory
+ --> $DIR/const-err-enum-discriminant.rs:10:21
+ |
+LL | Boo = [unsafe { Foo { b: () }.a }; 4][3],
+ | ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here
+ |
+ = note: the raw bytes of the constant (size: 8, align: 8) {
+ __ __ __ __ __ __ __ __ │ ░░░░░░░░
+ }
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-err-enum-discriminant.rs b/tests/ui/consts/const-err-enum-discriminant.rs
index 190ef47..5567460 100644
--- a/tests/ui/consts/const-err-enum-discriminant.rs
+++ b/tests/ui/consts/const-err-enum-discriminant.rs
@@ -1,3 +1,5 @@
+//@ stderr-per-bitwidth
+
#[derive(Copy, Clone)]
union Foo {
a: isize,
diff --git a/tests/ui/consts/const-err-enum-discriminant.stderr b/tests/ui/consts/const-err-enum-discriminant.stderr
deleted file mode 100644
index 8724333..0000000
--- a/tests/ui/consts/const-err-enum-discriminant.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/const-err-enum-discriminant.rs:8:21
- |
-LL | Boo = [unsafe { Foo { b: () }.a }; 4][3],
- | ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
index d28d684..60f6ef0 100644
--- a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
+++ b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
@@ -43,11 +43,15 @@
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC2[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory
--> $DIR/const-pointer-values-in-various-types.rs:42:47
|
LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::I32_REF_U128_UNION` failed here
+ |
+ = note: the raw bytes of the constant (size: 16, align: 16) {
+ ╾ALLOC0<imm>╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░
+ }
error[E0080]: unable to turn pointer into integer
--> $DIR/const-pointer-values-in-various-types.rs:45:43
@@ -85,11 +89,15 @@
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC3[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory
--> $DIR/const-pointer-values-in-various-types.rs:57:47
|
LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::I32_REF_I128_UNION` failed here
+ |
+ = note: the raw bytes of the constant (size: 16, align: 16) {
+ ╾ALLOC1<imm>╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░
+ }
error[E0080]: unable to turn pointer into integer
--> $DIR/const-pointer-values-in-various-types.rs:60:45
diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr
index 52af52d..2fd01b6 100644
--- a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr
+++ b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr
@@ -1,8 +1,12 @@
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x1..0x2], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
--> $DIR/ub-enum-overwrite.rs:11:14
|
LL | unsafe { *p }
| ^^ evaluation of `_` failed here
+ |
+ = note: the raw bytes of the constant (size: 2, align: 1) {
+ 01 __ │ .░
+ }
error: aborting due to 1 previous error
diff --git a/tests/ui/consts/const-eval/ub-enum.rs b/tests/ui/consts/const-eval/ub-enum.rs
index 52fc994..9c78bb6 100644
--- a/tests/ui/consts/const-eval/ub-enum.rs
+++ b/tests/ui/consts/const-eval/ub-enum.rs
@@ -1,7 +1,8 @@
// Strip out raw byte dumps to make comparison platform-independent:
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
-//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
+//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
//@ normalize-stderr: "0x0+" -> "0x0"
+//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
//@ dont-require-annotations: NOTE
#![feature(never_type)]
diff --git a/tests/ui/consts/const-eval/ub-enum.stderr b/tests/ui/consts/const-eval/ub-enum.stderr
index 29f7a1f..5cbd617 100644
--- a/tests/ui/consts/const-eval/ub-enum.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.stderr
@@ -1,5 +1,5 @@
error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x01, but expected a valid enum tag
- --> $DIR/ub-enum.rs:29:1
+ --> $DIR/ub-enum.rs:30:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -10,7 +10,7 @@
}
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-enum.rs:32:1
+ --> $DIR/ub-enum.rs:33:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_PTR` failed here
@@ -19,7 +19,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-enum.rs:35:1
+ --> $DIR/ub-enum.rs:36:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_WRAPPED` failed here
@@ -28,7 +28,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x0, but expected a valid enum tag
- --> $DIR/ub-enum.rs:47:1
+ --> $DIR/ub-enum.rs:48:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -39,7 +39,7 @@
}
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-enum.rs:49:1
+ --> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_PTR` failed here
@@ -48,7 +48,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-enum.rs:52:1
+ --> $DIR/ub-enum.rs:53:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_WRAPPED` failed here
@@ -56,14 +56,18 @@
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/ub-enum.rs:61:41
+error[E0080]: reading memory at ALLOC0[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
+ --> $DIR/ub-enum.rs:62:41
|
LL | const BAD_ENUM2_UNDEF: Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_UNDEF` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-enum.rs:65:1
+ --> $DIR/ub-enum.rs:66:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_OPTION_PTR` failed here
@@ -72,7 +76,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
- --> $DIR/ub-enum.rs:82:1
+ --> $DIR/ub-enum.rs:83:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -83,7 +87,7 @@
}
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
- --> $DIR/ub-enum.rs:84:1
+ --> $DIR/ub-enum.rs:85:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -94,7 +98,7 @@
}
error[E0080]: constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
- --> $DIR/ub-enum.rs:92:1
+ --> $DIR/ub-enum.rs:93:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -105,19 +109,19 @@
}
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
- --> $DIR/ub-enum.rs:97:77
+ --> $DIR/ub-enum.rs:98:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_WITH_DATA1` failed here
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
- --> $DIR/ub-enum.rs:99:77
+ --> $DIR/ub-enum.rs:100:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_WITH_DATA2` failed here
error[E0080]: read discriminant of an uninhabited enum variant
- --> $DIR/ub-enum.rs:105:9
+ --> $DIR/ub-enum.rs:106:9
|
LL | std::mem::discriminant(&*(&() as *const () as *const Never));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `TEST_ICE_89765` failed inside this call
diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr
index 314141e..19ae66c 100644
--- a/tests/ui/consts/const-eval/ub-nonnull.stderr
+++ b/tests/ui/consts/const-eval/ub-nonnull.stderr
@@ -37,11 +37,15 @@
HEX_DUMP
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
--> $DIR/ub-nonnull.rs:36:38
|
LL | const UNINIT: NonZero<u8> = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ __ │ ░
+ }
error[E0080]: constructing invalid value: encountered 42, but expected something in the range 10..=30
--> $DIR/ub-nonnull.rs:44:1
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs
index 64b4893..d8e5102 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs
@@ -1,8 +1,9 @@
// ignore-tidy-linelength
// Strip out raw byte dumps to make comparison platform-independent:
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
-//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
+//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
//@ dont-require-annotations: NOTE
+//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
#![allow(invalid_value)]
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index d5ccc39..451ebb6 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -1,5 +1,5 @@
error[E0080]: constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
- --> $DIR/ub-ref-ptr.rs:17:1
+ --> $DIR/ub-ref-ptr.rs:18:1
|
LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
| ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -10,7 +10,7 @@
}
error[E0080]: constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
- --> $DIR/ub-ref-ptr.rs:20:1
+ --> $DIR/ub-ref-ptr.rs:21:1
|
LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -21,7 +21,7 @@
}
error[E0080]: constructing invalid value: encountered a null reference
- --> $DIR/ub-ref-ptr.rs:23:1
+ --> $DIR/ub-ref-ptr.rs:24:1
|
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -32,7 +32,7 @@
}
error[E0080]: constructing invalid value: encountered a null box
- --> $DIR/ub-ref-ptr.rs:26:1
+ --> $DIR/ub-ref-ptr.rs:27:1
|
LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -43,7 +43,7 @@
}
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-ref-ptr.rs:33:1
+ --> $DIR/ub-ref-ptr.rs:34:1
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `REF_AS_USIZE` failed here
@@ -52,7 +52,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-ref-ptr.rs:36:39
+ --> $DIR/ub-ref-ptr.rs:37:39
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `REF_AS_USIZE_SLICE` failed here
@@ -61,13 +61,13 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
note: erroneous constant encountered
- --> $DIR/ub-ref-ptr.rs:36:38
+ --> $DIR/ub-ref-ptr.rs:37:38
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-ref-ptr.rs:39:86
+ --> $DIR/ub-ref-ptr.rs:40:86
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `REF_AS_USIZE_BOX_SLICE` failed here
@@ -76,13 +76,13 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
note: erroneous constant encountered
- --> $DIR/ub-ref-ptr.rs:39:85
+ --> $DIR/ub-ref-ptr.rs:40:85
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
| ^^^^^^^^^^^^^^^^^^^^^
error[E0080]: constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
- --> $DIR/ub-ref-ptr.rs:42:1
+ --> $DIR/ub-ref-ptr.rs:43:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -93,7 +93,7 @@
}
error[E0080]: constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
- --> $DIR/ub-ref-ptr.rs:45:1
+ --> $DIR/ub-ref-ptr.rs:46:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -103,14 +103,18 @@
HEX_DUMP
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/ub-ref-ptr.rs:48:41
+error[E0080]: reading memory at ALLOC3[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
+ --> $DIR/ub-ref-ptr.rs:49:41
|
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_PTR` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error[E0080]: constructing invalid value: encountered null pointer, but expected a function pointer
- --> $DIR/ub-ref-ptr.rs:51:1
+ --> $DIR/ub-ref-ptr.rs:52:1
|
LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -120,14 +124,18 @@
HEX_DUMP
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/ub-ref-ptr.rs:53:38
+error[E0080]: reading memory at ALLOC4[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
+ --> $DIR/ub-ref-ptr.rs:54:38
|
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_FN_PTR` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error[E0080]: constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
- --> $DIR/ub-ref-ptr.rs:55:1
+ --> $DIR/ub-ref-ptr.rs:56:1
|
LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -138,7 +146,7 @@
}
error[E0080]: constructing invalid value: encountered ALLOC2<imm>, but expected a function pointer
- --> $DIR/ub-ref-ptr.rs:57:1
+ --> $DIR/ub-ref-ptr.rs:58:1
|
LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
| ^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -149,7 +157,7 @@
}
error[E0080]: accessing memory based on pointer with alignment 1, but alignment 4 is required
- --> $DIR/ub-ref-ptr.rs:64:5
+ --> $DIR/ub-ref-ptr.rs:65:5
|
LL | ptr.read();
| ^^^^^^^^^^ evaluation of `UNALIGNED_READ` failed here
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs
index 8623589..0bbb104 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs
@@ -6,9 +6,10 @@
// Strip out raw byte dumps to make comparison platform-independent:
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
-//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
+//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
//@ normalize-stderr: "offset \d+" -> "offset N"
//@ normalize-stderr: "size \d+" -> "size N"
+//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
//@ dont-require-annotations: NOTE
/// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error
@@ -61,7 +62,7 @@ impl Trait for bool {}
const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) };
// bad slice: length uninit
const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
-//~^ ERROR uninitialized
+ //~^ ERROR uninitialized
let uninit_len = MaybeUninit::<usize> { uninit: () };
mem::transmute((42, uninit_len))
};
@@ -99,7 +100,7 @@ impl Trait for bool {}
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw
const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::MAX)) }; // ok because raw
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
-//~^ ERROR uninitialized
+ //~^ ERROR uninitialized
let uninit_len = MaybeUninit::<usize> { uninit: () };
mem::transmute((42, uninit_len))
};
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
index 8724dd9..ab15ba8 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -1,5 +1,5 @@
error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
- --> $DIR/ub-wide-ptr.rs:39:1
+ --> $DIR/ub-wide-ptr.rs:40:1
|
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -10,7 +10,7 @@
}
error[E0080]: constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
- --> $DIR/ub-wide-ptr.rs:41:1
+ --> $DIR/ub-wide-ptr.rs:42:1
|
LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -21,7 +21,7 @@
}
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-wide-ptr.rs:44:1
+ --> $DIR/ub-wide-ptr.rs:45:1
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `STR_LENGTH_PTR` failed here
@@ -30,7 +30,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-wide-ptr.rs:47:1
+ --> $DIR/ub-wide-ptr.rs:48:1
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `MY_STR_LENGTH_PTR` failed here
@@ -39,7 +39,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
- --> $DIR/ub-wide-ptr.rs:49:1
+ --> $DIR/ub-wide-ptr.rs:50:1
|
LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -50,7 +50,7 @@
}
error[E0080]: constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
- --> $DIR/ub-wide-ptr.rs:53:1
+ --> $DIR/ub-wide-ptr.rs:54:1
|
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -61,7 +61,7 @@
}
error[E0080]: constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
- --> $DIR/ub-wide-ptr.rs:56:1
+ --> $DIR/ub-wide-ptr.rs:57:1
|
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -71,14 +71,18 @@
HEX_DUMP
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/ub-wide-ptr.rs:63:1
+error[E0080]: reading memory at ALLOC32[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
+ --> $DIR/ub-wide-ptr.rs:64:1
|
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SLICE_LENGTH_UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
- --> $DIR/ub-wide-ptr.rs:69:1
+ --> $DIR/ub-wide-ptr.rs:70:1
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -89,7 +93,7 @@
}
error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
- --> $DIR/ub-wide-ptr.rs:72:1
+ --> $DIR/ub-wide-ptr.rs:73:1
|
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -100,7 +104,7 @@
}
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-wide-ptr.rs:75:1
+ --> $DIR/ub-wide-ptr.rs:76:1
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SLICE_LENGTH_PTR` failed here
@@ -109,7 +113,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
- --> $DIR/ub-wide-ptr.rs:78:1
+ --> $DIR/ub-wide-ptr.rs:79:1
|
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -120,7 +124,7 @@
}
error[E0080]: unable to turn pointer into integer
- --> $DIR/ub-wide-ptr.rs:81:1
+ --> $DIR/ub-wide-ptr.rs:82:1
|
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SLICE_LENGTH_PTR_BOX` failed here
@@ -129,7 +133,7 @@
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
- --> $DIR/ub-wide-ptr.rs:85:1
+ --> $DIR/ub-wide-ptr.rs:86:1
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -140,13 +144,13 @@
}
note: erroneous constant encountered
- --> $DIR/ub-wide-ptr.rs:85:40
+ --> $DIR/ub-wide-ptr.rs:86:40
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
- --> $DIR/ub-wide-ptr.rs:91:1
+ --> $DIR/ub-wide-ptr.rs:92:1
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -157,13 +161,13 @@
}
note: erroneous constant encountered
- --> $DIR/ub-wide-ptr.rs:91:42
+ --> $DIR/ub-wide-ptr.rs:92:42
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
- --> $DIR/ub-wide-ptr.rs:94:1
+ --> $DIR/ub-wide-ptr.rs:95:1
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -174,19 +178,23 @@
}
note: erroneous constant encountered
- --> $DIR/ub-wide-ptr.rs:94:42
+ --> $DIR/ub-wide-ptr.rs:95:42
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/ub-wide-ptr.rs:101:1
+error[E0080]: reading memory at ALLOC33[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
+ --> $DIR/ub-wide-ptr.rs:102:1
|
LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_SLICE_LENGTH_UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error[E0080]: constructing invalid value at .0: encountered ALLOC12<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:109:1
+ --> $DIR/ub-wide-ptr.rs:110:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -197,7 +205,7 @@
}
error[E0080]: constructing invalid value at .0: encountered ALLOC14<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:112:1
+ --> $DIR/ub-wide-ptr.rs:113:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -208,7 +216,7 @@
}
error[E0080]: constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:115:1
+ --> $DIR/ub-wide-ptr.rs:116:1
|
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -219,7 +227,7 @@
}
error[E0080]: constructing invalid value: encountered ALLOC17<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:117:1
+ --> $DIR/ub-wide-ptr.rs:118:1
|
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -230,7 +238,7 @@
}
error[E0080]: constructing invalid value: encountered ALLOC19<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:119:1
+ --> $DIR/ub-wide-ptr.rs:120:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -241,7 +249,7 @@
}
error[E0080]: constructing invalid value: encountered ALLOC21<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:121:1
+ --> $DIR/ub-wide-ptr.rs:122:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -252,7 +260,7 @@
}
error[E0080]: constructing invalid value at .0: encountered ALLOC23<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:123:1
+ --> $DIR/ub-wide-ptr.rs:124:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -263,7 +271,7 @@
}
error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
- --> $DIR/ub-wide-ptr.rs:127:1
+ --> $DIR/ub-wide-ptr.rs:128:1
|
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -274,7 +282,7 @@
}
error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:131:1
+ --> $DIR/ub-wide-ptr.rs:132:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -285,7 +293,7 @@
}
error[E0080]: constructing invalid value: encountered ALLOC28<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:133:1
+ --> $DIR/ub-wide-ptr.rs:134:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -296,7 +304,7 @@
}
error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:140:1
+ --> $DIR/ub-wide-ptr.rs:141:1
|
LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
@@ -307,7 +315,7 @@
}
error[E0080]: constructing invalid value: encountered ALLOC31<imm>, but expected a vtable pointer
- --> $DIR/ub-wide-ptr.rs:144:1
+ --> $DIR/ub-wide-ptr.rs:145:1
|
LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
diff --git a/tests/ui/consts/const-eval/union-const-eval-field.rs b/tests/ui/consts/const-eval/union-const-eval-field.rs
index 0ad94ee..719e59b 100644
--- a/tests/ui/consts/const-eval/union-const-eval-field.rs
+++ b/tests/ui/consts/const-eval/union-const-eval-field.rs
@@ -1,4 +1,5 @@
//@ dont-require-annotations: NOTE
+//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
type Field1 = i32;
type Field2 = f32;
diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr
index 07ff4c3..1843ce2 100644
--- a/tests/ui/consts/const-eval/union-const-eval-field.stderr
+++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr
@@ -1,17 +1,21 @@
-error[E0080]: using uninitialized data, but this operation requires initialized memory
- --> $DIR/union-const-eval-field.rs:28:37
+error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
+ --> $DIR/union-const-eval-field.rs:29:37
|
LL | const FIELD3: Field3 = unsafe { UNION.field3 };
| ^^^^^^^^^^^^ evaluation of `read_field3::FIELD3` failed here
+ |
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ 00 00 80 3f __ __ __ __ │ ...?░░░░
+ }
note: erroneous constant encountered
- --> $DIR/union-const-eval-field.rs:30:5
+ --> $DIR/union-const-eval-field.rs:31:5
|
LL | FIELD3
| ^^^^^^
note: erroneous constant encountered
- --> $DIR/union-const-eval-field.rs:30:5
+ --> $DIR/union-const-eval-field.rs:31:5
|
LL | FIELD3
| ^^^^^^
diff --git a/tests/ui/consts/const-eval/union-ice.stderr b/tests/ui/consts/const-eval/union-ice.stderr
index b00fcc9..0506be6 100644
--- a/tests/ui/consts/const-eval/union-ice.stderr
+++ b/tests/ui/consts/const-eval/union-ice.stderr
@@ -1,20 +1,32 @@
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
--> $DIR/union-ice.rs:14:33
|
LL | const FIELD3: Field3 = unsafe { UNION.field3 };
| ^^^^^^^^^^^^ evaluation of `FIELD3` failed here
+ |
+ = note: the raw bytes of the constant (size: 8, align: 8) {
+ 00 00 80 3f __ __ __ __ │ ...?░░░░
+ }
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC1[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
--> $DIR/union-ice.rs:19:17
|
LL | b: unsafe { UNION.field3 },
| ^^^^^^^^^^^^ evaluation of `FIELD_PATH` failed here
+ |
+ = note: the raw bytes of the constant (size: 8, align: 8) {
+ 00 00 80 3f __ __ __ __ │ ...?░░░░
+ }
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC2[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
--> $DIR/union-ice.rs:31:18
|
LL | unsafe { UNION.field3 },
| ^^^^^^^^^^^^ evaluation of `FIELD_PATH2` failed here
+ |
+ = note: the raw bytes of the constant (size: 8, align: 8) {
+ 00 00 80 3f __ __ __ __ │ ...?░░░░
+ }
error: aborting due to 3 previous errors
diff --git a/tests/ui/consts/const-eval/union-ub.32bit.stderr b/tests/ui/consts/const-eval/union-ub.32bit.stderr
index 9f06979..757bcea 100644
--- a/tests/ui/consts/const-eval/union-ub.32bit.stderr
+++ b/tests/ui/consts/const-eval/union-ub.32bit.stderr
@@ -9,11 +9,15 @@
2a │ *
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
--> $DIR/union-ub.rs:35:36
|
LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_BOOL` failed here
+ |
+ = note: the raw bytes of the constant (size: 1, align: 1) {
+ __ │ ░
+ }
error: aborting due to 2 previous errors
diff --git a/tests/ui/consts/const-eval/union-ub.64bit.stderr b/tests/ui/consts/const-eval/union-ub.64bit.stderr
index 9f06979..757bcea 100644
--- a/tests/ui/consts/const-eval/union-ub.64bit.stderr
+++ b/tests/ui/consts/const-eval/union-ub.64bit.stderr
@@ -9,11 +9,15 @@
2a │ *
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
--> $DIR/union-ub.rs:35:36
|
LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_BOOL` failed here
+ |
+ = note: the raw bytes of the constant (size: 1, align: 1) {
+ __ │ ░
+ }
error: aborting due to 2 previous errors
diff --git a/tests/ui/consts/rustc-const-stability-require-const.stderr b/tests/ui/consts/rustc-const-stability-require-const.stderr
index 4b13826..8d10bdd 100644
--- a/tests/ui/consts/rustc-const-stability-require-const.stderr
+++ b/tests/ui/consts/rustc-const-stability-require-const.stderr
@@ -23,30 +23,6 @@
| ^^^^^^^^^^^^
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
- --> $DIR/rustc-const-stability-require-const.rs:21:5
- |
-LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: make the function or method const
- --> $DIR/rustc-const-stability-require-const.rs:21:5
- |
-LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
- --> $DIR/rustc-const-stability-require-const.rs:26:5
- |
-LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: make the function or method const
- --> $DIR/rustc-const-stability-require-const.rs:26:5
- |
-LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
--> $DIR/rustc-const-stability-require-const.rs:32:1
|
LL | pub extern "C" fn bar_c() {}
@@ -86,5 +62,29 @@
LL | pub const fn barfoo_unstable() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:21:5
+ |
+LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:21:5
+ |
+LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:26:5
+ |
+LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:26:5
+ |
+LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
error: aborting due to 8 previous errors
diff --git a/tests/ui/contracts/contract-attributes-generics.rs b/tests/ui/contracts/contract-attributes-generics.rs
index fd79c6a..3763ce1 100644
--- a/tests/ui/contracts/contract-attributes-generics.rs
+++ b/tests/ui/contracts/contract-attributes-generics.rs
@@ -5,9 +5,9 @@
//@ [unchk_pass] run-pass
//@ [chk_pass] run-pass
//
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
-//@ [chk_const_fail] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
+//@ [chk_const_fail] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//
diff --git a/tests/ui/contracts/contract-attributes-nest.rs b/tests/ui/contracts/contract-attributes-nest.rs
index e1e61b8..d367687 100644
--- a/tests/ui/contracts/contract-attributes-nest.rs
+++ b/tests/ui/contracts/contract-attributes-nest.rs
@@ -5,8 +5,8 @@
//@ [unchk_fail_post] run-pass
//@ [chk_pass] run-pass
//
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/contract-attributes-tail.rs b/tests/ui/contracts/contract-attributes-tail.rs
index ce4a6be..43edfe5 100644
--- a/tests/ui/contracts/contract-attributes-tail.rs
+++ b/tests/ui/contracts/contract-attributes-tail.rs
@@ -5,8 +5,8 @@
//@ [unchk_fail_post] run-pass
//@ [chk_pass] run-pass
//
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/contract-captures-via-closure-copy.rs b/tests/ui/contracts/contract-captures-via-closure-copy.rs
index 32c6d2b..bc7e5b9 100644
--- a/tests/ui/contracts/contract-captures-via-closure-copy.rs
+++ b/tests/ui/contracts/contract-captures-via-closure-copy.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Zcontract-checks=yes
#![feature(contracts)]
diff --git a/tests/ui/contracts/contract-const-fn.rs b/tests/ui/contracts/contract-const-fn.rs
index 733a06a..fe8dd37 100644
--- a/tests/ui/contracts/contract-const-fn.rs
+++ b/tests/ui/contracts/contract-const-fn.rs
@@ -8,8 +8,8 @@
//
//@ [all_pass] run-pass
//
-//@ [runtime_fail_pre] run-fail
-//@ [runtime_fail_post] run-fail
+//@ [runtime_fail_pre] run-crash
+//@ [runtime_fail_post] run-crash
//
//@ [all_pass] compile-flags: -Zcontract-checks=yes
//@ [runtime_fail_pre] compile-flags: -Zcontract-checks=yes
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.rs b/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
index 034cead..44ae07d 100644
--- a/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
@@ -2,9 +2,9 @@
//
//@ [unchk_pass] run-pass
//@ [chk_pass] run-pass
-//@ [chk_fail_try] run-fail
-//@ [chk_fail_ret] run-fail
-//@ [chk_fail_yeet] run-fail
+//@ [chk_fail_try] run-crash
+//@ [chk_fail_ret] run-crash
+//@ [chk_fail_yeet] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [chk_pass] compile-flags: -Zcontract-checks=yes
diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
index 6d8cd39..4da0480 100644
--- a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
+++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
@@ -5,8 +5,8 @@
//@ [unchk_fail_post] run-pass
//@ [chk_pass] run-pass
//
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
index 07ec26f..f3cf5ce 100644
--- a/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
+++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
@@ -5,8 +5,8 @@
//@ [unchk_fail_post] run-pass
//@ [chk_pass] run-pass
//
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
index c62b8cc..6e613b5 100644
--- a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
+++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
@@ -3,8 +3,8 @@
//@ [default] run-pass
//@ [unchk_pass] run-pass
//@ [chk_pass] run-pass
-//@ [chk_fail_requires] run-fail
-//@ [chk_fail_ensures] run-fail
+//@ [chk_fail_requires] run-crash
+//@ [chk_fail_ensures] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [chk_pass] compile-flags: -Zcontract-checks=yes
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
index 73c5919..ac72d23 100644
--- a/tests/ui/contracts/internal_machinery/contract-lang-items.rs
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
@@ -4,7 +4,7 @@
//@ [unchk_fail_post] run-pass
//@ [chk_pass] run-pass
//
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_post] run-crash
//
//@ [unchk_pass] compile-flags: -Zcontract-checks=no
//@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/extern/extern-types-field-offset.rs b/tests/ui/extern/extern-types-field-offset.rs
index 75f3eab..035f063 100644
--- a/tests/ui/extern/extern-types-field-offset.rs
+++ b/tests/ui/extern/extern-types-field-offset.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ check-run-results
//@ exec-env:RUST_BACKTRACE=0
//@ normalize-stderr: "(core/src/panicking\.rs):[0-9]+:[0-9]+" -> "$1:$$LINE:$$COL"
diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
index 6a83274..9c727ae 100644
--- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
+++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
@@ -2,23 +2,13 @@
trait Trait1 {}
auto trait Trait2 {}
-trait Trait3: ?Trait1 {}
-//~^ ERROR `?Trait` is not permitted in supertraits
-trait Trait4 where Self: ?Trait1 {}
-//~^ ERROR ?Trait` bounds are only permitted at the point where a type parameter is declared
+trait Trait3: ?Trait1 {} //~ ERROR relaxed bounds are not permitted in supertrait bounds
+trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitted here
fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
-//~^ ERROR `?Trait` is not permitted in trait object types
+//~^ ERROR relaxed bounds are not permitted in trait object types
fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-
-trait Trait {}
-// Do not suggest `#![feature(more_maybe_bounds)]` for repetitions
-fn baz<T: ?Trait + ?Trait>(_ : T) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
+//~| ERROR bound modifier `?` can only be applied to `Sized`
fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
index 729df4e..da6ad5f 100644
--- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
@@ -1,71 +1,34 @@
-error[E0658]: `?Trait` is not permitted in supertraits
+error: relaxed bounds are not permitted in supertrait bounds
--> $DIR/feature-gate-more-maybe-bounds.rs:5:15
|
LL | trait Trait3: ?Trait1 {}
| ^^^^^^^
- |
- = note: traits are `?Trait1` by default
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/feature-gate-more-maybe-bounds.rs:10:28
- |
-LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
- | ^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/feature-gate-more-maybe-bounds.rs:7:26
+error: this relaxed bound is not permitted here
+ --> $DIR/feature-gate-more-maybe-bounds.rs:6:26
|
LL | trait Trait4 where Self: ?Trait1 {}
| ^^^^^^^
|
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/feature-gate-more-maybe-bounds.rs:12:11
+error: relaxed bounds are not permitted in trait object types
+ --> $DIR/feature-gate-more-maybe-bounds.rs:8:28
|
-LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
- | ^^^^^^^ ^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
+ | ^^^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/feature-gate-more-maybe-bounds.rs:12:11
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/feature-gate-more-maybe-bounds.rs:10:11
|
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
| ^^^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/feature-gate-more-maybe-bounds.rs:12:21
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/feature-gate-more-maybe-bounds.rs:10:21
|
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
| ^^^^^^^
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/feature-gate-more-maybe-bounds.rs:19:11
- |
-LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
- | ^^^^^^ ^^^^^^
+error: aborting due to 5 previous errors
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/feature-gate-more-maybe-bounds.rs:19:11
- |
-LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
- | ^^^^^^
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/feature-gate-more-maybe-bounds.rs:19:20
- |
-LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
- | ^^^^^^
-
-error: aborting due to 9 previous errors
-
-Some errors have detailed explanations: E0203, E0658.
-For more information about an error, try `rustc --explain E0203`.
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index d07201e..9740eaa 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -269,7 +269,13 @@ mod inner { #![automatically_derived] }
#[automatically_derived] type T = S;
//~^ WARN `#[automatically_derived]
+ #[automatically_derived] trait W { }
+ //~^ WARN `#[automatically_derived]
+
#[automatically_derived] impl S { }
+ //~^ WARN `#[automatically_derived]
+
+ #[automatically_derived] impl W for S { }
}
#[no_mangle]
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 5d7d1ca..9016ca1 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,5 +1,5 @@
warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:17
|
LL | mod inner { #![macro_escape] }
| ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@
= help: try an outer attribute: `#[macro_use]`
warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:388:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:394:1
|
LL | #[macro_escape]
| ^^^^^^^^^^^^^^^
@@ -198,14 +198,14 @@
LL | #![warn(unused_attributes, unknown_lints)]
| ^^^^^^^^^^^^^^^^^
-warning: `#[automatically_derived]` only has an effect on implementation blocks
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:1
|
LL | #[automatically_derived]
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1
|
LL | #[no_mangle]
| ^^^^^^^^^^^^
@@ -220,31 +220,31 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[should_panic]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:315:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:321:1
|
LL | #[should_panic]
| ^^^^^^^^^^^^^^^
warning: `#[ignore]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:1
|
LL | #[ignore]
| ^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:1
|
LL | #[reexport_test_harness_main = "2900"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:1
|
LL | #[no_std]
| ^^^^^^^^^
warning: attribute should be applied to a function definition
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:1
|
LL | #[cold]
| ^^^^^^^
@@ -260,7 +260,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:1
|
LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -276,7 +276,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:1
|
LL | #[link_section = "1800"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -292,7 +292,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:1
|
LL | #[link()]
| ^^^^^^^^^
@@ -308,55 +308,55 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[must_use]` has no effect when applied to a module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:595:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:601:1
|
LL | #[must_use]
| ^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:608:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:1
|
LL | #[windows_subsystem = "windows"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:1
|
LL | #[crate_name = "0900"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:1
|
LL | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:1
|
LL | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1
|
LL | #[no_main]
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1
|
LL | #[no_builtins]
| ^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:1
|
LL | #[recursion_limit="0200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:1
|
LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -417,6 +417,14 @@
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:85:12
+ |
+LL | #![feature(rust1)]
+ | ^^^^^
+ |
+ = note: `#[warn(stable_features)]` on by default
+
warning: `#[macro_use]` only has an effect on `extern crate` and modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:5
|
@@ -495,32 +503,44 @@
LL | #[path = "3800"] impl S { }
| ^^^^^^^^^^^^^^^^
-warning: `#[automatically_derived]` only has an effect on implementation blocks
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:17
|
LL | mod inner { #![automatically_derived] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: `#[automatically_derived]` only has an effect on implementation blocks
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5
|
LL | #[automatically_derived] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
-warning: `#[automatically_derived]` only has an effect on implementation blocks
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:5
|
LL | #[automatically_derived] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
-warning: `#[automatically_derived]` only has an effect on implementation blocks
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:5
|
LL | #[automatically_derived] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:272:5
+ |
+LL | #[automatically_derived] trait W { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: `#[automatically_derived]` only has an effect on trait implementation blocks
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:5
+ |
+LL | #[automatically_derived] impl S { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:286:17
|
LL | mod inner { #![no_mangle] }
| ------------^^^^^^^^^^^^^-- not a free function, impl method or static
@@ -528,7 +548,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:287:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:293:5
|
LL | #[no_mangle] struct S;
| ^^^^^^^^^^^^ --------- not a free function, impl method or static
@@ -536,7 +556,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:298:5
|
LL | #[no_mangle] type T = S;
| ^^^^^^^^^^^^ ----------- not a free function, impl method or static
@@ -544,7 +564,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:297:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:303:5
|
LL | #[no_mangle] impl S { }
| ^^^^^^^^^^^^ ---------- not a free function, impl method or static
@@ -552,7 +572,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:303:9
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:309:9
|
LL | #[no_mangle] fn foo();
| ^^^^^^^^^^^^ --------- not a free function, impl method or static
@@ -560,7 +580,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a free function, impl method or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:308:9
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:314:9
|
LL | #[no_mangle] fn bar() {}
| ^^^^^^^^^^^^ ----------- not a free function, impl method or static
@@ -568,163 +588,163 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[should_panic]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:17
|
LL | mod inner { #![should_panic] }
| ^^^^^^^^^^^^^^^^
warning: `#[should_panic]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:5
|
LL | #[should_panic] struct S;
| ^^^^^^^^^^^^^^^
warning: `#[should_panic]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:326:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5
|
LL | #[should_panic] type T = S;
| ^^^^^^^^^^^^^^^
warning: `#[should_panic]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5
|
LL | #[should_panic] impl S { }
| ^^^^^^^^^^^^^^^
warning: `#[ignore]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:17
|
LL | mod inner { #![ignore] }
| ^^^^^^^^^^
warning: `#[ignore]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5
|
LL | #[ignore] struct S;
| ^^^^^^^^^
warning: `#[ignore]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5
|
LL | #[ignore] type T = S;
| ^^^^^^^^^
warning: `#[ignore]` only has an effect on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:5
|
LL | #[ignore] impl S { }
| ^^^^^^^^^
warning: `#[no_implicit_prelude]` only has an effect on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
|
LL | #[no_implicit_prelude] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: `#[no_implicit_prelude]` only has an effect on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5
|
LL | #[no_implicit_prelude] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: `#[no_implicit_prelude]` only has an effect on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5
|
LL | #[no_implicit_prelude] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: `#[no_implicit_prelude]` only has an effect on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5
|
LL | #[no_implicit_prelude] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:17
|
LL | mod inner { #![reexport_test_harness_main="2900"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
|
LL | #[reexport_test_harness_main = "2900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5
|
LL | #[reexport_test_harness_main = "2900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5
|
LL | #[reexport_test_harness_main = "2900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5
|
LL | #[reexport_test_harness_main = "2900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[macro_escape]` only has an effect on `extern crate` and modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5
|
LL | #[macro_escape] fn f() { }
| ^^^^^^^^^^^^^^^
warning: `#[macro_escape]` only has an effect on `extern crate` and modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5
|
LL | #[macro_escape] struct S;
| ^^^^^^^^^^^^^^^
warning: `#[macro_escape]` only has an effect on `extern crate` and modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:5
|
LL | #[macro_escape] type T = S;
| ^^^^^^^^^^^^^^^
warning: `#[macro_escape]` only has an effect on `extern crate` and modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5
|
LL | #[macro_escape] impl S { }
| ^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:17
|
LL | mod inner { #![no_std] }
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:5
|
LL | #[no_std] fn f() { }
| ^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
|
LL | #[no_std] struct S;
| ^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5
|
LL | #[no_std] type T = S;
| ^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
|
LL | #[no_std] impl S { }
| ^^^^^^^^^
warning: attribute should be applied to a function definition
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:456:17
|
LL | mod inner { #![cold] }
| ------------^^^^^^^^-- not a function definition
@@ -732,7 +752,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function definition
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:5
|
LL | #[cold] struct S;
| ^^^^^^^ --------- not a function definition
@@ -740,7 +760,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function definition
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:468:5
|
LL | #[cold] type T = S;
| ^^^^^^^ ----------- not a function definition
@@ -748,7 +768,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function definition
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:5
|
LL | #[cold] impl S { }
| ^^^^^^^ ---------- not a function definition
@@ -756,7 +776,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:5
|
LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -766,13 +786,13 @@
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
help: try `#[link(name = "1900")]` instead
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:5
|
LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:17
|
LL | mod inner { #![link_name="1900"] }
| ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static
@@ -780,7 +800,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:491:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:497:5
|
LL | #[link_name = "1900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
@@ -788,7 +808,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
|
LL | #[link_name = "1900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static
@@ -796,7 +816,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:5
|
LL | #[link_name = "1900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static
@@ -804,7 +824,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:5
|
LL | #[link_name = "1900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
@@ -812,7 +832,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:17
|
LL | mod inner { #![link_section="1800"] }
| ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static
@@ -820,7 +840,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:531:5
|
LL | #[link_section = "1800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static
@@ -828,7 +848,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:530:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:5
|
LL | #[link_section = "1800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static
@@ -836,7 +856,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function or static
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
|
LL | #[link_section = "1800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
@@ -844,7 +864,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:17
|
LL | mod inner { #![link()] }
| ------------^^^^^^^^^^-- not an `extern` block
@@ -852,7 +872,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:561:5
|
LL | #[link()] fn f() { }
| ^^^^^^^^^ ---------- not an `extern` block
@@ -860,7 +880,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:560:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:566:5
|
LL | #[link()] struct S;
| ^^^^^^^^^ --------- not an `extern` block
@@ -868,7 +888,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:565:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
|
LL | #[link()] type T = S;
| ^^^^^^^^^ ----------- not an `extern` block
@@ -876,7 +896,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:570:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:576:5
|
LL | #[link()] impl S { }
| ^^^^^^^^^ ---------- not an `extern` block
@@ -884,7 +904,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:575:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:5
|
LL | #[link()] extern "Rust" {}
| ^^^^^^^^^
@@ -892,270 +912,262 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[must_use]` has no effect when applied to a module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:597:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:603:17
|
LL | mod inner { #![must_use] }
| ^^^^^^^^^^^^
warning: `#[must_use]` has no effect when applied to a type alias
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:603:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:609:5
|
LL | #[must_use] type T = S;
| ^^^^^^^^^^^
-warning: `#[must_use]` has no effect when applied to an implementation block
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:5
+warning: `#[must_use]` has no effect when applied to an inherent implementation block
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
|
LL | #[must_use] impl S { }
| ^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:17
|
LL | mod inner { #![windows_subsystem="windows"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:5
|
LL | #[windows_subsystem = "windows"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5
|
LL | #[windows_subsystem = "windows"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5
|
LL | #[windows_subsystem = "windows"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:5
|
LL | #[windows_subsystem = "windows"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:632:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17
|
LL | mod inner { #![crate_name="0900"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5
|
LL | #[crate_name = "0900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5
|
LL | #[crate_name = "0900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
|
LL | #[crate_name = "0900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5
|
LL | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:17
|
LL | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5
|
LL | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
|
LL | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5
|
LL | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
|
LL | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:670:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:17
|
LL | mod inner { #![feature(x0600)] }
| ^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
|
LL | #[feature(x0600)] fn f() { }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
|
LL | #[feature(x0600)] struct S;
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
|
LL | #[feature(x0600)] type T = S;
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5
|
LL | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17
|
LL | mod inner { #![no_main] }
| ^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5
|
LL | #[no_main] fn f() { }
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5
|
LL | #[no_main] struct S;
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5
|
LL | #[no_main] type T = S;
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
|
LL | #[no_main] impl S { }
| ^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:17
|
LL | mod inner { #![no_builtins] }
| ^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5
|
LL | #[no_builtins] fn f() { }
| ^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
|
LL | #[no_builtins] struct S;
| ^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5
|
LL | #[no_builtins] type T = S;
| ^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
|
LL | #[no_builtins] impl S { }
| ^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:17
|
LL | mod inner { #![recursion_limit="0200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
|
LL | #[recursion_limit="0200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
|
LL | #[recursion_limit="0200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5
|
LL | #[recursion_limit="0200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
|
LL | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:17
|
LL | mod inner { #![type_length_limit="0100"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5
|
LL | #[type_length_limit="0100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
|
LL | #[type_length_limit="0100"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
|
LL | #[type_length_limit="0100"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
|
LL | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:85:12
- |
-LL | #![feature(rust1)]
- | ^^^^^
- |
- = note: `#[warn(stable_features)]` on by default
-
-warning: 171 warnings emitted
+warning: 173 warnings emitted
diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
index 319056a..d599523 100644
--- a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
+++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
@@ -1,4 +1,18 @@
error: can't mark as unstable using an already stable feature
+ --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
+ |
+LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
+LL | const fn my_fun() {}
+ | -------------------- the stability attribute annotates this item
+ |
+help: consider removing the attribute
+ --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
+ |
+LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: can't mark as unstable using an already stable feature
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
|
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
@@ -13,19 +27,5 @@
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: can't mark as unstable using an already stable feature
- --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
- |
-LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
-LL | const fn my_fun() {}
- | -------------------- the stability attribute annotates this item
- |
-help: consider removing the attribute
- --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
- |
-LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
error: aborting due to 2 previous errors
diff --git a/tests/ui/impl-trait/in-bindings/implicit-sized.rs b/tests/ui/impl-trait/in-bindings/implicit-sized.rs
new file mode 100644
index 0000000..2f16db9
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/implicit-sized.rs
@@ -0,0 +1,19 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Trait {}
+impl<T: ?Sized> Trait for T {}
+
+fn doesnt_work() {
+ let x: &impl Trait = "hi";
+ //~^ ERROR the size for values of type `str` cannot be known at compilation time
+}
+
+fn works() {
+ let x: &(impl Trait + ?Sized) = "hi";
+ // No implicit sized.
+
+ let x: &impl Trait = &();
+ // Is actually sized.
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-bindings/implicit-sized.stderr b/tests/ui/impl-trait/in-bindings/implicit-sized.stderr
new file mode 100644
index 0000000..465a928
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/implicit-sized.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/implicit-sized.rs:7:13
+ |
+LL | let x: &impl Trait = "hi";
+ | ^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs b/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs
index 27c493a..7e0e1ea 100644
--- a/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs
+++ b/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs
@@ -3,8 +3,8 @@
use std::future::Future;
fn foo() -> impl ?Future<Output = impl Send> {
- //~^ ERROR: relaxing a default bound only does something for `?Sized`
- //~| ERROR: relaxing a default bound only does something for `?Sized`
+ //~^ ERROR: bound modifier `?` can only be applied to `Sized`
+ //~| ERROR: bound modifier `?` can only be applied to `Sized`
()
}
diff --git a/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr b/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr
index dc4314c..f99d6a7 100644
--- a/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr
+++ b/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr
@@ -1,10 +1,10 @@
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/opt-out-bound-not-satisfied.rs:5:18
|
LL | fn foo() -> impl ?Future<Output = impl Send> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/opt-out-bound-not-satisfied.rs:5:18
|
LL | fn foo() -> impl ?Future<Output = impl Send> {
diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
index 10f4d8d..5f4ef14 100644
--- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
+++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
@@ -3,6 +3,10 @@
|
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_PADDING` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 2) {
+ 01 __ 02 00 │ .░..
+ }
error[E0080]: unable to turn pointer into integer
--> $DIR/intrinsic-raw_eq-const-bad.rs:9:5
diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs
index 09d60b7..63f6479 100644
--- a/tests/ui/issues/issue-37534.rs
+++ b/tests/ui/issues/issue-37534.rs
@@ -1,5 +1,5 @@
struct Foo<T: ?Hash> {}
//~^ ERROR expected trait, found derive macro `Hash`
-//~| ERROR relaxing a default bound only does something for `?Sized`
+//~| ERROR bound modifier `?` can only be applied to `Sized`
fn main() {}
diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr
index 3219854..0860735 100644
--- a/tests/ui/issues/issue-37534.stderr
+++ b/tests/ui/issues/issue-37534.stderr
@@ -9,7 +9,7 @@
LL + use std::hash::Hash;
|
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/issue-37534.rs:1:15
|
LL | struct Foo<T: ?Hash> {}
diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs
index 4e4e35c..dd9dfc7 100644
--- a/tests/ui/issues/issue-87199.rs
+++ b/tests/ui/issues/issue-87199.rs
@@ -6,12 +6,12 @@
// Check that these function definitions only emit warnings, not errors
fn arg<T: ?Send>(_: T) {}
-//~^ ERROR: relaxing a default bound only does something for `?Sized`
+//~^ ERROR: bound modifier `?` can only be applied to `Sized`
fn ref_arg<T: ?Send>(_: &T) {}
-//~^ ERROR: relaxing a default bound only does something for `?Sized`
+//~^ ERROR: bound modifier `?` can only be applied to `Sized`
fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
-//~^ ERROR: relaxing a default bound only does something for `?Sized`
-//~| ERROR: relaxing a default bound only does something for `?Sized`
+//~^ ERROR: bound modifier `?` can only be applied to `Sized`
+//~| ERROR: bound modifier `?` can only be applied to `Sized`
// Check that there's no `?Sized` relaxation!
fn main() {
diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr
index acc4e84..8a930a3 100644
--- a/tests/ui/issues/issue-87199.stderr
+++ b/tests/ui/issues/issue-87199.stderr
@@ -1,22 +1,22 @@
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/issue-87199.rs:8:11
|
LL | fn arg<T: ?Send>(_: T) {}
| ^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/issue-87199.rs:10:15
|
LL | fn ref_arg<T: ?Send>(_: &T) {}
| ^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/issue-87199.rs:12:40
|
LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
| ^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/issue-87199.rs:12:40
|
LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
index f40f06a..ee29d62 100644
--- a/tests/ui/lint/invalid_null_args.rs
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -58,10 +58,9 @@ unsafe fn null_ptr() {
let _a: A = ptr::read_unaligned(ptr::null_mut());
//~^ ERROR calling this function with a null pointer is undefined behavior
+ // These two should *not* fire the lint.
let _a: A = ptr::read_volatile(ptr::null());
- //~^ ERROR calling this function with a null pointer is undefined behavior
let _a: A = ptr::read_volatile(ptr::null_mut());
- //~^ ERROR calling this function with a null pointer is undefined behavior
let _a: A = ptr::replace(ptr::null_mut(), v);
//~^ ERROR calling this function with a null pointer is undefined behavior
@@ -82,8 +81,8 @@ unsafe fn null_ptr() {
ptr::write_unaligned(ptr::null_mut(), v);
//~^ ERROR calling this function with a null pointer is undefined behavior
+ // This one should *not* fire the lint.
ptr::write_volatile(ptr::null_mut(), v);
- //~^ ERROR calling this function with a null pointer is undefined behavior
ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
//~^ ERROR calling this function with a null pointer is undefined behavior
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
index 11c6270..028bd70 100644
--- a/tests/ui/lint/invalid_null_args.stderr
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -164,27 +164,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:61:17
- |
-LL | let _a: A = ptr::read_volatile(ptr::null());
- | ^^^^^^^^^^^^^^^^^^^-----------^
- | |
- | null pointer originates from here
- |
- = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:63:17
- |
-LL | let _a: A = ptr::read_volatile(ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^---------------^
- | |
- | null pointer originates from here
- |
- = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:66:17
+ --> $DIR/invalid_null_args.rs:65:17
|
LL | let _a: A = ptr::replace(ptr::null_mut(), v);
| ^^^^^^^^^^^^^---------------^^^^
@@ -194,7 +174,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:69:5
+ --> $DIR/invalid_null_args.rs:68:5
|
LL | ptr::swap::<A>(ptr::null_mut(), &mut v);
| ^^^^^^^^^^^^^^^---------------^^^^^^^^^
@@ -204,7 +184,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:71:5
+ --> $DIR/invalid_null_args.rs:70:5
|
LL | ptr::swap::<A>(&mut v, ptr::null_mut());
| ^^^^^^^^^^^^^^^^^^^^^^^---------------^
@@ -214,7 +194,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:74:5
+ --> $DIR/invalid_null_args.rs:73:5
|
LL | ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^
@@ -224,7 +204,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:76:5
+ --> $DIR/invalid_null_args.rs:75:5
|
LL | ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -234,7 +214,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:79:5
+ --> $DIR/invalid_null_args.rs:78:5
|
LL | ptr::write(ptr::null_mut(), v);
| ^^^^^^^^^^^---------------^^^^
@@ -244,7 +224,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:82:5
+ --> $DIR/invalid_null_args.rs:81:5
|
LL | ptr::write_unaligned(ptr::null_mut(), v);
| ^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -254,17 +234,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:85:5
- |
-LL | ptr::write_volatile(ptr::null_mut(), v);
- | ^^^^^^^^^^^^^^^^^^^^---------------^^^^
- | |
- | null pointer originates from here
- |
- = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:88:5
+ --> $DIR/invalid_null_args.rs:87:5
|
LL | ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^
@@ -274,7 +244,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:93:18
+ --> $DIR/invalid_null_args.rs:92:18
|
LL | let _a: u8 = ptr::read(const_ptr);
| ^^^^^^^^^^^^^^^^^^^^
@@ -287,7 +257,7 @@
| ^^^^^^^^^^^^^^^
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:100:5
+ --> $DIR/invalid_null_args.rs:99:5
|
LL | std::slice::from_raw_parts::<()>(ptr::null(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@@ -297,7 +267,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:102:5
+ --> $DIR/invalid_null_args.rs:101:5
|
LL | std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@@ -307,7 +277,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:104:5
+ --> $DIR/invalid_null_args.rs:103:5
|
LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -317,7 +287,7 @@
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
- --> $DIR/invalid_null_args.rs:106:5
+ --> $DIR/invalid_null_args.rs:105:5
|
LL | std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -326,5 +296,5 @@
|
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-error: aborting due to 31 previous errors
+error: aborting due to 28 previous errors
diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr
index 51205ff..0399fab 100644
--- a/tests/ui/lint/lint-stability-deprecated.stderr
+++ b/tests/ui/lint/lint-stability-deprecated.stderr
@@ -1,8 +1,8 @@
-warning: use of deprecated function `lint_stability::deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:24:9
+warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
+ --> $DIR/lint-stability-deprecated.rs:97:48
|
-LL | deprecated();
- | ^^^^^^^^^^
+LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+ | ^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-stability-deprecated.rs:6:9
@@ -10,6 +10,12 @@
LL | #![warn(deprecated)]
| ^^^^^^^^^^
+warning: use of deprecated function `lint_stability::deprecated`: text
+ --> $DIR/lint-stability-deprecated.rs:24:9
+ |
+LL | deprecated();
+ | ^^^^^^^^^^
+
warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:29:16
|
@@ -317,12 +323,6 @@
| ^^^^^^^^^^
warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
- --> $DIR/lint-stability-deprecated.rs:97:48
- |
-LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
- | ^^^^^^^^^^^^^^^^^
-
-warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
--> $DIR/lint-stability-deprecated.rs:101:13
|
LL | TypeDeprecated = u16,
diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr
index fd57908..249f3cc 100644
--- a/tests/ui/lint/lint-stability.stderr
+++ b/tests/ui/lint/lint-stability.stderr
@@ -1,4 +1,13 @@
error[E0658]: use of unstable library feature `unstable_test_feature`
+ --> $DIR/lint-stability.rs:88:48
+ |
+LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `unstable_test_feature`
--> $DIR/lint-stability.rs:17:5
|
LL | extern crate stability_cfg2;
@@ -368,15 +377,6 @@
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: use of unstable library feature `unstable_test_feature`
- --> $DIR/lint-stability.rs:88:48
- |
-LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
- | ^^^^^^^^^^^^^^^
- |
- = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature `unstable_test_feature`
--> $DIR/lint-stability.rs:92:13
|
LL | TypeUnstable = u8,
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs
index bf94a42..cfa6c2b 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.rs
+++ b/tests/ui/lint/unused/unused-attr-duplicate.rs
@@ -66,9 +66,11 @@ fn t1() {}
#[non_exhaustive] //~ ERROR unused attribute
pub struct X;
+trait Trait {}
+
#[automatically_derived]
#[automatically_derived] //~ ERROR unused attribute
-impl X {}
+impl Trait for X {}
#[inline(always)]
#[inline(never)] //~ ERROR unused attribute
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 6db6af8..ecc1b7f 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -179,112 +179,112 @@
| ^^^^^^^^^^^^^^^^^
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:70:1
+ --> $DIR/unused-attr-duplicate.rs:72:1
|
LL | #[automatically_derived]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:69:1
+ --> $DIR/unused-attr-duplicate.rs:71:1
|
LL | #[automatically_derived]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:74:1
+ --> $DIR/unused-attr-duplicate.rs:76:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:73:1
+ --> $DIR/unused-attr-duplicate.rs:75:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:77:1
+ --> $DIR/unused-attr-duplicate.rs:79:1
|
LL | #[cold]
| ^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:76:1
+ --> $DIR/unused-attr-duplicate.rs:78:1
|
LL | #[cold]
| ^^^^^^^
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:79:1
+ --> $DIR/unused-attr-duplicate.rs:81:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:78:1
+ --> $DIR/unused-attr-duplicate.rs:80:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:86:5
+ --> $DIR/unused-attr-duplicate.rs:88:5
|
LL | #[link_name = "this_does_not_exist"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:88:5
+ --> $DIR/unused-attr-duplicate.rs:90:5
|
LL | #[link_name = "rust_dbg_extern_identity_u32"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:92:1
+ --> $DIR/unused-attr-duplicate.rs:94:1
|
LL | #[export_name = "exported_symbol_name"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:94:1
+ --> $DIR/unused-attr-duplicate.rs:96:1
|
LL | #[export_name = "exported_symbol_name2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:98:1
+ --> $DIR/unused-attr-duplicate.rs:100:1
|
LL | #[no_mangle]
| ^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:97:1
+ --> $DIR/unused-attr-duplicate.rs:99:1
|
LL | #[no_mangle]
| ^^^^^^^^^^^^
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:102:1
+ --> $DIR/unused-attr-duplicate.rs:104:1
|
LL | #[used]
| ^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:101:1
+ --> $DIR/unused-attr-duplicate.rs:103:1
|
LL | #[used]
| ^^^^^^^
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:105:1
+ --> $DIR/unused-attr-duplicate.rs:107:1
|
LL | #[link_section = ".text"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:108:1
+ --> $DIR/unused-attr-duplicate.rs:110:1
|
LL | #[link_section = ".bss"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
index 28fd8ee..862ffa4 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -45,7 +45,7 @@
LL | #[must_use]
| ^^^^^^^^^^^
-error: `#[must_use]` has no effect when applied to an implementation block
+error: `#[must_use]` has no effect when applied to an inherent implementation block
--> $DIR/unused_attributes-must_use.rs:33:1
|
LL | #[must_use]
@@ -69,7 +69,7 @@
LL | fn qux<#[must_use] T>(_: T) {}
| ^^^^^^^^^^^
-error: `#[must_use]` has no effect when applied to an implementation block
+error: `#[must_use]` has no effect when applied to an trait implementation block
--> $DIR/unused_attributes-must_use.rs:79:1
|
LL | #[must_use]
diff --git a/tests/ui/lto/debuginfo-lto-alloc.rs b/tests/ui/lto/debuginfo-lto-alloc.rs
index 8904327..d6855f8 100644
--- a/tests/ui/lto/debuginfo-lto-alloc.rs
+++ b/tests/ui/lto/debuginfo-lto-alloc.rs
@@ -8,8 +8,9 @@
// This test reproduces the circumstances that caused the error to appear, and checks
// that compilation is successful.
-//@ check-pass
+//@ build-pass
//@ compile-flags: --test -C debuginfo=2 -C lto=fat
+//@ no-prefer-dynamic
//@ incremental
extern crate alloc;
diff --git a/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs b/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs
index a22965c..6ba895f 100644
--- a/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs
+++ b/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ ignore-i686-pc-windows-msvc: #112480
//@ compile-flags: -C debug-assertions
//@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_borrow.rs b/tests/ui/mir/alignment/misaligned_borrow.rs
index de8912c..60c21de 100644
--- a/tests/ui/mir/alignment/misaligned_borrow.rs
+++ b/tests/ui/mir/alignment/misaligned_borrow.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ ignore-i686-pc-windows-msvc: #112480
//@ compile-flags: -C debug-assertions
//@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_lhs.rs b/tests/ui/mir/alignment/misaligned_lhs.rs
index b169823..e8ddb10 100644
--- a/tests/ui/mir/alignment/misaligned_lhs.rs
+++ b/tests/ui/mir/alignment/misaligned_lhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ ignore-i686-pc-windows-msvc: #112480
//@ compile-flags: -C debug-assertions
//@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_mut_borrow.rs b/tests/ui/mir/alignment/misaligned_mut_borrow.rs
index bba20ed..c066cc0 100644
--- a/tests/ui/mir/alignment/misaligned_mut_borrow.rs
+++ b/tests/ui/mir/alignment/misaligned_mut_borrow.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ ignore-i686-pc-windows-msvc: #112480
//@ compile-flags: -C debug-assertions
//@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_rhs.rs b/tests/ui/mir/alignment/misaligned_rhs.rs
index 55da30a..6bdc39c 100644
--- a/tests/ui/mir/alignment/misaligned_rhs.rs
+++ b/tests/ui/mir/alignment/misaligned_rhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ ignore-i686-pc-windows-msvc: #112480
//@ compile-flags: -C debug-assertions
//@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/two_pointers.rs b/tests/ui/mir/alignment/two_pointers.rs
index 198a1c9..fd8b2f5 100644
--- a/tests/ui/mir/alignment/two_pointers.rs
+++ b/tests/ui/mir/alignment/two_pointers.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ ignore-i686-pc-windows-msvc: #112480
//@ compile-flags: -C debug-assertions
//@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/enum/convert_non_integer_break.rs b/tests/ui/mir/enum/convert_non_integer_break.rs
index 2979519..b0778e2 100644
--- a/tests/ui/mir/enum/convert_non_integer_break.rs
+++ b/tests/ui/mir/enum/convert_non_integer_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value
diff --git a/tests/ui/mir/enum/convert_non_integer_niche_break.rs b/tests/ui/mir/enum/convert_non_integer_niche_break.rs
index 9ff4849..d26a3ae 100644
--- a/tests/ui/mir/enum/convert_non_integer_niche_break.rs
+++ b/tests/ui/mir/enum/convert_non_integer_niche_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x5
diff --git a/tests/ui/mir/enum/negative_discr_break.rs b/tests/ui/mir/enum/negative_discr_break.rs
index fa1284f..35ee8aa 100644
--- a/tests/ui/mir/enum/negative_discr_break.rs
+++ b/tests/ui/mir/enum/negative_discr_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0xfd
diff --git a/tests/ui/mir/enum/niche_option_tuple_break.rs b/tests/ui/mir/enum/niche_option_tuple_break.rs
index affdc47..0a933af 100644
--- a/tests/ui/mir/enum/niche_option_tuple_break.rs
+++ b/tests/ui/mir/enum/niche_option_tuple_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value
diff --git a/tests/ui/mir/enum/numbered_variants_break.rs b/tests/ui/mir/enum/numbered_variants_break.rs
index e3e71dc..fbe7d66 100644
--- a/tests/ui/mir/enum/numbered_variants_break.rs
+++ b/tests/ui/mir/enum/numbered_variants_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x3
diff --git a/tests/ui/mir/enum/option_with_bigger_niche_break.rs b/tests/ui/mir/enum/option_with_bigger_niche_break.rs
index c66614b..675d27f 100644
--- a/tests/ui/mir/enum/option_with_bigger_niche_break.rs
+++ b/tests/ui/mir/enum/option_with_bigger_niche_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x0
diff --git a/tests/ui/mir/enum/plain_no_data_break.rs b/tests/ui/mir/enum/plain_no_data_break.rs
index db68e75..966dd64 100644
--- a/tests/ui/mir/enum/plain_no_data_break.rs
+++ b/tests/ui/mir/enum/plain_no_data_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x1
diff --git a/tests/ui/mir/enum/single_with_repr_break.rs b/tests/ui/mir/enum/single_with_repr_break.rs
index 5a4ec85..53e4932 100644
--- a/tests/ui/mir/enum/single_with_repr_break.rs
+++ b/tests/ui/mir/enum/single_with_repr_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x1
diff --git a/tests/ui/mir/enum/with_niche_int_break.rs b/tests/ui/mir/enum/with_niche_int_break.rs
index 6a97eaa..d363dc7 100644
--- a/tests/ui/mir/enum/with_niche_int_break.rs
+++ b/tests/ui/mir/enum/with_niche_int_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value
diff --git a/tests/ui/mir/enum/wrap_break.rs b/tests/ui/mir/enum/wrap_break.rs
index 4491394..5c410af 100644
--- a/tests/ui/mir/enum/wrap_break.rs
+++ b/tests/ui/mir/enum/wrap_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x0
#![feature(never_type)]
diff --git a/tests/ui/mir/null/borrowed_mut_null.rs b/tests/ui/mir/null/borrowed_mut_null.rs
index d26452b9..a4660f4 100644
--- a/tests/ui/mir/null/borrowed_mut_null.rs
+++ b/tests/ui/mir/null/borrowed_mut_null.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
diff --git a/tests/ui/mir/null/borrowed_null.rs b/tests/ui/mir/null/borrowed_null.rs
index fefac3a..2a50058 100644
--- a/tests/ui/mir/null/borrowed_null.rs
+++ b/tests/ui/mir/null/borrowed_null.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
diff --git a/tests/ui/mir/null/borrowed_null_zst.rs b/tests/ui/mir/null/borrowed_null_zst.rs
index 835727c..106fa00 100644
--- a/tests/ui/mir/null/borrowed_null_zst.rs
+++ b/tests/ui/mir/null/borrowed_null_zst.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
diff --git a/tests/ui/mir/null/null_lhs.rs b/tests/ui/mir/null/null_lhs.rs
index 238d350..b593385 100644
--- a/tests/ui/mir/null/null_lhs.rs
+++ b/tests/ui/mir/null/null_lhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
diff --git a/tests/ui/mir/null/null_rhs.rs b/tests/ui/mir/null/null_rhs.rs
index 18eafb6..18fdad7 100644
--- a/tests/ui/mir/null/null_rhs.rs
+++ b/tests/ui/mir/null/null_rhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
diff --git a/tests/ui/mir/null/two_pointers.rs b/tests/ui/mir/null/two_pointers.rs
index 52b9510..b2aa7cf 100644
--- a/tests/ui/mir/null/two_pointers.rs
+++ b/tests/ui/mir/null/two_pointers.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -C debug-assertions
//@ error-pattern: null pointer dereference occurred
diff --git a/tests/ui/missing/missing-stability.stderr b/tests/ui/missing/missing-stability.stderr
index 659f8c7..bf8046c 100644
--- a/tests/ui/missing/missing-stability.stderr
+++ b/tests/ui/missing/missing-stability.stderr
@@ -1,17 +1,14 @@
error: function has missing stability attribute
--> $DIR/missing-stability.rs:8:1
|
-LL | / pub fn unmarked() {
-LL | |
-LL | | ()
-LL | | }
- | |_^
+LL | pub fn unmarked() {
+ | ^^^^^^^^^^^^^^^^^
error: function has missing stability attribute
--> $DIR/missing-stability.rs:22:5
|
LL | pub fn unmarked() {}
- | ^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
diff --git a/tests/ui/panics/panic-in-cleanup.rs b/tests/ui/panics/panic-in-cleanup.rs
index 8cddeb3..2e307de 100644
--- a/tests/ui/panics/panic-in-cleanup.rs
+++ b/tests/ui/panics/panic-in-cleanup.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ exec-env:RUST_BACKTRACE=0
//@ check-run-results
//@ error-pattern: panic in a destructor during cleanup
diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs
index 6068e4f..b926d0f 100644
--- a/tests/ui/panics/panic-in-ffi.rs
+++ b/tests/ui/panics/panic-in-ffi.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ exec-env:RUST_BACKTRACE=0
//@ check-run-results
//@ error-pattern: panic in a function that cannot unwind
diff --git a/tests/ui/panics/panic-in-message-fmt.rs b/tests/ui/panics/panic-in-message-fmt.rs
index 1e9bbaf..4d539f1 100644
--- a/tests/ui/panics/panic-in-message-fmt.rs
+++ b/tests/ui/panics/panic-in-message-fmt.rs
@@ -1,6 +1,6 @@
// Checks what happens when formatting the panic message panics.
-//@ run-fail
+//@ run-crash
//@ exec-env:RUST_BACKTRACE=0
//@ check-run-results
//@ error-pattern: panicked while processing panic
diff --git a/tests/ui/panics/panic-main.rs b/tests/ui/panics/panic-main.rs
index bf79de7..2009f69 100644
--- a/tests/ui/panics/panic-main.rs
+++ b/tests/ui/panics/panic-main.rs
@@ -1,27 +1,37 @@
//@ revisions: default abort-zero abort-one abort-full unwind-zero unwind-one unwind-full
+//@[default] run-fail
+
//@[abort-zero] compile-flags: -Cpanic=abort
//@[abort-zero] no-prefer-dynamic
//@[abort-zero] exec-env:RUST_BACKTRACE=0
+//@[abort-zero] run-crash
//@[abort-one] compile-flags: -Cpanic=abort
//@[abort-one] no-prefer-dynamic
//@[abort-one] exec-env:RUST_BACKTRACE=1
+//@[abort-one] run-crash
//@[abort-full] compile-flags: -Cpanic=abort
//@[abort-full] no-prefer-dynamic
//@[abort-full] exec-env:RUST_BACKTRACE=full
+//@[abort-full] run-crash
//@[unwind-zero] compile-flags: -Cpanic=unwind
//@[unwind-zero] exec-env:RUST_BACKTRACE=0
+//@[unwind-zero] needs-unwind
+//@[unwind-zero] run-fail
//@[unwind-one] compile-flags: -Cpanic=unwind
//@[unwind-one] exec-env:RUST_BACKTRACE=1
+//@[unwind-one] needs-unwind
+//@[unwind-one] run-fail
//@[unwind-full] compile-flags: -Cpanic=unwind
//@[unwind-full] exec-env:RUST_BACKTRACE=full
+//@[unwind-full] needs-unwind
+//@[unwind-full] run-fail
-//@ run-fail
//@ error-pattern:moop
//@ needs-subprocess
diff --git a/tests/ui/parser/deli-ident-issue-2.rs b/tests/ui/parser/deli-ident-issue-2.rs
index 5394760..419933c 100644
--- a/tests/ui/parser/deli-ident-issue-2.rs
+++ b/tests/ui/parser/deli-ident-issue-2.rs
@@ -1,6 +1,6 @@
fn main() {
if 1 < 2 {
- let _a = vec!]; //~ ERROR mismatched closing delimiter
+ let _a = vec!];
}
} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/deli-ident-issue-2.stderr b/tests/ui/parser/deli-ident-issue-2.stderr
index e0188cd..703cbf1 100644
--- a/tests/ui/parser/deli-ident-issue-2.stderr
+++ b/tests/ui/parser/deli-ident-issue-2.stderr
@@ -1,19 +1,13 @@
-error: mismatched closing delimiter: `]`
- --> $DIR/deli-ident-issue-2.rs:2:14
- |
-LL | if 1 < 2 {
- | ^ unclosed delimiter
-LL | let _a = vec!];
- | ^ mismatched closing delimiter
-
error: unexpected closing delimiter: `}`
--> $DIR/deli-ident-issue-2.rs:5:1
|
+LL | if 1 < 2 {
+ | - the nearest open delimiter
LL | let _a = vec!];
| - missing open `[` for this delimiter
LL | }
LL | }
| ^ unexpected closing delimiter
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr
index c067d12..f01fa4a 100644
--- a/tests/ui/parser/issues/issue-104367.stderr
+++ b/tests/ui/parser/issues/issue-104367.stderr
@@ -18,7 +18,6 @@
LL | #![cfg] {
| - unclosed delimiter
LL | #![w,)
- | - missing open `(` for this delimiter
LL |
| ^
diff --git a/tests/ui/parser/issues/issue-105209.rs b/tests/ui/parser/issues/issue-105209.rs
index f4e3315..12c902e 100644
--- a/tests/ui/parser/issues/issue-105209.rs
+++ b/tests/ui/parser/issues/issue-105209.rs
@@ -1,3 +1,3 @@
//@ compile-flags: -Zunpretty=ast-tree
#![c={#![c[)x //~ ERROR mismatched closing delimiter
- //~ ERROR this file contains an unclosed delimiter
+ //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr
index 72017e4..75643d1 100644
--- a/tests/ui/parser/issues/issue-105209.stderr
+++ b/tests/ui/parser/issues/issue-105209.stderr
@@ -7,16 +7,15 @@
| unclosed delimiter
error: this file contains an unclosed delimiter
- --> $DIR/issue-105209.rs:3:68
+ --> $DIR/issue-105209.rs:3:56
|
LL | #![c={#![c[)x
- | - - - - missing open `(` for this delimiter
- | | | |
- | | | unclosed delimiter
+ | - - - unclosed delimiter
+ | | |
| | unclosed delimiter
| unclosed delimiter
LL |
- | ^
+ | ^
error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index ea3e2be..c7fc5bc 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -18,10 +18,8 @@
--> $DIR/issue-62973.rs:10:2
|
LL | fn p() { match s { v, E { [) {) }
- | - - - - missing open `(` for this delimiter
- | | | |
- | | | missing open `(` for this delimiter
- | | unclosed delimiter
+ | - - unclosed delimiter
+ | |
| unclosed delimiter
LL |
LL |
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index e5bad84..736a0ac 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -10,9 +10,8 @@
--> $DIR/issue-63116.rs:4:18
|
LL | impl W <s(f;Y(;]
- | - -^
- | | |
- | | missing open `[` for this delimiter
+ | - ^
+ | |
| unclosed delimiter
error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
index b82b0f3..5301d43 100644
--- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
+++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
@@ -28,18 +28,14 @@
error: this file contains an unclosed delimiter
--> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:23:65
|
-LL | V = [PhantomData; { [ () ].len() ].len() as isize,
- | - missing open `[` for this delimiter
-...
-LL | V = [Vec::new; { [].len() ].len() as isize,
- | - missing open `[` for this delimiter
-...
LL | mod c {
| - unclosed delimiter
LL | enum Bug {
-LL | V = [Vec::new; { [0].len() ].len() as isize,
- | - missing open `[` for this delimiter
+ | - this delimiter might not be properly closed...
...
+LL | }
+ | - ...as it matches this but it has different indentation
+LL |
LL | fn main() {}
| ^
diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs
index 89aaa68..9b4452e 100644
--- a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs
+++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs
@@ -1,7 +1,7 @@
// FIXME: this case need more work to fix
// currently the TokenTree matching ')' with '{', which is not user friendly for diagnostics
async fn obstest() -> Result<> {
- let obs_connect = || -> Result<(), MyError) { //~ ERROR mismatched closing delimiter
+ let obs_connect = || -> Result<(), MyError) {
async {
}
}
diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr
index 0ecb748..c29a4ff 100644
--- a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr
+++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr
@@ -1,19 +1,13 @@
-error: mismatched closing delimiter: `)`
- --> $DIR/issue-68987-unmatch-issue-2.rs:3:32
- |
-LL | async fn obstest() -> Result<> {
- | ^ unclosed delimiter
-LL | let obs_connect = || -> Result<(), MyError) {
- | ^ mismatched closing delimiter
-
error: unexpected closing delimiter: `}`
--> $DIR/issue-68987-unmatch-issue-2.rs:14:1
|
+LL | async fn obstest() -> Result<> {
+ | - the nearest open delimiter
LL | let obs_connect = || -> Result<(), MyError) {
| - missing open `(` for this delimiter
...
LL | }
| ^ unexpected closing delimiter
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs
index e98df8d..e71e273 100644
--- a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs
+++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs
@@ -3,6 +3,6 @@ fn f(i: u32, j: u32) {
let res = String::new();
let mut cnt = i;
while cnt < j {
- write!&mut res, " "); //~ ERROR mismatched closing delimiter
+ write!&mut res, " ");
}
} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr
index dfc4407..6b012af 100644
--- a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr
+++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr
@@ -1,19 +1,13 @@
-error: mismatched closing delimiter: `)`
- --> $DIR/issue-68987-unmatch-issue-3.rs:5:19
- |
-LL | while cnt < j {
- | ^ unclosed delimiter
-LL | write!&mut res, " ");
- | ^ mismatched closing delimiter
-
error: unexpected closing delimiter: `}`
--> $DIR/issue-68987-unmatch-issue-3.rs:8:1
|
+LL | while cnt < j {
+ | - the nearest open delimiter
LL | write!&mut res, " ");
| - missing open `(` for this delimiter
LL | }
LL | }
| ^ unexpected closing delimiter
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr
index 986ed6b..9737c8c 100644
--- a/tests/ui/parser/issues/issue-81827.stderr
+++ b/tests/ui/parser/issues/issue-81827.stderr
@@ -11,9 +11,8 @@
--> $DIR/issue-81827.rs:7:27
|
LL | fn r()->i{0|{#[cfg(r(0{]0
- | - - - ^
- | | | |
- | | | missing open `[` for this delimiter
+ | - - ^
+ | | |
| | unclosed delimiter
| unclosed delimiter
diff --git a/tests/ui/parser/issues/unnessary-error-issue-138401.rs b/tests/ui/parser/issues/unnessary-error-issue-138401.rs
new file mode 100644
index 0000000..208c516
--- /dev/null
+++ b/tests/ui/parser/issues/unnessary-error-issue-138401.rs
@@ -0,0 +1,6 @@
+pub fn foo(x: i64) -> i64 {
+ x.abs)
+}
+//~^ ERROR unexpected closing delimiter: `}`
+
+fn main() {}
diff --git a/tests/ui/parser/issues/unnessary-error-issue-138401.stderr b/tests/ui/parser/issues/unnessary-error-issue-138401.stderr
new file mode 100644
index 0000000..54c73b5
--- /dev/null
+++ b/tests/ui/parser/issues/unnessary-error-issue-138401.stderr
@@ -0,0 +1,12 @@
+error: unexpected closing delimiter: `}`
+ --> $DIR/unnessary-error-issue-138401.rs:3:1
+ |
+LL | pub fn foo(x: i64) -> i64 {
+ | - the nearest open delimiter
+LL | x.abs)
+ | - missing open `(` for this delimiter
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/trait-object-trait-parens.rs b/tests/ui/parser/trait-object-trait-parens.rs
index 438034b..51f0e2d 100644
--- a/tests/ui/parser/trait-object-trait-parens.rs
+++ b/tests/ui/parser/trait-object-trait-parens.rs
@@ -6,17 +6,17 @@ fn f<T: (Copy) + (?Sized) + (for<'a> Trait<'a>)>() {}
fn main() {
let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
- //~^ ERROR `?Trait` is not permitted in trait object types
+ //~^ ERROR relaxed bounds are not permitted in trait object types
//~| ERROR only auto traits can be used as additional traits
//~| WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition
let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
- //~^ ERROR `?Trait` is not permitted in trait object types
+ //~^ ERROR relaxed bounds are not permitted in trait object types
//~| ERROR only auto traits can be used as additional traits
//~| WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition
let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
- //~^ ERROR `?Trait` is not permitted in trait object types
+ //~^ ERROR relaxed bounds are not permitted in trait object types
//~| ERROR only auto traits can be used as additional traits
//~| WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition
diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr
index d75352b..26d388f 100644
--- a/tests/ui/parser/trait-object-trait-parens.stderr
+++ b/tests/ui/parser/trait-object-trait-parens.stderr
@@ -1,29 +1,20 @@
-error[E0658]: `?Trait` is not permitted in trait object types
+error: relaxed bounds are not permitted in trait object types
--> $DIR/trait-object-trait-parens.rs:8:24
|
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
| ^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error[E0658]: `?Trait` is not permitted in trait object types
+error: relaxed bounds are not permitted in trait object types
--> $DIR/trait-object-trait-parens.rs:13:16
|
LL | let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
| ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error[E0658]: `?Trait` is not permitted in trait object types
+error: relaxed bounds are not permitted in trait object types
--> $DIR/trait-object-trait-parens.rs:18:44
|
LL | let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
| ^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-trait-parens.rs:8:16
@@ -100,5 +91,4 @@
error: aborting due to 6 previous errors; 3 warnings emitted
-Some errors have detailed explanations: E0225, E0658.
-For more information about an error, try `rustc --explain E0225`.
+For more information about this error, try `rustc --explain E0225`.
diff --git a/tests/ui/precondition-checks/alignment.rs b/tests/ui/precondition-checks/alignment.rs
index 9240052..038a625 100644
--- a/tests/ui/precondition-checks/alignment.rs
+++ b/tests/ui/precondition-checks/alignment.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: Alignment::new_unchecked requires
diff --git a/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
index 30c6f79..41ba2c5 100644
--- a/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
+++ b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: `ascii::Char::digit_unchecked` input cannot exceed 9
diff --git a/tests/ui/precondition-checks/assert_unchecked.rs b/tests/ui/precondition-checks/assert_unchecked.rs
index 22b2b41..da5383c 100644
--- a/tests/ui/precondition-checks/assert_unchecked.rs
+++ b/tests/ui/precondition-checks/assert_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: hint::assert_unchecked must never be called when the condition is false
diff --git a/tests/ui/precondition-checks/char-from_u32_unchecked.rs b/tests/ui/precondition-checks/char-from_u32_unchecked.rs
index d950f20..7c34d92 100644
--- a/tests/ui/precondition-checks/char-from_u32_unchecked.rs
+++ b/tests/ui/precondition-checks/char-from_u32_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: invalid value for `char`
diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs
index eacaa63..1d584dd 100644
--- a/tests/ui/precondition-checks/copy-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires
//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs
index 1fadd90..8faa56a 100644
--- a/tests/ui/precondition-checks/copy.rs
+++ b/tests/ui/precondition-checks/copy.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::copy requires
//@ revisions: null_src null_dst misaligned_src misaligned_dst
diff --git a/tests/ui/precondition-checks/layout.rs b/tests/ui/precondition-checks/layout.rs
index 4ee66cc..6755ebc 100644
--- a/tests/ui/precondition-checks/layout.rs
+++ b/tests/ui/precondition-checks/layout.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: Layout::from_size_align_unchecked requires
//@ revisions: toolarge badalign
diff --git a/tests/ui/precondition-checks/nonnull.rs b/tests/ui/precondition-checks/nonnull.rs
index 6b8edd4..75bbd65 100644
--- a/tests/ui/precondition-checks/nonnull.rs
+++ b/tests/ui/precondition-checks/nonnull.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: NonNull::new_unchecked requires
diff --git a/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
index 46ce7dc..d55707f 100644
--- a/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
+++ b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: NonZero::from_mut_unchecked requires
diff --git a/tests/ui/precondition-checks/nonzero-new_unchecked.rs b/tests/ui/precondition-checks/nonzero-new_unchecked.rs
index 7827a42..978f01f 100644
--- a/tests/ui/precondition-checks/nonzero-new_unchecked.rs
+++ b/tests/ui/precondition-checks/nonzero-new_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: NonZero::new_unchecked requires
diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs
index ada8932..33350df 100644
--- a/tests/ui/precondition-checks/read_volatile.rs
+++ b/tests/ui/precondition-checks/read_volatile.rs
@@ -1,9 +1,7 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
-//@ revisions: null misaligned
-
-#![allow(invalid_null_arguments)]
+//@ revisions: misaligned
use std::ptr;
@@ -11,8 +9,6 @@ fn main() {
let src = [0u16; 2];
let src = src.as_ptr();
unsafe {
- #[cfg(null)]
- ptr::read_volatile(ptr::null::<u8>());
#[cfg(misaligned)]
ptr::read_volatile(src.byte_add(1));
}
diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs
index 44afbd8..447a00c 100644
--- a/tests/ui/precondition-checks/replace.rs
+++ b/tests/ui/precondition-checks/replace.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::replace requires
//@ revisions: null misaligned
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
index 9b9ded6..b6397ab 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires
//@ revisions: null misaligned toolarge
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs
index 96578c1..a317e3d 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires
//@ revisions: null misaligned toolarge
diff --git a/tests/ui/precondition-checks/slice-get_unchecked.rs b/tests/ui/precondition-checks/slice-get_unchecked.rs
index 1d8188f..7bcb844 100644
--- a/tests/ui/precondition-checks/slice-get_unchecked.rs
+++ b/tests/ui/precondition-checks/slice-get_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked requires
//@ revisions: usize range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/slice-get_unchecked_mut.rs b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
index 34c1454..2ba3227 100644
--- a/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
+++ b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked_mut requires
//@ revisions: usize range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/str-get_unchecked.rs b/tests/ui/precondition-checks/str-get_unchecked.rs
index 14d17f9..2273190 100644
--- a/tests/ui/precondition-checks/str-get_unchecked.rs
+++ b/tests/ui/precondition-checks/str-get_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked requires
//@ revisions: range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/str-get_unchecked_mut.rs b/tests/ui/precondition-checks/str-get_unchecked_mut.rs
index ca1b169..53e6ee64 100644
--- a/tests/ui/precondition-checks/str-get_unchecked_mut.rs
+++ b/tests/ui/precondition-checks/str-get_unchecked_mut.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked_mut requires
//@ revisions: range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs
index ea1f6f3..81ba723 100644
--- a/tests/ui/precondition-checks/swap-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires
//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
diff --git a/tests/ui/precondition-checks/unchecked_add.rs b/tests/ui/precondition-checks/unchecked_add.rs
index f44a6ea..b7727ae 100644
--- a/tests/ui/precondition-checks/unchecked_add.rs
+++ b/tests/ui/precondition-checks/unchecked_add.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
diff --git a/tests/ui/precondition-checks/unchecked_mul.rs b/tests/ui/precondition-checks/unchecked_mul.rs
index 66655dd..3eea8b6 100644
--- a/tests/ui/precondition-checks/unchecked_mul.rs
+++ b/tests/ui/precondition-checks/unchecked_mul.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
diff --git a/tests/ui/precondition-checks/unchecked_shl.rs b/tests/ui/precondition-checks/unchecked_shl.rs
index 1c96db0..57c617e 100644
--- a/tests/ui/precondition-checks/unchecked_shl.rs
+++ b/tests/ui/precondition-checks/unchecked_shl.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shl cannot overflow
diff --git a/tests/ui/precondition-checks/unchecked_shr.rs b/tests/ui/precondition-checks/unchecked_shr.rs
index 4a6d9ff..18502d2 100644
--- a/tests/ui/precondition-checks/unchecked_shr.rs
+++ b/tests/ui/precondition-checks/unchecked_shr.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shr cannot overflow
diff --git a/tests/ui/precondition-checks/unchecked_sub.rs b/tests/ui/precondition-checks/unchecked_sub.rs
index 545dde0..bfe8f58 100644
--- a/tests/ui/precondition-checks/unchecked_sub.rs
+++ b/tests/ui/precondition-checks/unchecked_sub.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_sub cannot overflow
diff --git a/tests/ui/precondition-checks/unreachable_unchecked.rs b/tests/ui/precondition-checks/unreachable_unchecked.rs
index 2435450..f2855d0 100644
--- a/tests/ui/precondition-checks/unreachable_unchecked.rs
+++ b/tests/ui/precondition-checks/unreachable_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: hint::unreachable_unchecked must never be reached
diff --git a/tests/ui/precondition-checks/vec-from-parts.rs b/tests/ui/precondition-checks/vec-from-parts.rs
index 0bafb5a..ace9077 100644
--- a/tests/ui/precondition-checks/vec-from-parts.rs
+++ b/tests/ui/precondition-checks/vec-from-parts.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Cdebug-assertions=yes
//@ error-pattern: unsafe precondition(s) violated: Vec::from_parts_in requires that length <= capacity
#![feature(allocator_api)]
diff --git a/tests/ui/precondition-checks/vec-from-raw-parts.rs b/tests/ui/precondition-checks/vec-from-raw-parts.rs
index 884d34c..1bc8e6a 100644
--- a/tests/ui/precondition-checks/vec-from-raw-parts.rs
+++ b/tests/ui/precondition-checks/vec-from-raw-parts.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Cdebug-assertions=yes
//@ error-pattern: unsafe precondition(s) violated: Vec::from_raw_parts_in requires that length <= capacity
//@ revisions: vec_from_raw_parts vec_from_raw_parts_in string_from_raw_parts
diff --git a/tests/ui/precondition-checks/vec-set-len.rs b/tests/ui/precondition-checks/vec-set-len.rs
index 0987e7f..c6bdee7 100644
--- a/tests/ui/precondition-checks/vec-set-len.rs
+++ b/tests/ui/precondition-checks/vec-set-len.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Cdebug-assertions=yes
//@ error-pattern: unsafe precondition(s) violated: Vec::set_len requires that new_len <= capacity()
diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs
index 0d5ecb0..d6ad632 100644
--- a/tests/ui/precondition-checks/write_volatile.rs
+++ b/tests/ui/precondition-checks/write_volatile.rs
@@ -1,9 +1,7 @@
-//@ run-fail
+//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
-//@ revisions: null misaligned
-
-#![allow(invalid_null_arguments)]
+//@ revisions: misaligned
use std::ptr;
@@ -11,8 +9,6 @@ fn main() {
let mut dst = [0u16; 2];
let mut dst = dst.as_mut_ptr();
unsafe {
- #[cfg(null)]
- ptr::write_volatile(ptr::null_mut::<u8>(), 1u8);
#[cfg(misaligned)]
ptr::write_volatile(dst.byte_add(1), 1u16);
}
diff --git a/tests/ui/privacy/effective_visibilities_invariants.stderr b/tests/ui/privacy/effective_visibilities_invariants.stderr
index 64d0402..97bee1e 100644
--- a/tests/ui/privacy/effective_visibilities_invariants.stderr
+++ b/tests/ui/privacy/effective_visibilities_invariants.stderr
@@ -23,7 +23,7 @@
--> $DIR/effective_visibilities_invariants.rs:5:1
|
LL | pub mod m {}
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^
error: aborting due to 3 previous errors
diff --git a/tests/ui/privacy/issue-113860-1.stderr b/tests/ui/privacy/issue-113860-1.stderr
index dad9eba..764c9f4 100644
--- a/tests/ui/privacy/issue-113860-1.stderr
+++ b/tests/ui/privacy/issue-113860-1.stderr
@@ -20,28 +20,20 @@
error: trait has missing stability attribute
--> $DIR/issue-113860-1.rs:4:1
|
-LL | / pub trait Trait {
-LL | |
-LL | | fn fun() {}
-LL | |
-LL | | }
- | |_^
+LL | pub trait Trait {
+ | ^^^^^^^^^^^^^^^
error: implementation has missing stability attribute
--> $DIR/issue-113860-1.rs:10:1
|
-LL | / impl Trait for u8 {
-LL | |
-LL | | pub(self) fn fun() {}
-LL | |
-LL | | }
- | |_^
+LL | impl Trait for u8 {
+ | ^^^^^^^^^^^^^^^^^
error: associated function has missing stability attribute
--> $DIR/issue-113860-1.rs:6:5
|
LL | fn fun() {}
- | ^^^^^^^^^^^
+ | ^^^^^^^^
error: aborting due to 5 previous errors
diff --git a/tests/ui/privacy/issue-113860-2.stderr b/tests/ui/privacy/issue-113860-2.stderr
index 9805c22..d0847aa 100644
--- a/tests/ui/privacy/issue-113860-2.stderr
+++ b/tests/ui/privacy/issue-113860-2.stderr
@@ -20,28 +20,20 @@
error: trait has missing stability attribute
--> $DIR/issue-113860-2.rs:4:1
|
-LL | / pub trait Trait {
-LL | |
-LL | | type X;
-LL | |
-LL | | }
- | |_^
+LL | pub trait Trait {
+ | ^^^^^^^^^^^^^^^
error: implementation has missing stability attribute
--> $DIR/issue-113860-2.rs:10:1
|
-LL | / impl Trait for u8 {
-LL | |
-LL | | pub(self) type X = Self;
-LL | |
-LL | | }
- | |_^
+LL | impl Trait for u8 {
+ | ^^^^^^^^^^^^^^^^^
error: associated type has missing stability attribute
--> $DIR/issue-113860-2.rs:6:5
|
LL | type X;
- | ^^^^^^^
+ | ^^^^^^
error: aborting due to 5 previous errors
diff --git a/tests/ui/privacy/issue-113860.stderr b/tests/ui/privacy/issue-113860.stderr
index 88efcae..d7a1525 100644
--- a/tests/ui/privacy/issue-113860.stderr
+++ b/tests/ui/privacy/issue-113860.stderr
@@ -20,28 +20,20 @@
error: trait has missing stability attribute
--> $DIR/issue-113860.rs:4:1
|
-LL | / pub trait Trait {
-LL | |
-LL | | const X: u32;
-LL | |
-LL | | }
- | |_^
+LL | pub trait Trait {
+ | ^^^^^^^^^^^^^^^
error: implementation has missing stability attribute
--> $DIR/issue-113860.rs:10:1
|
-LL | / impl Trait for u8 {
-LL | |
-LL | | pub(self) const X: u32 = 3;
-LL | |
-LL | | }
- | |_^
+LL | impl Trait for u8 {
+ | ^^^^^^^^^^^^^^^^^
error: associated constant has missing stability attribute
--> $DIR/issue-113860.rs:6:5
|
LL | const X: u32;
- | ^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^
error: aborting due to 5 previous errors
diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs
index 746b98f..f79e464 100644
--- a/tests/ui/privacy/private-in-public-warn.rs
+++ b/tests/ui/privacy/private-in-public-warn.rs
@@ -35,6 +35,7 @@ impl PubTr for Pub {
mod traits {
trait PrivTr {}
+ impl PrivTr for () {}
pub struct Pub<T>(T);
pub trait PubTr {}
@@ -45,7 +46,10 @@ pub trait Tr2<T: PrivTr> {} //~ ERROR trait `traits::PrivTr` is more private tha
pub trait Tr3 {
type Alias: PrivTr;
//~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::Alias`
- fn f<T: PrivTr>(arg: T) {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
+ fn f<T: PrivTr>(arg: T) {}
+ //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
+ fn g() -> impl PrivTr;
+ fn h() -> impl PrivTr {}
}
impl<T: PrivTr> Pub<T> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
impl<T: PrivTr> PubTr for Pub<T> {} // OK, trait impl predicates
@@ -75,12 +79,18 @@ mod generics {
pub struct Pub<T = u8>(T);
trait PrivTr<T> {}
pub trait PubTr<T> {}
+ impl PrivTr<Priv<()>> for () {}
pub trait Tr1: PrivTr<Pub> {}
//~^ ERROR trait `generics::PrivTr<generics::Pub>` is more private than the item `generics::Tr1`
pub trait Tr2: PubTr<Priv> {} //~ ERROR type `generics::Priv` is more private than the item `generics::Tr2`
pub trait Tr3: PubTr<[Priv; 1]> {} //~ ERROR type `generics::Priv` is more private than the item `generics::Tr3`
pub trait Tr4: PubTr<Pub<Priv>> {} //~ ERROR type `generics::Priv` is more private than the item `Tr4`
+
+ pub trait Tr5 {
+ fn required() -> impl PrivTr<Priv<()>>;
+ fn provided() -> impl PrivTr<Priv<()>> {}
+ }
}
mod impls {
diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr
index 3743879..c2a57e3 100644
--- a/tests/ui/privacy/private-in-public-warn.stderr
+++ b/tests/ui/privacy/private-in-public-warn.stderr
@@ -130,7 +130,7 @@
| ^^^^^^^^^^ can't leak private type
error: trait `traits::PrivTr` is more private than the item `traits::Alias`
- --> $DIR/private-in-public-warn.rs:41:5
+ --> $DIR/private-in-public-warn.rs:42:5
|
LL | pub type Alias<T: PrivTr> = T;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ type alias `traits::Alias` is reachable at visibility `pub(crate)`
@@ -147,7 +147,7 @@
| ^^^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr1`
- --> $DIR/private-in-public-warn.rs:43:5
+ --> $DIR/private-in-public-warn.rs:44:5
|
LL | pub trait Tr1: PrivTr {}
| ^^^^^^^^^^^^^^^^^^^^^ trait `traits::Tr1` is reachable at visibility `pub(crate)`
@@ -159,7 +159,7 @@
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr2`
- --> $DIR/private-in-public-warn.rs:44:5
+ --> $DIR/private-in-public-warn.rs:45:5
|
LL | pub trait Tr2<T: PrivTr> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ trait `traits::Tr2` is reachable at visibility `pub(crate)`
@@ -171,7 +171,7 @@
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr3::Alias`
- --> $DIR/private-in-public-warn.rs:46:9
+ --> $DIR/private-in-public-warn.rs:47:9
|
LL | type Alias: PrivTr;
| ^^^^^^^^^^^^^^^^^^ associated type `traits::Tr3::Alias` is reachable at visibility `pub(crate)`
@@ -183,7 +183,7 @@
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
- --> $DIR/private-in-public-warn.rs:48:9
+ --> $DIR/private-in-public-warn.rs:49:9
|
LL | fn f<T: PrivTr>(arg: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits::Tr3::f` is reachable at visibility `pub(crate)`
@@ -195,7 +195,7 @@
| ^^^^^^^^^^^^
error: trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
- --> $DIR/private-in-public-warn.rs:50:5
+ --> $DIR/private-in-public-warn.rs:54:5
|
LL | impl<T: PrivTr> Pub<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^ implementation `traits::Pub<T>` is reachable at visibility `pub(crate)`
@@ -207,103 +207,103 @@
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Alias`
- --> $DIR/private-in-public-warn.rs:59:5
+ --> $DIR/private-in-public-warn.rs:63:5
|
LL | pub type Alias<T> where T: PrivTr = T;
| ^^^^^^^^^^^^^^^^^ type alias `traits_where::Alias` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:55:5
+ --> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2`
- --> $DIR/private-in-public-warn.rs:62:5
+ --> $DIR/private-in-public-warn.rs:66:5
|
LL | pub trait Tr2<T> where T: PrivTr {}
| ^^^^^^^^^^^^^^^^ trait `traits_where::Tr2` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:55:5
+ --> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr3::f`
- --> $DIR/private-in-public-warn.rs:65:9
+ --> $DIR/private-in-public-warn.rs:69:9
|
LL | fn f<T>(arg: T) where T: PrivTr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits_where::Tr3::f` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:55:5
+ --> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `traits_where::PrivTr` is more private than the item `traits_where::Pub<T>`
- --> $DIR/private-in-public-warn.rs:68:5
+ --> $DIR/private-in-public-warn.rs:72:5
|
LL | impl<T> Pub<T> where T: PrivTr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub<T>` is reachable at visibility `pub(crate)`
|
note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:55:5
+ --> $DIR/private-in-public-warn.rs:59:5
|
LL | trait PrivTr {}
| ^^^^^^^^^^^^
error: trait `generics::PrivTr<generics::Pub>` is more private than the item `generics::Tr1`
- --> $DIR/private-in-public-warn.rs:79:5
+ --> $DIR/private-in-public-warn.rs:84:5
|
LL | pub trait Tr1: PrivTr<Pub> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr1` is reachable at visibility `pub(crate)`
|
note: but trait `generics::PrivTr<generics::Pub>` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:76:5
+ --> $DIR/private-in-public-warn.rs:80:5
|
LL | trait PrivTr<T> {}
| ^^^^^^^^^^^^^^^
error: type `generics::Priv` is more private than the item `generics::Tr2`
- --> $DIR/private-in-public-warn.rs:81:5
+ --> $DIR/private-in-public-warn.rs:86:5
|
LL | pub trait Tr2: PubTr<Priv> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr2` is reachable at visibility `pub(crate)`
|
note: but type `generics::Priv` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:74:5
+ --> $DIR/private-in-public-warn.rs:78:5
|
LL | struct Priv<T = u8>(T);
| ^^^^^^^^^^^^^^^^^^^
error: type `generics::Priv` is more private than the item `generics::Tr3`
- --> $DIR/private-in-public-warn.rs:82:5
+ --> $DIR/private-in-public-warn.rs:87:5
|
LL | pub trait Tr3: PubTr<[Priv; 1]> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr3` is reachable at visibility `pub(crate)`
|
note: but type `generics::Priv` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:74:5
+ --> $DIR/private-in-public-warn.rs:78:5
|
LL | struct Priv<T = u8>(T);
| ^^^^^^^^^^^^^^^^^^^
error: type `generics::Priv` is more private than the item `Tr4`
- --> $DIR/private-in-public-warn.rs:83:5
+ --> $DIR/private-in-public-warn.rs:88:5
|
LL | pub trait Tr4: PubTr<Pub<Priv>> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `Tr4` is reachable at visibility `pub(crate)`
|
note: but type `generics::Priv` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:74:5
+ --> $DIR/private-in-public-warn.rs:78:5
|
LL | struct Priv<T = u8>(T);
| ^^^^^^^^^^^^^^^^^^^
error[E0446]: private type `impls::Priv` in public interface
- --> $DIR/private-in-public-warn.rs:109:9
+ --> $DIR/private-in-public-warn.rs:119:9
|
LL | struct Priv;
| ----------- `impls::Priv` declared as private
@@ -312,19 +312,19 @@
| ^^^^^^^^^^ can't leak private type
error: type `aliases_pub::Priv` is more private than the item `aliases_pub::<impl Pub2>::f`
- --> $DIR/private-in-public-warn.rs:180:9
+ --> $DIR/private-in-public-warn.rs:190:9
|
LL | pub fn f(arg: Priv) {}
| ^^^^^^^^^^^^^^^^^^^ associated function `aliases_pub::<impl Pub2>::f` is reachable at visibility `pub(crate)`
|
note: but type `aliases_pub::Priv` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:153:5
+ --> $DIR/private-in-public-warn.rs:163:5
|
LL | struct Priv;
| ^^^^^^^^^^^
error[E0446]: private type `aliases_pub::Priv` in public interface
- --> $DIR/private-in-public-warn.rs:183:9
+ --> $DIR/private-in-public-warn.rs:193:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -333,7 +333,7 @@
| ^^^^^^^^^^ can't leak private type
error[E0446]: private type `aliases_pub::Priv` in public interface
- --> $DIR/private-in-public-warn.rs:186:9
+ --> $DIR/private-in-public-warn.rs:196:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -342,7 +342,7 @@
| ^^^^^^^^^^ can't leak private type
error[E0446]: private type `aliases_pub::Priv` in public interface
- --> $DIR/private-in-public-warn.rs:189:9
+ --> $DIR/private-in-public-warn.rs:199:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -351,7 +351,7 @@
| ^^^^^^^^^^ can't leak private type
error[E0446]: private type `aliases_pub::Priv` in public interface
- --> $DIR/private-in-public-warn.rs:192:9
+ --> $DIR/private-in-public-warn.rs:202:9
|
LL | struct Priv;
| ----------- `aliases_pub::Priv` declared as private
@@ -360,43 +360,43 @@
| ^^^^^^^^^^ can't leak private type
error: trait `PrivTr1` is more private than the item `aliases_priv::Tr1`
- --> $DIR/private-in-public-warn.rs:222:5
+ --> $DIR/private-in-public-warn.rs:232:5
|
LL | pub trait Tr1: PrivUseAliasTr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr1` is reachable at visibility `pub(crate)`
|
note: but trait `PrivTr1` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:208:5
+ --> $DIR/private-in-public-warn.rs:218:5
|
LL | trait PrivTr1<T = u8> {
| ^^^^^^^^^^^^^^^^^^^^^
error: trait `PrivTr1<Priv2>` is more private than the item `aliases_priv::Tr2`
- --> $DIR/private-in-public-warn.rs:224:5
+ --> $DIR/private-in-public-warn.rs:234:5
|
LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)`
|
note: but trait `PrivTr1<Priv2>` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:208:5
+ --> $DIR/private-in-public-warn.rs:218:5
|
LL | trait PrivTr1<T = u8> {
| ^^^^^^^^^^^^^^^^^^^^^
error: type `Priv2` is more private than the item `aliases_priv::Tr2`
- --> $DIR/private-in-public-warn.rs:224:5
+ --> $DIR/private-in-public-warn.rs:234:5
|
LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)`
|
note: but type `Priv2` is only usable at visibility `pub(self)`
- --> $DIR/private-in-public-warn.rs:206:5
+ --> $DIR/private-in-public-warn.rs:216:5
|
LL | struct Priv2;
| ^^^^^^^^^^^^
warning: bounds on generic parameters in type aliases are not enforced
- --> $DIR/private-in-public-warn.rs:41:23
+ --> $DIR/private-in-public-warn.rs:42:23
|
LL | pub type Alias<T: PrivTr> = T;
| --^^^^^^
@@ -410,7 +410,7 @@
= note: `#[warn(type_alias_bounds)]` on by default
warning: where clauses on type aliases are not enforced
- --> $DIR/private-in-public-warn.rs:59:29
+ --> $DIR/private-in-public-warn.rs:63:29
|
LL | pub type Alias<T> where T: PrivTr = T;
| ------^^^^^^^^^
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
index 4eeecdc..7564014 100644
--- a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
@@ -1,5 +1,6 @@
pub struct OtherType;
pub trait OtherTrait {}
+impl OtherTrait for OtherType {}
#[macro_export]
macro_rules! m {
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
index 192ca0db..b85f275 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -44,8 +44,12 @@ fn priv_fn(param: OtherType) {}
pub trait MyPubTrait {
type Foo: OtherTrait;
+ //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+
+ fn required() -> impl OtherTrait;
+
+ fn provided() -> impl OtherTrait { OtherType }
}
-//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
pub trait WithSuperTrait: OtherTrait {}
//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
index 9da4782..24bd071 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -11,31 +11,31 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: macro `m` from private dependency 'priv_dep' is re-exported
- --> $DIR/pub-priv1.rs:94:9
+ --> $DIR/pub-priv1.rs:98:9
|
LL | pub use priv_dep::m;
| ^^^^^^^^^^^
error: macro `fn_like` from private dependency 'pm' is re-exported
- --> $DIR/pub-priv1.rs:96:9
+ --> $DIR/pub-priv1.rs:100:9
|
LL | pub use pm::fn_like;
| ^^^^^^^^^^^
error: derive macro `PmDerive` from private dependency 'pm' is re-exported
- --> $DIR/pub-priv1.rs:98:9
+ --> $DIR/pub-priv1.rs:102:9
|
LL | pub use pm::PmDerive;
| ^^^^^^^^^^^^
error: attribute macro `pm_attr` from private dependency 'pm' is re-exported
- --> $DIR/pub-priv1.rs:100:9
+ --> $DIR/pub-priv1.rs:104:9
|
LL | pub use pm::pm_attr;
| ^^^^^^^^^^^
error: variant `V1` from private dependency 'priv_dep' is re-exported
- --> $DIR/pub-priv1.rs:103:9
+ --> $DIR/pub-priv1.rs:107:9
|
LL | pub use priv_dep::E::V1;
| ^^^^^^^^^^^^^^^
@@ -65,61 +65,61 @@
| ^^^^^^^^^^^^^^^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:50:1
+ --> $DIR/pub-priv1.rs:54:1
|
LL | pub trait WithSuperTrait: OtherTrait {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:59:5
+ --> $DIR/pub-priv1.rs:63:5
|
LL | type X = OtherType;
| ^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:63:1
+ --> $DIR/pub-priv1.rs:67:1
|
LL | pub fn in_bounds<T: OtherTrait>(x: T) { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:66:1
+ --> $DIR/pub-priv1.rs:70:1
|
LL | pub fn private_in_generic() -> std::num::Saturating<OtherType> { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:69:1
+ --> $DIR/pub-priv1.rs:73:1
|
LL | pub static STATIC: OtherType = OtherType;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:72:1
+ --> $DIR/pub-priv1.rs:76:1
|
LL | pub const CONST: OtherType = OtherType;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:75:1
+ --> $DIR/pub-priv1.rs:79:1
|
LL | pub type Alias = OtherType;
| ^^^^^^^^^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:80:1
+ --> $DIR/pub-priv1.rs:84:1
|
LL | impl OtherTrait for PublicWithPrivateImpl {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:85:1
+ --> $DIR/pub-priv1.rs:89:1
|
LL | impl PubTraitOnPrivate for OtherType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:85:1
+ --> $DIR/pub-priv1.rs:89:1
|
LL | impl PubTraitOnPrivate for OtherType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr
index 23c93a4..4244c11 100644
--- a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr
+++ b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr
@@ -10,13 +10,13 @@
LL | #[doc(alias = "foo")]
| ^^^^^^^^^^^^^
-error: `#[doc(alias = "...")]` isn't allowed on implementation block
+error: `#[doc(alias = "...")]` isn't allowed on inherent implementation block
--> $DIR/check-doc-alias-attr-location.rs:12:7
|
LL | #[doc(alias = "bar")]
| ^^^^^^^^^^^^^
-error: `#[doc(alias = "...")]` isn't allowed on implementation block
+error: `#[doc(alias = "...")]` isn't allowed on trait implementation block
--> $DIR/check-doc-alias-attr-location.rs:18:7
|
LL | #[doc(alias = "foobar")]
diff --git a/tests/ui/sanitizer/address.rs b/tests/ui/sanitizer/address.rs
index 7a5e767..704d847 100644
--- a/tests/ui/sanitizer/address.rs
+++ b/tests/ui/sanitizer/address.rs
@@ -4,7 +4,7 @@
//
//@ compile-flags: -Z sanitizer=address -O -g
//
-//@ run-fail
+//@ run-fail-or-crash
//@ error-pattern: AddressSanitizer: stack-buffer-overflow
//@ error-pattern: 'xs' (line 14) <== Memory access at offset
diff --git a/tests/ui/sanitizer/badfree.rs b/tests/ui/sanitizer/badfree.rs
index ecbb58e..6b3aea7 100644
--- a/tests/ui/sanitizer/badfree.rs
+++ b/tests/ui/sanitizer/badfree.rs
@@ -4,7 +4,7 @@
//
//@ compile-flags: -Z sanitizer=address -O
//
-//@ run-fail
+//@ run-fail-or-crash
//@ regex-error-pattern: AddressSanitizer: (SEGV|attempting free on address which was not malloc)
use std::ffi::c_void;
diff --git a/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs b/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs
index b7dd4a4..c1a2c2f2 100644
--- a/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs
+++ b/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs
@@ -11,7 +11,7 @@
//@ compile-flags: -Zsanitizer=address -Clto=thin
//@[opt0]compile-flags: -Copt-level=0
//@[opt1]compile-flags: -Copt-level=1
-//@ run-fail
+//@ run-fail-or-crash
//@ error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
static mut P: *mut usize = std::ptr::null_mut();
diff --git a/tests/ui/sanitizer/thread.rs b/tests/ui/sanitizer/thread.rs
index 566774d..9073124 100644
--- a/tests/ui/sanitizer/thread.rs
+++ b/tests/ui/sanitizer/thread.rs
@@ -15,7 +15,7 @@
//
//@ compile-flags: -Z sanitizer=thread -O
//
-//@ run-fail
+//@ run-fail-or-crash
//@ error-pattern: WARNING: ThreadSanitizer: data race
//@ error-pattern: Location is heap block of size 4
//@ error-pattern: allocated by main thread
diff --git a/tests/ui/sanitizer/use-after-scope.rs b/tests/ui/sanitizer/use-after-scope.rs
index 4d7f6f6..106dc64 100644
--- a/tests/ui/sanitizer/use-after-scope.rs
+++ b/tests/ui/sanitizer/use-after-scope.rs
@@ -3,7 +3,7 @@
//@ ignore-cross-compile
//
//@ compile-flags: -Zsanitizer=address
-//@ run-fail
+//@ run-fail-or-crash
//@ error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
static mut P: *mut usize = std::ptr::null_mut();
diff --git a/tests/ui/sized-hierarchy/default-bound.rs b/tests/ui/sized-hierarchy/default-bound.rs
index 12b2eb2..bbb2c6d 100644
--- a/tests/ui/sized-hierarchy/default-bound.rs
+++ b/tests/ui/sized-hierarchy/default-bound.rs
@@ -14,13 +14,13 @@ fn neg_sized<T: ?Sized>() {}
fn metasized<T: MetaSized>() {}
fn neg_metasized<T: ?MetaSized>() {}
-//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
fn pointeesized<T: PointeeSized>() { }
fn neg_pointeesized<T: ?PointeeSized>() { }
-//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
fn main() {
diff --git a/tests/ui/sized-hierarchy/default-bound.stderr b/tests/ui/sized-hierarchy/default-bound.stderr
index 22f0fa2..0a4ea6f 100644
--- a/tests/ui/sized-hierarchy/default-bound.stderr
+++ b/tests/ui/sized-hierarchy/default-bound.stderr
@@ -1,10 +1,10 @@
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/default-bound.rs:16:21
|
LL | fn neg_metasized<T: ?MetaSized>() {}
| ^^^^^^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/default-bound.rs:22:24
|
LL | fn neg_pointeesized<T: ?PointeeSized>() { }
diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs
index b25acf9..ab3b28e 100644
--- a/tests/ui/sized-hierarchy/default-supertrait.rs
+++ b/tests/ui/sized-hierarchy/default-supertrait.rs
@@ -6,18 +6,18 @@
trait Sized_: Sized { }
trait NegSized: ?Sized { }
-//~^ ERROR `?Trait` is not permitted in supertraits
+//~^ ERROR relaxed bounds are not permitted in supertrait bounds
trait MetaSized_: MetaSized { }
trait NegMetaSized: ?MetaSized { }
-//~^ ERROR `?Trait` is not permitted in supertraits
+//~^ ERROR relaxed bounds are not permitted in supertrait bounds
trait PointeeSized_: PointeeSized { }
trait NegPointeeSized: ?PointeeSized { }
-//~^ ERROR `?Trait` is not permitted in supertraits
+//~^ ERROR relaxed bounds are not permitted in supertrait bounds
trait Bare {}
diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr
index de23936..f5589d6 100644
--- a/tests/ui/sized-hierarchy/default-supertrait.stderr
+++ b/tests/ui/sized-hierarchy/default-supertrait.stderr
@@ -1,32 +1,22 @@
-error[E0658]: `?Trait` is not permitted in supertraits
+error: relaxed bounds are not permitted in supertrait bounds
--> $DIR/default-supertrait.rs:8:17
|
LL | trait NegSized: ?Sized { }
| ^^^^^^
|
= note: traits are `?Sized` by default
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error[E0658]: `?Trait` is not permitted in supertraits
+error: relaxed bounds are not permitted in supertrait bounds
--> $DIR/default-supertrait.rs:13:21
|
LL | trait NegMetaSized: ?MetaSized { }
| ^^^^^^^^^^
- |
- = note: traits are `?MetaSized` by default
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error[E0658]: `?Trait` is not permitted in supertraits
+error: relaxed bounds are not permitted in supertrait bounds
--> $DIR/default-supertrait.rs:19:24
|
LL | trait NegPointeeSized: ?PointeeSized { }
| ^^^^^^^^^^^^^
- |
- = note: traits are `?PointeeSized` by default
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0277]: the size for values of type `T` cannot be known
--> $DIR/default-supertrait.rs:52:38
@@ -121,5 +111,4 @@
error: aborting due to 9 previous errors
-Some errors have detailed explanations: E0277, E0658.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/sized-hierarchy/pointee-validation.rs b/tests/ui/sized-hierarchy/pointee-validation.rs
new file mode 100644
index 0000000..dfc2882
--- /dev/null
+++ b/tests/ui/sized-hierarchy/pointee-validation.rs
@@ -0,0 +1,20 @@
+// Test that despite us dropping `PointeeSized` bounds during HIR ty lowering
+// we still validate it first.
+// issue: <https://github.com/rust-lang/rust/issues/142718>
+#![feature(sized_hierarchy)]
+
+use std::marker::PointeeSized;
+
+struct T where (): PointeeSized<(), Undefined = ()>;
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
+//~| ERROR associated type `Undefined` not found for `PointeeSized`
+
+const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+//~^ ERROR `const` can only be applied to `const` traits
+//~| ERROR `const` can only be applied to `const` traits
+//~| ERROR const trait impls are experimental
+//~| ERROR `[const]` can only be applied to `const` traits
+//~| ERROR `[const]` can only be applied to `const` traits
+//~| ERROR const trait impls are experimental
+
+fn main() {}
diff --git a/tests/ui/sized-hierarchy/pointee-validation.stderr b/tests/ui/sized-hierarchy/pointee-validation.stderr
new file mode 100644
index 0000000..a056d54
--- /dev/null
+++ b/tests/ui/sized-hierarchy/pointee-validation.stderr
@@ -0,0 +1,76 @@
+error[E0658]: const trait impls are experimental
+ --> $DIR/pointee-validation.rs:12:32
+ |
+LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+ | ^^^^^
+ |
+ = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: const trait impls are experimental
+ --> $DIR/pointee-validation.rs:12:55
+ |
+LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+ | ^^^^^^^
+ |
+ = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/pointee-validation.rs:8:20
+ |
+LL | struct T where (): PointeeSized<(), Undefined = ()>;
+ | ^^^^^^^^^^^^-------------------- help: remove the unnecessary generics
+ | |
+ | expected 0 generic arguments
+
+error[E0220]: associated type `Undefined` not found for `PointeeSized`
+ --> $DIR/pointee-validation.rs:8:37
+ |
+LL | struct T where (): PointeeSized<(), Undefined = ()>;
+ | ^^^^^^^^^ associated type `Undefined` not found
+
+error: `const` can only be applied to `const` traits
+ --> $DIR/pointee-validation.rs:12:32
+ |
+LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+ | ^^^^^ can't be applied to `PointeeSized`
+ |
+note: `PointeeSized` can't be used with `const` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+
+error: `[const]` can only be applied to `const` traits
+ --> $DIR/pointee-validation.rs:12:55
+ |
+LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+ | ^^^^^^^ can't be applied to `PointeeSized`
+ |
+note: `PointeeSized` can't be used with `[const]` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+
+error: `const` can only be applied to `const` traits
+ --> $DIR/pointee-validation.rs:12:32
+ |
+LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+ | ^^^^^ can't be applied to `PointeeSized`
+ |
+note: `PointeeSized` can't be used with `const` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `[const]` can only be applied to `const` traits
+ --> $DIR/pointee-validation.rs:12:55
+ |
+LL | const fn test<T, U>() where T: const PointeeSized, U: [const] PointeeSized {}
+ | ^^^^^^^ can't be applied to `PointeeSized`
+ |
+note: `PointeeSized` can't be used with `[const]` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0107, E0220, E0658.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs
index ece1702..89e4c15 100644
--- a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs
+++ b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs
@@ -3,7 +3,7 @@
use std::marker::PointeeSized;
type Foo = dyn PointeeSized;
-//~^ ERROR `PointeeSized` cannot be used with trait objects
+//~^ ERROR at least one trait is required for an object type
fn foo(f: &Foo) {}
@@ -12,5 +12,5 @@ fn main() {
let x = main;
let y: Box<dyn PointeeSized> = x;
-//~^ ERROR `PointeeSized` cannot be used with trait objects
+//~^ ERROR at least one trait is required for an object type
}
diff --git a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr
index a833c69..616b240 100644
--- a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr
+++ b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr
@@ -1,10 +1,10 @@
-error: `PointeeSized` cannot be used with trait objects
+error[E0224]: at least one trait is required for an object type
--> $DIR/reject-dyn-pointeesized.rs:5:12
|
LL | type Foo = dyn PointeeSized;
| ^^^^^^^^^^^^^^^^
-error: `PointeeSized` cannot be used with trait objects
+error[E0224]: at least one trait is required for an object type
--> $DIR/reject-dyn-pointeesized.rs:14:16
|
LL | let y: Box<dyn PointeeSized> = x;
@@ -12,3 +12,4 @@
error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr
index 70a2450..5748e20 100644
--- a/tests/ui/stability-attribute/missing-const-stability.stderr
+++ b/tests/ui/stability-attribute/missing-const-stability.stderr
@@ -2,29 +2,25 @@
--> $DIR/missing-const-stability.rs:7:1
|
LL | pub const fn foo() {}
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^
error: trait has missing const stability attribute
--> $DIR/missing-const-stability.rs:23:1
|
-LL | / pub const trait Bar {
-LL | |
-LL | | #[stable(feature = "stable", since = "1.0.0")]
-LL | | fn fun();
-LL | | }
- | |_^
+LL | pub const trait Bar {
+ | ^^^^^^^^^^^^^^^^^^^
error: function has missing const stability attribute
--> $DIR/missing-const-stability.rs:36:1
|
LL | pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: associated function has missing const stability attribute
--> $DIR/missing-const-stability.rs:16:5
|
LL | pub const fn foo() {}
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr
index a6d1ebf..d33bb53 100644
--- a/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr
+++ b/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr
@@ -1,10 +1,8 @@
error: macro has missing stability attribute
--> $DIR/stability-attribute-sanity-3.rs:8:1
|
-LL | / macro_rules! mac {
-LL | | () => ()
-LL | | }
- | |_^
+LL | macro_rules! mac {
+ | ^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/std/issue-81357-unsound-file-methods.rs b/tests/ui/std/issue-81357-unsound-file-methods.rs
index 838df40..99bd31a 100644
--- a/tests/ui/std/issue-81357-unsound-file-methods.rs
+++ b/tests/ui/std/issue-81357-unsound-file-methods.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
//@ only-windows
fn main() {
diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr
index bcbd46c..52306a2 100644
--- a/tests/ui/suggestions/issue-94171.stderr
+++ b/tests/ui/suggestions/issue-94171.stderr
@@ -22,9 +22,7 @@
--> $DIR/issue-94171.rs:5:52
|
LL | fn L(]{match
- | -- unclosed delimiter
- | |
- | missing open `[` for this delimiter
+ | - unclosed delimiter
LL | (; {`
| - - unclosed delimiter
| |
diff --git a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs b/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs
deleted file mode 100644
index e6d7f748..0000000
--- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Regression test for #127441
-
-// Tests that we make the correct suggestion
-// in case there are more than one `?Sized`
-// bounds on a function parameter
-
-use std::fmt::Debug;
-
-fn foo1<T: ?Sized>(a: T) {}
-//~^ ERROR he size for values of type `T` cannot be known at compilation time
-
-fn foo2<T: ?Sized + ?Sized>(a: T) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR the size for values of type `T` cannot be known at compilation time
-
-fn foo3<T: ?Sized + ?Sized + Debug>(a: T) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR he size for values of type `T` cannot be known at compilation time
-
-fn foo4<T: ?Sized + Debug + ?Sized >(a: T) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR the size for values of type `T` cannot be known at compilation time
-
-fn foo5(_: impl ?Sized) {}
-//~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time
-
-fn foo6(_: impl ?Sized + ?Sized) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation tim
-
-fn foo7(_: impl ?Sized + ?Sized + Debug) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time
-
-fn foo8(_: impl ?Sized + Debug + ?Sized ) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time
-
-fn main() {}
diff --git a/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs b/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs
new file mode 100644
index 0000000..a1681dd
--- /dev/null
+++ b/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs
@@ -0,0 +1,22 @@
+fn dupes<T: ?Sized + ?Sized + ?Iterator + ?Iterator>() {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR duplicate relaxed `Iterator` bounds
+//~| ERROR bound modifier `?` can only be applied to `Sized`
+//~| ERROR bound modifier `?` can only be applied to `Sized`
+
+trait Trait {
+ // We used to say "type parameter has more than one relaxed default bound"
+ // even on *associated types* like here. Test that we no longer do that.
+ type Type: ?Sized + ?Sized;
+ //~^ ERROR duplicate relaxed `Sized` bounds
+ //~| ERROR duplicate relaxed `Sized` bounds
+}
+
+// We used to emit an additional error about "multiple relaxed default bounds".
+// However, multiple relaxed bounds are actually *fine* if they're distinct.
+// Ultimately, we still reject this because `Sized` is
+// the only (stable) default trait, so we're fine.
+fn not_dupes<T: ?Sized + ?Iterator>() {}
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr b/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr
new file mode 100644
index 0000000..ccc723f
--- /dev/null
+++ b/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr
@@ -0,0 +1,47 @@
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/duplicate-relaxed-bounds.rs:1:13
+ |
+LL | fn dupes<T: ?Sized + ?Sized + ?Iterator + ?Iterator>() {}
+ | ^^^^^^ ^^^^^^
+
+error[E0203]: duplicate relaxed `Iterator` bounds
+ --> $DIR/duplicate-relaxed-bounds.rs:1:31
+ |
+LL | fn dupes<T: ?Sized + ?Sized + ?Iterator + ?Iterator>() {}
+ | ^^^^^^^^^ ^^^^^^^^^
+
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/duplicate-relaxed-bounds.rs:1:31
+ |
+LL | fn dupes<T: ?Sized + ?Sized + ?Iterator + ?Iterator>() {}
+ | ^^^^^^^^^
+
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/duplicate-relaxed-bounds.rs:1:43
+ |
+LL | fn dupes<T: ?Sized + ?Sized + ?Iterator + ?Iterator>() {}
+ | ^^^^^^^^^
+
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/duplicate-relaxed-bounds.rs:19:26
+ |
+LL | fn not_dupes<T: ?Sized + ?Iterator>() {}
+ | ^^^^^^^^^
+
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/duplicate-relaxed-bounds.rs:10:16
+ |
+LL | type Type: ?Sized + ?Sized;
+ | ^^^^^^ ^^^^^^
+
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/duplicate-relaxed-bounds.rs:10:16
+ |
+LL | type Type: ?Sized + ?Sized;
+ | ^^^^^^ ^^^^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0203`.
diff --git a/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs
new file mode 100644
index 0000000..1aa3620
--- /dev/null
+++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs
@@ -0,0 +1,38 @@
+// Test that we emit a correct structured suggestions for dynamically sized ("maybe unsized")
+// function parameters.
+// We used to emit a butchered suggestion if duplicate relaxed `Sized` bounds were present.
+// issue: <https://github.com/rust-lang/rust/issues/127441>.
+
+use std::fmt::Debug;
+
+fn foo1<T: ?Sized>(a: T) {}
+//~^ ERROR the size for values of type `T` cannot be known at compilation time
+
+fn foo2<T: ?Sized + ?Sized>(a: T) {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR the size for values of type `T` cannot be known at compilation time
+
+fn foo3<T: ?Sized + ?Sized + Debug>(a: T) {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR the size for values of type `T` cannot be known at compilation time
+
+fn foo4<T: ?Sized + Debug + ?Sized >(a: T) {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR the size for values of type `T` cannot be known at compilation time
+
+fn foo5(_: impl ?Sized) {}
+//~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time
+
+fn foo6(_: impl ?Sized + ?Sized) {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation tim
+
+fn foo7(_: impl ?Sized + ?Sized + Debug) {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time
+
+fn foo8(_: impl ?Sized + Debug + ?Sized ) {}
+//~^ ERROR duplicate relaxed `Sized` bounds
+//~| ERROR the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr
similarity index 79%
rename from tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr
rename to tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr
index 363f52d..7a9c2f0 100644
--- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr
+++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr
@@ -1,41 +1,41 @@
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:12:12
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:12
|
LL | fn foo2<T: ?Sized + ?Sized>(a: T) {}
| ^^^^^^ ^^^^^^
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:16:12
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:12
|
LL | fn foo3<T: ?Sized + ?Sized + Debug>(a: T) {}
| ^^^^^^ ^^^^^^
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:20:12
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:12
|
LL | fn foo4<T: ?Sized + Debug + ?Sized >(a: T) {}
| ^^^^^^ ^^^^^^
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:27:17
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:17
|
LL | fn foo6(_: impl ?Sized + ?Sized) {}
| ^^^^^^ ^^^^^^
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:31:17
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:30:17
|
LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {}
| ^^^^^^ ^^^^^^
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:35:17
+error[E0203]: duplicate relaxed `Sized` bounds
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:34:17
|
LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {}
| ^^^^^^ ^^^^^^
error[E0277]: the size for values of type `T` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:9:23
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:8:23
|
LL | fn foo1<T: ?Sized>(a: T) {}
| - ^ doesn't have a size known at compile-time
@@ -54,7 +54,7 @@
| +
error[E0277]: the size for values of type `T` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:12:32
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:32
|
LL | fn foo2<T: ?Sized + ?Sized>(a: T) {}
| - ^ doesn't have a size known at compile-time
@@ -73,7 +73,7 @@
| +
error[E0277]: the size for values of type `T` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:16:40
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:40
|
LL | fn foo3<T: ?Sized + ?Sized + Debug>(a: T) {}
| - ^ doesn't have a size known at compile-time
@@ -92,7 +92,7 @@
| +
error[E0277]: the size for values of type `T` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:20:41
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:41
|
LL | fn foo4<T: ?Sized + Debug + ?Sized >(a: T) {}
| - ^ doesn't have a size known at compile-time
@@ -111,7 +111,7 @@
| +
error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:24:12
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:23:12
|
LL | fn foo5(_: impl ?Sized) {}
| ^^^^^^^^^^^
@@ -131,7 +131,7 @@
| +
error[E0277]: the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:27:12
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:12
|
LL | fn foo6(_: impl ?Sized + ?Sized) {}
| ^^^^^^^^^^^^^^^^^^^^
@@ -151,7 +151,7 @@
| +
error[E0277]: the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:31:12
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:30:12
|
LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -171,7 +171,7 @@
| +
error[E0277]: the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time
- --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:35:12
+ --> $DIR/fix-dyn-sized-fn-param-sugg.rs:34:12
|
LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
index e5abcae..14a2667 100644
--- a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
+++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
@@ -2,6 +2,6 @@
fn test<T: ?self::<i32>::Trait>() {}
//~^ ERROR type arguments are not allowed on module `maybe_bound_has_path_args`
-//~| ERROR relaxing a default bound only does something for `?Sized`
+//~| ERROR bound modifier `?` can only be applied to `Sized`
fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
index dc55b26..bf968b0 100644
--- a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
+++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
@@ -1,4 +1,4 @@
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/maybe-bound-has-path-args.rs:3:12
|
LL | fn test<T: ?self::<i32>::Trait>() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
index 9127c2d..e123f18 100644
--- a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
+++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
@@ -2,11 +2,11 @@
type Assoc;
}
fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
-//~^ ERROR relaxing a default bound
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
trait NoAssoc {}
fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
-//~^ ERROR relaxing a default bound
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
//~| ERROR associated type `Missing` not found for `NoAssoc`
fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
index 36a1e0a..b2ae058 100644
--- a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
+++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
@@ -1,10 +1,10 @@
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/maybe-bound-with-assoc.rs:4:16
|
LL | fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
| ^^^^^^^^^^^^^^^^^^^^^
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+error: bound modifier `?` can only be applied to `Sized`
--> $DIR/maybe-bound-with-assoc.rs:8:15
|
LL | fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs
new file mode 100644
index 0000000..47348b0
--- /dev/null
+++ b/tests/ui/trait-bounds/more_maybe_bounds.rs
@@ -0,0 +1,29 @@
+// FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`,
+// trying to relax non-default bounds should still be an error in all contexts! As you can see
+// there are places like supertrait bounds and trait object types where we currently don't perform
+// this check.
+#![feature(auto_traits, more_maybe_bounds, negative_impls)]
+
+trait Trait1 {}
+auto trait Trait2 {}
+
+// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
+trait Trait3: ?Trait1 {}
+trait Trait4 where Self: Trait1 {}
+
+// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`.
+fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
+fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+//~^ ERROR bound modifier `?` can only be applied to default traits like `Sized`
+//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
+//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
+
+struct S;
+impl !Trait2 for S {}
+impl Trait1 for S {}
+impl Trait3 for S {}
+
+fn main() {
+ foo(Box::new(S));
+ bar(&S);
+}
diff --git a/tests/ui/trait-bounds/more_maybe_bounds.stderr b/tests/ui/trait-bounds/more_maybe_bounds.stderr
new file mode 100644
index 0000000..09c9fc3
--- /dev/null
+++ b/tests/ui/trait-bounds/more_maybe_bounds.stderr
@@ -0,0 +1,20 @@
+error: bound modifier `?` can only be applied to default traits like `Sized`
+ --> $DIR/more_maybe_bounds.rs:16:20
+ |
+LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+ | ^^^^^^^
+
+error: bound modifier `?` can only be applied to default traits like `Sized`
+ --> $DIR/more_maybe_bounds.rs:16:30
+ |
+LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+ | ^^^^^^^
+
+error: bound modifier `?` can only be applied to default traits like `Sized`
+ --> $DIR/more_maybe_bounds.rs:16:40
+ |
+LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs
index 5f47778..8d1d3a4 100644
--- a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs
+++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs
@@ -2,9 +2,12 @@
const fn maybe_const_maybe<T: [const] ?Sized>() {}
//~^ ERROR `[const]` trait not allowed with `?` trait polarity modifier
+//~| ERROR `[const]` can only be applied to `const` traits
+//~| ERROR `[const]` can only be applied to `const` traits
fn const_maybe<T: const ?Sized>() {}
//~^ ERROR `const` trait not allowed with `?` trait polarity modifier
+//~| ERROR `const` can only be applied to `const` traits
const fn maybe_const_negative<T: [const] !Trait>() {}
//~^ ERROR `[const]` trait not allowed with `!` trait polarity modifier
diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr
index 429131f..0ac40c5 100644
--- a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr
+++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr
@@ -7,7 +7,7 @@
| there is not a well-defined meaning for a `[const] ?` trait
error: `const` trait not allowed with `?` trait polarity modifier
- --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:25
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:8:25
|
LL | fn const_maybe<T: const ?Sized>() {}
| ----- ^
@@ -15,7 +15,7 @@
| there is not a well-defined meaning for a `const ?` trait
error: `[const]` trait not allowed with `!` trait polarity modifier
- --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:42
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:12:42
|
LL | const fn maybe_const_negative<T: [const] !Trait>() {}
| ------- ^
@@ -23,7 +23,7 @@
| there is not a well-defined meaning for a `[const] !` trait
error: `const` trait not allowed with `!` trait polarity modifier
- --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:16:28
|
LL | fn const_negative<T: const !Trait>() {}
| ----- ^
@@ -31,16 +31,44 @@
| there is not a well-defined meaning for a `const !` trait
error: negative bounds are not supported
- --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:42
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:12:42
|
LL | const fn maybe_const_negative<T: [const] !Trait>() {}
| ^
error: negative bounds are not supported
- --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:16:28
|
LL | fn const_negative<T: const !Trait>() {}
| ^
-error: aborting due to 6 previous errors
+error: `[const]` can only be applied to `const` traits
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31
+ |
+LL | const fn maybe_const_maybe<T: [const] ?Sized>() {}
+ | ^^^^^^^ can't be applied to `Sized`
+ |
+note: `Sized` can't be used with `[const]` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+
+error: `[const]` can only be applied to `const` traits
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31
+ |
+LL | const fn maybe_const_maybe<T: [const] ?Sized>() {}
+ | ^^^^^^^ can't be applied to `Sized`
+ |
+note: `Sized` can't be used with `[const]` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `const` can only be applied to `const` traits
+ --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:8:19
+ |
+LL | fn const_maybe<T: const ?Sized>() {}
+ | ^^^^^ can't be applied to `Sized`
+ |
+note: `Sized` can't be used with `const` because it isn't `const`
+ --> $SRC_DIR/core/src/marker.rs:LL:COL
+
+error: aborting due to 9 previous errors
diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs
index 5069cd2..e7cca41 100644
--- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs
+++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs
@@ -64,4 +64,8 @@ fn main() {
x.leak_foo();
//~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied
x.maybe_leak_foo();
+ // Ensure that we validate the generic args of relaxed bounds in trait object types.
+ let _: dyn Trait + ?Leak<(), Undefined = ()>;
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
+ //~| ERROR associated type `Undefined` not found for `Leak`
}
diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr
index 48745e4..350233b 100644
--- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr
+++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr
@@ -18,6 +18,27 @@
LL | fn leak_foo(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo`
-error: aborting due to 2 previous errors
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/maybe-bounds-in-dyn-traits.rs:68:25
+ |
+LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
+ | ^^^^-------------------- help: remove the unnecessary generics
+ | |
+ | expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/maybe-bounds-in-dyn-traits.rs:44:12
+ |
+LL | auto trait Leak {}
+ | ^^^^
-For more information about this error, try `rustc --explain E0277`.
+error[E0220]: associated type `Undefined` not found for `Leak`
+ --> $DIR/maybe-bounds-in-dyn-traits.rs:68:34
+ |
+LL | let _: dyn Trait + ?Leak<(), Undefined = ()>;
+ | ^^^^^^^^^ associated type `Undefined` not found
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0107, E0220, E0277.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/maybe-polarity-pass.rs b/tests/ui/traits/maybe-polarity-pass.rs
deleted file mode 100644
index 1ccd52b..0000000
--- a/tests/ui/traits/maybe-polarity-pass.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#![feature(auto_traits)]
-#![feature(more_maybe_bounds)]
-#![feature(negative_impls)]
-
-trait Trait1 {}
-auto trait Trait2 {}
-
-trait Trait3 : ?Trait1 {}
-trait Trait4 where Self: Trait1 {}
-
-fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
-fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
-//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-
-struct S;
-impl !Trait2 for S {}
-impl Trait1 for S {}
-impl Trait3 for S {}
-
-fn main() {
- foo(Box::new(S));
- bar(&S);
-}
diff --git a/tests/ui/traits/maybe-polarity-pass.stderr b/tests/ui/traits/maybe-polarity-pass.stderr
deleted file mode 100644
index 1f378dd..0000000
--- a/tests/ui/traits/maybe-polarity-pass.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-polarity-pass.rs:12:20
- |
-LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
- | ^^^^^^^
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-polarity-pass.rs:12:30
- |
-LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
- | ^^^^^^^
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-polarity-pass.rs:12:40
- |
-LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
- | ^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/tests/ui/traits/maybe-polarity-repeated.rs b/tests/ui/traits/maybe-polarity-repeated.rs
deleted file mode 100644
index fd1ef56..0000000
--- a/tests/ui/traits/maybe-polarity-repeated.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(more_maybe_bounds)]
-
-trait Trait {}
-fn foo<T: ?Trait + ?Trait>(_: T) {}
-//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-
-fn main() {}
diff --git a/tests/ui/traits/maybe-polarity-repeated.stderr b/tests/ui/traits/maybe-polarity-repeated.stderr
deleted file mode 100644
index 4fa1dc4..0000000
--- a/tests/ui/traits/maybe-polarity-repeated.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/maybe-polarity-repeated.rs:4:11
- |
-LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
- | ^^^^^^ ^^^^^^
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-polarity-repeated.rs:4:11
- |
-LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
- | ^^^^^^
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-polarity-repeated.rs:4:20
- |
-LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
- | ^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0203`.
diff --git a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs
deleted file mode 100644
index 04963c9..0000000
--- a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! Test that ?Trait bounds are forbidden in supertraits and trait object types.
-//!
-//! While `?Sized` and other maybe bounds are allowed in type parameter bounds and where clauses,
-//! they are explicitly forbidden in certain syntactic positions:
-//! - As supertraits in trait definitions
-//! - In trait object type expressions
-//!
-//! See https://github.com/rust-lang/rust/issues/20503
-
-trait Tr: ?Sized {}
-//~^ ERROR `?Trait` is not permitted in supertraits
-
-type A1 = dyn Tr + (?Sized);
-//~^ ERROR `?Trait` is not permitted in trait object types
-type A2 = dyn for<'a> Tr + (?Sized);
-//~^ ERROR `?Trait` is not permitted in trait object types
-
-fn main() {}
diff --git a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr
deleted file mode 100644
index bd0baa5..0000000
--- a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-error[E0658]: `?Trait` is not permitted in supertraits
- --> $DIR/maybe-trait-bounds-forbidden-locations.rs:10:11
- |
-LL | trait Tr: ?Sized {}
- | ^^^^^^
- |
- = note: traits are `?Sized` by default
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-trait-bounds-forbidden-locations.rs:13:20
- |
-LL | type A1 = dyn Tr + (?Sized);
- | ^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-trait-bounds-forbidden-locations.rs:15:28
- |
-LL | type A2 = dyn for<'a> Tr + (?Sized);
- | ^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/wf-object/maybe-bound.rs b/tests/ui/traits/wf-object/maybe-bound.rs
deleted file mode 100644
index 17771e9..0000000
--- a/tests/ui/traits/wf-object/maybe-bound.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects).
-
-trait Foo {}
-
-type _0 = dyn ?Sized + Foo;
-//~^ ERROR `?Trait` is not permitted in trait object types
-
-type _1 = dyn Foo + ?Sized;
-//~^ ERROR `?Trait` is not permitted in trait object types
-
-type _2 = dyn Foo + ?Sized + ?Sized;
-//~^ ERROR `?Trait` is not permitted in trait object types
-//~| ERROR `?Trait` is not permitted in trait object types
-
-type _3 = dyn ?Sized + Foo;
-//~^ ERROR `?Trait` is not permitted in trait object types
-
-fn main() {}
diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr
deleted file mode 100644
index be7afab..0000000
--- a/tests/ui/traits/wf-object/maybe-bound.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-bound.rs:5:15
- |
-LL | type _0 = dyn ?Sized + Foo;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-bound.rs:8:21
- |
-LL | type _1 = dyn Foo + ?Sized;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-bound.rs:11:21
- |
-LL | type _2 = dyn Foo + ?Sized + ?Sized;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-bound.rs:11:30
- |
-LL | type _2 = dyn Foo + ?Sized + ?Sized;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` is not permitted in trait object types
- --> $DIR/maybe-bound.rs:15:15
- |
-LL | type _3 = dyn ?Sized + Foo;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs
index 3e6db3e..96360e0 100644
--- a/tests/ui/traits/wf-object/only-maybe-bound.rs
+++ b/tests/ui/traits/wf-object/only-maybe-bound.rs
@@ -2,6 +2,6 @@
type _0 = dyn ?Sized;
//~^ ERROR at least one trait is required for an object type [E0224]
-//~| ERROR ?Trait` is not permitted in trait object types
+//~| ERROR relaxed bounds are not permitted in trait object types
fn main() {}
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr
index 2626947..6ae4568 100644
--- a/tests/ui/traits/wf-object/only-maybe-bound.stderr
+++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr
@@ -1,11 +1,8 @@
-error[E0658]: `?Trait` is not permitted in trait object types
+error: relaxed bounds are not permitted in trait object types
--> $DIR/only-maybe-bound.rs:3:15
|
LL | type _0 = dyn ?Sized;
| ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0224]: at least one trait is required for an object type
--> $DIR/only-maybe-bound.rs:3:11
@@ -15,5 +12,4 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0224, E0658.
-For more information about an error, try `rustc --explain E0224`.
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs
index a4e4969..432aacb 100644
--- a/tests/ui/type/pattern_types/validity.rs
+++ b/tests/ui/type/pattern_types/validity.rs
@@ -11,7 +11,7 @@
//~^ ERROR: constructing invalid value: encountered 0
const BAD_UNINIT: pattern_type!(u32 is 1..) =
- //~^ ERROR: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: this operation requires initialized memory
unsafe { std::mem::transmute(std::mem::MaybeUninit::<u32>::uninit()) };
const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&42) };
@@ -27,7 +27,7 @@
//~^ ERROR: constructing invalid value at .0.0: encountered 0
const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') =
- //~^ ERROR: using uninitialized data, but this operation requires initialized memory
+ //~^ ERROR: this operation requires initialized memory
unsafe { std::mem::transmute(std::mem::MaybeUninit::<u32>::uninit()) };
const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') };
diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr
index 4f4c160..b545cd7 100644
--- a/tests/ui/type/pattern_types/validity.stderr
+++ b/tests/ui/type/pattern_types/validity.stderr
@@ -9,11 +9,15 @@
HEX_DUMP
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> $DIR/validity.rs:13:1
|
LL | const BAD_UNINIT: pattern_type!(u32 is 1..) =
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+ }
error[E0080]: unable to turn pointer into integer
--> $DIR/validity.rs:17:1
@@ -46,11 +50,15 @@
HEX_DUMP
}
-error[E0080]: using uninitialized data, but this operation requires initialized memory
+error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory
--> $DIR/validity.rs:29:1
|
LL | const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') =
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `CHAR_UNINIT` failed here
+ |
+ = note: the raw bytes of the constant (size: 4, align: 4) {
+ __ __ __ __ │ ░░░░
+ }
error[E0080]: constructing invalid value: encountered 97, but expected something in the range 65..=89
--> $DIR/validity.rs:33:1
diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr
index 01e3491..a348e1e 100644
--- a/tests/ui/typeck/issue-91334.stderr
+++ b/tests/ui/typeck/issue-91334.stderr
@@ -11,9 +11,8 @@
--> $DIR/issue-91334.rs:7:23
|
LL | fn f(){||yield(((){),
- | - - - ^
- | | | |
- | | | missing open `(` for this delimiter
+ | - - ^
+ | | |
| | unclosed delimiter
| unclosed delimiter
diff --git a/tests/ui/unsized/maybe-bounds-where.rs b/tests/ui/unsized/maybe-bounds-where.rs
deleted file mode 100644
index 4c41416..0000000
--- a/tests/ui/unsized/maybe-bounds-where.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-struct S1<T>(T) where (T): ?Sized;
-//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
-
-struct S2<T>(T) where u8: ?Sized;
-//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
-
-struct S3<T>(T) where &'static T: ?Sized;
-//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
-
-trait Trait<'a> {}
-
-struct S4<T>(T) where for<'a> T: ?Trait<'a>;
-//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
-//~| ERROR relaxing a default bound only does something for `?Sized`
-
-struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
-//~^ ERROR type parameter has more than one relaxed default bound
-//~| ERROR relaxing a default bound only does something for `?Sized`
-
-impl<T> S1<T> {
- fn f() where T: ?Sized {}
- //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
-}
-
-fn main() {
- let u = vec![1, 2, 3];
- let _s: S5<[u8]> = S5(&u[..]); // OK
-}
diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/maybe-bounds-where.stderr
deleted file mode 100644
index fb6d37c..0000000
--- a/tests/ui/unsized/maybe-bounds-where.stderr
+++ /dev/null
@@ -1,70 +0,0 @@
-error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/maybe-bounds-where.rs:1:28
- |
-LL | struct S1<T>(T) where (T): ?Sized;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/maybe-bounds-where.rs:4:27
- |
-LL | struct S2<T>(T) where u8: ?Sized;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/maybe-bounds-where.rs:7:35
- |
-LL | struct S3<T>(T) where &'static T: ?Sized;
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/maybe-bounds-where.rs:12:34
- |
-LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
- | ^^^^^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/maybe-bounds-where.rs:21:21
- |
-LL | fn f() where T: ?Sized {}
- | ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-bounds-where.rs:12:34
- |
-LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
- | ^^^^^^^^^^
-
-error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/maybe-bounds-where.rs:16:33
- |
-LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
- | ^^^^^^^^^^^^^^^ ^^^^^^
- |
- = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
- --> $DIR/maybe-bounds-where.rs:16:33
- |
-LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
- | ^^^^^^^^^^^^^^^
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0203, E0658.
-For more information about an error, try `rustc --explain E0203`.
diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs
new file mode 100644
index 0000000..b8eda1e
--- /dev/null
+++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs
@@ -0,0 +1,34 @@
+// Test various places where relaxed bounds are not permitted.
+//
+// Relaxed bounds are only permitted inside impl-Trait, assoc ty item bounds and
+// on type params defined by the closest item.
+
+struct S1<T>(T) where (T): ?Sized; //~ ERROR this relaxed bound is not permitted here
+
+struct S2<T>(T) where u8: ?Sized; //~ ERROR this relaxed bound is not permitted here
+
+struct S3<T>(T) where &'static T: ?Sized; //~ ERROR this relaxed bound is not permitted here
+
+trait Trait<'a> {}
+
+struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+//~^ ERROR this relaxed bound is not permitted here
+//~| ERROR bound modifier `?` can only be applied to `Sized`
+
+struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+//~^ ERROR bound modifier `?` can only be applied to `Sized`
+
+impl<T> S1<T> {
+ fn f() where T: ?Sized {} //~ ERROR this relaxed bound is not permitted here
+}
+
+trait Tr: ?Sized {} //~ ERROR relaxed bounds are not permitted in supertrait bounds
+
+// Test that relaxed `Sized` bounds are rejected in trait object types:
+
+type O1 = dyn Tr + ?Sized; //~ ERROR relaxed bounds are not permitted in trait object types
+type O2 = dyn ?Sized + ?Sized + Tr;
+//~^ ERROR relaxed bounds are not permitted in trait object types
+//~| ERROR relaxed bounds are not permitted in trait object types
+
+fn main() {}
diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr
new file mode 100644
index 0000000..30285d6
--- /dev/null
+++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr
@@ -0,0 +1,80 @@
+error: this relaxed bound is not permitted here
+ --> $DIR/relaxed-bounds-invalid-places.rs:6:28
+ |
+LL | struct S1<T>(T) where (T): ?Sized;
+ | ^^^^^^
+ |
+ = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
+
+error: this relaxed bound is not permitted here
+ --> $DIR/relaxed-bounds-invalid-places.rs:8:27
+ |
+LL | struct S2<T>(T) where u8: ?Sized;
+ | ^^^^^^
+ |
+ = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
+
+error: this relaxed bound is not permitted here
+ --> $DIR/relaxed-bounds-invalid-places.rs:10:35
+ |
+LL | struct S3<T>(T) where &'static T: ?Sized;
+ | ^^^^^^
+ |
+ = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
+
+error: this relaxed bound is not permitted here
+ --> $DIR/relaxed-bounds-invalid-places.rs:14:34
+ |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+ | ^^^^^^^^^^
+ |
+ = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
+
+error: this relaxed bound is not permitted here
+ --> $DIR/relaxed-bounds-invalid-places.rs:22:21
+ |
+LL | fn f() where T: ?Sized {}
+ | ^^^^^^
+ |
+ = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
+
+error: relaxed bounds are not permitted in supertrait bounds
+ --> $DIR/relaxed-bounds-invalid-places.rs:25:11
+ |
+LL | trait Tr: ?Sized {}
+ | ^^^^^^
+ |
+ = note: traits are `?Sized` by default
+
+error: relaxed bounds are not permitted in trait object types
+ --> $DIR/relaxed-bounds-invalid-places.rs:29:20
+ |
+LL | type O1 = dyn Tr + ?Sized;
+ | ^^^^^^
+
+error: relaxed bounds are not permitted in trait object types
+ --> $DIR/relaxed-bounds-invalid-places.rs:30:15
+ |
+LL | type O2 = dyn ?Sized + ?Sized + Tr;
+ | ^^^^^^
+
+error: relaxed bounds are not permitted in trait object types
+ --> $DIR/relaxed-bounds-invalid-places.rs:30:24
+ |
+LL | type O2 = dyn ?Sized + ?Sized + Tr;
+ | ^^^^^^
+
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/relaxed-bounds-invalid-places.rs:14:34
+ |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+ | ^^^^^^^^^^
+
+error: bound modifier `?` can only be applied to `Sized`
+ --> $DIR/relaxed-bounds-invalid-places.rs:18:33
+ |
+LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
+