Merge from rustc
This commit is contained in:
commit
bd898e38af
269 changed files with 1722 additions and 1675 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>`.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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, ¶m, &mut feature)?,
|
||||
Some(sym::since) => insert_value_into_option_or_error(cx, ¶m, &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, ¶m, &mut feature)?,
|
||||
Some(sym::reason) => insert_value_into_option_or_error(cx, ¶m, &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;
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<_>, _>>()?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -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")]);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
36
src/ci/docker/host-x86_64/dist-sparcv9-solaris/Dockerfile
Normal file
36
src/ci/docker/host-x86_64/dist-sparcv9-solaris/Dockerfile
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
36
src/ci/docker/host-x86_64/dist-x86_64-solaris/Dockerfile
Normal file
36
src/ci/docker/host-x86_64/dist-x86_64-solaris/Dockerfile
Normal 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
|
||||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
162
src/ci/docker/scripts/solaris-toolchain.sh
Normal file
162
src/ci/docker/scripts/solaris-toolchain.sh
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 +
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
25
tests/incremental/print-dep-node-cycle.rs
Normal file
25
tests/incremental/print-dep-node-cycle.rs
Normal 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 }>();
|
||||
}
|
||||
|
|
@ -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!("")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<()>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue