Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 09ac6e4

Browse files
committedOct 31, 2023
Auto merge of #117459 - matthiaskrgr:rollup-t3osb3c, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #113241 (rustdoc: Document lack of object safety on affected traits) - #117388 (Turn const_caller_location from a query to a hook) - #117417 (Add a stable MIR visitor) - #117439 (prepopulate opaque ty storage before using it) - #117451 (Add support for pre-unix-epoch file dates on Apple platforms (#108277)) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9d83ac2 + d06200b commit 09ac6e4

File tree

22 files changed

+811
-103
lines changed

22 files changed

+811
-103
lines changed
 

‎compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
188188
&mut borrowck_context,
189189
);
190190

191-
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
192-
// predefined opaques in the typeck root.
193-
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
194-
checker.register_predefined_opaques_in_new_solver();
195-
}
191+
checker.check_user_type_annotations();
196192

197193
let mut verifier = TypeVerifier::new(&mut checker, promoted);
198194
verifier.visit_body(&body);
@@ -1021,7 +1017,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10211017
borrowck_context,
10221018
reported_errors: Default::default(),
10231019
};
1024-
checker.check_user_type_annotations();
1020+
1021+
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
1022+
// predefined opaques in the typeck root.
1023+
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
1024+
checker.register_predefined_opaques_in_new_solver();
1025+
}
1026+
10251027
checker
10261028
}
10271029

‎compiler/rustc_const_eval/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn provide(providers: &mut Providers) {
4949
const_eval::provide(providers);
5050
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
5151
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
52-
providers.const_caller_location = util::caller_location::const_caller_location_provider;
52+
providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider;
5353
providers.eval_to_valtree = |tcx, param_env_and_value| {
5454
let (param_env, raw) = param_env_and_value.into_parts();
5555
const_eval::eval_to_valtree(tcx, param_env, raw)

‎compiler/rustc_const_eval/src/util/caller_location.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use rustc_hir::LangItem;
22
use rustc_middle::mir;
3+
use rustc_middle::query::TyCtxtAt;
4+
use rustc_middle::ty;
35
use rustc_middle::ty::layout::LayoutOf;
4-
use rustc_middle::ty::{self, TyCtxt};
5-
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
6+
use rustc_span::symbol::Symbol;
67
use rustc_type_ir::Mutability;
78

89
use crate::const_eval::{mk_eval_cx, CanAccessStatics, CompileTimeEvalContext};
@@ -49,11 +50,13 @@ fn alloc_caller_location<'mir, 'tcx>(
4950
}
5051

5152
pub(crate) fn const_caller_location_provider(
52-
tcx: TyCtxt<'_>,
53-
(file, line, col): (Symbol, u32, u32),
53+
tcx: TyCtxtAt<'_>,
54+
file: Symbol,
55+
line: u32,
56+
col: u32,
5457
) -> mir::ConstValue<'_> {
5558
trace!("const_caller_location: {}:{}:{}", file, line, col);
56-
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
59+
let mut ecx = mk_eval_cx(tcx.tcx, tcx.span, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
5760

5861
let loc_place = alloc_caller_location(&mut ecx, file, line, col);
5962
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {

‎compiler/rustc_middle/src/hooks/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,7 @@ declare_hooks! {
6767
/// Tries to destructure an `mir::Const` ADT or array into its variant index
6868
/// and its field values. This should only be used for pretty printing.
6969
hook try_destructure_mir_constant_for_diagnostics(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>;
70+
71+
/// Getting a &core::panic::Location referring to a span.
72+
hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue<'tcx>;
7073
}

‎compiler/rustc_middle/src/mir/consts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,12 +590,12 @@ impl<'tcx> TyCtxt<'tcx> {
590590
pub fn span_as_caller_location(self, span: Span) -> ConstValue<'tcx> {
591591
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
592592
let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
593-
self.const_caller_location((
593+
self.const_caller_location(
594594
rustc_span::symbol::Symbol::intern(
595595
&caller.file.name.for_codegen(&self.sess).to_string_lossy(),
596596
),
597597
caller.line as u32,
598598
caller.col_display as u32 + 1,
599-
))
599+
)
600600
}
601601
}

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,10 +1101,6 @@ rustc_queries! {
11011101
desc { "destructuring type level constant"}
11021102
}
11031103

1104-
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> mir::ConstValue<'tcx> {
1105-
desc { "getting a &core::panic::Location referring to a span" }
1106-
}
1107-
11081104
// FIXME get rid of this with valtrees
11091105
query lit_to_const(
11101106
key: LitToConstInput<'tcx>

‎compiler/rustc_smir/src/rustc_smir/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
216216
tables.create_def_id(def_id)
217217
}
218218

219+
fn instance_mangled_name(&self, def: InstanceDef) -> String {
220+
let tables = self.0.borrow_mut();
221+
let instance = tables.instances[def];
222+
tables.tcx.symbol_name(instance).name.to_string()
223+
}
224+
219225
fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
220226
let mut tables = self.0.borrow_mut();
221227
let def_id = tables[item.0];

‎compiler/stable_mir/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ pub type DefKind = Opaque;
103103
pub type Filename = Opaque;
104104

105105
/// Holds information about an item in the crate.
106-
/// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to
107-
/// use this item.
108106
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
109107
pub struct CrateItem(pub DefId);
110108

@@ -224,6 +222,9 @@ pub trait Context {
224222
/// Get the instance.
225223
fn instance_def_id(&self, instance: InstanceDef) -> DefId;
226224

225+
/// Get the instance mangled name.
226+
fn instance_mangled_name(&self, instance: InstanceDef) -> String;
227+
227228
/// Convert a non-generic crate item into an instance.
228229
/// This function will panic if the item is generic.
229230
fn mono_instance(&self, item: CrateItem) -> Instance;
@@ -259,7 +260,7 @@ pub fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
259260
}
260261

261262
/// A type that provides internal information but that can still be used for debug purpose.
262-
#[derive(Clone)]
263+
#[derive(Clone, Eq, PartialEq)]
263264
pub struct Opaque(String);
264265

265266
impl std::fmt::Display for Opaque {

‎compiler/stable_mir/src/mir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
mod body;
22
pub mod mono;
3+
pub mod visit;
34

45
pub use body::*;
6+
pub use visit::MirVisitor;

‎compiler/stable_mir/src/mir/body.rs

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region};
1+
use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, Ty};
22
use crate::Opaque;
3-
use crate::{ty::Ty, Span};
3+
use crate::Span;
44

55
/// The SMIR representation of a single function.
66
#[derive(Clone, Debug)]
@@ -12,10 +12,10 @@ pub struct Body {
1212
// The first local is the return value pointer, followed by `arg_count`
1313
// locals for the function arguments, followed by any user-declared
1414
// variables and temporaries.
15-
locals: LocalDecls,
15+
pub(super) locals: LocalDecls,
1616

1717
// The number of arguments this function takes.
18-
arg_count: usize,
18+
pub(super) arg_count: usize,
1919
}
2020

2121
impl Body {
@@ -35,7 +35,7 @@ impl Body {
3535

3636
/// Return local that holds this function's return value.
3737
pub fn ret_local(&self) -> &LocalDecl {
38-
&self.locals[0]
38+
&self.locals[RETURN_LOCAL]
3939
}
4040

4141
/// Locals in `self` that correspond to this function's arguments.
@@ -60,7 +60,7 @@ impl Body {
6060

6161
type LocalDecls = Vec<LocalDecl>;
6262

63-
#[derive(Clone, Debug)]
63+
#[derive(Clone, Debug, Eq, PartialEq)]
6464
pub struct LocalDecl {
6565
pub ty: Ty,
6666
pub span: Span,
@@ -72,13 +72,13 @@ pub struct BasicBlock {
7272
pub terminator: Terminator,
7373
}
7474

75-
#[derive(Clone, Debug)]
75+
#[derive(Clone, Debug, Eq, PartialEq)]
7676
pub struct Terminator {
7777
pub kind: TerminatorKind,
7878
pub span: Span,
7979
}
8080

81-
#[derive(Clone, Debug)]
81+
#[derive(Clone, Debug, Eq, PartialEq)]
8282
pub enum TerminatorKind {
8383
Goto {
8484
target: usize,
@@ -122,7 +122,7 @@ pub enum TerminatorKind {
122122
},
123123
}
124124

125-
#[derive(Clone, Debug)]
125+
#[derive(Clone, Debug, Eq, PartialEq)]
126126
pub struct InlineAsmOperand {
127127
pub in_value: Option<Operand>,
128128
pub out_place: Option<Place>,
@@ -131,15 +131,15 @@ pub struct InlineAsmOperand {
131131
pub raw_rpr: String,
132132
}
133133

134-
#[derive(Clone, Debug)]
134+
#[derive(Clone, Debug, Eq, PartialEq)]
135135
pub enum UnwindAction {
136136
Continue,
137137
Unreachable,
138138
Terminate,
139139
Cleanup(usize),
140140
}
141141

142-
#[derive(Clone, Debug)]
142+
#[derive(Clone, Debug, Eq, PartialEq)]
143143
pub enum AssertMessage {
144144
BoundsCheck { len: Operand, index: Operand },
145145
Overflow(BinOp, Operand, Operand),
@@ -151,7 +151,7 @@ pub enum AssertMessage {
151151
MisalignedPointerDereference { required: Operand, found: Operand },
152152
}
153153

154-
#[derive(Clone, Debug)]
154+
#[derive(Clone, Debug, Eq, PartialEq)]
155155
pub enum BinOp {
156156
Add,
157157
AddUnchecked,
@@ -177,20 +177,20 @@ pub enum BinOp {
177177
Offset,
178178
}
179179

180-
#[derive(Clone, Debug)]
180+
#[derive(Clone, Debug, Eq, PartialEq)]
181181
pub enum UnOp {
182182
Not,
183183
Neg,
184184
}
185185

186-
#[derive(Clone, Debug)]
186+
#[derive(Clone, Debug, Eq, PartialEq)]
187187
pub enum CoroutineKind {
188188
Async(CoroutineSource),
189189
Coroutine,
190190
Gen(CoroutineSource),
191191
}
192192

193-
#[derive(Clone, Debug)]
193+
#[derive(Clone, Debug, Eq, PartialEq)]
194194
pub enum CoroutineSource {
195195
Block,
196196
Closure,
@@ -204,7 +204,7 @@ pub(crate) type LocalDefId = Opaque;
204204
pub(crate) type Coverage = Opaque;
205205

206206
/// The FakeReadCause describes the type of pattern why a FakeRead statement exists.
207-
#[derive(Clone, Debug)]
207+
#[derive(Clone, Debug, Eq, PartialEq)]
208208
pub enum FakeReadCause {
209209
ForMatchGuard,
210210
ForMatchedPlace(LocalDefId),
@@ -214,42 +214,42 @@ pub enum FakeReadCause {
214214
}
215215

216216
/// Describes what kind of retag is to be performed
217-
#[derive(Clone, Debug)]
217+
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
218218
pub enum RetagKind {
219219
FnEntry,
220220
TwoPhase,
221221
Raw,
222222
Default,
223223
}
224224

225-
#[derive(Clone, Debug)]
225+
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
226226
pub enum Variance {
227227
Covariant,
228228
Invariant,
229229
Contravariant,
230230
Bivariant,
231231
}
232232

233-
#[derive(Clone, Debug)]
233+
#[derive(Clone, Debug, Eq, PartialEq)]
234234
pub struct CopyNonOverlapping {
235235
pub src: Operand,
236236
pub dst: Operand,
237237
pub count: Operand,
238238
}
239239

240-
#[derive(Clone, Debug)]
240+
#[derive(Clone, Debug, Eq, PartialEq)]
241241
pub enum NonDivergingIntrinsic {
242242
Assume(Operand),
243243
CopyNonOverlapping(CopyNonOverlapping),
244244
}
245245

246-
#[derive(Clone, Debug)]
246+
#[derive(Clone, Debug, Eq, PartialEq)]
247247
pub struct Statement {
248248
pub kind: StatementKind,
249249
pub span: Span,
250250
}
251251

252-
#[derive(Clone, Debug)]
252+
#[derive(Clone, Debug, Eq, PartialEq)]
253253
pub enum StatementKind {
254254
Assign(Place, Rvalue),
255255
FakeRead(FakeReadCause, Place),
@@ -266,7 +266,7 @@ pub enum StatementKind {
266266
Nop,
267267
}
268268

269-
#[derive(Clone, Debug)]
269+
#[derive(Clone, Debug, Eq, PartialEq)]
270270
pub enum Rvalue {
271271
/// Creates a pointer with the indicated mutability to the place.
272272
///
@@ -378,7 +378,7 @@ pub enum Rvalue {
378378
Use(Operand),
379379
}
380380

381-
#[derive(Clone, Debug)]
381+
#[derive(Clone, Debug, Eq, PartialEq)]
382382
pub enum AggregateKind {
383383
Array(Ty),
384384
Tuple,
@@ -387,49 +387,51 @@ pub enum AggregateKind {
387387
Coroutine(CoroutineDef, GenericArgs, Movability),
388388
}
389389

390-
#[derive(Clone, Debug)]
390+
#[derive(Clone, Debug, Eq, PartialEq)]
391391
pub enum Operand {
392392
Copy(Place),
393393
Move(Place),
394394
Constant(Constant),
395395
}
396396

397-
#[derive(Clone, Debug)]
397+
#[derive(Clone, Debug, Eq, PartialEq)]
398398
pub struct Place {
399399
pub local: Local,
400400
/// projection out of a place (access a field, deref a pointer, etc)
401401
pub projection: String,
402402
}
403403

404-
#[derive(Clone, Debug)]
404+
#[derive(Clone, Debug, Eq, PartialEq)]
405405
pub struct UserTypeProjection {
406406
pub base: UserTypeAnnotationIndex,
407407
pub projection: String,
408408
}
409409

410410
pub type Local = usize;
411411

412+
pub const RETURN_LOCAL: Local = 0;
413+
412414
type FieldIdx = usize;
413415

414416
/// The source-order index of a variant in a type.
415417
pub type VariantIdx = usize;
416418

417419
type UserTypeAnnotationIndex = usize;
418420

419-
#[derive(Clone, Debug)]
421+
#[derive(Clone, Debug, Eq, PartialEq)]
420422
pub struct Constant {
421423
pub span: Span,
422424
pub user_ty: Option<UserTypeAnnotationIndex>,
423425
pub literal: Const,
424426
}
425427

426-
#[derive(Clone, Debug)]
428+
#[derive(Clone, Debug, Eq, PartialEq)]
427429
pub struct SwitchTarget {
428430
pub value: u128,
429431
pub target: usize,
430432
}
431433

432-
#[derive(Clone, Debug)]
434+
#[derive(Clone, Debug, Eq, PartialEq)]
433435
pub enum BorrowKind {
434436
/// Data must be immutable and is aliasable.
435437
Shared,
@@ -446,26 +448,26 @@ pub enum BorrowKind {
446448
},
447449
}
448450

449-
#[derive(Clone, Debug)]
451+
#[derive(Clone, Debug, Eq, PartialEq)]
450452
pub enum MutBorrowKind {
451453
Default,
452454
TwoPhaseBorrow,
453455
ClosureCapture,
454456
}
455457

456-
#[derive(Clone, Debug)]
458+
#[derive(Clone, Debug, PartialEq, Eq)]
457459
pub enum Mutability {
458460
Not,
459461
Mut,
460462
}
461463

462-
#[derive(Copy, Clone, Debug)]
464+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
463465
pub enum Safety {
464466
Unsafe,
465467
Normal,
466468
}
467469

468-
#[derive(Clone, Debug)]
470+
#[derive(Clone, Debug, Eq, PartialEq)]
469471
pub enum PointerCoercion {
470472
/// Go from a fn-item type to a fn-pointer type.
471473
ReifyFnPointer,
@@ -492,7 +494,7 @@ pub enum PointerCoercion {
492494
Unsize,
493495
}
494496

495-
#[derive(Clone, Debug)]
497+
#[derive(Clone, Debug, Eq, PartialEq)]
496498
pub enum CastKind {
497499
PointerExposeAddress,
498500
PointerFromExposedAddress,
@@ -507,7 +509,7 @@ pub enum CastKind {
507509
Transmute,
508510
}
509511

510-
#[derive(Clone, Debug)]
512+
#[derive(Clone, Debug, Eq, PartialEq)]
511513
pub enum NullOp {
512514
/// Returns the size of a value of that type.
513515
SizeOf,

‎compiler/stable_mir/src/mir/mono.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ impl Instance {
4242
with(|context| context.instance_ty(self.def))
4343
}
4444

45+
pub fn mangled_name(&self) -> String {
46+
with(|context| context.instance_mangled_name(self.def))
47+
}
48+
4549
/// Resolve an instance starting from a function definition and generic arguments.
4650
pub fn resolve(def: FnDef, args: &GenericArgs) -> Result<Instance, crate::Error> {
4751
with(|context| {

‎compiler/stable_mir/src/mir/visit.rs

Lines changed: 414 additions & 0 deletions
Large diffs are not rendered by default.

‎compiler/stable_mir/src/ty.rs

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ impl Ty {
2222
}
2323

2424
/// Represents a constant in MIR or from the Type system.
25-
#[derive(Clone, Debug)]
25+
#[derive(Clone, Debug, Eq, PartialEq)]
2626
pub struct Const {
2727
/// The constant kind.
28-
kind: ConstantKind,
28+
pub(crate) kind: ConstantKind,
2929
/// The constant type.
30-
ty: Ty,
30+
pub(crate) ty: Ty,
3131
/// Used for internal tracking of the internal constant.
3232
pub id: ConstId,
3333
}
@@ -54,12 +54,12 @@ pub struct ConstId(pub usize);
5454

5555
type Ident = Opaque;
5656

57-
#[derive(Debug, Clone)]
57+
#[derive(Clone, Debug, Eq, PartialEq)]
5858
pub struct Region {
5959
pub kind: RegionKind,
6060
}
6161

62-
#[derive(Debug, Clone)]
62+
#[derive(Clone, Debug, Eq, PartialEq)]
6363
pub enum RegionKind {
6464
ReEarlyBound(EarlyBoundRegion),
6565
ReLateBound(DebruijnIndex, BoundRegion),
@@ -70,7 +70,7 @@ pub enum RegionKind {
7070

7171
pub(crate) type DebruijnIndex = u32;
7272

73-
#[derive(Debug, Clone)]
73+
#[derive(Clone, Debug, Eq, PartialEq)]
7474
pub struct EarlyBoundRegion {
7575
pub def_id: RegionDef,
7676
pub index: u32,
@@ -79,15 +79,15 @@ pub struct EarlyBoundRegion {
7979

8080
pub(crate) type BoundVar = u32;
8181

82-
#[derive(Debug, Clone)]
82+
#[derive(Clone, Debug, Eq, PartialEq)]
8383
pub struct BoundRegion {
8484
pub var: BoundVar,
8585
pub kind: BoundRegionKind,
8686
}
8787

8888
pub(crate) type UniverseIndex = u32;
8989

90-
#[derive(Debug, Clone)]
90+
#[derive(Clone, Debug, Eq, PartialEq)]
9191
pub struct Placeholder<T> {
9292
pub universe: UniverseIndex,
9393
pub bound: T,
@@ -127,15 +127,15 @@ pub struct LineInfo {
127127
pub end_col: usize,
128128
}
129129

130-
#[derive(Clone, Debug)]
130+
#[derive(Clone, Debug, Eq, PartialEq)]
131131
pub enum TyKind {
132132
RigidTy(RigidTy),
133133
Alias(AliasKind, AliasTy),
134134
Param(ParamTy),
135135
Bound(usize, BoundTy),
136136
}
137137

138-
#[derive(Clone, Debug)]
138+
#[derive(Clone, Debug, Eq, PartialEq)]
139139
pub enum RigidTy {
140140
Bool,
141141
Char,
@@ -236,7 +236,7 @@ pub struct ImplDef(pub DefId);
236236
pub struct RegionDef(pub DefId);
237237

238238
/// A list of generic arguments.
239-
#[derive(Clone, Debug)]
239+
#[derive(Clone, Debug, Eq, PartialEq)]
240240
pub struct GenericArgs(pub Vec<GenericArgKind>);
241241

242242
impl std::ops::Index<ParamTy> for GenericArgs {
@@ -255,7 +255,7 @@ impl std::ops::Index<ParamConst> for GenericArgs {
255255
}
256256
}
257257

258-
#[derive(Clone, Debug)]
258+
#[derive(Clone, Debug, Eq, PartialEq)]
259259
pub enum GenericArgKind {
260260
Lifetime(Region),
261261
Type(Ty),
@@ -284,29 +284,29 @@ impl GenericArgKind {
284284
}
285285
}
286286

287-
#[derive(Clone, Debug)]
287+
#[derive(Clone, Debug, Eq, PartialEq)]
288288
pub enum TermKind {
289289
Type(Ty),
290290
Const(Const),
291291
}
292292

293-
#[derive(Clone, Debug)]
293+
#[derive(Clone, Debug, Eq, PartialEq)]
294294
pub enum AliasKind {
295295
Projection,
296296
Inherent,
297297
Opaque,
298298
Weak,
299299
}
300300

301-
#[derive(Clone, Debug)]
301+
#[derive(Clone, Debug, Eq, PartialEq)]
302302
pub struct AliasTy {
303303
pub def_id: AliasDef,
304304
pub args: GenericArgs,
305305
}
306306

307307
pub type PolyFnSig = Binder<FnSig>;
308308

309-
#[derive(Clone, Debug)]
309+
#[derive(Clone, Debug, Eq, PartialEq)]
310310
pub struct FnSig {
311311
pub inputs_and_output: Vec<Ty>,
312312
pub c_variadic: bool,
@@ -345,18 +345,18 @@ pub enum Abi {
345345
RiscvInterruptS,
346346
}
347347

348-
#[derive(Clone, Debug)]
348+
#[derive(Clone, Debug, Eq, PartialEq)]
349349
pub struct Binder<T> {
350350
pub value: T,
351351
pub bound_vars: Vec<BoundVariableKind>,
352352
}
353353

354-
#[derive(Clone, Debug)]
354+
#[derive(Clone, Debug, Eq, PartialEq)]
355355
pub struct EarlyBinder<T> {
356356
pub value: T,
357357
}
358358

359-
#[derive(Clone, Debug)]
359+
#[derive(Clone, Debug, Eq, PartialEq)]
360360
pub enum BoundVariableKind {
361361
Ty(BoundTyKind),
362362
Region(BoundRegionKind),
@@ -369,46 +369,46 @@ pub enum BoundTyKind {
369369
Param(ParamDef, String),
370370
}
371371

372-
#[derive(Clone, Debug)]
372+
#[derive(Clone, Debug, Eq, PartialEq)]
373373
pub enum BoundRegionKind {
374374
BrAnon,
375375
BrNamed(BrNamedDef, String),
376376
BrEnv,
377377
}
378378

379-
#[derive(Clone, Debug)]
379+
#[derive(Clone, Debug, Eq, PartialEq)]
380380
pub enum DynKind {
381381
Dyn,
382382
DynStar,
383383
}
384384

385-
#[derive(Clone, Debug)]
385+
#[derive(Clone, Debug, Eq, PartialEq)]
386386
pub enum ExistentialPredicate {
387387
Trait(ExistentialTraitRef),
388388
Projection(ExistentialProjection),
389389
AutoTrait(TraitDef),
390390
}
391391

392-
#[derive(Clone, Debug)]
392+
#[derive(Clone, Debug, Eq, PartialEq)]
393393
pub struct ExistentialTraitRef {
394394
pub def_id: TraitDef,
395395
pub generic_args: GenericArgs,
396396
}
397397

398-
#[derive(Clone, Debug)]
398+
#[derive(Clone, Debug, Eq, PartialEq)]
399399
pub struct ExistentialProjection {
400400
pub def_id: TraitDef,
401401
pub generic_args: GenericArgs,
402402
pub term: TermKind,
403403
}
404404

405-
#[derive(Clone, Debug)]
405+
#[derive(Clone, Debug, Eq, PartialEq)]
406406
pub struct ParamTy {
407407
pub index: u32,
408408
pub name: String,
409409
}
410410

411-
#[derive(Clone, Debug)]
411+
#[derive(Clone, Debug, Eq, PartialEq)]
412412
pub struct BoundTy {
413413
pub var: usize,
414414
pub kind: BoundTyKind,
@@ -424,22 +424,22 @@ pub type Promoted = u32;
424424
pub type InitMaskMaterialized = Vec<u64>;
425425

426426
/// Stores the provenance information of pointers stored in memory.
427-
#[derive(Clone, Debug)]
427+
#[derive(Clone, Debug, Eq, PartialEq)]
428428
pub struct ProvenanceMap {
429429
/// Provenance in this map applies from the given offset for an entire pointer-size worth of
430430
/// bytes. Two entries in this map are always at least a pointer size apart.
431431
pub ptrs: Vec<(Size, Prov)>,
432432
}
433433

434-
#[derive(Clone, Debug)]
434+
#[derive(Clone, Debug, Eq, PartialEq)]
435435
pub struct Allocation {
436436
pub bytes: Bytes,
437437
pub provenance: ProvenanceMap,
438438
pub align: Align,
439439
pub mutability: Mutability,
440440
}
441441

442-
#[derive(Clone, Debug)]
442+
#[derive(Clone, Debug, Eq, PartialEq)]
443443
pub enum ConstantKind {
444444
Allocated(Allocation),
445445
Unevaluated(UnevaluatedConst),
@@ -449,13 +449,13 @@ pub enum ConstantKind {
449449
ZeroSized,
450450
}
451451

452-
#[derive(Clone, Debug)]
452+
#[derive(Clone, Debug, Eq, PartialEq)]
453453
pub struct ParamConst {
454454
pub index: u32,
455455
pub name: String,
456456
}
457457

458-
#[derive(Clone, Debug)]
458+
#[derive(Clone, Debug, Eq, PartialEq)]
459459
pub struct UnevaluatedConst {
460460
pub def: ConstDef,
461461
pub args: GenericArgs,
@@ -469,7 +469,7 @@ pub enum TraitSpecializationKind {
469469
AlwaysApplicable,
470470
}
471471

472-
#[derive(Clone, Debug)]
472+
#[derive(Clone, Debug, Eq, PartialEq)]
473473
pub struct TraitDecl {
474474
pub def_id: TraitDef,
475475
pub unsafety: Safety,
@@ -500,13 +500,13 @@ impl TraitDecl {
500500

501501
pub type ImplTrait = EarlyBinder<TraitRef>;
502502

503-
#[derive(Clone, Debug)]
503+
#[derive(Clone, Debug, Eq, PartialEq)]
504504
pub struct TraitRef {
505505
pub def_id: TraitDef,
506506
pub args: GenericArgs,
507507
}
508508

509-
#[derive(Clone, Debug)]
509+
#[derive(Clone, Debug, Eq, PartialEq)]
510510
pub struct Generics {
511511
pub parent: Option<GenericDef>,
512512
pub parent_count: usize,
@@ -517,14 +517,14 @@ pub struct Generics {
517517
pub host_effect_index: Option<usize>,
518518
}
519519

520-
#[derive(Clone, Debug)]
520+
#[derive(Clone, Debug, Eq, PartialEq)]
521521
pub enum GenericParamDefKind {
522522
Lifetime,
523523
Type { has_default: bool, synthetic: bool },
524524
Const { has_default: bool },
525525
}
526526

527-
#[derive(Clone, Debug)]
527+
#[derive(Clone, Debug, Eq, PartialEq)]
528528
pub struct GenericParamDef {
529529
pub name: super::Symbol,
530530
pub def_id: GenericDef,
@@ -538,7 +538,7 @@ pub struct GenericPredicates {
538538
pub predicates: Vec<(PredicateKind, Span)>,
539539
}
540540

541-
#[derive(Clone, Debug)]
541+
#[derive(Clone, Debug, Eq, PartialEq)]
542542
pub enum PredicateKind {
543543
Clause(ClauseKind),
544544
ObjectSafe(TraitDef),
@@ -550,7 +550,7 @@ pub enum PredicateKind {
550550
AliasRelate(TermKind, TermKind, AliasRelationDirection),
551551
}
552552

553-
#[derive(Clone, Debug)]
553+
#[derive(Clone, Debug, Eq, PartialEq)]
554554
pub enum ClauseKind {
555555
Trait(TraitPredicate),
556556
RegionOutlives(RegionOutlivesPredicate),
@@ -561,50 +561,50 @@ pub enum ClauseKind {
561561
ConstEvaluatable(Const),
562562
}
563563

564-
#[derive(Clone, Debug)]
564+
#[derive(Clone, Debug, Eq, PartialEq)]
565565
pub enum ClosureKind {
566566
Fn,
567567
FnMut,
568568
FnOnce,
569569
}
570570

571-
#[derive(Clone, Debug)]
571+
#[derive(Clone, Debug, Eq, PartialEq)]
572572
pub struct SubtypePredicate {
573573
pub a: Ty,
574574
pub b: Ty,
575575
}
576576

577-
#[derive(Clone, Debug)]
577+
#[derive(Clone, Debug, Eq, PartialEq)]
578578
pub struct CoercePredicate {
579579
pub a: Ty,
580580
pub b: Ty,
581581
}
582582

583-
#[derive(Clone, Debug)]
583+
#[derive(Clone, Debug, Eq, PartialEq)]
584584
pub enum AliasRelationDirection {
585585
Equate,
586586
Subtype,
587587
}
588588

589-
#[derive(Clone, Debug)]
589+
#[derive(Clone, Debug, Eq, PartialEq)]
590590
pub struct TraitPredicate {
591591
pub trait_ref: TraitRef,
592592
pub polarity: ImplPolarity,
593593
}
594594

595-
#[derive(Clone, Debug)]
595+
#[derive(Clone, Debug, Eq, PartialEq)]
596596
pub struct OutlivesPredicate<A, B>(pub A, pub B);
597597

598598
pub type RegionOutlivesPredicate = OutlivesPredicate<Region, Region>;
599599
pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>;
600600

601-
#[derive(Clone, Debug)]
601+
#[derive(Clone, Debug, Eq, PartialEq)]
602602
pub struct ProjectionPredicate {
603603
pub projection_ty: AliasTy,
604604
pub term: TermKind,
605605
}
606606

607-
#[derive(Clone, Debug)]
607+
#[derive(Clone, Debug, Eq, PartialEq)]
608608
pub enum ImplPolarity {
609609
Positive,
610610
Negative,

‎library/std/src/fs/tests.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,48 @@ fn test_file_times() {
17081708
}
17091709
}
17101710

1711+
#[test]
1712+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
1713+
fn test_file_times_pre_epoch_with_nanos() {
1714+
#[cfg(target_os = "ios")]
1715+
use crate::os::ios::fs::FileTimesExt;
1716+
#[cfg(target_os = "macos")]
1717+
use crate::os::macos::fs::FileTimesExt;
1718+
#[cfg(target_os = "tvos")]
1719+
use crate::os::tvos::fs::FileTimesExt;
1720+
#[cfg(target_os = "watchos")]
1721+
use crate::os::watchos::fs::FileTimesExt;
1722+
1723+
let tmp = tmpdir();
1724+
let file = File::create(tmp.join("foo")).unwrap();
1725+
1726+
for (accessed, modified, created) in [
1727+
// The first round is to set filetimes to something we know works, but this time
1728+
// it's validated with nanoseconds as well which probe the numeric boundary.
1729+
(
1730+
SystemTime::UNIX_EPOCH + Duration::new(12345, 1),
1731+
SystemTime::UNIX_EPOCH + Duration::new(54321, 100_000_000),
1732+
SystemTime::UNIX_EPOCH + Duration::new(32123, 999_999_999),
1733+
),
1734+
// The second rounds uses pre-epoch dates along with nanoseconds that probe
1735+
// the numeric boundary.
1736+
(
1737+
SystemTime::UNIX_EPOCH - Duration::new(1, 1),
1738+
SystemTime::UNIX_EPOCH - Duration::new(60, 100_000_000),
1739+
SystemTime::UNIX_EPOCH - Duration::new(3600, 999_999_999),
1740+
),
1741+
] {
1742+
let mut times = FileTimes::new();
1743+
times = times.set_accessed(accessed).set_modified(modified).set_created(created);
1744+
file.set_times(times).unwrap();
1745+
1746+
let metadata = file.metadata().unwrap();
1747+
assert_eq!(metadata.accessed().unwrap(), accessed);
1748+
assert_eq!(metadata.modified().unwrap(), modified);
1749+
assert_eq!(metadata.created().unwrap(), created);
1750+
}
1751+
}
1752+
17111753
#[test]
17121754
#[cfg(windows)]
17131755
fn windows_unix_socket_exists() {

‎library/std/src/sys/unix/time.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,30 @@ impl Timespec {
7676
}
7777

7878
const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
79+
// On Apple OS, dates before epoch are represented differently than on other
80+
// Unix platforms: e.g. 1/10th of a second before epoch is represented as `seconds=-1`
81+
// and `nanoseconds=100_000_000` on other platforms, but is `seconds=0` and
82+
// `nanoseconds=-900_000_000` on Apple OS.
83+
//
84+
// To compensate, we first detect this special case by checking if both
85+
// seconds and nanoseconds are in range, and then correct the value for seconds
86+
// and nanoseconds to match the common unix representation.
87+
//
88+
// Please note that Apple OS nonetheless accepts the standard unix format when
89+
// setting file times, which makes this compensation round-trippable and generally
90+
// transparent.
91+
#[cfg(any(
92+
target_os = "macos",
93+
target_os = "ios",
94+
target_os = "tvos",
95+
target_os = "watchos"
96+
))]
97+
let (tv_sec, tv_nsec) =
98+
if (tv_sec <= 0 && tv_sec > i64::MIN) && (tv_nsec < 0 && tv_nsec > -1_000_000_000) {
99+
(tv_sec - 1, tv_nsec + 1_000_000_000)
100+
} else {
101+
(tv_sec, tv_nsec)
102+
};
79103
assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64);
80104
// SAFETY: The assert above checks tv_nsec is within the valid range
81105
Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } }

‎src/librustdoc/clean/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,9 @@ impl Trait {
14551455
pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety {
14561456
tcx.trait_def(self.def_id).unsafety
14571457
}
1458+
pub(crate) fn is_object_safe(&self, tcx: TyCtxt<'_>) -> bool {
1459+
tcx.check_is_object_safe(self.def_id)
1460+
}
14581461
}
14591462

14601463
#[derive(Clone, Debug)]

‎src/librustdoc/html/markdown.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,6 +2024,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
20242024
map.insert("required-associated-consts".into(), 1);
20252025
map.insert("required-methods".into(), 1);
20262026
map.insert("provided-methods".into(), 1);
2027+
map.insert("object-safety".into(), 1);
20272028
map.insert("implementors".into(), 1);
20282029
map.insert("synthetic-implementors".into(), 1);
20292030
map.insert("implementations-list".into(), 1);

‎src/librustdoc/html/render/print_item.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,21 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
954954
let cloned_shared = Rc::clone(&cx.shared);
955955
let cache = &cloned_shared.cache;
956956
let mut extern_crates = FxHashSet::default();
957+
958+
if !t.is_object_safe(cx.tcx()) {
959+
write_small_section_header(
960+
w,
961+
"object-safety",
962+
"Object Safety",
963+
&format!(
964+
"<div class=\"object-safety-info\">This trait is <b>not</b> \
965+
<a href=\"{base}/reference/items/traits.html#object-safety\">\
966+
object safe</a>.</div>",
967+
base = crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL
968+
),
969+
);
970+
}
971+
957972
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
958973
// The DefId is for the first Type found with that name. The bool is
959974
// if any Types with the same name but different DefId have been found.

‎src/librustdoc/html/render/sidebar.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@ fn sidebar_trait<'a>(
218218
.map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items))
219219
.collect();
220220
sidebar_assoc_items(cx, it, &mut blocks);
221+
222+
if !t.is_object_safe(cx.tcx()) {
223+
blocks.push(LinkBlock::forced(
224+
Link::new("object-safety", "Object Safety"),
225+
"object-safety-note",
226+
));
227+
}
228+
221229
blocks.push(LinkBlock::forced(Link::new("implementors", "Implementors"), "impl"));
222230
if t.is_auto(cx.tcx()) {
223231
blocks.push(LinkBlock::forced(

‎tests/rustdoc/sidebar-items.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// @has - '//*[@class="sidebar-elems"]//section//a' 'Output'
1515
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-types"]' 'Provided Associated Types'
1616
// @has - '//*[@class="sidebar-elems"]//section//a' 'Extra'
17+
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#object-safety"]' 'Object Safety'
1718
pub trait Foo {
1819
const FOO: usize;
1920
const BAR: u32 = 0;
@@ -24,6 +25,12 @@ pub trait Foo {
2425
fn bar() -> Self::Output;
2526
}
2627

28+
// @has foo/trait.Safe.html
29+
// @!has - '//div[@class="sidebar-elems"]//h3/a[@href="#object-safety"]' ''
30+
pub trait Safe {
31+
fn access(&self);
32+
}
33+
2734
// @has foo/struct.Bar.html
2835
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
2936
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f'

‎tests/rustdoc/trait-object-safe.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![crate_name = "foo"]
2+
3+
// @has 'foo/trait.Unsafe.html'
4+
// @has - '//*[@class="object-safety-info"]' 'This trait is not object safe.'
5+
// @has - '//*[@id="object-safety"]' 'Object Safety'
6+
pub trait Unsafe {
7+
fn foo() -> Self;
8+
}
9+
10+
// @has 'foo/trait.Unsafe2.html'
11+
// @has - '//*[@class="object-safety-info"]' 'This trait is not object safe.'
12+
// @has - '//*[@id="object-safety"]' 'Object Safety'
13+
pub trait Unsafe2<T> {
14+
fn foo(i: T);
15+
}
16+
17+
// @has 'foo/trait.Safe.html'
18+
// @!has - '//*[@class="object-safety-info"]' ''
19+
// @!has - '//*[@id="object-safety"]' ''
20+
pub trait Safe {
21+
fn foo(&self);
22+
}
23+
24+
// @has 'foo/struct.Foo.html'
25+
// @!has - '//*[@class="object-safety-info"]' ''
26+
// @!has - '//*[@id="object-safety"]' ''
27+
pub struct Foo;
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// run-pass
2+
//! Sanity check Stable MIR Visitor
3+
4+
// ignore-stage1
5+
// ignore-cross-compile
6+
// ignore-remote
7+
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
8+
// edition: 2021
9+
10+
#![feature(rustc_private)]
11+
#![feature(assert_matches)]
12+
#![feature(control_flow_enum)]
13+
14+
extern crate rustc_middle;
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 std::collections::HashSet;
22+
use rustc_middle::ty::TyCtxt;
23+
use rustc_smir::rustc_internal;
24+
use stable_mir::*;
25+
use stable_mir::mir::MirVisitor;
26+
use std::io::Write;
27+
use std::ops::ControlFlow;
28+
29+
const CRATE_NAME: &str = "input";
30+
31+
fn test_visitor(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
32+
let main_fn = stable_mir::entry_fn();
33+
let main_body = main_fn.unwrap().body();
34+
let main_visitor = TestVisitor::collect(&main_body);
35+
assert!(main_visitor.ret_val.is_some());
36+
assert!(main_visitor.args.is_empty());
37+
assert!(main_visitor.tys.contains(&main_visitor.ret_val.unwrap().ty));
38+
assert!(!main_visitor.calls.is_empty());
39+
40+
let exit_fn = main_visitor.calls.last().unwrap();
41+
assert!(exit_fn.mangled_name().contains("exit_fn"), "Unexpected last function: {exit_fn:?}");
42+
43+
let exit_body = exit_fn.body();
44+
let exit_visitor = TestVisitor::collect(&exit_body);
45+
assert!(exit_visitor.ret_val.is_some());
46+
assert_eq!(exit_visitor.args.len(), 1);
47+
assert!(exit_visitor.tys.contains(&exit_visitor.ret_val.unwrap().ty));
48+
assert!(exit_visitor.tys.contains(&exit_visitor.args[0].ty));
49+
ControlFlow::Continue(())
50+
}
51+
52+
struct TestVisitor<'a> {
53+
pub body: &'a mir::Body,
54+
pub tys: HashSet<ty::Ty>,
55+
pub ret_val: Option<mir::LocalDecl>,
56+
pub args: Vec<mir::LocalDecl>,
57+
pub calls: Vec<mir::mono::Instance>
58+
}
59+
60+
impl<'a> TestVisitor<'a> {
61+
fn collect(body: &'a mir::Body) -> TestVisitor<'a> {
62+
let mut visitor = TestVisitor {
63+
body: &body,
64+
tys: Default::default(),
65+
ret_val: None,
66+
args: vec![],
67+
calls: vec![],
68+
};
69+
visitor.visit_body(&body);
70+
visitor
71+
}
72+
}
73+
74+
impl<'a> mir::MirVisitor for TestVisitor<'a> {
75+
fn visit_ty(&mut self, ty: &ty::Ty, _location: mir::visit::Location) {
76+
self.tys.insert(*ty);
77+
self.super_ty(ty)
78+
}
79+
80+
fn visit_ret_decl(&mut self, local: mir::Local, decl: &mir::LocalDecl) {
81+
assert!(local == mir::RETURN_LOCAL);
82+
assert!(self.ret_val.is_none());
83+
self.ret_val = Some(decl.clone());
84+
self.super_ret_decl(local, decl);
85+
}
86+
87+
fn visit_arg_decl(&mut self, local: mir::Local, decl: &mir::LocalDecl) {
88+
self.args.push(decl.clone());
89+
assert_eq!(local, self.args.len());
90+
self.super_arg_decl(local, decl);
91+
}
92+
93+
fn visit_terminator(&mut self, term: &mir::Terminator, location: mir::visit::Location) {
94+
if let mir::TerminatorKind::Call { func, .. } = &term.kind {
95+
let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).kind() else { unreachable!
96+
() };
97+
let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() };
98+
self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap());
99+
}
100+
self.super_terminator(term, location);
101+
}
102+
}
103+
104+
/// This test will generate and analyze a dummy crate using the stable mir.
105+
/// For that, it will first write the dummy crate into a file.
106+
/// Then it will create a `StableMir` using custom arguments and then
107+
/// it will run the compiler.
108+
fn main() {
109+
let path = "sim_visitor_input.rs";
110+
generate_input(&path).unwrap();
111+
let args = vec![
112+
"rustc".to_string(),
113+
"-Cpanic=abort".to_string(),
114+
"--crate-name".to_string(),
115+
CRATE_NAME.to_string(),
116+
path.to_string(),
117+
];
118+
run!(args, tcx, test_visitor(tcx)).unwrap();
119+
}
120+
121+
fn generate_input(path: &str) -> std::io::Result<()> {
122+
let mut file = std::fs::File::create(path)?;
123+
write!(
124+
file,
125+
r#"
126+
fn main() -> std::process::ExitCode {{
127+
let inputs = Inputs::new();
128+
let total = inputs.values.iter().sum();
129+
exit_fn(total)
130+
}}
131+
132+
fn exit_fn(code: u8) -> std::process::ExitCode {{
133+
std::process::ExitCode::from(code)
134+
}}
135+
136+
struct Inputs {{
137+
values: [u8; 3],
138+
}}
139+
140+
impl Inputs {{
141+
fn new() -> Inputs {{
142+
Inputs {{ values: [0, 1, 2] }}
143+
}}
144+
}}
145+
"#
146+
)?;
147+
Ok(())
148+
}

0 commit comments

Comments
 (0)
Please sign in to comment.