Auto merge of #126396 - fmease:rollup-3j7f6wk, r=fmease
Rollup of 6 pull requests Successful merges: - #126347 (Simplify `try_*`'s signature on `Iterator`) - #126348 (Improve error message if dependency installation in tidy fails) - #126366 (Add a new trait to retrieve StableMir definition Ty) - #126370 (compiletest: Stricter parsing of `//@ normalize-*` headers) - #126379 (interpret: update doc comment for find_closest_untracked_caller_location) - #126384 (add tracking issue for is_none_or) Failed merges: - #126388 (const-eval: make lint scope computation consistent) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9fdbfe1441
@ -250,7 +250,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
|
|||||||
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
|
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
|
||||||
/// Get the current location within the Frame.
|
/// Get the current location within the Frame.
|
||||||
///
|
///
|
||||||
/// If this is `Left`, we are not currently executing any particular statement in
|
/// If this is `Right`, we are not currently executing any particular statement in
|
||||||
/// this frame (can happen e.g. during frame initialization, and during unwinding on
|
/// this frame (can happen e.g. during frame initialization, and during unwinding on
|
||||||
/// frames without cleanup code).
|
/// frames without cleanup code).
|
||||||
///
|
///
|
||||||
@ -500,6 +500,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the span of the currently executed statement/terminator.
|
||||||
|
/// This is the span typically used for error reporting.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn cur_span(&self) -> Span {
|
pub fn cur_span(&self) -> Span {
|
||||||
// This deliberately does *not* honor `requires_caller_location` since it is used for much
|
// This deliberately does *not* honor `requires_caller_location` since it is used for much
|
||||||
@ -507,8 +509,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
self.stack().last().map_or(self.tcx.span, |f| f.current_span())
|
self.stack().last().map_or(self.tcx.span, |f| f.current_span())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the first stack frame that is within the current crate, if any;
|
||||||
|
/// otherwise return the crate's HirId.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
/// Find the first stack frame that is within the current crate, if any, otherwise return the crate's HirId
|
|
||||||
pub fn best_lint_scope(&self) -> hir::HirId {
|
pub fn best_lint_scope(&self) -> hir::HirId {
|
||||||
self.stack()
|
self.stack()
|
||||||
.iter()
|
.iter()
|
||||||
@ -632,7 +635,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
|
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
|
||||||
/// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
|
/// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
|
||||||
|
/// and is primarily intended for the panic machinery.
|
||||||
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
|
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
|
||||||
for frame in self.stack().iter().rev() {
|
for frame in self.stack().iter().rev() {
|
||||||
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
|
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module that define a common trait for things that represent a crate definition,
|
//! Module that define a common trait for things that represent a crate definition,
|
||||||
//! such as, a function, a trait, an enum, and any other definitions.
|
//! such as, a function, a trait, an enum, and any other definitions.
|
||||||
|
|
||||||
use crate::ty::Span;
|
use crate::ty::{GenericArgs, Span, Ty};
|
||||||
use crate::{with, Crate, Symbol};
|
use crate::{with, Crate, Symbol};
|
||||||
|
|
||||||
/// A unique identification number for each item accessible for the current compilation unit.
|
/// A unique identification number for each item accessible for the current compilation unit.
|
||||||
@ -52,6 +52,23 @@ pub trait CrateDef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait that can be used to retrieve a definition's type.
|
||||||
|
///
|
||||||
|
/// Note that not every CrateDef has a type `Ty`. They should not implement this trait.
|
||||||
|
pub trait CrateDefType: CrateDef {
|
||||||
|
/// Returns the type of this crate item.
|
||||||
|
fn ty(&self) -> Ty {
|
||||||
|
with(|cx| cx.def_ty(self.def_id()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the type of this definition by instantiating and normalizing it with `args`.
|
||||||
|
///
|
||||||
|
/// This will panic if instantiation fails.
|
||||||
|
fn ty_with_args(&self, args: &GenericArgs) -> Ty {
|
||||||
|
with(|cx| cx.def_ty_with_args(self.def_id(), args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! crate_def {
|
macro_rules! crate_def {
|
||||||
( $(#[$attr:meta])*
|
( $(#[$attr:meta])*
|
||||||
$vis:vis $name:ident $(;)?
|
$vis:vis $name:ident $(;)?
|
||||||
@ -67,3 +84,21 @@ macro_rules! crate_def {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! crate_def_with_ty {
|
||||||
|
( $(#[$attr:meta])*
|
||||||
|
$vis:vis $name:ident $(;)?
|
||||||
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||||
|
$vis struct $name(pub DefId);
|
||||||
|
|
||||||
|
impl CrateDef for $name {
|
||||||
|
fn def_id(&self) -> DefId {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CrateDefType for $name {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -22,8 +22,7 @@ use std::fmt::Debug;
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::compiler_interface::with;
|
use crate::compiler_interface::with;
|
||||||
pub use crate::crate_def::CrateDef;
|
pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
|
||||||
pub use crate::crate_def::DefId;
|
|
||||||
pub use crate::error::*;
|
pub use crate::error::*;
|
||||||
use crate::mir::Body;
|
use crate::mir::Body;
|
||||||
use crate::mir::Mutability;
|
use crate::mir::Mutability;
|
||||||
@ -115,12 +114,15 @@ pub enum CtorKind {
|
|||||||
|
|
||||||
pub type Filename = String;
|
pub type Filename = String;
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
/// Holds information about an item in a crate.
|
/// Holds information about an item in a crate.
|
||||||
pub CrateItem;
|
pub CrateItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateItem {
|
impl CrateItem {
|
||||||
|
/// This will return the body of an item.
|
||||||
|
///
|
||||||
|
/// This will panic if no body is available.
|
||||||
pub fn body(&self) -> mir::Body {
|
pub fn body(&self) -> mir::Body {
|
||||||
with(|cx| cx.mir_body(self.0))
|
with(|cx| cx.mir_body(self.0))
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,10 @@ use super::{
|
|||||||
with, DefId, Error, Symbol,
|
with, DefId, Error, Symbol,
|
||||||
};
|
};
|
||||||
use crate::abi::Layout;
|
use crate::abi::Layout;
|
||||||
|
use crate::crate_def::{CrateDef, CrateDefType};
|
||||||
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
|
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
|
||||||
|
use crate::mir::mono::StaticDef;
|
||||||
use crate::target::MachineInfo;
|
use crate::target::MachineInfo;
|
||||||
use crate::{crate_def::CrateDef, mir::mono::StaticDef};
|
|
||||||
use crate::{Filename, Opaque};
|
use crate::{Filename, Opaque};
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
@ -504,6 +505,15 @@ impl TyKind {
|
|||||||
pub fn discriminant_ty(&self) -> Option<Ty> {
|
pub fn discriminant_ty(&self) -> Option<Ty> {
|
||||||
self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
|
self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deconstruct a function type if this is one.
|
||||||
|
pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> {
|
||||||
|
if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self {
|
||||||
|
Some((*def, args))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeAndMut {
|
pub struct TypeAndMut {
|
||||||
@ -629,7 +639,7 @@ impl ForeignModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
/// Hold information about a ForeignItem in a crate.
|
/// Hold information about a ForeignItem in a crate.
|
||||||
pub ForeignDef;
|
pub ForeignDef;
|
||||||
}
|
}
|
||||||
@ -647,7 +657,7 @@ pub enum ForeignItemKind {
|
|||||||
Type(Ty),
|
Type(Ty),
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
/// Hold information about a function definition in a crate.
|
/// Hold information about a function definition in a crate.
|
||||||
pub FnDef;
|
pub FnDef;
|
||||||
}
|
}
|
||||||
@ -668,9 +678,15 @@ impl FnDef {
|
|||||||
pub fn is_intrinsic(&self) -> bool {
|
pub fn is_intrinsic(&self) -> bool {
|
||||||
self.as_intrinsic().is_some()
|
self.as_intrinsic().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the function signature for this function definition.
|
||||||
|
pub fn fn_sig(&self) -> PolyFnSig {
|
||||||
|
let kind = self.ty().kind();
|
||||||
|
kind.fn_sig().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
pub IntrinsicDef;
|
pub IntrinsicDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +726,7 @@ crate_def! {
|
|||||||
pub BrNamedDef;
|
pub BrNamedDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
pub AdtDef;
|
pub AdtDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,7 +882,7 @@ crate_def! {
|
|||||||
pub GenericDef;
|
pub GenericDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate_def! {
|
crate_def_with_ty! {
|
||||||
pub ConstDef;
|
pub ConstDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2080,8 +2080,7 @@ pub trait Iterator {
|
|||||||
fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
|
fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
<Self as Iterator>::Item: Try,
|
Self::Item: Try<Residual: Residual<B>>,
|
||||||
<<Self as Iterator>::Item as Try>::Residual: Residual<B>,
|
|
||||||
B: FromIterator<<Self::Item as Try>::Output>,
|
B: FromIterator<<Self::Item as Try>::Output>,
|
||||||
{
|
{
|
||||||
try_process(ByRefSized(self), |i| i.collect())
|
try_process(ByRefSized(self), |i| i.collect())
|
||||||
@ -2689,12 +2688,13 @@ pub trait Iterator {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
|
#[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
|
||||||
#[rustc_do_not_const_check]
|
#[rustc_do_not_const_check]
|
||||||
fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>>
|
fn try_reduce<R>(
|
||||||
|
&mut self,
|
||||||
|
f: impl FnMut(Self::Item, Self::Item) -> R,
|
||||||
|
) -> ChangeOutputType<R, Option<R::Output>>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(Self::Item, Self::Item) -> R,
|
R: Try<Output = Self::Item, Residual: Residual<Option<Self::Item>>>,
|
||||||
R: Try<Output = Self::Item>,
|
|
||||||
R::Residual: Residual<Option<Self::Item>>,
|
|
||||||
{
|
{
|
||||||
let first = match self.next() {
|
let first = match self.next() {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
@ -2956,12 +2956,13 @@ pub trait Iterator {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
|
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
|
||||||
#[rustc_do_not_const_check]
|
#[rustc_do_not_const_check]
|
||||||
fn try_find<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<Self::Item>>
|
fn try_find<R>(
|
||||||
|
&mut self,
|
||||||
|
f: impl FnMut(&Self::Item) -> R,
|
||||||
|
) -> ChangeOutputType<R, Option<Self::Item>>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(&Self::Item) -> R,
|
R: Try<Output = bool, Residual: Residual<Option<Self::Item>>>,
|
||||||
R: Try<Output = bool>,
|
|
||||||
R::Residual: Residual<Option<Self::Item>>,
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn check<I, V, R>(
|
fn check<I, V, R>(
|
||||||
|
@ -672,7 +672,7 @@ impl<T> Option<T> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "is_none_or", issue = "none")]
|
#[unstable(feature = "is_none_or", issue = "126383")]
|
||||||
pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
|
pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
|
||||||
match self {
|
match self {
|
||||||
None => true,
|
None => true,
|
||||||
|
@ -14,6 +14,7 @@ use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
|||||||
use crate::header::cfg::parse_cfg_name_directive;
|
use crate::header::cfg::parse_cfg_name_directive;
|
||||||
use crate::header::cfg::MatchOutcome;
|
use crate::header::cfg::MatchOutcome;
|
||||||
use crate::header::needs::CachedNeedsConditions;
|
use crate::header::needs::CachedNeedsConditions;
|
||||||
|
use crate::util::static_regex;
|
||||||
use crate::{extract_cdb_version, extract_gdb_version};
|
use crate::{extract_cdb_version, extract_gdb_version};
|
||||||
|
|
||||||
mod cfg;
|
mod cfg;
|
||||||
@ -1186,11 +1187,11 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> {
|
fn parse_custom_normalization(&self, line: &str, prefix: &str) -> Option<(String, String)> {
|
||||||
if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match {
|
if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match {
|
||||||
let from = parse_normalization_string(&mut line)?;
|
let (regex, replacement) = parse_normalize_rule(line)
|
||||||
let to = parse_normalization_string(&mut line)?;
|
.unwrap_or_else(|| panic!("couldn't parse custom normalization rule: `{line}`"));
|
||||||
Some((from, to))
|
Some((regex, replacement))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -1311,24 +1312,29 @@ fn expand_variables(mut value: String, config: &Config) -> String {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the next quoted string `"..."` in `line`, and extract the content from it. Move the `line`
|
/// Parses the regex and replacement values of a `//@ normalize-*` header,
|
||||||
/// variable after the end of the quoted string.
|
/// in the format:
|
||||||
///
|
/// ```text
|
||||||
/// # Examples
|
/// normalize-*: "REGEX" -> "REPLACEMENT"
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
|
fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
|
||||||
/// let first = parse_normalization_string(&mut s);
|
// FIXME(#126370): A colon after the header name should be mandatory, but
|
||||||
/// assert_eq!(first, Some("something (32 bits)".to_owned()));
|
// currently is not, and there are many tests that lack the colon.
|
||||||
/// assert_eq!(s, " -> \"something ($WORD bits)\".");
|
// FIXME: Support escaped double-quotes in strings.
|
||||||
/// ```
|
let captures = static_regex!(
|
||||||
fn parse_normalization_string(line: &mut &str) -> Option<String> {
|
r#"(?x) # (verbose mode regex)
|
||||||
// FIXME support escapes in strings.
|
^
|
||||||
let begin = line.find('"')? + 1;
|
[^:\s]+:?\s* # (header name followed by optional colon)
|
||||||
let end = line[begin..].find('"')? + begin;
|
"(?<regex>[^"]*)" # "REGEX"
|
||||||
let result = line[begin..end].to_owned();
|
\s+->\s+ # ->
|
||||||
*line = &line[end + 1..];
|
"(?<replacement>[^"]*)" # "REPLACEMENT"
|
||||||
Some(result)
|
$
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.captures(header)?;
|
||||||
|
let regex = captures["regex"].to_owned();
|
||||||
|
let replacement = captures["replacement"].to_owned();
|
||||||
|
Some((regex, replacement))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_llvm_version(version: &str) -> Option<u32> {
|
pub fn extract_llvm_version(version: &str) -> Option<u32> {
|
||||||
|
@ -3,7 +3,7 @@ use std::path::Path;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::common::{Config, Debugger, Mode};
|
use crate::common::{Config, Debugger, Mode};
|
||||||
use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
|
use crate::header::{parse_normalize_rule, EarlyProps, HeadersCache};
|
||||||
|
|
||||||
use super::iter_header;
|
use super::iter_header;
|
||||||
|
|
||||||
@ -32,35 +32,41 @@ fn make_test_description<R: Read>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_normalization_string() {
|
fn test_parse_normalize_rule() {
|
||||||
let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
|
let good_data = &[
|
||||||
let first = parse_normalization_string(&mut s);
|
(
|
||||||
assert_eq!(first, Some("something (32 bits)".to_owned()));
|
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)""#,
|
||||||
assert_eq!(s, " -> \"something ($WORD bits)\".");
|
"something (32 bits)",
|
||||||
|
"something ($WORD bits)",
|
||||||
|
),
|
||||||
|
// FIXME(#126370): A colon after the header name should be mandatory,
|
||||||
|
// but currently is not, and there are many tests that lack the colon.
|
||||||
|
(
|
||||||
|
r#"normalize-stderr-32bit "something (32 bits)" -> "something ($WORD bits)""#,
|
||||||
|
"something (32 bits)",
|
||||||
|
"something ($WORD bits)",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
// Nothing to normalize (No quotes)
|
for &(input, expected_regex, expected_replacement) in good_data {
|
||||||
let mut s = "normalize-stderr-32bit: something (32 bits) -> something ($WORD bits).";
|
let parsed = parse_normalize_rule(input);
|
||||||
let first = parse_normalization_string(&mut s);
|
let parsed =
|
||||||
assert_eq!(first, None);
|
parsed.as_ref().map(|(regex, replacement)| (regex.as_str(), replacement.as_str()));
|
||||||
assert_eq!(s, r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."#);
|
assert_eq!(parsed, Some((expected_regex, expected_replacement)));
|
||||||
|
}
|
||||||
|
|
||||||
// Nothing to normalize (Only a single quote)
|
let bad_data = &[
|
||||||
let mut s = "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).";
|
r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)"#,
|
||||||
let first = parse_normalization_string(&mut s);
|
r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)"#,
|
||||||
assert_eq!(first, None);
|
r#"normalize-stderr-32bit: "something (32 bits) -> something ($WORD bits)"#,
|
||||||
assert_eq!(s, "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).");
|
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"#,
|
||||||
|
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"."#,
|
||||||
|
];
|
||||||
|
|
||||||
// Nothing to normalize (Three quotes)
|
for &input in bad_data {
|
||||||
let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits).";
|
let parsed = parse_normalize_rule(input);
|
||||||
let first = parse_normalization_string(&mut s);
|
assert_eq!(parsed, None);
|
||||||
assert_eq!(first, Some("something (32 bits)".to_owned()));
|
}
|
||||||
assert_eq!(s, " -> \"something ($WORD bits).");
|
|
||||||
|
|
||||||
// Nothing to normalize (No quotes, 16-bit)
|
|
||||||
let mut s = "normalize-stderr-16bit: something (16 bits) -> something ($WORD bits).";
|
|
||||||
let first = parse_normalization_string(&mut s);
|
|
||||||
assert_eq!(first, None);
|
|
||||||
assert_eq!(s, r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)."#);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -15,7 +15,7 @@ use crate::errors::{self, Error, ErrorKind};
|
|||||||
use crate::header::TestProps;
|
use crate::header::TestProps;
|
||||||
use crate::json;
|
use crate::json;
|
||||||
use crate::read2::{read2_abbreviated, Truncated};
|
use crate::read2::{read2_abbreviated, Truncated};
|
||||||
use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, PathBufExt};
|
use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
|
||||||
use crate::ColorConfig;
|
use crate::ColorConfig;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
|
use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
|
||||||
@ -48,14 +48,6 @@ use debugger::DebuggerCommands;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
macro_rules! static_regex {
|
|
||||||
($re:literal) => {{
|
|
||||||
static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
|
|
||||||
RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
use static_regex;
|
|
||||||
|
|
||||||
const FAKE_SRC_BASE: &str = "fake-test-src-base";
|
const FAKE_SRC_BASE: &str = "fake-test-src-base";
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -7,7 +7,8 @@ use std::process::Command;
|
|||||||
use glob::glob;
|
use glob::glob;
|
||||||
|
|
||||||
use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP};
|
use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP};
|
||||||
use crate::runtest::{static_regex, Emit, ProcRes, TestCx, WillExecute};
|
use crate::runtest::{Emit, ProcRes, TestCx, WillExecute};
|
||||||
|
use crate::util::static_regex;
|
||||||
|
|
||||||
impl<'test> TestCx<'test> {
|
impl<'test> TestCx<'test> {
|
||||||
fn coverage_dump_path(&self) -> &Path {
|
fn coverage_dump_path(&self) -> &Path {
|
||||||
|
@ -90,3 +90,11 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Re
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! static_regex {
|
||||||
|
($re:literal) => {{
|
||||||
|
static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
|
||||||
|
RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
pub(crate) use static_regex;
|
||||||
|
@ -274,13 +274,18 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> {
|
|||||||
if out.status.success() {
|
if out.status.success() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let err = if String::from_utf8_lossy(&out.stderr).contains("No module named virtualenv") {
|
|
||||||
|
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||||
|
let err = if stderr.contains("No module named virtualenv") {
|
||||||
Error::Generic(format!(
|
Error::Generic(format!(
|
||||||
"virtualenv not found: you may need to install it \
|
"virtualenv not found: you may need to install it \
|
||||||
(`python3 -m pip install venv`)"
|
(`python3 -m pip install venv`)"
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Error::Generic(format!("failed to create venv at '{}' using {sys_py}", path.display()))
|
Error::Generic(format!(
|
||||||
|
"failed to create venv at '{}' using {sys_py}: {stderr}",
|
||||||
|
path.display()
|
||||||
|
))
|
||||||
};
|
};
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
114
tests/ui-fulldeps/stable-mir/check_def_ty.rs
Normal file
114
tests/ui-fulldeps/stable-mir/check_def_ty.rs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
//@ run-pass
|
||||||
|
//! Test that users are able to use stable mir APIs to retrieve type information from a crate item
|
||||||
|
//! definition.
|
||||||
|
|
||||||
|
//@ ignore-stage1
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
//@ ignore-remote
|
||||||
|
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||||
|
//@ edition: 2021
|
||||||
|
|
||||||
|
#![feature(rustc_private)]
|
||||||
|
#![feature(assert_matches)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate rustc_smir;
|
||||||
|
extern crate rustc_driver;
|
||||||
|
extern crate rustc_interface;
|
||||||
|
extern crate stable_mir;
|
||||||
|
|
||||||
|
use rustc_smir::rustc_internal;
|
||||||
|
use stable_mir::ty::{Ty, ForeignItemKind};
|
||||||
|
use stable_mir::*;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
const CRATE_NAME: &str = "crate_def_ty";
|
||||||
|
|
||||||
|
/// Test if we can retrieve type information from different definitions.
|
||||||
|
fn test_def_tys() -> ControlFlow<()> {
|
||||||
|
let items = stable_mir::all_local_items();
|
||||||
|
for item in &items {
|
||||||
|
// Type from crate items.
|
||||||
|
let ty = item.ty();
|
||||||
|
match item.name().as_str() {
|
||||||
|
"STATIC_STR" => assert!(ty.kind().is_ref()),
|
||||||
|
"CONST_U32" => assert!(ty.kind().is_integral()),
|
||||||
|
"main" => { check_fn_def(ty) }
|
||||||
|
_ => unreachable!("Unexpected item: `{item:?}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let foreign_items = stable_mir::local_crate().foreign_modules();
|
||||||
|
for item in foreign_items[0].module().items() {
|
||||||
|
// Type from foreign items.
|
||||||
|
let ty = item.ty();
|
||||||
|
let item_kind = item.kind();
|
||||||
|
let name = item.name();
|
||||||
|
match item_kind {
|
||||||
|
ForeignItemKind::Fn(fn_def) => {
|
||||||
|
assert_eq!(&name, "extern_fn");
|
||||||
|
assert_eq!(ty, fn_def.ty());
|
||||||
|
check_fn_def(ty)
|
||||||
|
}
|
||||||
|
ForeignItemKind::Static(def) => {
|
||||||
|
assert_eq!(&name, "EXT_STATIC");
|
||||||
|
assert_eq!(ty, def.ty());
|
||||||
|
assert!(ty.kind().is_integral())
|
||||||
|
}
|
||||||
|
_ => unreachable!("Unexpected kind: {item_kind:?}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_fn_def(ty: Ty) {
|
||||||
|
let kind = ty.kind();
|
||||||
|
let (def, args) = kind.fn_def().expect(&format!("Expected function type, but found: {ty}"));
|
||||||
|
assert!(def.ty().kind().is_fn());
|
||||||
|
assert_eq!(def.ty_with_args(args), ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||||
|
/// For that, it will first write the dummy crate into a file.
|
||||||
|
/// Then it will create a `StableMir` using custom arguments and then
|
||||||
|
/// it will run the compiler.
|
||||||
|
fn main() {
|
||||||
|
let path = "defs_ty_input.rs";
|
||||||
|
generate_input(&path).unwrap();
|
||||||
|
let args = vec![
|
||||||
|
"rustc".to_string(),
|
||||||
|
"-Cpanic=abort".to_string(),
|
||||||
|
"--crate-name".to_string(),
|
||||||
|
CRATE_NAME.to_string(),
|
||||||
|
path.to_string(),
|
||||||
|
];
|
||||||
|
run!(args, test_def_tys).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
|
let mut file = std::fs::File::create(path)?;
|
||||||
|
write!(
|
||||||
|
file,
|
||||||
|
r#"
|
||||||
|
// We would like to check intrinsic definition.
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
static STATIC_STR: &str = "foo";
|
||||||
|
const CONST_U32: u32 = 0u32;
|
||||||
|
|
||||||
|
fn main() {{
|
||||||
|
let _c = core::char::from_u32(99);
|
||||||
|
let _v = Vec::<u8>::new();
|
||||||
|
let _i = std::intrinsics::size_of::<u8>();
|
||||||
|
}}
|
||||||
|
|
||||||
|
extern "C" {{
|
||||||
|
fn extern_fn(x: i32) -> i32;
|
||||||
|
static EXT_STATIC: i32;
|
||||||
|
}}
|
||||||
|
"#
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user