Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-06-05 05:02:35 +00:00
commit bd898e38af
269 changed files with 1722 additions and 1675 deletions

View file

@ -758,7 +758,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
niche_variants,
niche_start,
},
tag_field: 0,
tag_field: FieldIdx::new(0),
variants: IndexVec::new(),
},
fields: FieldsShape::Arbitrary {
@ -1072,7 +1072,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
variants: Variants::Multiple {
tag,
tag_encoding: TagEncoding::Direct,
tag_field: 0,
tag_field: FieldIdx::new(0),
variants: IndexVec::new(),
},
fields: FieldsShape::Arbitrary {

View file

@ -158,7 +158,7 @@ pub(super) fn layout<
// Build a prefix layout, including "promoting" all ineligible
// locals as part of the prefix. We compute the layout of all of
// these fields at once to get optimal packing.
let tag_index = prefix_layouts.len();
let tag_index = prefix_layouts.next_index();
// `variant_fields` already accounts for the reserved variants, so no need to add them.
let max_discr = (variant_fields.len() - 1) as u128;
@ -187,7 +187,7 @@ pub(super) fn layout<
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
// "outer" and "promoted" fields respectively.
let b_start = FieldIdx::new(tag_index + 1);
let b_start = tag_index.plus(1);
let offsets_b = IndexVec::from_raw(offsets.raw.split_off(b_start.index()));
let offsets_a = offsets;

View file

@ -1573,7 +1573,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
Multiple {
tag: Scalar,
tag_encoding: TagEncoding<VariantIdx>,
tag_field: usize,
tag_field: FieldIdx,
variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
},
}

View file

@ -57,7 +57,9 @@ impl TokenTree {
match (self, other) {
(TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind,
(TokenTree::Delimited(.., delim, tts), TokenTree::Delimited(.., delim2, tts2)) => {
delim == delim2 && tts.eq_unspanned(tts2)
delim == delim2
&& tts.len() == tts2.len()
&& tts.iter().zip(tts2.iter()).all(|(a, b)| a.eq_unspanned(b))
}
_ => false,
}
@ -694,18 +696,6 @@ impl TokenStream {
TokenStreamIter::new(self)
}
/// Compares two `TokenStream`s, checking equality without regarding span information.
pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
let mut iter1 = self.iter();
let mut iter2 = other.iter();
for (tt1, tt2) in iter::zip(&mut iter1, &mut iter2) {
if !tt1.eq_unspanned(tt2) {
return false;
}
}
iter1.next().is_none() && iter2.next().is_none()
}
/// Create a token stream containing a single token with alone spacing. The
/// spacing used for the final token in a constructed stream doesn't matter
/// because it's never used. In practice we arbitrarily use

View file

@ -121,6 +121,10 @@ pub enum LifetimeCtxt {
/// explicitly, you need to override each method. (And you also need
/// to monitor future changes to `Visitor` in case a new method with a
/// new default implementation gets introduced.)
///
/// Every `walk_*` method uses deconstruction to access fields of structs and
/// enums. This will result in a compile error if a field is added, which makes
/// it more likely the appropriate visit call will be added for it.
pub trait Visitor<'ast>: Sized {
/// The result type of the `visit_*` methods. Can be either `()`,
/// or `ControlFlow<T>`.

View file

@ -53,7 +53,7 @@ fn parse_unstable<'a>(
for param in list.mixed() {
let param_span = param.span();
if let Some(ident) = param.meta_item().and_then(|i| i.path_without_args().word()) {
if let Some(ident) = param.meta_item().and_then(|i| i.path().word()) {
res.push(ident.name);
} else {
cx.emit_err(session_diagnostics::ExpectsFeatures {

View file

@ -79,7 +79,7 @@ impl SingleAttributeParser for DeprecationParser {
return None;
};
let ident_name = param.path_without_args().word_sym();
let ident_name = param.path().word_sym();
match ident_name {
Some(name @ sym::since) => {
@ -102,7 +102,7 @@ impl SingleAttributeParser for DeprecationParser {
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param_span,
item: param.path_without_args().to_string(),
item: param.path().to_string(),
expected: if features.deprecated_suggestion() {
&["since", "note", "suggestion"]
} else {

View file

@ -96,7 +96,7 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option<Repr
// FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
// structure.
let (name, ident_span) = if let Some(ident) = param.path_without_args().word() {
let (name, ident_span) = if let Some(ident) = param.path().word() {
(Some(ident.name), ident.span)
} else {
(None, DUMMY_SP)

View file

@ -204,7 +204,7 @@ fn insert_value_into_option_or_error(
if item.is_some() {
cx.emit_err(session_diagnostics::MultipleItem {
span: param.span(),
item: param.path_without_args().to_string(),
item: param.path().to_string(),
});
None
} else if let Some(v) = param.args().name_value()
@ -242,13 +242,13 @@ pub(crate) fn parse_stability(
return None;
};
match param.path_without_args().word_sym() {
match param.path().word_sym() {
Some(sym::feature) => insert_value_into_option_or_error(cx, &param, &mut feature)?,
Some(sym::since) => insert_value_into_option_or_error(cx, &param, &mut since)?,
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param_span,
item: param.path_without_args().to_string(),
item: param.path().to_string(),
expected: &["feature", "since"],
});
return None;
@ -310,7 +310,7 @@ pub(crate) fn parse_unstability(
return None;
};
match param.path_without_args().word_sym() {
match param.path().word_sym() {
Some(sym::feature) => insert_value_into_option_or_error(cx, &param, &mut feature)?,
Some(sym::reason) => insert_value_into_option_or_error(cx, &param, &mut reason)?,
Some(sym::issue) => {
@ -349,7 +349,7 @@ pub(crate) fn parse_unstability(
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param.span(),
item: param.path_without_args().to_string(),
item: param.path().to_string(),
expected: &["feature", "reason", "issue", "soft", "implied_by"],
});
return None;

View file

@ -264,7 +264,8 @@ impl<'sess> AttributeParser<'sess> {
// }
ast::AttrKind::Normal(n) => {
let parser = MetaItemParser::from_attr(n, self.dcx());
let (path, args) = parser.deconstruct();
let path = parser.path();
let args = parser.args();
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
if let Some(accept) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {

View file

@ -252,9 +252,13 @@ impl<'a> MetaItemParser<'a> {
}
}
/// Gets just the path, without the args.
pub fn path_without_args(&self) -> PathParser<'a> {
self.path.clone()
/// Gets just the path, without the args. Some examples:
///
/// - `#[rustfmt::skip]`: `rustfmt::skip` is a path
/// - `#[allow(clippy::complexity)]`: `clippy::complexity` is a path
/// - `#[inline]`: `inline` is a single segment path
pub fn path(&self) -> &PathParser<'a> {
&self.path
}
/// Gets just the args parser, without caring about the path.
@ -262,50 +266,14 @@ impl<'a> MetaItemParser<'a> {
&self.args
}
pub fn deconstruct(&self) -> (PathParser<'a>, &ArgParser<'a>) {
(self.path_without_args(), self.args())
}
/// Asserts that this MetaItem starts with a path. Some examples:
///
/// - `#[rustfmt::skip]`: `rustfmt::skip` is a path
/// - `#[allow(clippy::complexity)]`: `clippy::complexity` is a path
/// - `#[inline]`: `inline` is a single segment path
pub fn path(&self) -> (PathParser<'a>, &ArgParser<'a>) {
self.deconstruct()
}
/// Asserts that this MetaItem starts with a word, or single segment path.
/// Doesn't return the args parser.
///
/// For examples. see [`Self::word`]
pub fn word_without_args(&self) -> Option<Ident> {
Some(self.word()?.0)
}
/// Asserts that this MetaItem starts with a word, or single segment path.
///
/// Some examples:
/// - `#[inline]`: `inline` is a word
/// - `#[rustfmt::skip]`: `rustfmt::skip` is a path,
/// and not a word and should instead be parsed using [`path`](Self::path)
pub fn word(&self) -> Option<(Ident, &ArgParser<'a>)> {
let (path, args) = self.deconstruct();
Some((path.word()?, args))
}
/// Asserts that this MetaItem starts with some specific word.
///
/// See [`word`](Self::word) for examples of what a word is.
pub fn word_is(&self, sym: Symbol) -> Option<&ArgParser<'a>> {
self.path_without_args().word_is(sym).then(|| self.args())
}
/// Asserts that this MetaItem starts with some specific path.
///
/// See [`word`](Self::path) for examples of what a word is.
pub fn path_is(&self, segments: &[Symbol]) -> Option<&ArgParser<'a>> {
self.path_without_args().segments_is(segments).then(|| self.args())
self.path().word_is(sym).then(|| self.args())
}
}
@ -548,7 +516,7 @@ impl<'a> MetaItemListParser<'a> {
}
/// Lets you pick and choose as what you want to parse each element in the list
pub fn mixed<'s>(&'s self) -> impl Iterator<Item = &'s MetaItemOrLitParser<'a>> + 's {
pub fn mixed(&self) -> impl Iterator<Item = &MetaItemOrLitParser<'a>> {
self.sub_parsers.iter()
}
@ -560,20 +528,6 @@ impl<'a> MetaItemListParser<'a> {
self.len() == 0
}
/// Asserts that every item in the list is another list starting with a word.
///
/// See [`MetaItemParser::word`] for examples of words.
pub fn all_word_list<'s>(&'s self) -> Option<Vec<(Ident, &'s ArgParser<'a>)>> {
self.mixed().map(|i| i.meta_item()?.word()).collect()
}
/// Asserts that every item in the list is another list starting with a full path.
///
/// See [`MetaItemParser::path`] for examples of paths.
pub fn all_path_list<'s>(&'s self) -> Option<Vec<(PathParser<'a>, &'s ArgParser<'a>)>> {
self.mixed().map(|i| Some(i.meta_item()?.path())).collect()
}
/// Returns Some if the list contains only a single element.
///
/// Inside the Some is the parser to parse this single element.

View file

@ -3314,7 +3314,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
"function parameter".to_string(),
"function parameter borrowed here".to_string(),
),
LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
LocalKind::Temp
if self.body.local_decls[local].is_user_variable()
&& !self.body.local_decls[local]
.source_info
.span
.in_external_macro(self.infcx.tcx.sess.source_map()) =>
{
("local binding".to_string(), "local binding introduced here".to_string())
}
LocalKind::ReturnPointer | LocalKind::Temp => {

View file

@ -28,7 +28,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
tag_encoding: TagEncoding::Direct,
variants: _,
} => {
let ptr = place.place_field(fx, FieldIdx::new(tag_field));
let ptr = place.place_field(fx, tag_field);
let to = layout.ty.discriminant_for_variant(fx.tcx, variant_index).unwrap().val;
let to = match ptr.layout().ty.kind() {
ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
@ -53,7 +53,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
variants: _,
} => {
if variant_index != untagged_variant {
let niche = place.place_field(fx, FieldIdx::new(tag_field));
let niche = place.place_field(fx, tag_field);
let niche_type = fx.clif_type(niche.layout().ty).unwrap();
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
let niche_value = (niche_value as u128).wrapping_add(niche_start);
@ -118,7 +118,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
let cast_to = fx.clif_type(dest_layout.ty).unwrap();
// Read the tag/niche-encoded discriminant from memory.
let tag = value.value_field(fx, FieldIdx::new(tag_field));
let tag = value.value_field(fx, tag_field);
let tag = tag.load_scalar(fx);
// Decode the discriminant (specifically if it's niche-encoded).

View file

@ -1,7 +1,7 @@
use std::borrow::Cow;
use libc::c_uint;
use rustc_abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
use rustc_abi::{Align, Endian, FieldIdx, Size, TagEncoding, VariantIdx, Variants};
use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods};
@ -401,7 +401,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
enum_type_and_layout: TyAndLayout<'tcx>,
enum_type_di_node: &'ll DIType,
variant_indices: impl Iterator<Item = VariantIdx> + Clone,
tag_field: usize,
tag_field: FieldIdx,
untagged_variant_index: Option<VariantIdx>,
) -> SmallVec<&'ll DIType> {
let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
@ -805,7 +805,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
variant_field_infos: &[VariantFieldInfo<'ll>],
discr_type_di_node: &'ll DIType,
tag_base_type: Ty<'tcx>,
tag_field: usize,
tag_field: FieldIdx,
untagged_variant_index: Option<VariantIdx>,
di_flags: DIFlags,
) -> SmallVec<&'ll DIType> {
@ -858,7 +858,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
}));
assert_eq!(
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field.as_usize()).ty),
cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout))
);
@ -875,7 +875,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
Endian::Big => (8, 0),
};
let tag_field_offset = enum_type_and_layout.fields.offset(tag_field).bytes();
let tag_field_offset = enum_type_and_layout.fields.offset(tag_field.as_usize()).bytes();
let lo_offset = Size::from_bytes(tag_field_offset + lo_offset);
let hi_offset = Size::from_bytes(tag_field_offset + hi_offset);
@ -905,8 +905,8 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
cx,
enum_type_di_node,
TAG_FIELD_NAME,
enum_type_and_layout.field(cx, tag_field),
enum_type_and_layout.fields.offset(tag_field),
enum_type_and_layout.field(cx, tag_field.as_usize()),
enum_type_and_layout.fields.offset(tag_field.as_usize()),
di_flags,
tag_base_type_di_node,
None,

View file

@ -373,7 +373,7 @@ fn build_discr_member_di_node<'ll, 'tcx>(
file,
UNKNOWN_LINE_NUMBER,
layout,
enum_or_coroutine_type_and_layout.fields.offset(tag_field),
enum_or_coroutine_type_and_layout.fields.offset(tag_field.as_usize()),
DIFlags::FlagArtificial,
ty,
))

View file

@ -282,6 +282,14 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
}
// Filter out features that are not supported by the current LLVM version
("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
(
"s390x",
"message-security-assist-extension12"
| "concurrent-functions"
| "miscellaneous-extensions-4"
| "vector-enhancements-3"
| "vector-packed-decimal-enhancement-3",
) if get_version().0 < 20 => None,
// Enable the evex512 target feature if an avx512 target feature is enabled.
("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
s,

View file

@ -462,10 +462,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
let tag_op = match self.val {
OperandValue::ZeroSized => bug!(),
OperandValue::Immediate(_) | OperandValue::Pair(_, _) => {
self.extract_field(fx, bx, tag_field)
self.extract_field(fx, bx, tag_field.as_usize())
}
OperandValue::Ref(place) => {
let tag = place.with_type(self.layout).project_field(bx, tag_field);
let tag = place.with_type(self.layout).project_field(bx, tag_field.as_usize());
bx.load_operand(tag)
}
};

View file

@ -250,7 +250,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
Variants::Single { index } => assert_eq!(index, variant_index),
Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
let ptr = self.project_field(bx, tag_field);
let ptr = self.project_field(bx, tag_field.as_usize());
let to =
self.layout.ty.discriminant_for_variant(bx.tcx(), variant_index).unwrap().val;
bx.store_to_place(
@ -265,7 +265,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
..
} => {
if variant_index != untagged_variant {
let niche = self.project_field(bx, tag_field);
let niche = self.project_field(bx, tag_field.as_usize());
let niche_llty = bx.cx().immediate_backend_type(niche.layout);
let BackendRepr::Scalar(scalar) = niche.layout.backend_repr else {
bug!("expected a scalar placeref for the niche");

View file

@ -1,6 +1,6 @@
//! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants};
use rustc_abi::{self as abi, FieldIdx, TagEncoding, VariantIdx, Variants};
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty};
use rustc_middle::{mir, span_bug};
@ -26,7 +26,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// No need to validate that the discriminant here because the
// `TyAndLayout::for_variant()` call earlier already checks the
// variant is valid.
let tag_dest = self.project_field(dest, tag_field)?;
let tag_dest = self.project_field(dest, tag_field.as_usize())?;
self.write_scalar(tag, &tag_dest)
}
None => {
@ -96,7 +96,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
// Read tag and sanity-check `tag_layout`.
let tag_val = self.read_immediate(&self.project_field(op, tag_field)?)?;
let tag_val = self.read_immediate(&self.project_field(op, tag_field.as_usize())?)?;
assert_eq!(tag_layout.size, tag_val.layout.size);
assert_eq!(tag_layout.backend_repr.is_signed(), tag_val.layout.backend_repr.is_signed());
trace!("tag value: {}", tag_val);
@ -231,7 +231,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
&self,
layout: TyAndLayout<'tcx>,
variant_index: VariantIdx,
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
) -> InterpResult<'tcx, Option<(ScalarInt, FieldIdx)>> {
// Layout computation excludes uninhabited variants from consideration.
// Therefore, there's no way to represent those variants in the given layout.
// Essentially, uninhabited variants do not have a tag that corresponds to their

View file

@ -294,7 +294,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
// First, check if we are projecting to a variant.
match layout.variants {
Variants::Multiple { tag_field, .. } => {
if tag_field == field {
if tag_field.as_usize() == field {
return match layout.ty.kind() {
ty::Adt(def, ..) if def.is_enum() => PathElem::EnumTag,
ty::Coroutine(..) => PathElem::CoroutineTag,

View file

@ -200,6 +200,10 @@ use nested_filter::NestedFilter;
/// explicitly, you need to override each method. (And you also need
/// to monitor future changes to `Visitor` in case a new method with a
/// new default implementation gets introduced.)
///
/// Every `walk_*` method uses deconstruction to access fields of structs and
/// enums. This will result in a compile error if a field is added, which makes
/// it more likely the appropriate visit call will be added for it.
pub trait Visitor<'v>: Sized {
// This type should not be overridden, it exists for convenient usage as `Self::MaybeTyCtxt`.
type MaybeTyCtxt: HirTyCtxt<'v> = <Self::NestedFilter as NestedFilter<'v>>::MaybeTyCtxt;
@ -1201,7 +1205,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
visitor: &mut V,
trait_item: &'v TraitItem<'v>,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
try_visit!(visitor.visit_ident(ident));
@ -1240,7 +1243,6 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
trait_item_ref: &'v TraitItemRef,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref;
try_visit!(visitor.visit_nested_trait_item(id));
try_visit!(visitor.visit_ident(ident));
@ -1251,7 +1253,6 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
visitor: &mut V,
impl_item: &'v ImplItem<'v>,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItem {
owner_id: _,
ident,
@ -1286,7 +1287,6 @@ pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
foreign_item_ref: &'v ForeignItemRef,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
try_visit!(visitor.visit_nested_foreign_item(id));
visitor.visit_ident(ident)
@ -1296,7 +1296,6 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
impl_item_ref: &'v ImplItemRef,
) -> V::Result {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref;
try_visit!(visitor.visit_nested_impl_item(id));
try_visit!(visitor.visit_ident(ident));
@ -1333,8 +1332,9 @@ pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>(
match *arg {
PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt),
PreciseCapturingArg::Param(param) => {
let PreciseCapturingNonLifetimeArg { hir_id, ident: _, res: _ } = param;
visitor.visit_id(hir_id)
let PreciseCapturingNonLifetimeArg { hir_id, ident, res: _ } = param;
try_visit!(visitor.visit_id(hir_id));
visitor.visit_ident(ident)
}
}
}

View file

@ -702,6 +702,29 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let generics = tcx.generics_of(def_id);
for param in &generics.own_params {
match param.kind {
ty::GenericParamDefKind::Lifetime { .. } => {}
ty::GenericParamDefKind::Type { has_default, .. } => {
if has_default {
tcx.ensure_ok().type_of(param.def_id);
}
}
ty::GenericParamDefKind::Const { has_default, .. } => {
tcx.ensure_ok().type_of(param.def_id);
if has_default {
// need to store default and type of default
let ct = tcx.const_param_default(param.def_id).skip_binder();
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
tcx.ensure_ok().type_of(uv.def);
}
}
}
}
}
match tcx.def_kind(def_id) {
DefKind::Static { .. } => {
check_static_inhabited(tcx, def_id);
@ -770,6 +793,16 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
} else {
check_opaque(tcx, def_id);
}
tcx.ensure_ok().predicates_of(def_id);
tcx.ensure_ok().explicit_item_bounds(def_id);
tcx.ensure_ok().explicit_item_self_bounds(def_id);
tcx.ensure_ok().item_bounds(def_id);
tcx.ensure_ok().item_self_bounds(def_id);
if tcx.is_conditionally_const(def_id) {
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
tcx.ensure_ok().const_conditions(def_id);
}
}
DefKind::TyAlias => {
check_type_alias_type_params_are_used(tcx, def_id);
@ -827,6 +860,15 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
}
}
DefKind::Closure => {
// This is guaranteed to be called by metadata encoding,
// we still call it in wfcheck eagerly to ensure errors in codegen
// attrs prevent lints from spamming the output.
tcx.ensure_ok().codegen_fn_attrs(def_id);
// We do not call `type_of` for closures here as that
// depends on typecheck and would therefore hide
// any further errors in case one typeck fails.
}
_ => {}
}
}

View file

@ -7,7 +7,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{AmbigArg, ItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@ -40,7 +40,6 @@ use tracing::{debug, instrument};
use {rustc_ast as ast, rustc_hir as hir};
use crate::autoderef::Autoderef;
use crate::collect::CollectItemTypesVisitor;
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
use crate::errors::InvalidReceiverTyHint;
use crate::{errors, fluent_generated as fluent};
@ -195,7 +194,9 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
hir::Node::TraitItem(item) => check_trait_item(tcx, item),
hir::Node::ImplItem(item) => check_impl_item(tcx, item),
hir::Node::ForeignItem(item) => check_foreign_item(tcx, item),
hir::Node::OpaqueTy(_) => Ok(crate::check::check::check_item_type(tcx, def_id)),
hir::Node::ConstBlock(_) | hir::Node::Expr(_) | hir::Node::OpaqueTy(_) => {
Ok(crate::check::check::check_item_type(tcx, def_id))
}
_ => unreachable!("{node:?}"),
};
@ -229,7 +230,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
?item.owner_id,
item.name = ? tcx.def_path_str(def_id)
);
CollectItemTypesVisitor { tcx }.visit_item(item);
crate::collect::lower_item(tcx, item.item_id());
crate::collect::reject_placeholder_type_signatures_in_item(tcx, item);
let res = match item.kind {
// Right now we check that every default trait implementation
@ -350,8 +352,6 @@ fn check_foreign_item<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let def_id = item.owner_id.def_id;
CollectItemTypesVisitor { tcx }.visit_foreign_item(item);
debug!(
?item.owner_id,
item.name = ? tcx.def_path_str(def_id)
@ -374,7 +374,7 @@ fn check_trait_item<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let def_id = trait_item.owner_id.def_id;
CollectItemTypesVisitor { tcx }.visit_trait_item(trait_item);
crate::collect::lower_trait_item(tcx, trait_item.trait_item_id());
let (method_sig, span) = match trait_item.kind {
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@ -939,7 +939,7 @@ fn check_impl_item<'tcx>(
tcx: TyCtxt<'tcx>,
impl_item: &'tcx hir::ImplItem<'tcx>,
) -> Result<(), ErrorGuaranteed> {
CollectItemTypesVisitor { tcx }.visit_impl_item(impl_item);
crate::collect::lower_impl_item(tcx, impl_item.impl_item_id());
let (method_sig, span) = match impl_item.kind {
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
@ -2402,8 +2402,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
}
}
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
let items = tcx.hir_module_items(module);
fn check_type_wf(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> {
let items = tcx.hir_crate_items(());
let res = items
.par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))
.and(items.par_impl_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)))
@ -2411,10 +2411,10 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
.and(
items.par_foreign_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)),
)
.and(items.par_nested_bodies(|item| tcx.ensure_ok().check_well_formed(item)))
.and(items.par_opaques(|item| tcx.ensure_ok().check_well_formed(item)));
if module == LocalModDefId::CRATE_DEF_ID {
super::entry::check_for_entry_fn(tcx);
}
super::entry::check_for_entry_fn(tcx);
res
}
@ -2552,5 +2552,5 @@ struct RedundantLifetimeArgsLint<'tcx> {
}
pub fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
*providers = Providers { check_type_wf, check_well_formed, ..*providers };
}

View file

@ -28,11 +28,10 @@ use rustc_errors::{
};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics};
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_generics};
use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
use rustc_middle::hir::nested_filter;
use rustc_middle::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions};
@ -148,10 +147,6 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
}
}
pub(crate) struct CollectItemTypesVisitor<'tcx> {
pub tcx: TyCtxt<'tcx>,
}
/// If there are any placeholder types (`_`), emit an error explaining that this is not allowed
/// and suggest adding type parameters in the appropriate place, taking into consideration any and
/// all already existing generic type parameters to avoid suggesting a name that is already in use.
@ -243,7 +238,7 @@ pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>(
err
}
fn reject_placeholder_type_signatures_in_item<'tcx>(
pub(super) fn reject_placeholder_type_signatures_in_item<'tcx>(
tcx: TyCtxt<'tcx>,
item: &'tcx hir::Item<'tcx>,
) {
@ -274,81 +269,6 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
);
}
impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
self.tcx
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
lower_item(self.tcx, item.item_id());
reject_placeholder_type_signatures_in_item(self.tcx, item);
intravisit::walk_item(self, item);
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
for param in generics.params {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { default: Some(_), .. } => {
self.tcx.ensure_ok().type_of(param.def_id);
}
hir::GenericParamKind::Type { .. } => {}
hir::GenericParamKind::Const { default, .. } => {
self.tcx.ensure_ok().type_of(param.def_id);
if let Some(default) = default {
// need to store default and type of default
self.tcx.ensure_ok().const_param_default(param.def_id);
if let hir::ConstArgKind::Anon(ac) = default.kind {
self.tcx.ensure_ok().type_of(ac.def_id);
}
}
}
}
}
intravisit::walk_generics(self, generics);
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Closure(closure) = expr.kind {
self.tcx.ensure_ok().generics_of(closure.def_id);
self.tcx.ensure_ok().codegen_fn_attrs(closure.def_id);
// We do not call `type_of` for closures here as that
// depends on typecheck and would therefore hide
// any further errors in case one typeck fails.
}
intravisit::walk_expr(self, expr);
}
/// Don't call `type_of` on opaque types, since that depends on type checking function bodies.
/// `check_item_type` ensures that it's called instead.
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
let def_id = opaque.def_id;
self.tcx.ensure_ok().generics_of(def_id);
self.tcx.ensure_ok().predicates_of(def_id);
self.tcx.ensure_ok().explicit_item_bounds(def_id);
self.tcx.ensure_ok().explicit_item_self_bounds(def_id);
self.tcx.ensure_ok().item_bounds(def_id);
self.tcx.ensure_ok().item_self_bounds(def_id);
if self.tcx.is_conditionally_const(def_id) {
self.tcx.ensure_ok().explicit_implied_const_bounds(def_id);
self.tcx.ensure_ok().const_conditions(def_id);
}
intravisit::walk_opaque_ty(self, opaque);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
lower_trait_item(self.tcx, trait_item.trait_item_id());
intravisit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
lower_impl_item(self.tcx, impl_item.impl_item_id());
intravisit::walk_impl_item(self, impl_item);
}
}
///////////////////////////////////////////////////////////////////////////
// Utility types and common code for the above passes.
@ -669,7 +589,7 @@ fn get_new_lifetime_name<'tcx>(
}
#[instrument(level = "debug", skip_all)]
fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
let it = tcx.hir_item(item_id);
debug!(item = ?it.kind.ident(), id = %it.hir_id());
let def_id = item_id.owner_id.def_id;
@ -790,7 +710,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
}
}
fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
pub(crate) fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
let trait_item = tcx.hir_trait_item(trait_item_id);
let def_id = trait_item_id.owner_id;
tcx.ensure_ok().generics_of(def_id);
@ -861,7 +781,7 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
tcx.ensure_ok().predicates_of(def_id);
}
fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
pub(super) fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
let def_id = impl_item_id.owner_id;
tcx.ensure_ok().generics_of(def_id);
tcx.ensure_ok().type_of(def_id);

View file

@ -182,9 +182,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
// what we are intending to discard, to help future type-based refactoring.
type R = Result<(), ErrorGuaranteed>;
tcx.par_hir_for_each_module(|module| {
let _: R = tcx.ensure_ok().check_mod_type_wf(module);
});
let _: R = tcx.ensure_ok().check_type_wf(());
for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
let _: R = tcx.ensure_ok().coherent_trait(trait_def_id);

View file

@ -234,6 +234,32 @@ impl<T: Idx> DenseBitSet<T> {
self.clear_excess_bits();
}
/// Checks whether any bit in the given range is a 1.
#[inline]
pub fn contains_any(&self, elems: impl RangeBounds<T>) -> bool {
let Some((start, end)) = inclusive_start_end(elems, self.domain_size) else {
return false;
};
let (start_word_index, start_mask) = word_index_and_mask(start);
let (end_word_index, end_mask) = word_index_and_mask(end);
if start_word_index == end_word_index {
self.words[start_word_index] & (end_mask | (end_mask - start_mask)) != 0
} else {
if self.words[start_word_index] & !(start_mask - 1) != 0 {
return true;
}
let remaining = start_word_index + 1..end_word_index;
if remaining.start <= remaining.end {
self.words[remaining].iter().any(|&w| w != 0)
|| self.words[end_word_index] & (end_mask | (end_mask - 1)) != 0
} else {
false
}
}
}
/// Returns `true` if the set has changed.
#[inline]
pub fn remove(&mut self, elem: T) -> bool {

View file

@ -692,6 +692,25 @@ fn dense_last_set_before() {
}
}
#[test]
fn dense_contains_any() {
let mut set: DenseBitSet<usize> = DenseBitSet::new_empty(300);
assert!(!set.contains_any(0..300));
set.insert_range(10..20);
set.insert_range(60..70);
set.insert_range(150..=250);
assert!(set.contains_any(0..30));
assert!(set.contains_any(5..100));
assert!(set.contains_any(250..255));
assert!(!set.contains_any(20..59));
assert!(!set.contains_any(256..290));
set.insert(22);
assert!(set.contains_any(20..59));
}
#[bench]
fn bench_insert(b: &mut Bencher) {
let mut bs = DenseBitSet::new_filled(99999usize);

View file

@ -374,8 +374,6 @@ lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
.label = not FFI-safe
.note = the type is defined here
lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
lint_improper_ctypes_array_help = consider passing a pointer to the array
lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe

View file

@ -1,9 +1,7 @@
use std::iter;
use std::ops::ControlFlow;
use rustc_abi::{
BackendRepr, Integer, IntegerType, TagEncoding, VariantIdx, Variants, WrappingRange,
};
use rustc_abi::{BackendRepr, TagEncoding, VariantIdx, Variants, WrappingRange};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagMessage;
use rustc_hir::intravisit::VisitorExt;
@ -1284,14 +1282,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
};
}
if let Some(IntegerType::Fixed(Integer::I128, _)) = def.repr().int {
return FfiUnsafe {
ty,
reason: fluent::lint_improper_ctypes_128bit,
help: None,
};
}
use improper_ctypes::check_non_exhaustive_variant;
let non_exhaustive = def.variant_list_has_applicable_non_exhaustive();
@ -1324,10 +1314,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// but only the base type is relevant for being representable in FFI.
ty::Pat(base, ..) => self.check_type_for_ffi(acc, base),
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
}
// Primitive types with a stable representation.
ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe,

View file

@ -2,6 +2,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_query_system::ich::StableHashingContext;
use rustc_session::Session;
use crate::ty::print::with_reduced_queries;
use crate::ty::{self, TyCtxt};
#[macro_use]
@ -84,4 +85,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> {
&self.query_kinds[dk.as_usize()]
}
fn with_reduced_queries<T>(self, f: impl FnOnce() -> T) -> T {
with_reduced_queries!(f())
}
}

View file

@ -71,6 +71,7 @@ impl ModuleItems {
self.opaques.iter().copied()
}
/// Closures and inline consts
pub fn nested_bodies(&self) -> impl Iterator<Item = LocalDefId> {
self.nested_bodies.iter().copied()
}
@ -79,6 +80,14 @@ impl ModuleItems {
self.owners().map(|id| id.def_id)
}
/// Closures and inline consts
pub fn par_nested_bodies(
&self,
f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
try_par_for_each_in(&self.nested_bodies[..], |&&id| f(id))
}
pub fn par_items(
&self,
f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,

View file

@ -1148,8 +1148,8 @@ rustc_queries! {
desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) }
}
query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
query check_type_wf(key: ()) -> Result<(), ErrorGuaranteed> {
desc { "checking that types are well-formed" }
return_result_from_ensure_ok
}

View file

@ -3,6 +3,9 @@ use super::{
Pat, PatKind, Stmt, StmtKind, Thir,
};
/// Every `walk_*` method uses deconstruction to access fields of structs and
/// enums. This will result in a compile error if a field is added, which makes
/// it more likely the appropriate visit call will be added for it.
pub trait Visitor<'thir, 'tcx: 'thir>: Sized {
fn thir(&self) -> &'thir Thir<'tcx>;

View file

@ -934,7 +934,7 @@ where
.unwrap(),
),
Variants::Multiple { tag, tag_field, .. } => {
if i == tag_field {
if FieldIdx::from_usize(i) == tag_field {
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
}
TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
@ -1060,8 +1060,10 @@ where
tag_field,
variants,
..
} if variants.len() == 2 && this.fields.offset(*tag_field) == offset => {
let tagged_variant = if untagged_variant.as_u32() == 0 {
} if variants.len() == 2
&& this.fields.offset(tag_field.as_usize()) == offset =>
{
let tagged_variant = if *untagged_variant == VariantIdx::ZERO {
VariantIdx::from_u32(1)
} else {
VariantIdx::from_u32(0)

View file

@ -1886,7 +1886,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
) -> Result<(), PrintError> {
define_scoped_cx!(self);
if self.should_print_verbose() {
if with_reduced_queries() || self.should_print_verbose() {
p!(write("ValTree({:?}: ", cv.valtree), print(cv.ty), ")");
return Ok(());
}

View file

@ -382,12 +382,34 @@ pub(super) fn expand_async_drops<'tcx>(
dropline_call_bb = Some(drop_call_bb);
}
// value needed only for return-yields or gen-coroutines, so just const here
let value = Operand::Constant(Box::new(ConstOperand {
span: body.span,
user_ty: None,
const_: Const::from_bool(tcx, false),
}));
let value =
if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _))
{
// For AsyncGen we need `yield Poll<OptRet>::Pending`
let full_yield_ty = body.yield_ty().unwrap();
let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() };
let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() };
let yield_ty = args.type_at(0);
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
const_: Const::Unevaluated(
UnevaluatedConst::new(
tcx.require_lang_item(LangItem::AsyncGenPending, None),
tcx.mk_args(&[yield_ty.into()]),
),
full_yield_ty,
),
user_ty: None,
}))
} else {
// value needed only for return-yields or gen-coroutines, so just const here
Operand::Constant(Box::new(ConstOperand {
span: body.span,
user_ty: None,
const_: Const::from_bool(tcx, false),
}))
};
use rustc_middle::mir::AssertKind::ResumedAfterDrop;
let panic_bb = insert_panic_block(tcx, body, ResumedAfterDrop(coroutine_kind));

View file

@ -35,8 +35,6 @@ fn do_check_simd_vector_abi<'tcx>(
is_call: bool,
loc: impl Fn() -> (Span, HirId),
) {
// We check this on all functions, including those using the "Rust" ABI.
// For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
let feature_def = tcx.sess.target.features_for_correct_vector_abi();
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
let have_feature = |feat: Symbol| {
@ -123,8 +121,9 @@ fn do_check_wasm_abi<'tcx>(
is_call: bool,
loc: impl Fn() -> (Span, HirId),
) {
// Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`),
// and only proceed if `wasm_c_abi_opt` indicates we should emit the lint.
// Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what
// `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`), and only proceed if
// `wasm_c_abi_opt` indicates we should emit the lint.
if !(tcx.sess.target.arch == "wasm32"
&& tcx.sess.target.os == "unknown"
&& tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
@ -157,8 +156,15 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
else {
// An error will be reported during codegen if we cannot determine the ABI of this
// function.
tcx.dcx().delayed_bug("ABI computation failure should lead to compilation failure");
return;
};
// Unlike the call-site check, we do also check "Rust" ABI functions here.
// This should never trigger, *except* if we start making use of vector registers
// for the "Rust" ABI and the user disables those vector registers (which should trigger a
// warning as that's clearly disabling a "required" target feature for this target).
// Using such a function is where disabling the vector register actually can start leading
// to soundness issues, so erroring here seems good.
let loc = || {
let def_id = instance.def_id();
(
@ -179,7 +185,8 @@ fn check_call_site_abi<'tcx>(
loc: impl Fn() -> (Span, HirId) + Copy,
) {
if callee.fn_sig(tcx).abi().is_rustic_abi() {
// we directly handle the soundness of Rust ABIs
// We directly handle the soundness of Rust ABIs -- so let's skip the majority of
// call sites to avoid a perf regression.
return;
}
let typing_env = ty::TypingEnv::fully_monomorphized();

View file

@ -14,6 +14,10 @@ fn sp(a: u32, b: u32) -> Span {
Span::with_root_ctxt(BytePos(a), BytePos(b))
}
fn cmp_token_stream(a: &TokenStream, b: &TokenStream) -> bool {
a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.eq_unspanned(y))
}
#[test]
fn test_concat() {
create_default_session_globals_then(|| {
@ -25,7 +29,7 @@ fn test_concat() {
eq_res.push_stream(test_snd);
assert_eq!(test_res.iter().count(), 5);
assert_eq!(eq_res.iter().count(), 5);
assert_eq!(test_res.eq_unspanned(&eq_res), true);
assert_eq!(cmp_token_stream(&test_res, &eq_res), true);
})
}
@ -104,7 +108,7 @@ fn test_dotdotdot() {
stream.push_tree(TokenTree::token_joint(token::Dot, sp(0, 1)));
stream.push_tree(TokenTree::token_joint(token::Dot, sp(1, 2)));
stream.push_tree(TokenTree::token_alone(token::Dot, sp(2, 3)));
assert!(stream.eq_unspanned(&string_to_ts("...")));
assert!(cmp_token_stream(&stream, &string_to_ts("...")));
assert_eq!(stream.iter().count(), 1);
})
}

View file

@ -178,9 +178,7 @@ pub trait DepNodeParams<Tcx: DepContext>: fmt::Debug + Sized {
panic!("Not implemented. Accidentally called on anonymous node?")
}
fn to_debug_str(&self, _: Tcx) -> String {
format!("{self:?}")
}
fn to_debug_str(&self, tcx: Tcx) -> String;
/// This method tries to recover the query key from the given `DepNode`,
/// something which is needed when forcing `DepNode`s during red-green
@ -210,8 +208,11 @@ where
}
#[inline(always)]
default fn to_debug_str(&self, _: Tcx) -> String {
format!("{:?}", *self)
default fn to_debug_str(&self, tcx: Tcx) -> String {
// Make sure to print dep node params with reduced queries since printing
// may themselves call queries, which may lead to (possibly untracked!)
// query cycles.
tcx.with_reduced_queries(|| format!("{self:?}"))
}
#[inline(always)]

View file

@ -88,6 +88,8 @@ pub trait DepContext: Copy {
f(self, dep_node)
}
}
fn with_reduced_queries<T>(self, _: impl FnOnce() -> T) -> T;
}
pub trait Deps: DynSync {

View file

@ -180,7 +180,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::
VariantsShape::Multiple {
tag: tag.stable(tables),
tag_encoding: tag_encoding.stable(tables),
tag_field: *tag_field,
tag_field: tag_field.stable(tables),
variants: variants.iter().as_slice().stable(tables),
}
}

View file

@ -7,7 +7,7 @@ use rustc_abi::{
use rustc_macros::HashStable_Generic;
pub use crate::spec::AbiMap;
use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi};
use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
mod aarch64;
mod amdgpu;
@ -696,24 +696,6 @@ impl<'a, Ty> FnAbi<'a, Ty> {
_ => {}
};
// Decides whether we can pass the given SIMD argument via `PassMode::Direct`.
// May only return `true` if the target will always pass those arguments the same way,
// no matter what the user does with `-Ctarget-feature`! In other words, whatever
// target features are required to pass a SIMD value in registers must be listed in
// the `abi_required_features` for the current target and ABI.
let can_pass_simd_directly = |arg: &ArgAbi<'_, Ty>| match &*spec.arch {
// On x86, if we have SSE2 (which we have by default for x86_64), we can always pass up
// to 128-bit-sized vectors.
"x86" if spec.rustc_abi == Some(RustcAbi::X86Sse2) => arg.layout.size.bits() <= 128,
"x86_64" if spec.rustc_abi != Some(RustcAbi::X86Softfloat) => {
// FIXME once https://github.com/bytecodealliance/wasmtime/issues/10254 is fixed
// accept vectors up to 128bit rather than vectors of exactly 128bit.
arg.layout.size.bits() == 128
}
// So far, we haven't implemented this logic for any other target.
_ => false,
};
for (arg_idx, arg) in self
.args
.iter_mut()
@ -813,9 +795,10 @@ impl<'a, Ty> FnAbi<'a, Ty> {
// target feature sets. Some more information about this
// issue can be found in #44367.
//
// Note that the intrinsic ABI is exempt here as those are not
// real functions anyway, and the backend expects very specific types.
if spec.simd_types_indirect && !can_pass_simd_directly(arg) {
// We *could* do better in some cases, e.g. on x86_64 targets where SSE2 is
// required. However, it turns out that that makes LLVM worse at optimizing this
// code, so we pass things indirectly even there. See #139029 for more on that.
if spec.simd_types_indirect {
arg.make_indirect();
}
}

View file

@ -710,29 +710,35 @@ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-end
];
#[rustfmt::skip]
const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
("backchain", Unstable(sym::s390x_target_feature), &[]),
("concurrent-functions", Unstable(sym::s390x_target_feature), &[]),
("deflate-conversion", Unstable(sym::s390x_target_feature), &[]),
("enhanced-sort", Unstable(sym::s390x_target_feature), &[]),
("guarded-storage", Unstable(sym::s390x_target_feature), &[]),
("high-word", Unstable(sym::s390x_target_feature), &[]),
// LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11.
("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]),
("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]),
("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]),
("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]),
("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]),
("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]),
("miscellaneous-extensions-2", Unstable(sym::s390x_target_feature), &[]),
("miscellaneous-extensions-3", Unstable(sym::s390x_target_feature), &[]),
("miscellaneous-extensions-4", Unstable(sym::s390x_target_feature), &[]),
("nnp-assist", Unstable(sym::s390x_target_feature), &["vector"]),
("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
("vector", Unstable(sym::s390x_target_feature), &[]),
("vector-enhancements-1", Unstable(sym::s390x_target_feature), &["vector"]),
("vector-enhancements-2", Unstable(sym::s390x_target_feature), &["vector-enhancements-1"]),
("vector-enhancements-3", Unstable(sym::s390x_target_feature), &["vector-enhancements-2"]),
("vector-packed-decimal", Unstable(sym::s390x_target_feature), &["vector"]),
(
"vector-packed-decimal-enhancement",
Unstable(sym::s390x_target_feature),
&["vector-packed-decimal"],
),
(
"vector-packed-decimal-enhancement-2",
Unstable(sym::s390x_target_feature),
&["vector-packed-decimal-enhancement"],
),
("vector-packed-decimal-enhancement", Unstable(sym::s390x_target_feature), &["vector-packed-decimal"]),
("vector-packed-decimal-enhancement-2", Unstable(sym::s390x_target_feature), &["vector-packed-decimal-enhancement"]),
("vector-packed-decimal-enhancement-3", Unstable(sym::s390x_target_feature), &["vector-packed-decimal-enhancement-2"]),
// tidy-alphabetical-end
];

View file

@ -3841,7 +3841,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
.expr_ty_adjusted_opt(inner_expr)
.unwrap_or(Ty::new_misc_error(tcx));
let span = inner_expr.span;
if Some(span) != err.span.primary_span() {
if Some(span) != err.span.primary_span()
&& !span.in_external_macro(tcx.sess.source_map())
{
err.span_label(
span,
if ty.references_error() {

View file

@ -451,7 +451,7 @@ pub(crate) mod rustc {
// For enums (but not coroutines), the tag field is
// currently always the first field of the layout.
assert_eq!(*tag_field, 0);
assert_eq!(*tag_field, FieldIdx::ZERO);
let variants = def.discriminants(cx.tcx()).try_fold(
Self::uninhabited(),

View file

@ -932,7 +932,7 @@ fn variant_info_for_coroutine<'tcx>(
// However, if the discriminant is placed past the end of the variant, then we need
// to factor in the size of the discriminant manually. This really should be refactored
// better, but this "works" for now.
if layout.fields.offset(tag_field) >= variant_size {
if layout.fields.offset(tag_field.as_usize()) >= variant_size {
variant_size += match tag_encoding {
TagEncoding::Direct => tag.size(cx),
_ => Size::ZERO,

View file

@ -4,7 +4,6 @@ use std::ops::Deref;
use rustc_ast_ir::Movability;
use rustc_index::bit_set::DenseBitSet;
use smallvec::SmallVec;
use crate::fold::TypeFoldable;
use crate::inherent::*;
@ -382,28 +381,45 @@ impl<T, R> CollectAndApply<T, R> for T {
F: FnOnce(&[T]) -> R,
{
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
// `size_hint` is incorrect a panic will occur via an `unwrap` or an
// `assert`.
match iter.size_hint() {
(0, Some(0)) => {
assert!(iter.next().is_none());
f(&[])
}
(1, Some(1)) => {
let t0 = iter.next().unwrap();
assert!(iter.next().is_none());
f(&[t0])
}
(2, Some(2)) => {
let t0 = iter.next().unwrap();
let t1 = iter.next().unwrap();
assert!(iter.next().is_none());
f(&[t0, t1])
}
_ => f(&iter.collect::<SmallVec<[_; 8]>>()),
}
// common length lists, to avoid the overhead of `Vec` creation.
let Some(t0) = iter.next() else {
return f(&[]);
};
let Some(t1) = iter.next() else {
return f(&[t0]);
};
let Some(t2) = iter.next() else {
return f(&[t0, t1]);
};
let Some(t3) = iter.next() else {
return f(&[t0, t1, t2]);
};
let Some(t4) = iter.next() else {
return f(&[t0, t1, t2, t3]);
};
let Some(t5) = iter.next() else {
return f(&[t0, t1, t2, t3, t4]);
};
let Some(t6) = iter.next() else {
return f(&[t0, t1, t2, t3, t4, t5]);
};
let Some(t7) = iter.next() else {
return f(&[t0, t1, t2, t3, t4, t5, t6]);
};
let Some(t8) = iter.next() else {
return f(&[t0, t1, t2, t3, t4, t5, t6, t7]);
};
f(&[t0, t1, t2, t3, t4, t5, t6, t7, t8].into_iter().chain(iter).collect::<Vec<_>>())
}
}
@ -419,29 +435,57 @@ impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
F: FnOnce(&[T]) -> R,
{
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
// `size_hint` is incorrect a panic will occur via an `unwrap` or an
// `assert`, unless a failure happens first, in which case the result
// will be an error anyway.
Ok(match iter.size_hint() {
(0, Some(0)) => {
assert!(iter.next().is_none());
f(&[])
}
(1, Some(1)) => {
let t0 = iter.next().unwrap()?;
assert!(iter.next().is_none());
f(&[t0])
}
(2, Some(2)) => {
let t0 = iter.next().unwrap()?;
let t1 = iter.next().unwrap()?;
assert!(iter.next().is_none());
f(&[t0, t1])
}
_ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
})
// common length lists, to avoid the overhead of `Vec` creation.
let Some(t0) = iter.next() else {
return Ok(f(&[]));
};
let t0 = t0?;
let Some(t1) = iter.next() else {
return Ok(f(&[t0]));
};
let t1 = t1?;
let Some(t2) = iter.next() else {
return Ok(f(&[t0, t1]));
};
let t2 = t2?;
let Some(t3) = iter.next() else {
return Ok(f(&[t0, t1, t2]));
};
let t3 = t3?;
let Some(t4) = iter.next() else {
return Ok(f(&[t0, t1, t2, t3]));
};
let t4 = t4?;
let Some(t5) = iter.next() else {
return Ok(f(&[t0, t1, t2, t3, t4]));
};
let t5 = t5?;
let Some(t6) = iter.next() else {
return Ok(f(&[t0, t1, t2, t3, t4, t5]));
};
let t6 = t6?;
let Some(t7) = iter.next() else {
return Ok(f(&[t0, t1, t2, t3, t4, t5, t6]));
};
let t7 = t7?;
let Some(t8) = iter.next() else {
return Ok(f(&[t0, t1, t2, t3, t4, t5, t6, t7]));
};
let t8 = t8?;
Ok(f(&[Ok(t0), Ok(t1), Ok(t2), Ok(t3), Ok(t4), Ok(t5), Ok(t6), Ok(t7), Ok(t8)]
.into_iter()
.chain(iter)
.collect::<Result<Vec<_>, _>>()?))
}
}

View file

@ -1416,18 +1416,18 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
///
/// # Examples
///
/// Splitting a map into even and odd keys, reusing the original map:
///
/// ```
/// #![feature(btree_extract_if)]
/// use std::collections::BTreeMap;
///
/// // Splitting a map into even and odd keys, reusing the original map:
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let evens: BTreeMap<_, _> = map.extract_if(.., |k, _v| k % 2 == 0).collect();
/// let odds = map;
/// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]);
/// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);
///
/// // Splitting a map into low and high halves, reusing the original map:
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let low: BTreeMap<_, _> = map.extract_if(0..4, |_k, _v| true).collect();
/// let high = map;

View file

@ -1201,21 +1201,21 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// [`retain`]: BTreeSet::retain
/// # Examples
///
/// Splitting a set into even and odd values, reusing the original set:
///
/// ```
/// #![feature(btree_extract_if)]
/// use std::collections::BTreeSet;
///
/// // Splitting a set into even and odd values, reusing the original set:
/// let mut set: BTreeSet<i32> = (0..8).collect();
/// let evens: BTreeSet<_> = set.extract_if(.., |v| v % 2 == 0).collect();
/// let odds = set;
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
///
/// let mut map: BTreeSet<i32> = (0..8).collect();
/// let low: BTreeSet<_> = map.extract_if(0..4, |_v| true).collect();
/// let high = map;
/// // Splitting a set into low and high halves, reusing the original set:
/// let mut set: BTreeSet<i32> = (0..8).collect();
/// let low: BTreeSet<_> = set.extract_if(0..4, |_v| true).collect();
/// let high = set;
/// assert_eq!(low.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
/// assert_eq!(high.into_iter().collect::<Vec<_>>(), [4, 5, 6, 7]);
/// ```

View file

@ -175,7 +175,6 @@ impl_from!(u8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")
impl_from!(u8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);

View file

@ -928,6 +928,20 @@ pub use macros::Debug;
/// [tostring]: ../../std/string/trait.ToString.html
/// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string
///
/// # Completeness and parseability
///
/// `Display` for a type might not necessarily be a lossless or complete representation of the type.
/// It may omit internal state, precision, or other information the type does not consider important
/// for user-facing output, as determined by the type. As such, the output of `Display` might not be
/// possible to parse, and even if it is, the result of parsing might not exactly match the original
/// value.
///
/// However, if a type has a lossless `Display` implementation whose output is meant to be
/// conveniently machine-parseable and not just meant for human consumption, then the type may wish
/// to accept the same format in `FromStr`, and document that usage. Having both `Display` and
/// `FromStr` implementations where the result of `Display` cannot be parsed with `FromStr` may
/// surprise users.
///
/// # Internationalization
///
/// Because a type can only have one `Display` implementation, it is often preferable

View file

@ -1428,6 +1428,18 @@ mod prim_i64 {}
#[rustc_doc_primitive = "i128"]
//
/// The 128-bit signed integer type.
///
/// # ABI compatibility
///
/// Rust's `i128` is expected to be ABI-compatible with C's `__int128` on platforms where the type
/// is available, which includes most 64-bit architectures. If any platforms that do not specify
/// `__int128` are updated to introduce it, the Rust `i128` ABI on relevant targets will be changed
/// to match.
///
/// It is important to note that in C, `__int128` is _not_ the same as `_BitInt(128)`, and the two
/// types are allowed to have different ABIs. In particular, on x86, `__int128` and `_BitInt(128)`
/// do not use the same alignment. `i128` is intended to always match `__int128` and does not
/// attempt to match `_BitInt(128)` on platforms without `__int128`.
#[stable(feature = "i128", since = "1.26.0")]
mod prim_i128 {}
@ -1458,6 +1470,8 @@ mod prim_u64 {}
#[rustc_doc_primitive = "u128"]
//
/// The 128-bit unsigned integer type.
///
/// Please see [the documentation for `i128`](prim@i128) for information on ABI compatibility.
#[stable(feature = "i128", since = "1.26.0")]
mod prim_u128 {}

View file

@ -756,6 +756,20 @@ unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> {
/// parse an `i32` with `FromStr`, but not a `&i32`. You can parse a struct that
/// contains an `i32`, but not one that contains an `&i32`.
///
/// # Input format and round-tripping
///
/// The input format expected by a type's `FromStr` implementation depends on the type. Check the
/// type's documentation for the input formats it knows how to parse. Note that the input format of
/// a type's `FromStr` implementation might not necessarily accept the output format of its
/// `Display` implementation, and even if it does, the `Display` implementation may not be lossless
/// so the round-trip may lose information.
///
/// However, if a type has a lossless `Display` implementation whose output is meant to be
/// conveniently machine-parseable and not just meant for human consumption, then the type may wish
/// to accept the same format in `FromStr`, and document that usage. Having both `Display` and
/// `FromStr` implementations where the result of `Display` cannot be parsed with `FromStr` may
/// surprise users.
///
/// # Examples
///
/// Basic implementation of `FromStr` on an example `Point` type:

View file

@ -30,6 +30,7 @@
#![feature(duration_constructors)]
#![feature(duration_constructors_lite)]
#![feature(error_generic_member_access)]
#![feature(exact_div)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(extern_types)]

View file

@ -683,5 +683,43 @@ macro_rules! int_module {
assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
}
}
const EXACT_DIV_SUCCESS_DIVIDEND1: $T = 42;
const EXACT_DIV_SUCCESS_DIVISOR1: $T = 6;
const EXACT_DIV_SUCCESS_QUOTIENT1: $T = 7;
const EXACT_DIV_SUCCESS_DIVIDEND2: $T = 18;
const EXACT_DIV_SUCCESS_DIVISOR2: $T = 3;
const EXACT_DIV_SUCCESS_QUOTIENT2: $T = 6;
const EXACT_DIV_SUCCESS_DIVIDEND3: $T = -91;
const EXACT_DIV_SUCCESS_DIVISOR3: $T = 13;
const EXACT_DIV_SUCCESS_QUOTIENT3: $T = -7;
const EXACT_DIV_SUCCESS_DIVIDEND4: $T = -57;
const EXACT_DIV_SUCCESS_DIVISOR4: $T = -3;
const EXACT_DIV_SUCCESS_QUOTIENT4: $T = 19;
test_runtime_and_compiletime! {
fn test_exact_div() {
// 42 / 6
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), Some(EXACT_DIV_SUCCESS_QUOTIENT1));
assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), EXACT_DIV_SUCCESS_QUOTIENT1);
// 18 / 3
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), Some(EXACT_DIV_SUCCESS_QUOTIENT2));
assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), EXACT_DIV_SUCCESS_QUOTIENT2);
// -91 / 13
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND3, EXACT_DIV_SUCCESS_DIVISOR3), Some(EXACT_DIV_SUCCESS_QUOTIENT3));
assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND3, EXACT_DIV_SUCCESS_DIVISOR3), EXACT_DIV_SUCCESS_QUOTIENT3);
// -57 / -3
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND4, EXACT_DIV_SUCCESS_DIVISOR4), Some(EXACT_DIV_SUCCESS_QUOTIENT4));
assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND4, EXACT_DIV_SUCCESS_DIVISOR4), EXACT_DIV_SUCCESS_QUOTIENT4);
// failures
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(1, 2), None);
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(<$T>::MIN, -1), None);
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(0, 0), None);
}
}
};
}

View file

@ -516,5 +516,28 @@ macro_rules! uint_module {
assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
}
}
const EXACT_DIV_SUCCESS_DIVIDEND1: $T = 42;
const EXACT_DIV_SUCCESS_DIVISOR1: $T = 6;
const EXACT_DIV_SUCCESS_QUOTIENT1: $T = 7;
const EXACT_DIV_SUCCESS_DIVIDEND2: $T = 18;
const EXACT_DIV_SUCCESS_DIVISOR2: $T = 3;
const EXACT_DIV_SUCCESS_QUOTIENT2: $T = 6;
test_runtime_and_compiletime! {
fn test_exact_div() {
// 42 / 6
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), Some(EXACT_DIV_SUCCESS_QUOTIENT1));
assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND1, EXACT_DIV_SUCCESS_DIVISOR1), EXACT_DIV_SUCCESS_QUOTIENT1);
// 18 / 3
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), Some(EXACT_DIV_SUCCESS_QUOTIENT2));
assert_eq_const_safe!($T: <$T>::exact_div(EXACT_DIV_SUCCESS_DIVIDEND2, EXACT_DIV_SUCCESS_DIVISOR2), EXACT_DIV_SUCCESS_QUOTIENT2);
// failures
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(1, 2), None);
assert_eq_const_safe!(Option<$T>: <$T>::checked_exact_div(0, 0), None);
}
}
};
}

View file

@ -137,7 +137,8 @@ impl OsString {
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
pub fn new() -> OsString {
#[rustc_const_unstable(feature = "const_pathbuf_osstring_new", issue = "141520")]
pub const fn new() -> OsString {
OsString { inner: Buf::from_string(String::new()) }
}

View file

@ -1191,7 +1191,8 @@ impl PathBuf {
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
pub fn new() -> PathBuf {
#[rustc_const_unstable(feature = "const_pathbuf_osstring_new", issue = "141520")]
pub const fn new() -> PathBuf {
PathBuf { inner: OsString::new() }
}

View file

@ -115,7 +115,7 @@ impl Buf {
}
#[inline]
pub fn from_string(s: String) -> Buf {
pub const fn from_string(s: String) -> Buf {
Buf { inner: s.into_bytes() }
}

View file

@ -92,7 +92,7 @@ impl Buf {
}
#[inline]
pub fn from_string(s: String) -> Buf {
pub const fn from_string(s: String) -> Buf {
Buf { inner: Wtf8Buf::from_string(s) }
}

View file

@ -209,7 +209,7 @@ impl Wtf8Buf {
///
/// Since WTF-8 is a superset of UTF-8, this always succeeds.
#[inline]
pub fn from_string(string: String) -> Wtf8Buf {
pub const fn from_string(string: String) -> Wtf8Buf {
Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true }
}

View file

@ -28,13 +28,16 @@ pub struct Std {
/// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
/// which is not useful if we only want to lint a few crates with specific rules.
override_build_kind: Option<Kind>,
/// Never use this from outside calls. It is intended for internal use only within `check::Std::make_run`
/// and `check::Std::run`.
custom_stage: Option<u32>,
}
impl Std {
const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
pub fn new(target: TargetSelection) -> Self {
Self { target, crates: vec![], override_build_kind: None }
Self { target, crates: vec![], override_build_kind: None, custom_stage: None }
}
pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
@ -48,24 +51,29 @@ impl Step for Std {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
builder.top_stage
} else {
1
};
let mut run = run;
for c in Std::CRATE_OR_DEPS {
run = run.crate_or_deps(c);
}
run.path("library").default_condition(stage != 0)
run.path("library")
}
fn make_run(run: RunConfig<'_>) {
let crates = std_crates_for_run_make(&run);
run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 1 {
run.builder.top_stage
} else {
1
};
run.builder.ensure(Std {
target: run.target,
crates,
override_build_kind: None,
custom_stage: Some(stage),
});
}
fn run(self, builder: &Builder<'_>) {
@ -78,11 +86,7 @@ impl Step for Std {
builder.require_submodule("library/stdarch", None);
let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
builder.top_stage
} else {
1
};
let stage = self.custom_stage.unwrap_or(builder.top_stage);
let target = self.target;
let compiler = builder.compiler(stage, builder.config.build);

View file

@ -1878,23 +1878,27 @@ impl Step for Sysroot {
// so that any tools relying on `rust-src` also work for local builds,
// and also for translating the virtual `/rustc/$hash` back to the real
// directory (for running tests with `rust.remap-debuginfo = true`).
let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
eprintln!(
"ERROR: creating symbolic link `{}` to `{}` failed with {}",
sysroot_lib_rustlib_src_rust.display(),
builder.src.display(),
e,
);
if builder.config.rust_remap_debuginfo {
if compiler.stage != 0 {
let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
if let Err(e) =
symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
{
eprintln!(
"ERROR: some `tests/ui` tests will fail when lacking `{}`",
"ERROR: creating symbolic link `{}` to `{}` failed with {}",
sysroot_lib_rustlib_src_rust.display(),
builder.src.display(),
e,
);
if builder.config.rust_remap_debuginfo {
eprintln!(
"ERROR: some `tests/ui` tests will fail when lacking `{}`",
sysroot_lib_rustlib_src_rust.display(),
);
}
build_helper::exit!(1);
}
build_helper::exit!(1);
}
// rustc-src component is already part of CI rustc's sysroot

View file

@ -2707,16 +2707,6 @@ impl Step for Crate {
.arg(builder.src.join("library/sysroot/Cargo.toml"));
} else {
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
// `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`,
// but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`.
// Override it.
if builder.download_rustc() && compiler.stage > 0 {
let sysroot = builder
.out
.join(compiler.host)
.join(format!("stage{}-test-sysroot", compiler.stage));
cargo.env("RUSTC_SYSROOT", sysroot);
}
}
}
Mode::Rustc => {

View file

@ -945,7 +945,6 @@ impl<'a> Builder<'a> {
clippy::CI,
),
Kind::Check | Kind::Fix => describe!(
check::Std,
check::Rustc,
check::Rustdoc,
check::CodegenBackend,
@ -961,6 +960,13 @@ impl<'a> Builder<'a> {
check::Compiletest,
check::FeaturesStatusDump,
check::CoverageDump,
// This has special staging logic, it may run on stage 1 while others run on stage 0.
// It takes quite some time to build stage 1, so put this at the end.
//
// FIXME: This also helps bootstrap to not interfere with stage 0 builds. We should probably fix
// that issue somewhere else, but we still want to keep `check::Std` at the end so that the
// quicker steps run before this.
check::Std,
),
Kind::Test => describe!(
crate::core::build_steps::toolstate::ToolStateCheck,

View file

@ -0,0 +1,36 @@
FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /tmp/
RUN bash /tmp/cross-apt-packages.sh
# Required gcc dependencies.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libgmp-dev \
libmpfr-dev \
libmpc-dev \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/shared.sh /tmp/
COPY scripts/solaris-toolchain.sh /tmp/
RUN bash /tmp/solaris-toolchain.sh sparcv9 sysroot
RUN bash /tmp/solaris-toolchain.sh sparcv9 binutils
RUN bash /tmp/solaris-toolchain.sh sparcv9 gcc
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
COPY scripts/cmake.sh /scripts/
RUN /scripts/cmake.sh
ENV \
AR_sparcv9_sun_solaris=sparcv9-solaris-ar \
RANLIB_sparcv9_sun_solaris=sparcv9-solaris-ranlib \
CC_sparcv9_sun_solaris=sparcv9-solaris-gcc \
CXX_sparcv9_sun_solaris=sparcv9-solaris-g++
ENV HOSTS=sparcv9-sun-solaris
ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS

View file

@ -43,12 +43,6 @@ ENV \
CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \
CXXFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
LDFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/lib" \
AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-ar \
CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-gcc \
CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-g++ \
AR_x86_64_pc_solaris=x86_64-pc-solaris2.10-ar \
CC_x86_64_pc_solaris=x86_64-pc-solaris2.10-gcc \
CXX_x86_64_pc_solaris=x86_64-pc-solaris2.10-g++ \
CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-9 \
CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-9 \
AR_x86_64_fortanix_unknown_sgx=ar \
@ -84,9 +78,6 @@ WORKDIR /tmp
COPY scripts/shared.sh /tmp/
COPY scripts/build-fuchsia-toolchain.sh /tmp/
RUN /tmp/build-fuchsia-toolchain.sh
COPY host-x86_64/dist-various-2/build-solaris-toolchain.sh /tmp/
RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 pc
RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun
COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh
@ -118,8 +109,6 @@ ENV TARGETS=$TARGETS,wasm32-wasip1
ENV TARGETS=$TARGETS,wasm32-wasip1-threads
ENV TARGETS=$TARGETS,wasm32-wasip2
ENV TARGETS=$TARGETS,wasm32v1-none
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
ENV TARGETS=$TARGETS,x86_64-pc-solaris
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx
ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda

View file

@ -1,111 +0,0 @@
#!/usr/bin/env bash
set -ex
source shared.sh
ARCH=$1
LIB_ARCH=$2
APT_ARCH=$3
MANUFACTURER=$4
BINUTILS=2.28.1
GCC=6.5.0
TARGET=${ARCH}-${MANUFACTURER}-solaris2.10
# First up, build binutils
mkdir binutils
cd binutils
curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.xz | tar xJf -
mkdir binutils-build
cd binutils-build
hide_output ../binutils-$BINUTILS/configure --target=$TARGET
hide_output make -j10
hide_output make install
cd ../..
rm -rf binutils
# Next, download and install the relevant solaris packages
mkdir solaris
cd solaris
dpkg --add-architecture $APT_ARCH
apt-get update
apt-get install -y --download-only \
libc:$APT_ARCH \
liblgrp:$APT_ARCH \
libm-dev:$APT_ARCH \
libpthread:$APT_ARCH \
libresolv:$APT_ARCH \
librt:$APT_ARCH \
libsendfile:$APT_ARCH \
libsocket:$APT_ARCH \
system-crt:$APT_ARCH \
system-header:$APT_ARCH
for deb in /var/cache/apt/archives/*$APT_ARCH.deb; do
dpkg -x $deb .
done
apt-get clean
# The -dev packages are not available from the apt repository we're using.
# However, those packages are just symlinks from *.so to *.so.<version>.
# This makes all those symlinks.
for lib in $(find -name '*.so.*'); do
target=${lib%.so.*}.so
ln -s ${lib##*/} $target || echo "warning: silenced error symlinking $lib"
done
# Remove Solaris 11 functions that are optionally used by libbacktrace.
# This is for Solaris 10 compatibility.
rm usr/include/link.h
patch -p0 << 'EOF'
--- usr/include/string.h
+++ usr/include/string10.h
@@ -93 +92,0 @@
-extern size_t strnlen(const char *, size_t);
EOF
mkdir /usr/local/$TARGET/usr
mv usr/include /usr/local/$TARGET/usr/include
mv usr/lib/$LIB_ARCH/* /usr/local/$TARGET/lib
mv lib/$LIB_ARCH/* /usr/local/$TARGET/lib
ln -s usr/include /usr/local/$TARGET/sys-include
ln -s usr/include /usr/local/$TARGET/include
cd ..
rm -rf solaris
# Finally, download and build gcc to target solaris
mkdir gcc
cd gcc
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | tar xJf -
cd gcc-$GCC
mkdir ../gcc-build
cd ../gcc-build
hide_output ../gcc-$GCC/configure \
--enable-languages=c,c++ \
--target=$TARGET \
--with-gnu-as \
--with-gnu-ld \
--disable-multilib \
--disable-nls \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libcilkrts \
--disable-libada \
--disable-libsanitizer \
--disable-libquadmath-support \
--disable-lto
hide_output make -j10
hide_output make install
cd ../..
rm -rf gcc

View file

@ -15,6 +15,7 @@ RUN apt-get update && \
python2.7 \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/shared.sh /tmp/
COPY scripts/illumos-toolchain.sh /tmp/
RUN bash /tmp/illumos-toolchain.sh x86_64 sysroot

View file

@ -0,0 +1,36 @@
FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /tmp/
RUN bash /tmp/cross-apt-packages.sh
# Required gcc dependencies.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libgmp-dev \
libmpfr-dev \
libmpc-dev \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/shared.sh /tmp/
COPY scripts/solaris-toolchain.sh /tmp/
RUN bash /tmp/solaris-toolchain.sh x86_64 sysroot
RUN bash /tmp/solaris-toolchain.sh x86_64 binutils
RUN bash /tmp/solaris-toolchain.sh x86_64 gcc
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
COPY scripts/cmake.sh /scripts/
RUN /scripts/cmake.sh
ENV \
AR_x86_64_pc_solaris=x86_64-solaris-ar \
RANLIB_x86_64_pc_solaris=x86_64-solaris-ranlib \
CC_x86_64_pc_solaris=x86_64-solaris-gcc \
CXX_x86_64_pc_solaris=x86_64-solaris-g++
ENV HOSTS=x86_64-pc-solaris
ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS

View file

@ -4,6 +4,8 @@ set -o errexit
set -o pipefail
set -o xtrace
source /tmp/shared.sh
ARCH="$1"
PHASE="$2"
@ -59,52 +61,13 @@ BINUTILS_TAR="$BINUTILS_BASE.tar.bz2"
BINUTILS_URL="https://ftp.gnu.org/gnu/binutils/$BINUTILS_TAR"
download_file() {
local file="$1"
local url="$2"
local sum="$3"
while :; do
if [[ -f "$file" ]]; then
if ! h="$(sha256sum "$file" | awk '{ print $1 }')"; then
printf 'ERROR: reading hash\n' >&2
exit 1
fi
if [[ "$h" == "$sum" ]]; then
return 0
fi
printf 'WARNING: hash mismatch: %s != expected %s\n' \
"$h" "$sum" >&2
rm -f "$file"
fi
printf 'Downloading: %s\n' "$url"
if ! curl -f -L -o "$file" "$url"; then
rm -f "$file"
sleep 1
fi
done
}
case "$PHASE" in
sysroot)
download_file "/tmp/$SYSROOT_TAR" "$SYSROOT_URL" "$SYSROOT_SUM"
mkdir -p "$SYSROOT_DIR"
cd "$SYSROOT_DIR"
tar -xzf "/tmp/$SYSROOT_TAR"
rm -f "/tmp/$SYSROOT_TAR"
download_tar_and_extract_into_dir "$SYSROOT_URL" "$SYSROOT_SUM" "$SYSROOT_DIR"
;;
binutils)
download_file "/tmp/$BINUTILS_TAR" "$BINUTILS_URL" "$BINUTILS_SUM"
mkdir -p /ws/src/binutils
cd /ws/src/binutils
tar -xjf "/tmp/$BINUTILS_TAR"
rm -f "/tmp/$BINUTILS_TAR"
download_tar_and_extract_into_dir "$BINUTILS_URL" "$BINUTILS_SUM" /ws/src/binutils
mkdir -p /ws/build/binutils
cd /ws/build/binutils
"/ws/src/binutils/$BINUTILS_BASE/configure" \
@ -123,12 +86,7 @@ binutils)
;;
gcc)
download_file "/tmp/$GCC_TAR" "$GCC_URL" "$GCC_SUM"
mkdir -p /ws/src/gcc
cd /ws/src/gcc
tar -xJf "/tmp/$GCC_TAR"
rm -f "/tmp/$GCC_TAR"
download_tar_and_extract_into_dir "$GCC_URL" "$GCC_SUM" /ws/src/gcc
mkdir -p /ws/build/gcc
cd /ws/build/gcc
export CFLAGS='-fPIC'

View file

@ -40,3 +40,37 @@ function retry {
}
done
}
download_tar_and_extract_into_dir() {
local url="$1"
local sum="$2"
local dir="$3"
local file=$(mktemp -u)
while :; do
if [[ -f "$file" ]]; then
if ! h="$(sha256sum "$file" | awk '{ print $1 }')"; then
printf 'ERROR: reading hash\n' >&2
exit 1
fi
if [[ "$h" == "$sum" ]]; then
break
fi
printf 'WARNING: hash mismatch: %s != expected %s\n' "$h" "$sum" >&2
rm -f "$file"
fi
printf 'Downloading: %s\n' "$url"
if ! curl -f -L -o "$file" "$url"; then
rm -f "$file"
sleep 1
fi
done
mkdir -p "$dir"
cd "$dir"
tar -xf "$file"
rm -f "$file"
}

View file

@ -0,0 +1,162 @@
#!/bin/bash
set -o errexit
set -o pipefail
set -o xtrace
source /tmp/shared.sh
ARCH="$1"
PHASE="$2"
JOBS="$(getconf _NPROCESSORS_ONLN)"
case "$ARCH" in
x86_64)
SYSROOT_MACH='i386'
;;
sparcv9)
SYSROOT_MACH='sparc'
;;
*)
printf 'ERROR: unknown architecture: %s\n' "$ARCH"
exit 1
esac
BUILD_TARGET="$ARCH-pc-solaris2.11"
#
# The illumos and the Solaris build both use the same GCC-level host triple,
# though different versions of GCC are used and with different configuration
# options. To ensure as little accidental cross-pollination as possible, we
# build the illumos toolchain in a specific directory tree and just symlink the
# expected tools into /usr/local/bin at the end. We omit /usr/local/bin from
# PATH here for similar reasons.
#
PREFIX="/opt/solaris/$ARCH"
export PATH="$PREFIX/bin:/usr/bin:/bin:/usr/sbin:/sbin"
#
# NOTE: The compiler version selected here is more specific than might appear.
# GCC 7.X releases do not appear to cross-compile correctly for Solaris
# targets, at least insofar as they refuse to enable TLS in libstdc++. When
# changing the GCC version in future, one must carefully verify that TLS is
# enabled in all of the static libraries we intend to include in output
# binaries.
#
GCC_VERSION='8.4.0'
GCC_SUM='e30a6e52d10e1f27ed55104ad233c30bd1e99cfb5ff98ab022dc941edd1b2dd4'
GCC_BASE="gcc-$GCC_VERSION"
GCC_TAR="gcc-$GCC_VERSION.tar.xz"
GCC_URL="https://ci-mirrors.rust-lang.org/rustc/$GCC_TAR"
SYSROOT_VER='2025-02-21'
if [ $ARCH = "x86_64" ]; then
SYSROOT_SUM='e82b78c14464cc2dc71f3cdab312df3dd63441d7c23eeeaf34d41d8b947688d3'
SYSROOT_TAR="solaris-11.4.42.111.0-i386-sysroot-v$SYSROOT_VER.tar.bz2"
SYSROOT_DIR="$PREFIX/sysroot-x86_64"
else
SYSROOT_SUM='e249a7ef781b9b3297419bd014fa0574800703981d84e113d6af3a897a8b4ffc'
SYSROOT_TAR="solaris-11.4.42.111.0-sparc-sysroot-v$SYSROOT_VER.tar.bz2"
SYSROOT_DIR="$PREFIX/sysroot-sparcv9"
fi
SYSROOT_URL="https://ci-mirrors.rust-lang.org/rustc/$SYSROOT_TAR"
BINUTILS_VERSION='2.44'
BINUTILS_SUM='ce2017e059d63e67ddb9240e9d4ec49c2893605035cd60e92ad53177f4377237'
BINUTILS_BASE="binutils-$BINUTILS_VERSION"
BINUTILS_TAR="$BINUTILS_BASE.tar.xz"
BINUTILS_URL="https://ci-mirrors.rust-lang.org/rustc/$BINUTILS_TAR"
case "$PHASE" in
sysroot)
download_tar_and_extract_into_dir "$SYSROOT_URL" "$SYSROOT_SUM" "$SYSROOT_DIR"
;;
binutils)
download_tar_and_extract_into_dir "$BINUTILS_URL" "$BINUTILS_SUM" /ws/src/binutils
cat > binutils.patch <<EOF
Workaround for: https://github.com/rust-lang/rust/issues/137997
--- binutils-2.44/bfd/elflink.c
+++ binutils-2.44/bfd/elflink.c
@@ -5150,7 +5150,7 @@
if it is not a function, because it might be the version
symbol itself. FIXME: What if it isn't? */
if ((iver.vs_vers & VERSYM_HIDDEN) != 0
- || (vernum > 1
+ || (vernum > 1 && strcmp(name, "logb") != 0
&& (!bfd_is_abs_section (sec)
|| bed->is_function_type (ELF_ST_TYPE (isym->st_info)))))
{
EOF
f=binutils-$BINUTILS_VERSION/bfd/elflink.c && expand -t 4 "$f" > "$f.exp"
mv binutils-$BINUTILS_VERSION/bfd/elflink.c.exp binutils-$BINUTILS_VERSION/bfd/elflink.c
patch binutils-$BINUTILS_VERSION/bfd/elflink.c < binutils.patch
rm binutils.patch
mkdir -p /ws/build/binutils
cd /ws/build/binutils
"/ws/src/binutils/$BINUTILS_BASE/configure" \
--prefix="$PREFIX" \
--target="$BUILD_TARGET" \
--program-prefix="$ARCH-solaris-" \
--with-sysroot="$SYSROOT_DIR"
make -j "$JOBS"
mkdir -p "$PREFIX"
make install
cd
rm -rf /ws/src/binutils /ws/build/binutils
;;
gcc)
download_tar_and_extract_into_dir "$GCC_URL" "$GCC_SUM" /ws/src/gcc
mkdir -p /ws/build/gcc
cd /ws/build/gcc
export CFLAGS='-fPIC'
export CXXFLAGS='-fPIC'
export CXXFLAGS_FOR_TARGET='-fPIC'
export CFLAGS_FOR_TARGET='-fPIC'
"/ws/src/gcc/$GCC_BASE/configure" \
--prefix="$PREFIX" \
--target="$BUILD_TARGET" \
--program-prefix="$ARCH-solaris-" \
--with-sysroot="$SYSROOT_DIR" \
--with-gnu-as \
--with-gnu-ld \
--disable-nls \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libcilkrts \
--disable-libada \
--disable-libsanitizer \
--disable-libquadmath-support \
--disable-shared \
--enable-tls
make -j "$JOBS"
mkdir -p "$PREFIX"
make install
#
# Link toolchain commands into /usr/local/bin so that cmake and others
# can find them:
#
(cd "$PREFIX/bin" && ls -U) | grep "^$ARCH-solaris-" |
xargs -t -I% ln -s "$PREFIX/bin/%" '/usr/local/bin/'
cd
rm -rf /ws/src/gcc /ws/build/gcc
;;
*)
printf 'ERROR: unknown phase "%s"\n' "$PHASE" >&2
exit 100
;;
esac

View file

@ -253,6 +253,12 @@ auto:
- name: dist-x86_64-netbsd
<<: *job-linux-4c
- name: dist-x86_64-solaris
<<: *job-linux-4c
- name: dist-sparcv9-solaris
<<: *job-linux-4c
# The i686-gnu job is split into multiple jobs to run tests in parallel.
# i686-gnu-1 skips tests that run in i686-gnu-2.
- name: i686-gnu-1

View file

@ -192,7 +192,7 @@ to save information after compiling a crate to be reused when recompiling the
crate, improving re-compile times. This takes a path to a directory where
incremental files will be stored.
Using incremental compilation inhibits certain optimizations (for example by increasing the amount of codegen units) and is therefore not recommend for release builds.
Using incremental compilation inhibits certain optimizations (for example by increasing the amount of codegen units) and is therefore not recommended for release builds.
## inline-threshold

View file

@ -110,6 +110,8 @@ target | notes
`x86_64-unknown-linux-musl` | 64-bit Linux with musl 1.2.3
[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | x86_64 OpenHarmony
[`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64
[`x86_64-pc-solaris`](platform-support/solaris.md) | 64-bit x86 Solaris 11.4
[`sparcv9-sun-solaris`](platform-support/solaris.md) | SPARC V9 Solaris 11.4
## Tier 2 without Host Tools
@ -183,7 +185,6 @@ target | std | notes
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
[`sparcv9-sun-solaris`](platform-support/solaris.md) | ✓ | SPARC V9 Solaris 11.4
[`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M
[`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M
[`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat
@ -203,7 +204,6 @@ target | std | notes
[`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
[`x86_64-pc-solaris`](platform-support/solaris.md) | ✓ | 64-bit x86 Solaris 11.4
[`x86_64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI
[`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)

View file

@ -12,7 +12,9 @@ Rust for Solaris operating system.
## Requirements
Binary built for this target is expected to run on sparcv9 or x86_64, and Solaris 11.4.
The `sparcv9-sun-solaris` and `x86_64-pc-solaris` targets are Tier 2 with host tools.
Binary built for these targets are expected to run on sparcv9 or x86_64, and Solaris 11.4.
## Testing

View file

@ -2,120 +2,8 @@
# -*- coding: utf-8 -*-
r"""
htmldocck.py is a custom checker script for Rustdoc HTML outputs.
# How and why?
The principle is simple: This script receives a path to generated HTML
documentation and a "template" script, which has a series of check
commands like `@has` or `@matches`. Each command is used to check if
some pattern is present or not present in the particular file or in
a particular node of the HTML tree. In many cases, the template script
happens to be the source code given to rustdoc.
While it indeed is possible to test in smaller portions, it has been
hard to construct tests in this fashion and major rendering errors were
discovered much later. This script is designed to make black-box and
regression testing of Rustdoc easy. This does not preclude the needs for
unit testing, but can be used to complement related tests by quickly
showing the expected renderings.
In order to avoid one-off dependencies for this task, this script uses
a reasonably working HTML parser and the existing XPath implementation
from Python's standard library. Hopefully, we won't render
non-well-formed HTML.
# Commands
Commands start with an `@` followed by a command name (letters and
hyphens), and zero or more arguments separated by one or more whitespace
characters and optionally delimited with single or double quotes. The `@`
mark cannot be preceded by a non-whitespace character. Other lines
(including every text up to the first `@`) are ignored, but it is
recommended to avoid the use of `@` in the template file.
There are a number of supported commands:
* `@has PATH` checks for the existence of the given file.
`PATH` is relative to the output directory. It can be given as `-`
which repeats the most recently used `PATH`.
* `@hasraw PATH PATTERN` and `@matchesraw PATH PATTERN` checks
for the occurrence of the given pattern `PATTERN` in the specified file.
Only one occurrence of the pattern is enough.
For `@hasraw`, `PATTERN` is a whitespace-normalized (every consecutive
whitespace being replaced by one single space character) string.
The entire file is also whitespace-normalized including newlines.
For `@matchesraw`, `PATTERN` is a Python-supported regular expression.
The file remains intact but the regexp is matched without the `MULTILINE`
and `IGNORECASE` options. You can still use a prefix `(?m)` or `(?i)`
to override them, and `\A` and `\Z` for definitely matching
the beginning and end of the file.
(The same distinction goes to other variants of these commands.)
* `@has PATH XPATH PATTERN` and `@matches PATH XPATH PATTERN` checks for
the presence of the given XPath `XPATH` in the specified HTML file,
and also the occurrence of the given pattern `PATTERN` in the matching
node or attribute. Only one occurrence of the pattern in the match
is enough.
`PATH` should be a valid and well-formed HTML file. It does *not*
accept arbitrary HTML5; it should have matching open and close tags
and correct entity references at least.
`XPATH` is an XPath expression to match. The XPath is fairly limited:
`tag`, `*`, `.`, `//`, `..`, `[@attr]`, `[@attr='value']`, `[tag]`,
`[POS]` (element located in given `POS`), `[last()-POS]`, `text()`
and `@attr` (both as the last segment) are supported. Some examples:
- `//pre` or `.//pre` matches any element with a name `pre`.
- `//a[@href]` matches any element with an `href` attribute.
- `//*[@class="impl"]//code` matches any element with a name `code`,
which is an ancestor of some element which `class` attr is `impl`.
- `//h1[@class="fqn"]/span[1]/a[last()]/@class` matches a value of
`class` attribute in the last `a` element (can be followed by more
elements that are not `a`) inside the first `span` in the `h1` with
a class of `fqn`. Note that there cannot be any additional elements
between them due to the use of `/` instead of `//`.
Do not try to use non-absolute paths, it won't work due to the flawed
ElementTree implementation. The script rejects them.
For the text matches (i.e. paths not ending with `@attr`), any
subelements are flattened into one string; this is handy for ignoring
highlights for example. If you want to simply check for the presence of
a given node or attribute, use an empty string (`""`) as a `PATTERN`.
* `@count PATH XPATH COUNT` checks for the occurrence of the given XPath
in the specified file. The number of occurrences must match the given
count.
* `@count PATH XPATH TEXT COUNT` checks for the occurrence of the given XPath
with the given text in the specified file. The number of occurrences must
match the given count.
* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
A snapshot test captures a subtree of the DOM, at the location
determined by the XPath, and compares it to a pre-recorded value
in a file. The file's name is the test's name with the `.rs` extension
replaced with `.NAME.html`, where NAME is the snapshot's name.
htmldocck supports the `--bless` option to accept the current subtree
as expected, saving it to the file determined by the snapshot's name.
compiletest's `--bless` flag is forwarded to htmldocck.
* `@has-dir PATH` checks for the existence of the given directory.
* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly
`[ENTRIES]`.
All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
checks if the given file does not exist, for example.
For documentation and usage instructions, please see
https://rustc-dev-guide.rust-lang.org/rustdoc-internals/rustdoc-test-suite.html
"""
from __future__ import absolute_import, print_function, unicode_literals

View file

@ -345,9 +345,7 @@ pub(crate) fn run_global_ctxt(
// (see `override_queries` in the `config`)
// NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
let _ = tcx.sess.time("wf_checking", || {
tcx.try_par_hir_for_each_module(|module| tcx.ensure_ok().check_mod_type_wf(module))
});
let _ = tcx.sess.time("wf_checking", || tcx.ensure_ok().check_type_wf(()));
tcx.dcx().abort_if_errors();

View file

@ -960,5 +960,7 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
}
pub fn eq_delim_args(l: &DelimArgs, r: &DelimArgs) -> bool {
l.delim == r.delim && l.tokens.eq_unspanned(&r.tokens)
l.delim == r.delim
&& l.tokens.len() == r.tokens.len()
&& l.tokens.iter().zip(r.tokens.iter()).all(|(a, b)| a.eq_unspanned(b))
}

View file

@ -145,10 +145,7 @@ impl IsolatedAlloc {
if pinfo.domain_size() < offset_pinfo + size_pinfo {
break;
}
// FIXME: is there a more efficient way to check whether the entire range is unset
// in the bitset?
let range_avail = !(offset_pinfo..offset_pinfo + size_pinfo).any(|i| pinfo.contains(i));
if range_avail {
if !pinfo.contains_any(offset_pinfo..offset_pinfo + size_pinfo) {
pinfo.insert_range(offset_pinfo..offset_pinfo + size_pinfo);
// SAFETY: We checked the available bytes after `idx` in the call
// to `domain_size` above and asserted there are at least `idx +

View file

@ -27,8 +27,9 @@ trait Copy {}
#[repr(simd)]
pub struct Sse([f32; 4]);
// x86-64: <4 x float> @sse_id(<4 x float> {{[^,]*}})
// x86-32: <4 x float> @sse_id(<4 x float> {{[^,]*}})
// FIXME: due to #139029 we are passing them all indirectly.
// x86-64: void @sse_id(ptr{{( [^,]*)?}} sret([16 x i8]){{( .*)?}}, ptr{{( [^,]*)?}})
// x86-32: void @sse_id(ptr{{( [^,]*)?}} sret([16 x i8]){{( .*)?}}, ptr{{( [^,]*)?}})
// x86-32-nosse: void @sse_id(ptr{{( [^,]*)?}} sret([16 x i8]){{( .*)?}}, ptr{{( [^,]*)?}})
#[no_mangle]
pub fn sse_id(x: Sse) -> Sse {

View file

@ -1,14 +1,8 @@
//
//@ compile-flags: -C no-prepopulate-passes
// LLVM IR isn't very portable and the one tested here depends on the ABI
// which is different between x86 (where we use SSE registers) and others.
// `x86-64` and `x86-32-sse2` are identical, but compiletest does not support
// taking the union of multiple `only` annotations.
//@ revisions: x86-64 x86-32-sse2 other
//@[x86-64] only-x86_64
//@[x86-32-sse2] only-rustc_abi-x86-sse2
//@[other] ignore-rustc_abi-x86-sse2
//@[other] ignore-x86_64
// 32bit MSVC does not align things properly so we suppress high alignment annotations (#112480)
//@ ignore-i686-pc-windows-msvc
//@ ignore-i686-pc-windows-gnu
#![crate_type = "lib"]
#![allow(non_camel_case_types)]
@ -47,9 +41,7 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> {
#[no_mangle]
pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> {
// CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
// x86-32: ret <4 x float> %[[VAL:.+]]
// x86-64: ret <4 x float> %[[VAL:.+]]
// other: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
unsafe { std::mem::transmute(x) }
}
@ -64,8 +56,6 @@ pub fn build_array_t(x: [f32; 4]) -> T {
#[no_mangle]
pub fn build_array_transmute_t(x: [f32; 4]) -> T {
// CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]]
// x86-32: ret <4 x float> %[[VAL:.+]]
// x86-64: ret <4 x float> %[[VAL:.+]]
// other: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
// CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]]
unsafe { std::mem::transmute(x) }
}

View file

@ -30,16 +30,18 @@ fn load<T, const N: usize>(v: PackedSimd<T, N>) -> FullSimd<T, N> {
}
}
// CHECK-LABEL: define <3 x float> @square_packed_full(ptr{{[a-z_ ]*}} align 4 {{[^,]*}})
// CHECK-LABEL: square_packed_full
// CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align (8|16)]]{{[^%]*}} [[RET_VREG:%[_0-9]*]]
// CHECK-SAME: ptr{{[a-z_ ]*}} align 4
#[no_mangle]
pub fn square_packed_full(x: PackedSimd<f32, 3>) -> FullSimd<f32, 3> {
// The unoptimized version of this is not very interesting to check
// since `load` does not get inlined.
// opt3-NEXT: start:
// opt3-NEXT: load <3 x float>
// CHECK-NEXT: start
// noopt: alloca [[RET_TYPE]], [[RET_ALIGN]]
// CHECK: load <3 x float>
let x = load(x);
// opt3-NEXT: [[VREG:%[a-z0-9_]+]] = fmul <3 x float>
// opt3-NEXT: ret <3 x float> [[VREG:%[a-z0-9_]+]]
// CHECK: [[VREG:%[a-z0-9_]+]] = fmul <3 x float>
// CHECK-NEXT: store <3 x float> [[VREG]], ptr [[RET_VREG]], [[RET_ALIGN]]
// CHECK-NEXT: ret void
unsafe { intrinsics::simd_mul(x, x) }
}

View file

@ -1,14 +0,0 @@
//@ known-bug: #121429
#![feature(generic_const_exprs)]
struct FixedI8<const X: usize>;
const FRAC_LHS: usize = 0;
const FRAC_RHS: usize = 1;
pub trait True {}
impl<const N: usize = { const { 3 } }> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> where
If<{}>: True
{
}

View file

@ -0,0 +1,25 @@
//@ compile-flags: -Z query-dep-graph
//@ revisions: rpass1
// Exercises a debug-assertions-only query cycle that when printing a valtree const in
// a dep node's debug representation, we end up invoking a query that also has a valtree
// const in its dep node's debug representation, which leads to a cycle (and ICE, since
// deps are not tracked when printing dep nodes' debug representations).
#![feature(adt_const_params)]
use std::marker::ConstParamTy;
#[derive(Debug, ConstParamTy, PartialEq, Eq)]
enum Foo {
A1,
}
#[inline(never)]
fn hello<const F: Foo>() {
println!("{:#?}", F);
}
fn main() {
hello::<{ Foo::A1 }>();
}

View file

@ -7,6 +7,5 @@ use std::arch::naked_asm;
#[unsafe(naked)]
pub extern "C" fn naked(p: char) -> u128 {
//~^ WARN uses type `char`
//~| WARN uses type `u128`
naked_asm!("")
}

View file

@ -8,13 +8,5 @@ LL | pub extern "C" fn naked(p: char) -> u128 {
= note: the `char` type has no C equivalent
= note: `#[warn(improper_ctypes_definitions)]` on by default
warning: `extern` fn uses type `u128`, which is not FFI-safe
--> $DIR/naked-functions-ffi.rs:8:37
|
LL | pub extern "C" fn naked(p: char) -> u128 {
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
warning: 2 warnings emitted
warning: 1 warning emitted

View file

@ -1,3 +1,11 @@
error: unconstrained opaque type
--> $DIR/issue-109299-1.rs:10:10
|
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `X` must be used in combination with a concrete type within the same crate
error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current scope
--> $DIR/issue-109299-1.rs:10:40
|
@ -23,14 +31,6 @@ LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
- `Lexer<i32>`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unconstrained opaque type
--> $DIR/issue-109299-1.rs:10:10
|
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `X` must be used in combination with a concrete type within the same crate
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0220`.

View file

@ -198,16 +198,6 @@ LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:133:42
|
LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:139:42
|
@ -216,24 +206,6 @@ LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:139:42
|
LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:145:45
|
LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:145:45
|
@ -241,8 +213,6 @@ LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:151:40
@ -340,60 +310,6 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:189:40
|
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:189:40
|
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:193:40
|
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:193:40
|
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:197:43
|
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:197:43
|
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:202:36
|
@ -664,6 +580,16 @@ LL | type A: Iterator<Item: 'static, Item: 'static>;
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:133:42
|
LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0282]: type annotations needed
--> $DIR/duplicate.rs:136:5
|
@ -675,6 +601,16 @@ help: consider specifying the generic argument
LL | iter::empty::<T>()
| +++++
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:139:42
|
LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0282]: type annotations needed
--> $DIR/duplicate.rs:142:5
|
@ -686,6 +622,16 @@ help: consider specifying the generic argument
LL | iter::empty::<T>()
| +++++
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:145:45
|
LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0282]: type annotations needed
--> $DIR/duplicate.rs:148:5
|
@ -729,6 +675,24 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
|
= note: `ETAI4` must be used in combination with a concrete type within the same crate
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:189:40
|
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:189:40
|
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unconstrained opaque type
--> $DIR/duplicate.rs:193:14
|
@ -737,6 +701,24 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
|
= note: `ETAI5` must be used in combination with a concrete type within the same crate
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:193:40
|
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:193:40
|
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unconstrained opaque type
--> $DIR/duplicate.rs:197:14
|
@ -745,6 +727,24 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
|
= note: `ETAI6` must be used in combination with a concrete type within the same crate
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:197:43
|
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:197:43
|
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 87 previous errors
Some errors have detailed explanations: E0282, E0719.

View file

@ -1,7 +1,8 @@
//@ known-bug: #140530
// ex-ice: #140530
//@ edition: 2024
//@ build-pass
#![feature(async_drop, gen_blocks)]
#![allow(incomplete_features)]
async gen fn a() {
_ = async {}
}

View file

@ -14,28 +14,28 @@ impl Bar2 {
mod foo {
#[derive(Default)]
pub struct Bar { i: ::Bar2 }
pub struct Bar { i: crate::Bar2 }
#[derive(Default)]
pub struct Baz(::Baz2);
pub struct Baz(crate::Baz2);
impl Bar {
fn f(&self) -> bool { false }
}
impl ::std::ops::Deref for Bar {
type Target = ::Bar2;
fn deref(&self) -> &::Bar2 { &self.i }
type Target = crate::Bar2;
fn deref(&self) -> &crate::Bar2 { &self.i }
}
impl ::std::ops::Deref for Baz {
type Target = ::Baz2;
fn deref(&self) -> &::Baz2 { &self.0 }
type Target = crate::Baz2;
fn deref(&self) -> &crate::Baz2 { &self.0 }
}
pub fn f(bar: &Bar, baz: &Baz) {
// Since the private fields and methods are visible here, there should be no autoderefs.
let _: &::Bar2 = &bar.i;
let _: &::Baz2 = &baz.0;
let _: &crate::Bar2 = &bar.i;
let _: &crate::Baz2 = &baz.0;
assert!(!bar.f());
}
}

View file

@ -16,7 +16,7 @@ pub mod name_pool {
}
pub mod rust {
pub use name_pool::add;
pub use crate::name_pool::add;
pub type rt = Box<()>;

View file

@ -44,7 +44,7 @@ mod m {
#[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
pub(crate) b_crate: i32,
#[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
pub(in m) c_mod: i32,
pub(in crate::m) c_mod: i32,
#[stable(feature = "unit_test", since = "1.0.0")] // SILLY
d_priv: i32
}
@ -60,7 +60,7 @@ mod m {
pub i32,
pub(crate) i32,
pub(in m) i32,
pub(in crate::m) i32,
i32);
impl Record {
@ -113,7 +113,7 @@ mod m {
#[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
pub(crate) fn pub_crate(&self) -> i32 { self.d_priv }
#[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
pub(in m) fn pub_mod(&self) -> i32 { self.d_priv }
pub(in crate::m) fn pub_mod(&self) -> i32 { self.d_priv }
#[stable(feature = "unit_test", since = "1.0.0")] // SILLY
fn private(&self) -> i32 { self.d_priv }
}
@ -127,7 +127,7 @@ mod m {
pub fn stable(&self) -> i32 { self.0 }
pub(crate) fn pub_crate(&self) -> i32 { self.0 }
pub(in m) fn pub_mod(&self) -> i32 { self.0 }
pub(in crate::m) fn pub_mod(&self) -> i32 { self.0 }
fn private(&self) -> i32 { self.0 }
}
}

View file

@ -62,6 +62,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`c`
`cache`
`cmpxchg16b`
`concurrent-functions`
`crc`
`crt-static`
`cssc`
@ -159,6 +160,15 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`lzcnt`
`m`
`mclass`
`message-security-assist-extension12`
`message-security-assist-extension3`
`message-security-assist-extension4`
`message-security-assist-extension5`
`message-security-assist-extension8`
`message-security-assist-extension9`
`miscellaneous-extensions-2`
`miscellaneous-extensions-3`
`miscellaneous-extensions-4`
`mops`
`movbe`
`movrs`
@ -287,9 +297,11 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`vector`
`vector-enhancements-1`
`vector-enhancements-2`
`vector-enhancements-3`
`vector-packed-decimal`
`vector-packed-decimal-enhancement`
`vector-packed-decimal-enhancement-2`
`vector-packed-decimal-enhancement-3`
`vfp2`
`vfp3`
`vfp4`

View file

@ -15,8 +15,8 @@ mod Lib {
mod Import {
// Trait is in scope here:
use Lib::TheStruct;
use Lib::TheTrait;
use crate::Lib::TheStruct;
use crate::Lib::TheTrait;
fn call_the_fn(s: &TheStruct) {
s.the_fn();
@ -25,7 +25,7 @@ mod Import {
mod NoImport {
// Trait is not in scope here:
use Lib::TheStruct;
use crate::Lib::TheStruct;
fn call_the_fn(s: &TheStruct) {
s.the_fn();

View file

@ -4,7 +4,7 @@
struct Bar;
mod non_constants {
use Bar;
use crate::Bar;
fn no_impl_copy_empty_value_multiple_elements() {
let x = None;

View file

@ -5,7 +5,7 @@
struct Bar;
mod constants {
use Bar;
use crate::Bar;
fn no_impl_copy_empty_value_no_elements() {
const FOO: Option<Bar> = None;
@ -69,7 +69,7 @@ mod constants {
}
mod non_constants {
use Bar;
use crate::Bar;
fn no_impl_copy_empty_value_no_elements() {
let x = None;

View file

@ -4,7 +4,7 @@
struct Bar;
mod non_constants {
use Bar;
use crate::Bar;
fn no_impl_copy_empty_value_multiple_elements() {
let x = None;

View file

@ -5,7 +5,7 @@
struct Bar;
mod constants {
use Bar;
use crate::Bar;
fn no_impl_copy_empty_value_no_elements() {
const FOO: Option<Bar> = None;
@ -69,7 +69,7 @@ mod constants {
}
mod non_constants {
use Bar;
use crate::Bar;
fn no_impl_copy_empty_value_no_elements() {
let x = None;

Some files were not shown because too many files have changed in this diff Show more