Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #65227

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
dd2356f
add testcase for generator move suggestion
csmoe Oct 6, 2019
50932ea
add more info in debug traces for gcu merging
andjo403 Oct 6, 2019
543449d
[RFC 2091] Add #[track_caller] attribute.
ayosec Jul 20, 2019
6c04c8e
track_caller run-pass test, lint cleanup, PR review.
anp Oct 3, 2019
43d4b70
track_caller feature gate starts in 1.40.0.
anp Oct 3, 2019
d931afe
Mark #![feature(track_caller)] as incomplete.
anp Oct 3, 2019
9900211
track_caller error numbers and text.
anp Oct 3, 2019
53096c5
track_caller tests account for incomplete feature warning.
anp Oct 3, 2019
8992c30
E0735 -> E0739
anp Oct 4, 2019
bdc4bd1
E073[6-8] include failing code examples.
anp Oct 4, 2019
130be6d
Expand E0738 to cover different cases.
anp Oct 4, 2019
f70ed29
Update expected error output.
anp Oct 5, 2019
190212c
Prohibit #[track_caller] within trait impls as well as decls.
anp Oct 5, 2019
c49966b
Clarify variable names when checking track_caller methods.
anp Oct 5, 2019
cca58d1
Fix syntax typo in error message.
anp Oct 7, 2019
d1d2565
suggest to add move keyword for generator
csmoe Oct 6, 2019
2afd277
Fix calling function pointer const parameters. Also fixes inference of
skinnyBat Oct 1, 2019
a59eb6d
Pretty print function pointer const values.
skinnyBat Oct 2, 2019
cf3b561
Gate use of raw and function pointers in const generics behind
skinnyBat Oct 4, 2019
43badf9
Substitute and normalize all types of consts within collect const
skinnyBat Oct 4, 2019
9677cbe
Refactor pretty print const to use a big match statement
skinnyBat Oct 4, 2019
50ea5f4
Fix reify_fn_ptr test as we now pretty print const function pointers.
skinnyBat Oct 5, 2019
16b7f44
Update feature gate error message
skinnyBat Oct 7, 2019
5986fe2
Update ui tests
skinnyBat Oct 8, 2019
2c81089
Update LLVM for Emscripten exception handling support
tlively Oct 8, 2019
bdcc21c
Implement (HashMap) Entry::insert as per #60142
passcod Sep 21, 2019
c1ef7d5
Rollup merge of #64656 - passcod:map-entry-insert, r=Amanieu
Centril Oct 9, 2019
6b1eab9
Rollup merge of #64986 - skinny121:fn-ptr-const-generics, r=varkor
Centril Oct 9, 2019
e261879
Rollup merge of #65037 - anp:track-caller, r=oli-obk
Centril Oct 9, 2019
ddcaded
Rollup merge of #65166 - csmoe:async-move, r=estebank
Centril Oct 9, 2019
db99e5a
Rollup merge of #65175 - andjo403:partitioning, r=zackmdavis
Centril Oct 9, 2019
813785b
Rollup merge of #65220 - tlively:update-llvm-for-emscripten-exception…
Centril Oct 9, 2019
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
21 changes: 18 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ dependencies = [
"winapi 0.3.6",
]

[[package]]
name = "autocfg"
version = "0.1.6"
source = "registry+https:/rust-lang/crates.io-index"
checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"

[[package]]
name = "backtrace"
version = "0.3.37"
Expand Down Expand Up @@ -1269,7 +1275,7 @@ version = "2.0.1"
source = "registry+https:/rust-lang/crates.io-index"
checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
dependencies = [
"hashbrown",
"hashbrown 0.5.0",
"lazy_static 1.3.0",
"log",
"pest",
Expand All @@ -1286,10 +1292,19 @@ version = "0.5.0"
source = "registry+https:/rust-lang/crates.io-index"
checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
dependencies = [
"serde",
]

[[package]]
name = "hashbrown"
version = "0.6.1"
source = "registry+https:/rust-lang/crates.io-index"
checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a"
dependencies = [
"autocfg",
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
"serde",
]

[[package]]
Expand Down Expand Up @@ -4109,7 +4124,7 @@ dependencies = [
"core",
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown",
"hashbrown 0.6.1",
"libc",
"panic_abort",
"panic_unwind",
Expand Down
5 changes: 5 additions & 0 deletions src/doc/unstable-book/src/language-features/track-caller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `track_caller`

The tracking issue for this feature is: [#47809](https:/rust-lang/rust/issues/47809).

------------------------
20 changes: 20 additions & 0 deletions src/librustc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2120,6 +2120,25 @@ These attributes are meant to only be used by the standard library and are
rejected in your own crates.
"##,

E0736: r##"
#[track_caller] and #[naked] cannot be applied to the same function.

Erroneous code example:

```compile_fail,E0736
#![feature(track_caller)]

#[naked]
#[track_caller]
fn foo() {}
```

This is primarily due to ABI incompatibilities between the two attributes.
See [RFC 2091] for details on this and other limitations.

[RFC 2091]: https:/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
"##,

;
// E0006, // merged with E0005
// E0101, // replaced with E0282
Expand Down Expand Up @@ -2179,4 +2198,5 @@ rejected in your own crates.
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
E0727, // `async` generators are not yet supported
E0728, // `await` must be in an `async` function or block
E0739, // invalid track_caller application/syntax
}
30 changes: 29 additions & 1 deletion src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::ty::TyCtxt;
use crate::ty::query::Providers;

use std::fmt::{self, Display};
use syntax::symbol::sym;
use syntax::{attr, symbol::sym};
use syntax_pos::Span;

#[derive(Copy, Clone, PartialEq)]
Expand Down Expand Up @@ -103,6 +103,8 @@ impl CheckAttrVisitor<'tcx> {
self.check_marker(attr, item, target)
} else if attr.check_name(sym::target_feature) {
self.check_target_feature(attr, item, target)
} else if attr.check_name(sym::track_caller) {
self.check_track_caller(attr, &item, target)
} else {
true
};
Expand Down Expand Up @@ -135,6 +137,32 @@ impl CheckAttrVisitor<'tcx> {
}
}

/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
if target != Target::Fn {
struct_span_err!(
self.tcx.sess,
attr.span,
E0739,
"attribute should be applied to function"
)
.span_label(item.span, "not a function")
.emit();
false
} else if attr::contains_name(&item.attrs, sym::naked) {
struct_span_err!(
self.tcx.sess,
attr.span,
E0736,
"cannot use `#[track_caller]` with `#[naked]`",
)
.emit();
false
} else {
true
}
}

/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
fn check_non_exhaustive(
&self,
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2734,7 +2734,9 @@ bitflags! {
const USED = 1 << 9;
/// #[ffi_returns_twice], indicates that an extern function can return
/// multiple times
const FFI_RETURNS_TWICE = 1 << 10;
const FFI_RETURNS_TWICE = 1 << 10;
/// #[track_caller]: allow access to the caller location
const TRACK_CALLER = 1 << 11;
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,14 @@ impl<'tcx> AllocMap<'tcx> {
}
}

/// Panics if the `AllocId` does not refer to a function
pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> {
match self.get(id) {
Some(GlobalAlloc::Function(instance)) => instance,
_ => bug!("expected allocation ID {} to point to a function", id),
}
}

/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
/// call this function twice, even with the same `Allocation` will ICE the compiler.
pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
Expand Down
217 changes: 106 additions & 111 deletions src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,125 +863,120 @@ pub trait PrettyPrinter<'tcx>:
}

let u8 = self.tcx().types.u8;
if let ty::FnDef(did, substs) = ct.ty.kind {
p!(print_value_path(did, substs));
return Ok(self);
}
if let ConstValue::Unevaluated(did, substs) = ct.val {
match self.tcx().def_kind(did) {
| Some(DefKind::Static)
| Some(DefKind::Const)
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
_ => if did.is_local() {
let span = self.tcx().def_span(did);
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
p!(write("{}", snip))

match (ct.val, &ct.ty.kind) {
(_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
(ConstValue::Unevaluated(did, substs), _) => {
match self.tcx().def_kind(did) {
| Some(DefKind::Static)
| Some(DefKind::Const)
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
_ => if did.is_local() {
let span = self.tcx().def_span(did);
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
p!(write("{}", snip))
} else {
p!(write("_: "), print(ct.ty))
}
} else {
p!(write("_: "), print(ct.ty))
}
},
}
},
(ConstValue::Infer(..), _) => p!(write("_: "), print(ct.ty)),
(ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) =>
p!(write("{}", if data == 0 { "false" } else { "true" })),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) =>
p!(write("{}f32", Single::from_bits(data))),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) =>
p!(write("{}f64", Double::from_bits(data))),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => {
let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size();
let max = truncate(u128::max_value(), bit_size);

if data == max {
p!(write("std::{}::MAX", ui))
} else {
p!(write("_: "), print(ct.ty))
},
}
return Ok(self);
}
if let ConstValue::Infer(..) = ct.val {
p!(write("_: "), print(ct.ty));
return Ok(self);
}
if let ConstValue::Param(ParamConst { name, .. }) = ct.val {
p!(write("{}", name));
return Ok(self);
}
if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val {
match ct.ty.kind {
ty::Bool => {
p!(write("{}", if data == 0 { "false" } else { "true" }));
return Ok(self);
},
ty::Float(ast::FloatTy::F32) => {
p!(write("{}f32", Single::from_bits(data)));
return Ok(self);
},
ty::Float(ast::FloatTy::F64) => {
p!(write("{}f64", Double::from_bits(data)));
return Ok(self);
},
ty::Uint(ui) => {
let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(ui)).size();
let max = truncate(u128::max_value(), bit_size);
p!(write("{}{}", data, ui))
};
},
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {
let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i))
.size().bits() as u128;
let min = 1u128 << (bit_size - 1);
let max = min - 1;

let ty = self.tcx().lift(&ct.ty).unwrap();
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
.unwrap()
.size;
match data {
d if d == min => p!(write("std::{}::MIN", i)),
d if d == max => p!(write("std::{}::MAX", i)),
_ => p!(write("{}{}", sign_extend(data, size) as i128, i))
}
},
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) =>
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())),
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {
let instance = {
let alloc_map = self.tcx().alloc_map.lock();
alloc_map.unwrap_fn(ptr.alloc_id)
};
p!(print_value_path(instance.def_id(), instance.substs));
},
_ => {
let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
let byte_str = match (ct.val, &ref_ty.kind) {
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
Some(self.tcx()
.alloc_map.lock()
.unwrap_memory(ptr.alloc_id)
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
},
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
// The `inspect` here is okay since we checked the bounds, and there are
// no relocations (we have an active slice reference here). We don't use
// this result to affect interpreter execution.
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
},
_ => None,
};

if data == max {
p!(write("std::{}::MAX", ui))
if let Some(byte_str) = byte_str {
p!(write("b\""));
for &c in byte_str {
for e in std::ascii::escape_default(c) {
self.write_char(e as char)?;
}
}
p!(write("\""));
true
} else if let (ConstValue::Slice { data, start, end }, ty::Str) =
(ct.val, &ref_ty.kind)
{
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
let s = ::std::str::from_utf8(slice)
.expect("non utf8 str from miri");
p!(write("{:?}", s));
true
} else {
p!(write("{}{}", data, ui))
};
return Ok(self);
},
ty::Int(i) =>{
let bit_size = Integer::from_attr(&self.tcx(), SignedInt(i))
.size().bits() as u128;
let min = 1u128 << (bit_size - 1);
let max = min - 1;

let ty = self.tcx().lift(&ct.ty).unwrap();
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
.unwrap()
.size;
match data {
d if d == min => p!(write("std::{}::MIN", i)),
d if d == max => p!(write("std::{}::MAX", i)),
_ => p!(write("{}{}", sign_extend(data, size) as i128, i))
}
return Ok(self);
},
ty::Char => {
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()));
return Ok(self);
}
_ => {},
}
}
if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
let byte_str = match (ct.val, &ref_ty.kind) {
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
Some(self.tcx()
.alloc_map.lock()
.unwrap_memory(ptr.alloc_id)
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
},
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active slice reference here). We don't use this
// result to affect interpreter execution.
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
},
(ConstValue::Slice { data, start, end }, ty::Str) => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
let s = ::std::str::from_utf8(slice)
.expect("non utf8 str from miri");
p!(write("{:?}", s));
return Ok(self);
},
_ => None,
};
if let Some(byte_str) = byte_str {
p!(write("b\""));
for &c in byte_str {
for e in std::ascii::escape_default(c) {
self.write_char(e as char)?;
false
}
} else {
false
};
if !printed {
// fallback
p!(write("{:?} : ", ct.val), print(ct.ty))
}
p!(write("\""));
return Ok(self);
}
}
p!(write("{:?} : ", ct.val), print(ct.ty));

};
Ok(self)
}
}
Expand Down
Loading