Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ generic std gap is planned here even when moq never calls it.
- [Fresh writes beside a zipped iterator that points at a part](/quest/m3/ts-fresh-shapes.md) - zipping slots with a `Vec<[T; N]>`, `vec![row; n]`, or `copied` of what the slot holds translates
- [Python's wake on the loop's own thread](/quest/m3/ffi-python-wake.md) - a wake on the event loop's thread resumes the future with no socket pair
- [Python's call cost](/quest/m3/ffi-python-calls.md) - a call on an object costs what BoltFFI's does, or the gap is explained
- [A name or an operator argument at its own Rust span](/quest/m3/ts-argument-spans.md) - a `tsc` error on a plain-name or operator argument names that argument's Rust, not the method it is passed to
- [A panic's Location](/quest/m3/ts-panic-location.md) - `Location::caller` and `#[track_caller]` translate with native Rust's locations
- [A panic hook](/quest/m3/ts-panic-hook.md) - `set_hook`, `take_hook`, and `PanicHookInfo` translate, every panic running the hook
- [A string Cow's variant](/quest/m3/ts-cow-str-variant.md) - matching a `Cow<str>`'s `Borrowed` or `Owned`, and `to_mut`'s change of it, translate as std's
22 changes: 0 additions & 22 deletions quest/m3/ts-argument-spans.md

This file was deleted.

2 changes: 1 addition & 1 deletion ts/fixtures/reject/spans.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Rust that translates, which the stand-in `tsc` the test puts on `PATH` fails at each
# `return` and each argument: `spans.txt` holds where each is reported.
package = "reject-fixture"
roots = ["spans::tail", "spans::early", "spans::method", "spans::chained"]
roots = ["spans::tail", "spans::early", "spans::method", "spans::chained", "spans::operators"]
22 changes: 14 additions & 8 deletions ts/fixtures/reject/spans.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
fixtures/reject/src/spans.rs:chained+1:2: spans.ts:23:2 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:chained+1:2: spans.ts:23:68 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, v
fixtures/reject/src/spans.rs:chained+1:4: spans.ts:23:55 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.iterSlice(v)
fixtures/reject/src/spans.rs:chained+1:4: spans.ts:23:68 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, v
fixtures/reject/src/spans.rs:chained+1:11: spans.ts:23:44 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.iterMap(rt.iterSlice(v), (x: rt.u32): rt.u32 => {
fixtures/reject/src/spans.rs:chained+1:11: spans.ts:23:72 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, (x: rt.u32): rt.u32 => {
fixtures/reject/src/spans.rs:chained+1:19: spans.ts:24:29 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, x
fixtures/reject/src/spans.rs:chained+1:19: spans.ts:24:3 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:chained+1:21: spans.ts:24:29 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, x
fixtures/reject/src/spans.rs:chained+1:38: spans.ts:23:33 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.iterMax(rt.iterMap(rt.iterSlice(v), (x: rt.u32): rt.u32 => {
fixtures/reject/src/spans.rs:chained+1:38: spans.ts:25:6 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.lt
fixtures/reject/src/spans.rs:chained+1:44: spans.ts:25:14 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 0
fixtures/reject/src/spans.rs:early+2:10: spans.ts:15:2 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:early+2:12: spans.ts:15:26 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:early+2:10: spans.ts:15:26 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:early+2:12: spans.ts:15:29 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 2
fixtures/reject/src/spans.rs:early+2:12: spans.ts:15:32 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 32
fixtures/reject/src/spans.rs:early+2:12: spans.ts:15:36 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, false
fixtures/reject/src/spans.rs:early+4:2: spans.ts:13:26 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:early+4:2: spans.ts:13:3 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:early+4:4: spans.ts:13:26 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:early+4:4: spans.ts:13:29 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 32
fixtures/reject/src/spans.rs:early+4:4: spans.ts:13:33 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, false
fixtures/reject/src/spans.rs:impl Meter+2:3: spans.Meter.ts:10:19 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, self.reads[rt.idx(self.reads, at)]
Expand All @@ -23,15 +23,21 @@ fixtures/reject/src/spans.rs:impl Meter+2:3: spans.Meter.ts:10:37 doesn't type-c
fixtures/reject/src/spans.rs:impl Meter+2:3: spans.Meter.ts:10:49 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, at
fixtures/reject/src/spans.rs:impl Meter+2:3: spans.Meter.ts:10:55 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, by
fixtures/reject/src/spans.rs:method+1:2: spans.ts:19:2 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:method+1:4: spans.ts:19:22 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, m
fixtures/reject/src/spans.rs:method+1:2: spans.ts:19:22 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, m
fixtures/reject/src/spans.rs:method+1:11: spans.ts:19:43 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:method+1:13: spans.ts:19:25 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.u32WrappingAdd(a, 1)
fixtures/reject/src/spans.rs:method+1:13: spans.ts:19:43 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:method+1:13: spans.ts:19:46 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 1
fixtures/reject/src/spans.rs:method+1:30: spans.ts:19:50 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.usizeSub(m.reads.length, 1)
fixtures/reject/src/spans.rs:method+1:30: spans.ts:19:78 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 1
fixtures/reject/src/spans.rs:method+1:38: spans.ts:19:62 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, m.reads.length
fixtures/reject/src/spans.rs:operators+1:2: spans.ts:29:2 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:operators+1:2: spans.ts:29:22 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, m
fixtures/reject/src/spans.rs:operators+1:11: spans.ts:29:25 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, (a ^ 7) >>> 0
fixtures/reject/src/spans.rs:operators+1:18: spans.ts:29:40 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.usizeDiv(at, 2)
fixtures/reject/src/spans.rs:operators+1:18: spans.ts:29:52 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, at
fixtures/reject/src/spans.rs:operators+1:18: spans.ts:29:56 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, 2
fixtures/reject/src/spans.rs:tail+2:2: spans.ts:8:2 doesn't type-check, which is a bug in rust2-ts: error TS2322: a return
fixtures/reject/src/spans.rs:tail+2:2: spans.ts:8:37 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, (a ^ b) >>> 0
fixtures/reject/src/spans.rs:tail+2:2: spans.ts:8:56 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, b
fixtures/reject/src/spans.rs:tail+2:4: spans.ts:8:19 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, rt.u32WrappingMul((a ^ b) >>> 0, a)
fixtures/reject/src/spans.rs:tail+2:4: spans.ts:8:37 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, (a ^ b) >>> 0
fixtures/reject/src/spans.rs:tail+2:4: spans.ts:8:52 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
fixtures/reject/src/spans.rs:tail+2:17: spans.ts:8:52 doesn't type-check, which is a bug in rust2-ts: error TS2345: an argument, a
7 changes: 6 additions & 1 deletion ts/fixtures/reject/src/spans.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Rust that translates, for the stand-in `tsc` of `spans.toml`, which fails each `return`
//! and each argument, to be reported at the Rust each comes from.
//! and each argument, to be reported at the Rust each comes from: a call, a name, or an
//! operator.

pub struct Meter {
pub reads: Vec<u32>,
Expand Down Expand Up @@ -30,3 +31,7 @@ pub fn method(m: &Meter, a: u32) -> u32 {
pub fn chained(v: &[u32]) -> u32 {
v.iter().map(|x| x.leading_zeros()).max().unwrap_or(0)
}

pub fn operators(m: &Meter, a: u32, at: usize) -> u32 {
m.scaled(a ^ 7, at / 2)
}
60 changes: 59 additions & 1 deletion ts/src/lower/mir/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::lower::fmt::{self, Piece};
use crate::lower::lend::{self, Plan};
use crate::lower::library::{self, Flow, Std};
use crate::lower::num::Int;
use crate::ts::{Expr, Stmt, StmtKind};
use crate::ts::{self, Expr, Stmt, StmtKind};

/// What a `&mut` borrows: its path, and the place a store through the reference writes,
/// unless the reference is refused.
Expand All @@ -30,6 +30,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
out: &mut Vec<Stmt>,
) {
let tcx = self.tcx;
self.arguments.clear();
if self.forwards(dest) {
self.forward_call(args, span, out);
return;
Expand Down Expand Up @@ -134,6 +135,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
Some(local) if self.stepped.contains(&local) => self.stepped_make(value, span),
_ => value,
};
let value = self.locate_arguments(value);
let value = match self.b.t.loc(span) {
Some(loc) if effect => Expr::Located(loc, Box::new(value)),
_ => value,
Expand Down Expand Up @@ -214,11 +216,26 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
}
_ => value,
});
if arg.node.place().is_some()
&& let Some(value) = values.last().filter(|v| !matches!(v, Expr::Located(..)))
&& let Some(loc) = self.b.t.loc(arg.span)
{
self.arguments.push((value.clone(), loc));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recordings made here can also be dropped silently on a few flows, worth knowing even though each falls back to the whole call's span exactly as before this PR: intercept's DerefMut::deref_mut alias-slot arm records then returns Some(None) early, so that nested call's args never reach a locate_arguments; lend::give rewraps values[i] after recording so equality fails; and slotted_raw applies Expr::typed after recording, which strips an As(Str|Array|Object) wrapper. No wrong location is possible on any of these, map rows only, and all predate this PR's behavior for such args, so nothing needs to change.

}
}
self.into_frozen = saved;
values
}

/// `call` with each argument [`Self::operands`] read from a place at that argument's
/// own Rust. Std's mappings match the arguments' shapes, so they are given them bare,
/// and each is located where it appears as an argument of what they made.
pub(super) fn locate_arguments(&mut self, mut call: Expr) -> Expr {
let mut arguments = std::mem::take(&mut self.arguments);
locate(&mut call, &mut arguments);
call
}

/// An argument, which the callee copies if it changes it in place.
fn operand_frozen(&mut self, op: &Operand<'tcx>, span: Span, out: &mut Vec<Stmt>) -> Expr {
match op {
Expand Down Expand Up @@ -2085,3 +2102,44 @@ fn assignable(e: &Expr) -> bool {
e => e.is_path(),
}
}

/// Locate each of `arguments` at the first argument of a call or `new` in `e` it is, and
/// drop it from the list.
fn locate(e: &mut Expr, arguments: &mut Vec<(Expr, ts::Loc)>) {
if arguments.is_empty() {
return;
}
match e {
Expr::Call(callee, args) | Expr::New(callee, args) => {
locate(callee, arguments);
for arg in args {
match arguments.iter().position(|(value, _)| value == arg) {
Some(i) => {
let (_, loc) = arguments.remove(i);
*arg = Expr::Located(loc, Box::new(std::mem::replace(arg, Expr::undefined())));
}
None => locate(arg, arguments),
}
}
}
Expr::Member(e, _)
| Expr::Unary(_, e)
| Expr::Postfix(e, _)
| Expr::As(e, _)
| Expr::Instantiate(e, _)
| Expr::Lambda(_, e)
| Expr::Located(_, e) => locate(e, arguments),
Expr::Index(a, b) | Expr::Binary(a, _, b) | Expr::Assign(a, b) => {
locate(a, arguments);
locate(b, arguments);
}
Expr::Cond(a, b, c) => {
locate(a, arguments);
locate(b, arguments);
locate(c, arguments);
}
Expr::Array(es) => es.iter_mut().for_each(|e| locate(e, arguments)),
Expr::Object(props) => props.iter_mut().for_each(|(_, e)| locate(e, arguments)),
_ => {}
}
}
4 changes: 4 additions & 0 deletions ts/src/lower/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,9 @@ pub struct Fx<'m, 'b, 'a, 'tcx> {
redirect: FxHashMap<BasicBlock, BasicBlock>,
/// Whether the operands lowered now go to a local nothing changes in place.
into_frozen: bool,
/// Each argument read from a place for the call being lowered, and its Rust, which
/// [`Self::locate_arguments`] locates in the call once std's mappings made it.
arguments: Vec<(Expr, ts::Loc)>,
/// Whether the value held back next is copied unless it folds into an argument.
copy_on_flush: bool,
/// Whether a copy lowered now shares what it copies, whatever it reads from.
Expand Down Expand Up @@ -499,6 +502,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
rereadable_parts: None,
redirect: FxHashMap::default(),
into_frozen: false,
arguments: Vec::new(),
copy_on_flush: false,
force_share: false,
arg_use: IndexVec::from_elem_n(false, n),
Expand Down
1 change: 1 addition & 0 deletions ts/src/lower/mir/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1921,6 +1921,7 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> {
let values = values.into_iter().map(Expr::typed).collect();
let mut pre = Vec::new();
let call = self.b.direct_call(instance, values, span, &mut pre);
let call = self.locate_arguments(call);
self.emit(pre, false, out);
match self.b.t.loc(span) {
Some(loc) => Expr::Located(loc, Box::new(call)),
Expand Down