mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Implement BeginPanic for mir eval
This commit is contained in:
parent
a9140e197c
commit
6de838c255
4 changed files with 44 additions and 7 deletions
|
@ -27,6 +27,7 @@ pub trait TyExt {
|
||||||
fn is_scalar(&self) -> bool;
|
fn is_scalar(&self) -> bool;
|
||||||
fn is_floating_point(&self) -> bool;
|
fn is_floating_point(&self) -> bool;
|
||||||
fn is_never(&self) -> bool;
|
fn is_never(&self) -> bool;
|
||||||
|
fn is_str(&self) -> bool;
|
||||||
fn is_unknown(&self) -> bool;
|
fn is_unknown(&self) -> bool;
|
||||||
fn contains_unknown(&self) -> bool;
|
fn contains_unknown(&self) -> bool;
|
||||||
fn is_ty_var(&self) -> bool;
|
fn is_ty_var(&self) -> bool;
|
||||||
|
@ -87,6 +88,10 @@ impl TyExt for Ty {
|
||||||
matches!(self.kind(Interner), TyKind::Never)
|
matches!(self.kind(Interner), TyKind::Never)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_str(&self) -> bool {
|
||||||
|
matches!(self.kind(Interner), TyKind::Str)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_unknown(&self) -> bool {
|
fn is_unknown(&self) -> bool {
|
||||||
matches!(self.kind(Interner), TyKind::Error)
|
matches!(self.kind(Interner), TyKind::Error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1138,7 +1138,7 @@ impl Evaluator<'_> {
|
||||||
let mut ty = self.operand_ty(lhs, locals)?;
|
let mut ty = self.operand_ty(lhs, locals)?;
|
||||||
while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
|
while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
|
||||||
ty = z.clone();
|
ty = z.clone();
|
||||||
let size = if ty.kind(Interner) == &TyKind::Str {
|
let size = if ty.is_str() {
|
||||||
if *op != BinOp::Eq {
|
if *op != BinOp::Eq {
|
||||||
never!("Only eq is builtin for `str`");
|
never!("Only eq is builtin for `str`");
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,9 +132,7 @@ impl Evaluator<'_> {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
if let Some(it) = self.detect_lang_function(def) {
|
if let Some(it) = self.detect_lang_function(def) {
|
||||||
let arg_bytes =
|
let result = self.exec_lang_item(it, generic_args, args, locals, span)?;
|
||||||
args.iter().map(|it| Ok(it.get(self)?.to_owned())).collect::<Result<Vec<_>>>()?;
|
|
||||||
let result = self.exec_lang_item(it, generic_args, &arg_bytes, locals, span)?;
|
|
||||||
destination.write_from_bytes(self, &result)?;
|
destination.write_from_bytes(self, &result)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
@ -333,18 +331,52 @@ impl Evaluator<'_> {
|
||||||
&mut self,
|
&mut self,
|
||||||
it: LangItem,
|
it: LangItem,
|
||||||
generic_args: &Substitution,
|
generic_args: &Substitution,
|
||||||
args: &[Vec<u8>],
|
args: &[IntervalAndTy],
|
||||||
locals: &Locals,
|
locals: &Locals,
|
||||||
span: MirSpan,
|
span: MirSpan,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
use LangItem::*;
|
use LangItem::*;
|
||||||
let mut args = args.iter();
|
let mut args = args.iter();
|
||||||
match it {
|
match it {
|
||||||
BeginPanic => Err(MirEvalError::Panic("<unknown-panic-payload>".to_owned())),
|
BeginPanic => {
|
||||||
|
let mut arg = args
|
||||||
|
.next()
|
||||||
|
.ok_or(MirEvalError::InternalError(
|
||||||
|
"argument of BeginPanic is not provided".into(),
|
||||||
|
))?
|
||||||
|
.clone();
|
||||||
|
while let TyKind::Ref(_, _, ty) = arg.ty.kind(Interner) {
|
||||||
|
if ty.is_str() {
|
||||||
|
let (pointee, metadata) = arg.interval.get(self)?.split_at(self.ptr_size());
|
||||||
|
let len = from_bytes!(usize, metadata);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Err(MirEvalError::Panic(
|
||||||
|
std::str::from_utf8(
|
||||||
|
self.read_memory(Address::from_bytes(pointee)?, len)?,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.to_owned(),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let size = self.size_of_sized(&ty, locals, "begin panic arg")?;
|
||||||
|
let pointee = arg.interval.get(self)?;
|
||||||
|
arg = IntervalAndTy {
|
||||||
|
interval: Interval::new(Address::from_bytes(pointee)?, size),
|
||||||
|
ty: ty.clone(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(MirEvalError::Panic(format!(
|
||||||
|
"unknown-panic-payload: {:?}",
|
||||||
|
arg.ty.kind(Interner)
|
||||||
|
)))
|
||||||
|
}
|
||||||
SliceLen => {
|
SliceLen => {
|
||||||
let arg = args.next().ok_or(MirEvalError::InternalError(
|
let arg = args.next().ok_or(MirEvalError::InternalError(
|
||||||
"argument of <[T]>::len() is not provided".into(),
|
"argument of <[T]>::len() is not provided".into(),
|
||||||
))?;
|
))?;
|
||||||
|
let arg = arg.get(self)?;
|
||||||
let ptr_size = arg.len() / 2;
|
let ptr_size = arg.len() / 2;
|
||||||
Ok(arg[ptr_size..].into())
|
Ok(arg[ptr_size..].into())
|
||||||
}
|
}
|
||||||
|
@ -358,6 +390,7 @@ impl Evaluator<'_> {
|
||||||
let arg = args.next().ok_or(MirEvalError::InternalError(
|
let arg = args.next().ok_or(MirEvalError::InternalError(
|
||||||
"argument of drop_in_place is not provided".into(),
|
"argument of drop_in_place is not provided".into(),
|
||||||
))?;
|
))?;
|
||||||
|
let arg = arg.interval.get(self)?.to_owned();
|
||||||
self.run_drop_glue_deep(
|
self.run_drop_glue_deep(
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
locals,
|
locals,
|
||||||
|
|
|
@ -104,7 +104,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
panic!("a");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue