mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #153865 - Zalathar:rollup-tKflfa5, r=Zalathar
Rollup of 5 pull requests Successful merges: - rust-lang/rust#153769 (target specs: stricter checks for LLVM ABI values, and correlate that with cfg(target_abi)) - rust-lang/rust#153811 (Don't pass a separate `DepKind` to `query_feed`) - rust-lang/rust#153817 (relocate several ui tests) - rust-lang/rust#153840 (tests/debuginfo/basic-stepping.rs: Add cdb test) - rust-lang/rust#153858 (Use named fields in ChunkedBitSet's `Chunk::Mixed`)
This commit is contained in:
@@ -294,18 +294,13 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
|
||||
_ => elf::EF_MIPS_ARCH_64R2,
|
||||
};
|
||||
|
||||
// If the ABI is explicitly given, use it, or default to O32 on 32-bit MIPS,
|
||||
// which is the only "true" 32-bit option that LLVM supports.
|
||||
// Use the explicitly given ABI.
|
||||
match sess.target.options.llvm_abiname.as_ref() {
|
||||
"o32" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
|
||||
"n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2,
|
||||
"n64" if !is_32bit => {}
|
||||
"" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
|
||||
"" => sess.dcx().fatal("LLVM ABI must be specified for 64-bit MIPS targets"),
|
||||
s if is_32bit => {
|
||||
sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 32-bit MIPS target", s))
|
||||
}
|
||||
s => sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 64-bit MIPS target", s)),
|
||||
// The rest is invalid (which is already ensured by the target spec check).
|
||||
s => bug!("invalid LLVM ABI `{}` for MIPS target", s),
|
||||
};
|
||||
|
||||
if sess.target.options.relocation_model != RelocModel::Static {
|
||||
|
||||
@@ -509,14 +509,20 @@ enum Chunk {
|
||||
/// to store the length, which would make this type larger. These excess
|
||||
/// words are always zero, as are any excess bits in the final in-use word.
|
||||
///
|
||||
/// The `ChunkSize` field is the count of 1s set in the chunk, and
|
||||
/// must satisfy `0 < count < chunk_domain_size`.
|
||||
///
|
||||
/// The words are within an `Rc` because it's surprisingly common to
|
||||
/// duplicate an entire chunk, e.g. in `ChunkedBitSet::clone_from()`, or
|
||||
/// when a `Mixed` chunk is union'd into a `Zeros` chunk. When we do need
|
||||
/// to modify a chunk we use `Rc::make_mut`.
|
||||
Mixed(ChunkSize, Rc<[Word; CHUNK_WORDS]>),
|
||||
Mixed {
|
||||
/// Count of set bits (1s) in this chunk's words.
|
||||
///
|
||||
/// Invariant: `0 < ones_count < chunk_domain_size`.
|
||||
///
|
||||
/// Tracking this separately allows individual insert/remove calls to
|
||||
/// know that the chunk has become all-zeroes or all-ones, in O(1) time.
|
||||
ones_count: ChunkSize,
|
||||
words: Rc<[Word; CHUNK_WORDS]>,
|
||||
},
|
||||
}
|
||||
|
||||
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
@@ -613,7 +619,7 @@ pub fn contains(&self, elem: T) -> bool {
|
||||
match &chunk {
|
||||
Zeros => false,
|
||||
Ones => true,
|
||||
Mixed(_, words) => {
|
||||
Mixed { ones_count: _, words } => {
|
||||
let (word_index, mask) = chunk_word_index_and_mask(elem);
|
||||
(words[word_index] & mask) != 0
|
||||
}
|
||||
@@ -644,19 +650,19 @@ pub fn insert(&mut self, elem: T) -> bool {
|
||||
|
||||
let (word_index, mask) = chunk_word_index_and_mask(elem);
|
||||
words_ref[word_index] |= mask;
|
||||
*chunk = Mixed(1, words);
|
||||
*chunk = Mixed { ones_count: 1, words };
|
||||
} else {
|
||||
*chunk = Ones;
|
||||
}
|
||||
true
|
||||
}
|
||||
Ones => false,
|
||||
Mixed(ref mut count, ref mut words) => {
|
||||
Mixed { ref mut ones_count, ref mut words } => {
|
||||
// We skip all the work if the bit is already set.
|
||||
let (word_index, mask) = chunk_word_index_and_mask(elem);
|
||||
if (words[word_index] & mask) == 0 {
|
||||
*count += 1;
|
||||
if *count < chunk_domain_size {
|
||||
*ones_count += 1;
|
||||
if *ones_count < chunk_domain_size {
|
||||
let words = Rc::make_mut(words);
|
||||
words[word_index] |= mask;
|
||||
} else {
|
||||
@@ -702,18 +708,18 @@ pub fn remove(&mut self, elem: T) -> bool {
|
||||
);
|
||||
let (word_index, mask) = chunk_word_index_and_mask(elem);
|
||||
words_ref[word_index] &= !mask;
|
||||
*chunk = Mixed(chunk_domain_size - 1, words);
|
||||
*chunk = Mixed { ones_count: chunk_domain_size - 1, words };
|
||||
} else {
|
||||
*chunk = Zeros;
|
||||
}
|
||||
true
|
||||
}
|
||||
Mixed(ref mut count, ref mut words) => {
|
||||
Mixed { ref mut ones_count, ref mut words } => {
|
||||
// We skip all the work if the bit is already clear.
|
||||
let (word_index, mask) = chunk_word_index_and_mask(elem);
|
||||
if (words[word_index] & mask) != 0 {
|
||||
*count -= 1;
|
||||
if *count > 0 {
|
||||
*ones_count -= 1;
|
||||
if *ones_count > 0 {
|
||||
let words = Rc::make_mut(words);
|
||||
words[word_index] &= !mask;
|
||||
} else {
|
||||
@@ -732,7 +738,7 @@ fn chunk_iter(&self, chunk_index: usize) -> ChunkIter<'_> {
|
||||
match self.chunks.get(chunk_index) {
|
||||
Some(Zeros) => ChunkIter::Zeros,
|
||||
Some(Ones) => ChunkIter::Ones(0..chunk_domain_size as usize),
|
||||
Some(Mixed(_, words)) => {
|
||||
Some(Mixed { ones_count: _, words }) => {
|
||||
let num_words = num_words(chunk_domain_size as usize);
|
||||
ChunkIter::Mixed(BitIter::new(&words[0..num_words]))
|
||||
}
|
||||
@@ -765,14 +771,14 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
|
||||
match (&mut self_chunk, &other_chunk) {
|
||||
(_, Zeros) | (Ones, _) => {}
|
||||
(Zeros, _) | (Mixed(..), Ones) => {
|
||||
(Zeros, _) | (Mixed { .. }, Ones) => {
|
||||
// `other_chunk` fully overwrites `self_chunk`
|
||||
*self_chunk = other_chunk.clone();
|
||||
changed = true;
|
||||
}
|
||||
(
|
||||
Mixed(self_chunk_count, self_chunk_words),
|
||||
Mixed(_other_chunk_count, other_chunk_words),
|
||||
Mixed { ones_count: self_chunk_ones, words: self_chunk_words },
|
||||
Mixed { ones_count: _, words: other_chunk_words },
|
||||
) => {
|
||||
// First check if the operation would change
|
||||
// `self_chunk.words`. If not, we can avoid allocating some
|
||||
@@ -807,8 +813,8 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
op,
|
||||
);
|
||||
debug_assert!(has_changed);
|
||||
*self_chunk_count = count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_count == chunk_domain_size {
|
||||
*self_chunk_ones = count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_ones == chunk_domain_size {
|
||||
*self_chunk = Ones;
|
||||
}
|
||||
changed = true;
|
||||
@@ -839,11 +845,11 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
|
||||
match (&mut self_chunk, &other_chunk) {
|
||||
(Zeros, _) | (_, Zeros) => {}
|
||||
(Ones | Mixed(..), Ones) => {
|
||||
(Ones | Mixed { .. }, Ones) => {
|
||||
changed = true;
|
||||
*self_chunk = Zeros;
|
||||
}
|
||||
(Ones, Mixed(other_chunk_count, other_chunk_words)) => {
|
||||
(Ones, Mixed { ones_count: other_chunk_ones, words: other_chunk_words }) => {
|
||||
changed = true;
|
||||
let num_words = num_words(chunk_domain_size as usize);
|
||||
debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS);
|
||||
@@ -854,16 +860,17 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
*word = !*word & tail_mask;
|
||||
tail_mask = Word::MAX;
|
||||
}
|
||||
let self_chunk_count = chunk_domain_size - *other_chunk_count;
|
||||
let self_chunk_ones = chunk_domain_size - *other_chunk_ones;
|
||||
debug_assert_eq!(
|
||||
self_chunk_count,
|
||||
self_chunk_ones,
|
||||
count_ones(&self_chunk_words[0..num_words]) as ChunkSize
|
||||
);
|
||||
*self_chunk = Mixed(self_chunk_count, Rc::new(self_chunk_words));
|
||||
*self_chunk =
|
||||
Mixed { ones_count: self_chunk_ones, words: Rc::new(self_chunk_words) };
|
||||
}
|
||||
(
|
||||
Mixed(self_chunk_count, self_chunk_words),
|
||||
Mixed(_other_chunk_count, other_chunk_words),
|
||||
Mixed { ones_count: self_chunk_ones, words: self_chunk_words },
|
||||
Mixed { ones_count: _, words: other_chunk_words },
|
||||
) => {
|
||||
// See `ChunkedBitSet::union` for details on what is happening here.
|
||||
let num_words = num_words(chunk_domain_size as usize);
|
||||
@@ -883,8 +890,8 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
op,
|
||||
);
|
||||
debug_assert!(has_changed);
|
||||
*self_chunk_count = count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_count == 0 {
|
||||
*self_chunk_ones = count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_ones == 0 {
|
||||
*self_chunk = Zeros;
|
||||
}
|
||||
changed = true;
|
||||
@@ -915,13 +922,13 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
|
||||
match (&mut self_chunk, &other_chunk) {
|
||||
(Zeros, _) | (_, Ones) => {}
|
||||
(Ones, Zeros | Mixed(..)) | (Mixed(..), Zeros) => {
|
||||
(Ones, Zeros | Mixed { .. }) | (Mixed { .. }, Zeros) => {
|
||||
changed = true;
|
||||
*self_chunk = other_chunk.clone();
|
||||
}
|
||||
(
|
||||
Mixed(self_chunk_count, self_chunk_words),
|
||||
Mixed(_other_chunk_count, other_chunk_words),
|
||||
Mixed { ones_count: self_chunk_ones, words: self_chunk_words },
|
||||
Mixed { ones_count: _, words: other_chunk_words },
|
||||
) => {
|
||||
// See `ChunkedBitSet::union` for details on what is happening here.
|
||||
let num_words = num_words(chunk_domain_size as usize);
|
||||
@@ -941,8 +948,8 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
op,
|
||||
);
|
||||
debug_assert!(has_changed);
|
||||
*self_chunk_count = count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_count == 0 {
|
||||
*self_chunk_ones = count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_ones == 0 {
|
||||
*self_chunk = Zeros;
|
||||
}
|
||||
changed = true;
|
||||
@@ -1023,11 +1030,11 @@ fn assert_valid(&self, chunk_domain_size: ChunkSize) {
|
||||
assert!(chunk_domain_size as usize <= CHUNK_BITS);
|
||||
match *self {
|
||||
Zeros | Ones => {}
|
||||
Mixed(count, ref words) => {
|
||||
assert!(0 < count && count < chunk_domain_size);
|
||||
Mixed { ones_count, ref words } => {
|
||||
assert!(0 < ones_count && ones_count < chunk_domain_size);
|
||||
|
||||
// Check the number of set bits matches `count`.
|
||||
assert_eq!(count_ones(words.as_slice()) as ChunkSize, count);
|
||||
assert_eq!(count_ones(words.as_slice()) as ChunkSize, ones_count);
|
||||
|
||||
// Check the not-in-use words are all zeroed.
|
||||
let num_words = num_words(chunk_domain_size as usize);
|
||||
@@ -1043,7 +1050,7 @@ fn count(&self, chunk_domain_size: ChunkSize) -> usize {
|
||||
match *self {
|
||||
Zeros => 0,
|
||||
Ones => chunk_domain_size as usize,
|
||||
Mixed(count, _) => count as usize,
|
||||
Mixed { ones_count, words: _ } => usize::from(ones_count),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,16 +162,16 @@ fn chunked_bitset() {
|
||||
assert!(!b100.contains(20) && b100.contains(30) && !b100.contains(99) && b100.contains(50));
|
||||
assert_eq!(
|
||||
b100.chunks(),
|
||||
vec![Mixed(
|
||||
97,
|
||||
vec![Mixed {
|
||||
ones_count: 97,
|
||||
#[rustfmt::skip]
|
||||
Rc::new([
|
||||
words: Rc::new([
|
||||
0b11111111_11111111_11111110_11111111_11111111_11101111_11111111_11111111,
|
||||
0b00000000_00000000_00000000_00000111_11111111_11111111_11111111_11111111,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
])
|
||||
)],
|
||||
}],
|
||||
);
|
||||
b100.assert_valid();
|
||||
let mut num_removed = 0;
|
||||
@@ -228,14 +228,14 @@ fn chunked_bitset() {
|
||||
b4096.chunks(),
|
||||
#[rustfmt::skip]
|
||||
vec![
|
||||
Mixed(1, Rc::new([
|
||||
Mixed { ones_count: 1, words:Rc::new([
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
])),
|
||||
Mixed(1, Rc::new([
|
||||
])},
|
||||
Mixed { ones_count: 1, words: Rc::new([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000_0000_0000_0000
|
||||
])),
|
||||
])},
|
||||
],
|
||||
);
|
||||
assert_eq!(b4096.count(), 2);
|
||||
@@ -265,14 +265,14 @@ fn chunked_bitset() {
|
||||
#[rustfmt::skip]
|
||||
vec![
|
||||
Zeros,
|
||||
Mixed(1, Rc::new([
|
||||
Mixed { ones_count: 1, words: Rc::new([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100_0000_0000_0000, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
])),
|
||||
Mixed(1, Rc::new([
|
||||
])},
|
||||
Mixed { ones_count: 1, words: Rc::new([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
])),
|
||||
])},
|
||||
Zeros,
|
||||
Zeros,
|
||||
],
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
self, CrateInherentImpls, GenericArg, GenericArgsRef, LitToConstInput, PseudoCanonicalInput,
|
||||
SizedTraitKind, Ty, TyCtxt, TyCtxtFeed,
|
||||
};
|
||||
use crate::{dep_graph, mir, thir};
|
||||
use crate::{mir, thir};
|
||||
|
||||
// Each of these queries corresponds to a function pointer field in the
|
||||
// `Providers` struct for requesting a value of that type, and a method
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
use crate::dep_graph;
|
||||
use crate::dep_graph::{DepKind, DepNodeKey};
|
||||
use crate::dep_graph::DepNodeKey;
|
||||
use crate::query::erase::{self, Erasable, Erased};
|
||||
use crate::query::plumbing::QueryVTable;
|
||||
use crate::query::{EnsureMode, QueryCache, QueryMode};
|
||||
@@ -98,26 +98,26 @@ pub(crate) fn query_ensure_result<'tcx, C, T>(
|
||||
}
|
||||
}
|
||||
|
||||
/// Common implementation of query feeding, used by `define_feedable!`.
|
||||
/// "Feeds" a feedable query by adding a given key/value pair to its in-memory cache.
|
||||
/// Called by macro-generated methods of [`rustc_middle::ty::TyCtxtFeed`].
|
||||
pub(crate) fn query_feed<'tcx, C>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
dep_kind: DepKind,
|
||||
query_vtable: &QueryVTable<'tcx, C>,
|
||||
query: &'tcx QueryVTable<'tcx, C>,
|
||||
key: C::Key,
|
||||
value: C::Value,
|
||||
) where
|
||||
C: QueryCache,
|
||||
C::Key: DepNodeKey<'tcx>,
|
||||
{
|
||||
let format_value = query_vtable.format_value;
|
||||
let format_value = query.format_value;
|
||||
|
||||
// Check whether the in-memory cache already has a value for this key.
|
||||
match try_get_cached(tcx, &query_vtable.cache, key) {
|
||||
match try_get_cached(tcx, &query.cache, key) {
|
||||
Some(old) => {
|
||||
// The query already has a cached value for this key.
|
||||
// That's OK if both values are the same, i.e. they have the same hash,
|
||||
// so now we check their hashes.
|
||||
if let Some(hash_value_fn) = query_vtable.hash_value_fn {
|
||||
if let Some(hash_value_fn) = query.hash_value_fn {
|
||||
let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| {
|
||||
(hash_value_fn(hcx, &old), hash_value_fn(hcx, &value))
|
||||
});
|
||||
@@ -126,7 +126,7 @@ pub(crate) fn query_feed<'tcx, C>(
|
||||
// results is tainted by errors. In this case, delay a bug to
|
||||
// ensure compilation is doomed, and keep the `old` value.
|
||||
tcx.dcx().delayed_bug(format!(
|
||||
"Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
|
||||
"Trying to feed an already recorded value for query {query:?} key={key:?}:\n\
|
||||
old value: {old}\nnew value: {value}",
|
||||
old = format_value(&old),
|
||||
value = format_value(&value),
|
||||
@@ -137,7 +137,7 @@ pub(crate) fn query_feed<'tcx, C>(
|
||||
// If feeding the same value multiple times needs to be supported,
|
||||
// the query should not be marked `no_hash`.
|
||||
bug!(
|
||||
"Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
|
||||
"Trying to feed an already recorded value for query {query:?} key={key:?}:\n\
|
||||
old value: {old}\nnew value: {value}",
|
||||
old = format_value(&old),
|
||||
value = format_value(&value),
|
||||
@@ -147,15 +147,15 @@ pub(crate) fn query_feed<'tcx, C>(
|
||||
None => {
|
||||
// There is no cached value for this key, so feed the query by
|
||||
// adding the provided value to the cache.
|
||||
let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key);
|
||||
let dep_node = dep_graph::DepNode::construct(tcx, query.dep_kind, &key);
|
||||
let dep_node_index = tcx.dep_graph.with_feed_task(
|
||||
dep_node,
|
||||
tcx,
|
||||
&value,
|
||||
query_vtable.hash_value_fn,
|
||||
query_vtable.format_value,
|
||||
query.hash_value_fn,
|
||||
query.format_value,
|
||||
);
|
||||
query_vtable.cache.complete(key, value, dep_node_index);
|
||||
query.cache.complete(key, value, dep_node_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,7 +493,6 @@ pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
|
||||
let erased_value = $name::provided_to_erased(self.tcx, value);
|
||||
$crate::query::inner::query_feed(
|
||||
self.tcx,
|
||||
dep_graph::DepKind::$name,
|
||||
&self.tcx.query_system.query_vtables.$name,
|
||||
key,
|
||||
erased_value,
|
||||
|
||||
@@ -127,7 +127,12 @@ pub(crate) fn base(
|
||||
let link_env_remove = link_env_remove(&os);
|
||||
let unversioned_llvm_target = unversioned_llvm_target(&os, arch, env);
|
||||
let mut opts = TargetOptions {
|
||||
llvm_floatabi: Some(FloatAbi::Hard),
|
||||
llvm_floatabi: if arch.target_arch() == crate::spec::Arch::Arm {
|
||||
Some(FloatAbi::Hard)
|
||||
} else {
|
||||
// `llvm_floatabi` makes no sense on x86 and aarch64.
|
||||
None
|
||||
},
|
||||
os,
|
||||
env: env.target_env(),
|
||||
abi: env.target_abi(),
|
||||
|
||||
@@ -1005,7 +1005,7 @@ pub enum FloatAbi {
|
||||
pub enum RustcAbi {
|
||||
/// On x86-32 only: make use of SSE and SSE2 for ABI purposes.
|
||||
X86Sse2 = "x86-sse2",
|
||||
/// On x86-32/64 and S390x: do not use any FPU or SIMD registers for the ABI.
|
||||
/// On x86-32/64, aarch64, and S390x: do not use any FPU or SIMD registers for the ABI.
|
||||
Softfloat = "softfloat", "x86-softfloat",
|
||||
}
|
||||
|
||||
@@ -3183,69 +3183,277 @@ macro_rules! check_matches {
|
||||
);
|
||||
}
|
||||
|
||||
// Check that RISC-V targets always specify which ABI they use,
|
||||
// and that ARM targets specify their float ABI.
|
||||
// Check ABI flag consistency, for the architectures where we have proper ABI treatment.
|
||||
// To ensure targets are trated consistently, please consult with the team before allowing
|
||||
// new cases.
|
||||
match self.arch {
|
||||
Arch::RiscV32 => {
|
||||
Arch::X86 => {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on x86-32");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-32");
|
||||
check_matches!(
|
||||
&*self.llvm_abiname,
|
||||
"ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
|
||||
"invalid RISC-V ABI name: {}",
|
||||
(&self.rustc_abi, &self.abi),
|
||||
// FIXME: we do not currently set a target_abi for softfloat targets here,
|
||||
// but we probably should, so we already allow it.
|
||||
(Some(RustcAbi::Softfloat), Abi::SoftFloat | Abi::Unspecified | Abi::Other(_))
|
||||
| (
|
||||
Some(RustcAbi::X86Sse2) | None,
|
||||
Abi::Uwp | Abi::Llvm | Abi::Sim | Abi::Unspecified | Abi::Other(_)
|
||||
),
|
||||
"invalid x86-32 Rust-specific ABI and `cfg(target_abi)` combination:\n\
|
||||
Rust-specific ABI: {:?}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.rustc_abi,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::X86_64 => {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on x86-64");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-64");
|
||||
// FIXME: we do not currently set a target_abi for softfloat targets here, but we
|
||||
// probably should, so we already allow it.
|
||||
// FIXME: Ensure that target_abi = "x32" correlates with actually using that ABI.
|
||||
// Do any of the others need a similar check?
|
||||
check_matches!(
|
||||
(&self.rustc_abi, &self.abi),
|
||||
(Some(RustcAbi::Softfloat), Abi::SoftFloat | Abi::Unspecified | Abi::Other(_))
|
||||
| (
|
||||
None,
|
||||
Abi::X32
|
||||
| Abi::Llvm
|
||||
| Abi::Fortanix
|
||||
| Abi::Uwp
|
||||
| Abi::MacAbi
|
||||
| Abi::Sim
|
||||
| Abi::Unspecified
|
||||
| Abi::Other(_)
|
||||
),
|
||||
"invalid x86-64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
|
||||
Rust-specific ABI: {:?}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.rustc_abi,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::RiscV32 => {
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("ilp32", Abi::Unspecified | Abi::Other(_))
|
||||
| ("ilp32f", Abi::Unspecified | Abi::Other(_))
|
||||
| ("ilp32d", Abi::Unspecified | Abi::Other(_))
|
||||
| ("ilp32e", Abi::Ilp32e),
|
||||
"invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::RiscV64 => {
|
||||
// Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
|
||||
check_matches!(
|
||||
&*self.llvm_abiname,
|
||||
"lp64" | "lp64f" | "lp64d" | "lp64e",
|
||||
"invalid RISC-V ABI name: {}",
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("lp64", Abi::Unspecified | Abi::Other(_))
|
||||
| ("lp64f", Abi::Unspecified | Abi::Other(_))
|
||||
| ("lp64d", Abi::Unspecified | Abi::Other(_))
|
||||
| ("lp64e", Abi::Unspecified | Abi::Other(_)),
|
||||
"invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::Arm => {
|
||||
check!(
|
||||
self.llvm_floatabi.is_some(),
|
||||
"ARM targets must set `llvm-floatabi` to `hard` or `soft`",
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on ARM");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on ARM");
|
||||
check_matches!(
|
||||
(&self.llvm_floatabi, &self.abi),
|
||||
(
|
||||
Some(FloatAbi::Hard),
|
||||
Abi::EabiHf | Abi::Uwp | Abi::Unspecified | Abi::Other(_)
|
||||
) | (Some(FloatAbi::Soft), Abi::Eabi),
|
||||
"Invalid combination of float ABI and `cfg(target_abi)` for ARM target\n\
|
||||
float ABI: {:?}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_floatabi,
|
||||
self.abi,
|
||||
)
|
||||
}
|
||||
// PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
|
||||
Arch::AArch64 => {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on aarch64");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on aarch64");
|
||||
// FIXME: Ensure that target_abi = "ilp32" correlates with actually using that ABI.
|
||||
// Do any of the others need a similar check?
|
||||
check_matches!(
|
||||
(&self.rustc_abi, &self.abi),
|
||||
(Some(RustcAbi::Softfloat), Abi::SoftFloat)
|
||||
| (
|
||||
None,
|
||||
Abi::Ilp32
|
||||
| Abi::Llvm
|
||||
| Abi::MacAbi
|
||||
| Abi::Sim
|
||||
| Abi::Uwp
|
||||
| Abi::Unspecified
|
||||
| Abi::Other(_)
|
||||
),
|
||||
"invalid aarch64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
|
||||
Rust-specific ABI: {:?}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.rustc_abi,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::PowerPC => {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on PowerPC");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on PowerPC");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on PowerPC");
|
||||
// FIXME: Check that `target_abi` matches the actually configured ABI (with or
|
||||
// without SPE).
|
||||
check_matches!(
|
||||
self.abi,
|
||||
Abi::Spe | Abi::Unspecified | Abi::Other(_),
|
||||
"invalid `target_abi` for PowerPC"
|
||||
);
|
||||
}
|
||||
Arch::PowerPC64 => {
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on PowerPC64");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on PowerPC64");
|
||||
// PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
|
||||
if self.os == Os::Aix {
|
||||
check!(
|
||||
self.llvm_abiname.is_empty(),
|
||||
"AIX targets always use the AIX ABI and `llvm_abiname` should be left empty",
|
||||
// FIXME: Check that `target_abi` matches the actually configured ABI
|
||||
// (vec-default vs vec-ext).
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("", Abi::VecDefault | Abi::VecExtAbi),
|
||||
"invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
} else if self.endian == Endian::Big {
|
||||
check_matches!(
|
||||
&*self.llvm_abiname,
|
||||
"elfv1" | "elfv2",
|
||||
"invalid PowerPC64 ABI name: {}",
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("elfv1", Abi::ElfV1) | ("elfv2", Abi::ElfV2),
|
||||
"invalid PowerPC64 big-endian ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
} else {
|
||||
check!(
|
||||
self.llvm_abiname == "elfv2",
|
||||
"little-endian PowerPC64 targets only support the `elfv2` ABI",
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("elfv2", Abi::ElfV2),
|
||||
"invalid PowerPC64 little-endian ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Check consistency of Rust ABI declaration.
|
||||
if let Some(rust_abi) = self.rustc_abi {
|
||||
match rust_abi {
|
||||
RustcAbi::X86Sse2 => check_matches!(
|
||||
self.arch,
|
||||
Arch::X86,
|
||||
"`x86-sse2` ABI is only valid for x86-32 targets"
|
||||
),
|
||||
RustcAbi::Softfloat => check_matches!(
|
||||
self.arch,
|
||||
Arch::X86 | Arch::X86_64 | Arch::S390x | Arch::AArch64,
|
||||
"`softfloat` ABI is only valid for x86, s390x, and aarch64 targets"
|
||||
),
|
||||
Arch::S390x => {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on s390x");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on s390x");
|
||||
check_matches!(
|
||||
(&self.rustc_abi, &self.abi),
|
||||
(Some(RustcAbi::Softfloat), Abi::SoftFloat)
|
||||
| (None, Abi::Unspecified | Abi::Other(_)),
|
||||
"invalid s390x Rust-specific ABI and `cfg(target_abi)` combination:\n\
|
||||
Rust-specific ABI: {:?}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.rustc_abi,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::LoongArch32 => {
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("ilp32s", Abi::SoftFloat)
|
||||
| ("ilp32f", Abi::Unspecified | Abi::Other(_))
|
||||
| ("ilp32d", Abi::Unspecified | Abi::Other(_)),
|
||||
"invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::LoongArch64 => {
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("lp64s", Abi::SoftFloat)
|
||||
| ("lp64f", Abi::Unspecified | Abi::Other(_))
|
||||
| ("lp64d", Abi::Unspecified | Abi::Other(_)),
|
||||
"invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::Mips | Arch::Mips32r6 => {
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
("o32", Abi::Unspecified | Abi::Other(_)),
|
||||
"invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::Mips64 | Arch::Mips64r6 => {
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
|
||||
check_matches!(
|
||||
(&*self.llvm_abiname, &self.abi),
|
||||
// No in-tree targets use "n32" but at least for now we let out-of-tree targets
|
||||
// experiment with that.
|
||||
("n64", Abi::Abi64) | ("n32", Abi::Unspecified | Abi::Other(_)),
|
||||
"invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
|
||||
ABI name: {}\n\
|
||||
cfg(target_abi): {}",
|
||||
self.llvm_abiname,
|
||||
self.abi,
|
||||
);
|
||||
}
|
||||
Arch::CSky => {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on CSky");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on CSky");
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on CSky");
|
||||
// FIXME: Check that `target_abi` matches the actually configured ABI (v2 vs v2hf).
|
||||
check_matches!(
|
||||
self.abi,
|
||||
Abi::AbiV2 | Abi::AbiV2Hf,
|
||||
"invalid `target_abi` for CSky"
|
||||
);
|
||||
}
|
||||
ref arch => {
|
||||
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on {arch}");
|
||||
// Ensure consistency among built-in targets, but give JSON targets the opportunity
|
||||
// to experiment with these.
|
||||
if kind == TargetKind::Builtin {
|
||||
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on {arch}");
|
||||
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on {arch}");
|
||||
check_matches!(
|
||||
self.abi,
|
||||
Abi::Unspecified | Abi::Other(_),
|
||||
"`target_abi` is unused on {arch}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3305,7 +3513,8 @@ fn test_target(mut self) {
|
||||
let recycled_target =
|
||||
Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
|
||||
self.update_to_cli();
|
||||
self.check_consistency(TargetKind::Builtin).unwrap();
|
||||
self.check_consistency(TargetKind::Builtin)
|
||||
.unwrap_or_else(|err| panic!("Target consistency check failed:\n{err}"));
|
||||
assert_eq!(recycled_target, Ok(self));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ pub(crate) fn target() -> Target {
|
||||
endian: Endian::Big,
|
||||
cpu: "mips32r2".into(),
|
||||
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
|
||||
features: "+mips32r2,+soft-float,+noabicalls".into(),
|
||||
|
||||
@@ -18,6 +18,7 @@ pub(crate) fn target() -> Target {
|
||||
endian: Endian::Big,
|
||||
cpu: "mips32r2".into(),
|
||||
features: "+mips32r2,+fpxx,+nooddspreg".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
mcount: "_mcount".into(),
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ pub(crate) fn target() -> Target {
|
||||
pointer_width: 32,
|
||||
data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
|
||||
arch: Arch::Mips,
|
||||
options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
|
||||
options: TargetOptions {
|
||||
endian: Endian::Big,
|
||||
llvm_abiname: "o32".into(),
|
||||
mcount: "_mcount".into(),
|
||||
..base
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ pub(crate) fn target() -> Target {
|
||||
endian: Endian::Big,
|
||||
cpu: "mips32r2".into(),
|
||||
features: "+mips32r2,+soft-float".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
mcount: "_mcount".into(),
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ pub(crate) fn target() -> Target {
|
||||
endian: Endian::Little,
|
||||
cpu: "mips32r2".into(),
|
||||
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
|
||||
features: "+mips32r2,+soft-float,+noabicalls".into(),
|
||||
|
||||
@@ -36,6 +36,7 @@ pub(crate) fn target() -> Target {
|
||||
|
||||
// PSP does not support trap-on-condition instructions.
|
||||
llvm_args: cvs!["-mno-check-zero-division"],
|
||||
llvm_abiname: "o32".into(),
|
||||
pre_link_args,
|
||||
link_script: Some(LINKER_SCRIPT.into()),
|
||||
..Default::default()
|
||||
|
||||
@@ -16,6 +16,7 @@ pub(crate) fn target() -> Target {
|
||||
options: TargetOptions {
|
||||
cpu: "mips32r2".into(),
|
||||
features: "+mips32r2,+fpxx,+nooddspreg".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
mcount: "_mcount".into(),
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ pub(crate) fn target() -> Target {
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
|
||||
arch: Arch::Mips,
|
||||
options: TargetOptions { mcount: "_mcount".into(), ..base },
|
||||
options: TargetOptions { llvm_abiname: "o32".into(), mcount: "_mcount".into(), ..base },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ pub(crate) fn target() -> Target {
|
||||
options: TargetOptions {
|
||||
cpu: "mips32r2".into(),
|
||||
features: "+mips32r2,+soft-float".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
mcount: "_mcount".into(),
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ pub(crate) fn target() -> Target {
|
||||
arch: Arch::Mips,
|
||||
options: TargetOptions {
|
||||
features: "+soft-float".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
mcount: "__mcount".into(),
|
||||
endian: Endian::Little,
|
||||
..base
|
||||
|
||||
@@ -23,6 +23,7 @@ pub(crate) fn target() -> Target {
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
cpu: "mips32r2".into(),
|
||||
features: "+mips32r2,+soft-float,+noabicalls".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
linker: Some("rust-lld".into()),
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
|
||||
@@ -18,6 +18,7 @@ pub(crate) fn target() -> Target {
|
||||
endian: Endian::Big,
|
||||
cpu: "mips32r6".into(),
|
||||
features: "+mips32r6".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
mcount: "_mcount".into(),
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ pub(crate) fn target() -> Target {
|
||||
options: TargetOptions {
|
||||
cpu: "mips32r6".into(),
|
||||
features: "+mips32r6".into(),
|
||||
llvm_abiname: "o32".into(),
|
||||
max_atomic_width: Some(32),
|
||||
mcount: "_mcount".into(),
|
||||
|
||||
|
||||
@@ -88,6 +88,45 @@
|
||||
//@ lldb-command: frame select
|
||||
//@ lldb-check: [...]let m: *const() = &a;[...]
|
||||
|
||||
// === CDB TESTS ===================================================================================
|
||||
|
||||
// Enable source line support. See
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/-lines--toggle-source-line-support-.
|
||||
//@ cdb-command: .lines -e
|
||||
// Display source lines and source line numbers at the command prompt. See
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/l---l---set-source-options-.
|
||||
//@ cdb-command: l+s
|
||||
// Enter "source mode" so `p` steps source lines and not assembly instructions.
|
||||
//@ cdb-command: l+t
|
||||
|
||||
// `g` means "go". See
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/g--go-.
|
||||
//@ cdb-command: g
|
||||
// `p` means "step". See
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/p--step-.
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let mut c = 27;
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let d = c = 99;
|
||||
//@ [no-SingleUseConsts-mir-pass] cdb-command: p
|
||||
//@ [no-SingleUseConsts-mir-pass] cdb-check: [...]: let e = "hi bob";
|
||||
//@ [no-SingleUseConsts-mir-pass] cdb-command: p
|
||||
//@ [no-SingleUseConsts-mir-pass] cdb-check: [...]: let f = b"hi bob";
|
||||
//@ [no-SingleUseConsts-mir-pass] cdb-command: p
|
||||
//@ [no-SingleUseConsts-mir-pass] cdb-check: [...]: let g = b'9';
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let h = ["whatever"; 8];
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let i = [1,2,3,4];
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let j = (23, "hi");
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let k = 2..3;
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let l = &i[k];
|
||||
//@ cdb-command: p
|
||||
//@ cdb-check: [...]: let m: *const() = &a;
|
||||
|
||||
#![allow(unused_assignments, unused_variables)]
|
||||
|
||||
fn main () {
|
||||
|
||||
@@ -1000,12 +1000,6 @@ Tests on lifetimes on objects, such as a lifetime bound not being able to be ded
|
||||
|
||||
**FIXME**: Just a more specific subset of `ui/lifetimes`.
|
||||
|
||||
## `tests/ui/obsolete-in-place/`
|
||||
|
||||
Contains a single test. Check that we reject the ancient Rust syntax `x <- y` and `in(BINDING) {}` construct.
|
||||
|
||||
**FIXME**: Definitely should be rehomed, maybe to `tests/ui/deprecation/`.
|
||||
|
||||
## `tests/ui/offload`
|
||||
|
||||
Exercises the offload feature.
|
||||
@@ -1023,10 +1017,6 @@ Exercises the [`std::mem::offset_of` macro](https://doc.rust-lang.org/beta/std/m
|
||||
|
||||
Exercises the `#[rustc_on_unimplemented]`.
|
||||
|
||||
## `tests/ui/operator-recovery/`
|
||||
|
||||
**FIXME**: Probably move under `tests/ui/binop/` or `tests/ui/parser/`.
|
||||
|
||||
## `tests/ui/or-patterns/`
|
||||
|
||||
Exercises `||` and `|` in patterns.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
error: unexpected token: `<-`
|
||||
--> $DIR/bad.rs:5:7
|
||||
--> $DIR/removed-syntax-obsolete-in-place.rs:5:7
|
||||
|
|
||||
LL | x <- y;
|
||||
| ^^
|
||||
@@ -10,7 +10,7 @@ LL | x < - y;
|
||||
| +
|
||||
|
||||
error: expected expression, found keyword `in`
|
||||
--> $DIR/bad.rs:10:5
|
||||
--> $DIR/removed-syntax-obsolete-in-place.rs:10:5
|
||||
|
|
||||
LL | in(foo) { bar };
|
||||
| ^^ expected expression
|
||||
Reference in New Issue
Block a user