Skip to content

Commit 9fdbfe1

Browse files
committedJun 13, 2024
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
2 parents 921645c + f1a4f30 commit 9fdbfe1

File tree

13 files changed

+277
-87
lines changed

13 files changed

+277
-87
lines changed
 

‎compiler/rustc_const_eval/src/interpret/eval_context.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
250250
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
251251
/// Get the current location within the Frame.
252252
///
253-
/// If this is `Left`, we are not currently executing any particular statement in
253+
/// If this is `Right`, we are not currently executing any particular statement in
254254
/// this frame (can happen e.g. during frame initialization, and during unwinding on
255255
/// frames without cleanup code).
256256
///
@@ -500,15 +500,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
500500
}
501501
}
502502

503+
/// Returns the span of the currently executed statement/terminator.
504+
/// This is the span typically used for error reporting.
503505
#[inline(always)]
504506
pub fn cur_span(&self) -> Span {
505507
// This deliberately does *not* honor `requires_caller_location` since it is used for much
506508
// more than just panics.
507509
self.stack().last().map_or(self.tcx.span, |f| f.current_span())
508510
}
509511

512+
/// Find the first stack frame that is within the current crate, if any;
513+
/// otherwise return the crate's HirId.
510514
#[inline(always)]
511-
/// Find the first stack frame that is within the current crate, if any, otherwise return the crate's HirId
512515
pub fn best_lint_scope(&self) -> hir::HirId {
513516
self.stack()
514517
.iter()
@@ -632,7 +635,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
632635
}
633636

634637
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
635-
/// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
638+
/// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
639+
/// and is primarily intended for the panic machinery.
636640
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
637641
for frame in self.stack().iter().rev() {
638642
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);

‎compiler/stable_mir/src/crate_def.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Module that define a common trait for things that represent a crate definition,
22
//! such as, a function, a trait, an enum, and any other definitions.
33
4-
use crate::ty::Span;
4+
use crate::ty::{GenericArgs, Span, Ty};
55
use crate::{with, Crate, Symbol};
66

77
/// A unique identification number for each item accessible for the current compilation unit.
@@ -52,6 +52,23 @@ pub trait CrateDef {
5252
}
5353
}
5454

55+
/// A trait that can be used to retrieve a definition's type.
56+
///
57+
/// Note that not every CrateDef has a type `Ty`. They should not implement this trait.
58+
pub trait CrateDefType: CrateDef {
59+
/// Returns the type of this crate item.
60+
fn ty(&self) -> Ty {
61+
with(|cx| cx.def_ty(self.def_id()))
62+
}
63+
64+
/// Retrieve the type of this definition by instantiating and normalizing it with `args`.
65+
///
66+
/// This will panic if instantiation fails.
67+
fn ty_with_args(&self, args: &GenericArgs) -> Ty {
68+
with(|cx| cx.def_ty_with_args(self.def_id(), args))
69+
}
70+
}
71+
5572
macro_rules! crate_def {
5673
( $(#[$attr:meta])*
5774
$vis:vis $name:ident $(;)?
@@ -67,3 +84,21 @@ macro_rules! crate_def {
6784
}
6885
};
6986
}
87+
88+
macro_rules! crate_def_with_ty {
89+
( $(#[$attr:meta])*
90+
$vis:vis $name:ident $(;)?
91+
) => {
92+
$(#[$attr])*
93+
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
94+
$vis struct $name(pub DefId);
95+
96+
impl CrateDef for $name {
97+
fn def_id(&self) -> DefId {
98+
self.0
99+
}
100+
}
101+
102+
impl CrateDefType for $name {}
103+
};
104+
}

‎compiler/stable_mir/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ use std::fmt::Debug;
2222
use std::io;
2323

2424
use crate::compiler_interface::with;
25-
pub use crate::crate_def::CrateDef;
26-
pub use crate::crate_def::DefId;
25+
pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
2726
pub use crate::error::*;
2827
use crate::mir::Body;
2928
use crate::mir::Mutability;
@@ -115,12 +114,15 @@ pub enum CtorKind {
115114

116115
pub type Filename = String;
117116

118-
crate_def! {
117+
crate_def_with_ty! {
119118
/// Holds information about an item in a crate.
120119
pub CrateItem;
121120
}
122121

123122
impl CrateItem {
123+
/// This will return the body of an item.
124+
///
125+
/// This will panic if no body is available.
124126
pub fn body(&self) -> mir::Body {
125127
with(|cx| cx.mir_body(self.0))
126128
}

‎compiler/stable_mir/src/ty.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use super::{
33
with, DefId, Error, Symbol,
44
};
55
use crate::abi::Layout;
6+
use crate::crate_def::{CrateDef, CrateDefType};
67
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
8+
use crate::mir::mono::StaticDef;
79
use crate::target::MachineInfo;
8-
use crate::{crate_def::CrateDef, mir::mono::StaticDef};
910
use crate::{Filename, Opaque};
1011
use std::fmt::{self, Debug, Display, Formatter};
1112
use std::ops::Range;
@@ -504,6 +505,15 @@ impl TyKind {
504505
pub fn discriminant_ty(&self) -> Option<Ty> {
505506
self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
506507
}
508+
509+
/// Deconstruct a function type if this is one.
510+
pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> {
511+
if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self {
512+
Some((*def, args))
513+
} else {
514+
None
515+
}
516+
}
507517
}
508518

509519
pub struct TypeAndMut {
@@ -629,7 +639,7 @@ impl ForeignModule {
629639
}
630640
}
631641

632-
crate_def! {
642+
crate_def_with_ty! {
633643
/// Hold information about a ForeignItem in a crate.
634644
pub ForeignDef;
635645
}
@@ -647,7 +657,7 @@ pub enum ForeignItemKind {
647657
Type(Ty),
648658
}
649659

650-
crate_def! {
660+
crate_def_with_ty! {
651661
/// Hold information about a function definition in a crate.
652662
pub FnDef;
653663
}
@@ -668,9 +678,15 @@ impl FnDef {
668678
pub fn is_intrinsic(&self) -> bool {
669679
self.as_intrinsic().is_some()
670680
}
681+
682+
/// Get the function signature for this function definition.
683+
pub fn fn_sig(&self) -> PolyFnSig {
684+
let kind = self.ty().kind();
685+
kind.fn_sig().unwrap()
686+
}
671687
}
672688

673-
crate_def! {
689+
crate_def_with_ty! {
674690
pub IntrinsicDef;
675691
}
676692

@@ -710,7 +726,7 @@ crate_def! {
710726
pub BrNamedDef;
711727
}
712728

713-
crate_def! {
729+
crate_def_with_ty! {
714730
pub AdtDef;
715731
}
716732

@@ -866,7 +882,7 @@ crate_def! {
866882
pub GenericDef;
867883
}
868884

869-
crate_def! {
885+
crate_def_with_ty! {
870886
pub ConstDef;
871887
}
872888

‎library/core/src/iter/traits/iterator.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -2080,8 +2080,7 @@ pub trait Iterator {
20802080
fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
20812081
where
20822082
Self: Sized,
2083-
<Self as Iterator>::Item: Try,
2084-
<<Self as Iterator>::Item as Try>::Residual: Residual<B>,
2083+
Self::Item: Try<Residual: Residual<B>>,
20852084
B: FromIterator<<Self::Item as Try>::Output>,
20862085
{
20872086
try_process(ByRefSized(self), |i| i.collect())
@@ -2689,12 +2688,13 @@ pub trait Iterator {
26892688
#[inline]
26902689
#[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
26912690
#[rustc_do_not_const_check]
2692-
fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>>
2691+
fn try_reduce<R>(
2692+
&mut self,
2693+
f: impl FnMut(Self::Item, Self::Item) -> R,
2694+
) -> ChangeOutputType<R, Option<R::Output>>
26932695
where
26942696
Self: Sized,
2695-
F: FnMut(Self::Item, Self::Item) -> R,
2696-
R: Try<Output = Self::Item>,
2697-
R::Residual: Residual<Option<Self::Item>>,
2697+
R: Try<Output = Self::Item, Residual: Residual<Option<Self::Item>>>,
26982698
{
26992699
let first = match self.next() {
27002700
Some(i) => i,
@@ -2956,12 +2956,13 @@ pub trait Iterator {
29562956
#[inline]
29572957
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
29582958
#[rustc_do_not_const_check]
2959-
fn try_find<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<Self::Item>>
2959+
fn try_find<R>(
2960+
&mut self,
2961+
f: impl FnMut(&Self::Item) -> R,
2962+
) -> ChangeOutputType<R, Option<Self::Item>>
29602963
where
29612964
Self: Sized,
2962-
F: FnMut(&Self::Item) -> R,
2963-
R: Try<Output = bool>,
2964-
R::Residual: Residual<Option<Self::Item>>,
2965+
R: Try<Output = bool, Residual: Residual<Option<Self::Item>>>,
29652966
{
29662967
#[inline]
29672968
fn check<I, V, R>(

‎library/core/src/option.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ impl<T> Option<T> {
672672
/// ```
673673
#[must_use]
674674
#[inline]
675-
#[unstable(feature = "is_none_or", issue = "none")]
675+
#[unstable(feature = "is_none_or", issue = "126383")]
676676
pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
677677
match self {
678678
None => true,

‎src/tools/compiletest/src/header.rs

+27-21
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
1414
use crate::header::cfg::parse_cfg_name_directive;
1515
use crate::header::cfg::MatchOutcome;
1616
use crate::header::needs::CachedNeedsConditions;
17+
use crate::util::static_regex;
1718
use crate::{extract_cdb_version, extract_gdb_version};
1819

1920
mod cfg;
@@ -1186,11 +1187,11 @@ impl Config {
11861187
}
11871188
}
11881189

1189-
fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> {
1190+
fn parse_custom_normalization(&self, line: &str, prefix: &str) -> Option<(String, String)> {
11901191
if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match {
1191-
let from = parse_normalization_string(&mut line)?;
1192-
let to = parse_normalization_string(&mut line)?;
1193-
Some((from, to))
1192+
let (regex, replacement) = parse_normalize_rule(line)
1193+
.unwrap_or_else(|| panic!("couldn't parse custom normalization rule: `{line}`"));
1194+
Some((regex, replacement))
11941195
} else {
11951196
None
11961197
}
@@ -1311,24 +1312,29 @@ fn expand_variables(mut value: String, config: &Config) -> String {
13111312
value
13121313
}
13131314

1314-
/// Finds the next quoted string `"..."` in `line`, and extract the content from it. Move the `line`
1315-
/// variable after the end of the quoted string.
1316-
///
1317-
/// # Examples
1318-
///
1319-
/// ```
1320-
/// let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
1321-
/// let first = parse_normalization_string(&mut s);
1322-
/// assert_eq!(first, Some("something (32 bits)".to_owned()));
1323-
/// assert_eq!(s, " -> \"something ($WORD bits)\".");
1315+
/// Parses the regex and replacement values of a `//@ normalize-*` header,
1316+
/// in the format:
1317+
/// ```text
1318+
/// normalize-*: "REGEX" -> "REPLACEMENT"
13241319
/// ```
1325-
fn parse_normalization_string(line: &mut &str) -> Option<String> {
1326-
// FIXME support escapes in strings.
1327-
let begin = line.find('"')? + 1;
1328-
let end = line[begin..].find('"')? + begin;
1329-
let result = line[begin..end].to_owned();
1330-
*line = &line[end + 1..];
1331-
Some(result)
1320+
fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
1321+
// FIXME(#126370): A colon after the header name should be mandatory, but
1322+
// currently is not, and there are many tests that lack the colon.
1323+
// FIXME: Support escaped double-quotes in strings.
1324+
let captures = static_regex!(
1325+
r#"(?x) # (verbose mode regex)
1326+
^
1327+
[^:\s]+:?\s* # (header name followed by optional colon)
1328+
"(?<regex>[^"]*)" # "REGEX"
1329+
\s+->\s+ # ->
1330+
"(?<replacement>[^"]*)" # "REPLACEMENT"
1331+
$
1332+
"#
1333+
)
1334+
.captures(header)?;
1335+
let regex = captures["regex"].to_owned();
1336+
let replacement = captures["replacement"].to_owned();
1337+
Some((regex, replacement))
13321338
}
13331339

13341340
pub fn extract_llvm_version(version: &str) -> Option<u32> {

‎src/tools/compiletest/src/header/tests.rs

+36-30
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::path::Path;
33
use std::str::FromStr;
44

55
use crate::common::{Config, Debugger, Mode};
6-
use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
6+
use crate::header::{parse_normalize_rule, EarlyProps, HeadersCache};
77

88
use super::iter_header;
99

@@ -32,35 +32,41 @@ fn make_test_description<R: Read>(
3232
}
3333

3434
#[test]
35-
fn test_parse_normalization_string() {
36-
let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
37-
let first = parse_normalization_string(&mut s);
38-
assert_eq!(first, Some("something (32 bits)".to_owned()));
39-
assert_eq!(s, " -> \"something ($WORD bits)\".");
40-
41-
// Nothing to normalize (No quotes)
42-
let mut s = "normalize-stderr-32bit: something (32 bits) -> something ($WORD bits).";
43-
let first = parse_normalization_string(&mut s);
44-
assert_eq!(first, None);
45-
assert_eq!(s, r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."#);
46-
47-
// Nothing to normalize (Only a single quote)
48-
let mut s = "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).";
49-
let first = parse_normalization_string(&mut s);
50-
assert_eq!(first, None);
51-
assert_eq!(s, "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).");
52-
53-
// Nothing to normalize (Three quotes)
54-
let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits).";
55-
let first = parse_normalization_string(&mut s);
56-
assert_eq!(first, Some("something (32 bits)".to_owned()));
57-
assert_eq!(s, " -> \"something ($WORD bits).");
58-
59-
// Nothing to normalize (No quotes, 16-bit)
60-
let mut s = "normalize-stderr-16bit: something (16 bits) -> something ($WORD bits).";
61-
let first = parse_normalization_string(&mut s);
62-
assert_eq!(first, None);
63-
assert_eq!(s, r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)."#);
35+
fn test_parse_normalize_rule() {
36+
let good_data = &[
37+
(
38+
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)""#,
39+
"something (32 bits)",
40+
"something ($WORD bits)",
41+
),
42+
// FIXME(#126370): A colon after the header name should be mandatory,
43+
// but currently is not, and there are many tests that lack the colon.
44+
(
45+
r#"normalize-stderr-32bit "something (32 bits)" -> "something ($WORD bits)""#,
46+
"something (32 bits)",
47+
"something ($WORD bits)",
48+
),
49+
];
50+
51+
for &(input, expected_regex, expected_replacement) in good_data {
52+
let parsed = parse_normalize_rule(input);
53+
let parsed =
54+
parsed.as_ref().map(|(regex, replacement)| (regex.as_str(), replacement.as_str()));
55+
assert_eq!(parsed, Some((expected_regex, expected_replacement)));
56+
}
57+
58+
let bad_data = &[
59+
r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)"#,
60+
r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)"#,
61+
r#"normalize-stderr-32bit: "something (32 bits) -> something ($WORD bits)"#,
62+
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"#,
63+
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"."#,
64+
];
65+
66+
for &input in bad_data {
67+
let parsed = parse_normalize_rule(input);
68+
assert_eq!(parsed, None);
69+
}
6470
}
6571

6672
#[derive(Default)]

‎src/tools/compiletest/src/runtest.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::errors::{self, Error, ErrorKind};
1515
use crate::header::TestProps;
1616
use crate::json;
1717
use crate::read2::{read2_abbreviated, Truncated};
18-
use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, PathBufExt};
18+
use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
1919
use crate::ColorConfig;
2020
use colored::Colorize;
2121
use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
@@ -48,14 +48,6 @@ use debugger::DebuggerCommands;
4848
#[cfg(test)]
4949
mod tests;
5050

51-
macro_rules! static_regex {
52-
($re:literal) => {{
53-
static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
54-
RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
55-
}};
56-
}
57-
use static_regex;
58-
5951
const FAKE_SRC_BASE: &str = "fake-test-src-base";
6052

6153
#[cfg(windows)]

‎src/tools/compiletest/src/runtest/coverage.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use std::process::Command;
77
use glob::glob;
88

99
use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP};
10-
use crate::runtest::{static_regex, Emit, ProcRes, TestCx, WillExecute};
10+
use crate::runtest::{Emit, ProcRes, TestCx, WillExecute};
11+
use crate::util::static_regex;
1112

1213
impl<'test> TestCx<'test> {
1314
fn coverage_dump_path(&self) -> &Path {

‎src/tools/compiletest/src/util.rs

+8
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,11 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Re
9090
}
9191
Ok(())
9292
}
93+
94+
macro_rules! static_regex {
95+
($re:literal) => {{
96+
static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
97+
RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
98+
}};
99+
}
100+
pub(crate) use static_regex;

‎src/tools/tidy/src/ext_tool_checks.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,18 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> {
274274
if out.status.success() {
275275
return Ok(());
276276
}
277-
let err = if String::from_utf8_lossy(&out.stderr).contains("No module named virtualenv") {
277+
278+
let stderr = String::from_utf8_lossy(&out.stderr);
279+
let err = if stderr.contains("No module named virtualenv") {
278280
Error::Generic(format!(
279281
"virtualenv not found: you may need to install it \
280282
(`python3 -m pip install venv`)"
281283
))
282284
} else {
283-
Error::Generic(format!("failed to create venv at '{}' using {sys_py}", path.display()))
285+
Error::Generic(format!(
286+
"failed to create venv at '{}' using {sys_py}: {stderr}",
287+
path.display()
288+
))
284289
};
285290
Err(err)
286291
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//@ run-pass
2+
//! Test that users are able to use stable mir APIs to retrieve type information from a crate item
3+
//! definition.
4+
5+
//@ ignore-stage1
6+
//@ ignore-cross-compile
7+
//@ ignore-remote
8+
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
9+
//@ edition: 2021
10+
11+
#![feature(rustc_private)]
12+
#![feature(assert_matches)]
13+
#![feature(control_flow_enum)]
14+
15+
#[macro_use]
16+
extern crate rustc_smir;
17+
extern crate rustc_driver;
18+
extern crate rustc_interface;
19+
extern crate stable_mir;
20+
21+
use rustc_smir::rustc_internal;
22+
use stable_mir::ty::{Ty, ForeignItemKind};
23+
use stable_mir::*;
24+
use std::io::Write;
25+
use std::ops::ControlFlow;
26+
27+
const CRATE_NAME: &str = "crate_def_ty";
28+
29+
/// Test if we can retrieve type information from different definitions.
30+
fn test_def_tys() -> ControlFlow<()> {
31+
let items = stable_mir::all_local_items();
32+
for item in &items {
33+
// Type from crate items.
34+
let ty = item.ty();
35+
match item.name().as_str() {
36+
"STATIC_STR" => assert!(ty.kind().is_ref()),
37+
"CONST_U32" => assert!(ty.kind().is_integral()),
38+
"main" => { check_fn_def(ty) }
39+
_ => unreachable!("Unexpected item: `{item:?}`")
40+
}
41+
}
42+
43+
let foreign_items = stable_mir::local_crate().foreign_modules();
44+
for item in foreign_items[0].module().items() {
45+
// Type from foreign items.
46+
let ty = item.ty();
47+
let item_kind = item.kind();
48+
let name = item.name();
49+
match item_kind {
50+
ForeignItemKind::Fn(fn_def) => {
51+
assert_eq!(&name, "extern_fn");
52+
assert_eq!(ty, fn_def.ty());
53+
check_fn_def(ty)
54+
}
55+
ForeignItemKind::Static(def) => {
56+
assert_eq!(&name, "EXT_STATIC");
57+
assert_eq!(ty, def.ty());
58+
assert!(ty.kind().is_integral())
59+
}
60+
_ => unreachable!("Unexpected kind: {item_kind:?}")
61+
};
62+
}
63+
64+
ControlFlow::Continue(())
65+
}
66+
67+
fn check_fn_def(ty: Ty) {
68+
let kind = ty.kind();
69+
let (def, args) = kind.fn_def().expect(&format!("Expected function type, but found: {ty}"));
70+
assert!(def.ty().kind().is_fn());
71+
assert_eq!(def.ty_with_args(args), ty);
72+
}
73+
74+
/// This test will generate and analyze a dummy crate using the stable mir.
75+
/// For that, it will first write the dummy crate into a file.
76+
/// Then it will create a `StableMir` using custom arguments and then
77+
/// it will run the compiler.
78+
fn main() {
79+
let path = "defs_ty_input.rs";
80+
generate_input(&path).unwrap();
81+
let args = vec![
82+
"rustc".to_string(),
83+
"-Cpanic=abort".to_string(),
84+
"--crate-name".to_string(),
85+
CRATE_NAME.to_string(),
86+
path.to_string(),
87+
];
88+
run!(args, test_def_tys).unwrap();
89+
}
90+
91+
fn generate_input(path: &str) -> std::io::Result<()> {
92+
let mut file = std::fs::File::create(path)?;
93+
write!(
94+
file,
95+
r#"
96+
// We would like to check intrinsic definition.
97+
#![feature(core_intrinsics)]
98+
static STATIC_STR: &str = "foo";
99+
const CONST_U32: u32 = 0u32;
100+
101+
fn main() {{
102+
let _c = core::char::from_u32(99);
103+
let _v = Vec::<u8>::new();
104+
let _i = std::intrinsics::size_of::<u8>();
105+
}}
106+
107+
extern "C" {{
108+
fn extern_fn(x: i32) -> i32;
109+
static EXT_STATIC: i32;
110+
}}
111+
"#
112+
)?;
113+
Ok(())
114+
}

0 commit comments

Comments
 (0)
Please sign in to comment.