Skip to content

Commit c587071

Browse files
committed
Auto merge of #65227 - Centril:rollup-6qslas2, r=Centril
Rollup of 6 pull requests Successful merges: - #64656 (Implement (HashMap) Entry::insert as per #60142) - #64986 (Function pointers as const generic arguments) - #65037 (`#[track_caller]` feature gate (RFC 2091 1/N)) - #65166 (Suggest to add `move` keyword for generator capture) - #65175 (add more info in debug traces for gcu merging) - #65220 (Update LLVM for Emscripten exception handling support) Failed merges: r? @ghost
2 parents b5bd31e + 813785b commit c587071

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+923
-162
lines changed

Cargo.lock

+18-3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ dependencies = [
107107
"winapi 0.3.6",
108108
]
109109

110+
[[package]]
111+
name = "autocfg"
112+
version = "0.1.6"
113+
source = "registry+https://github.com/rust-lang/crates.io-index"
114+
checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
115+
110116
[[package]]
111117
name = "backtrace"
112118
version = "0.3.37"
@@ -1269,7 +1275,7 @@ version = "2.0.1"
12691275
source = "registry+https://github.com/rust-lang/crates.io-index"
12701276
checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
12711277
dependencies = [
1272-
"hashbrown",
1278+
"hashbrown 0.5.0",
12731279
"lazy_static 1.3.0",
12741280
"log",
12751281
"pest",
@@ -1286,10 +1292,19 @@ version = "0.5.0"
12861292
source = "registry+https://github.com/rust-lang/crates.io-index"
12871293
checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
12881294
dependencies = [
1295+
"serde",
1296+
]
1297+
1298+
[[package]]
1299+
name = "hashbrown"
1300+
version = "0.6.1"
1301+
source = "registry+https://github.com/rust-lang/crates.io-index"
1302+
checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a"
1303+
dependencies = [
1304+
"autocfg",
12891305
"compiler_builtins",
12901306
"rustc-std-workspace-alloc",
12911307
"rustc-std-workspace-core",
1292-
"serde",
12931308
]
12941309

12951310
[[package]]
@@ -4109,7 +4124,7 @@ dependencies = [
41094124
"core",
41104125
"dlmalloc",
41114126
"fortanix-sgx-abi",
4112-
"hashbrown",
4127+
"hashbrown 0.6.1",
41134128
"libc",
41144129
"panic_abort",
41154130
"panic_unwind",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `track_caller`
2+
3+
The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
4+
5+
------------------------

src/librustc/error_codes.rs

+20
Original file line numberDiff line numberDiff line change
@@ -2120,6 +2120,25 @@ These attributes are meant to only be used by the standard library and are
21202120
rejected in your own crates.
21212121
"##,
21222122

2123+
E0736: r##"
2124+
#[track_caller] and #[naked] cannot be applied to the same function.
2125+
2126+
Erroneous code example:
2127+
2128+
```compile_fail,E0736
2129+
#![feature(track_caller)]
2130+
2131+
#[naked]
2132+
#[track_caller]
2133+
fn foo() {}
2134+
```
2135+
2136+
This is primarily due to ABI incompatibilities between the two attributes.
2137+
See [RFC 2091] for details on this and other limitations.
2138+
2139+
[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
2140+
"##,
2141+
21232142
;
21242143
// E0006, // merged with E0005
21252144
// E0101, // replaced with E0282
@@ -2179,4 +2198,5 @@ rejected in your own crates.
21792198
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
21802199
E0727, // `async` generators are not yet supported
21812200
E0728, // `await` must be in an `async` function or block
2201+
E0739, // invalid track_caller application/syntax
21822202
}

src/librustc/hir/check_attr.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::ty::TyCtxt;
1111
use crate::ty::query::Providers;
1212

1313
use std::fmt::{self, Display};
14-
use syntax::symbol::sym;
14+
use syntax::{attr, symbol::sym};
1515
use syntax_pos::Span;
1616

1717
#[derive(Copy, Clone, PartialEq)]
@@ -103,6 +103,8 @@ impl CheckAttrVisitor<'tcx> {
103103
self.check_marker(attr, item, target)
104104
} else if attr.check_name(sym::target_feature) {
105105
self.check_target_feature(attr, item, target)
106+
} else if attr.check_name(sym::track_caller) {
107+
self.check_track_caller(attr, &item, target)
106108
} else {
107109
true
108110
};
@@ -135,6 +137,32 @@ impl CheckAttrVisitor<'tcx> {
135137
}
136138
}
137139

140+
/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
141+
fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
142+
if target != Target::Fn {
143+
struct_span_err!(
144+
self.tcx.sess,
145+
attr.span,
146+
E0739,
147+
"attribute should be applied to function"
148+
)
149+
.span_label(item.span, "not a function")
150+
.emit();
151+
false
152+
} else if attr::contains_name(&item.attrs, sym::naked) {
153+
struct_span_err!(
154+
self.tcx.sess,
155+
attr.span,
156+
E0736,
157+
"cannot use `#[track_caller]` with `#[naked]`",
158+
)
159+
.emit();
160+
false
161+
} else {
162+
true
163+
}
164+
}
165+
138166
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
139167
fn check_non_exhaustive(
140168
&self,

src/librustc/hir/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2734,7 +2734,9 @@ bitflags! {
27342734
const USED = 1 << 9;
27352735
/// #[ffi_returns_twice], indicates that an extern function can return
27362736
/// multiple times
2737-
const FFI_RETURNS_TWICE = 1 << 10;
2737+
const FFI_RETURNS_TWICE = 1 << 10;
2738+
/// #[track_caller]: allow access to the caller location
2739+
const TRACK_CALLER = 1 << 11;
27382740
}
27392741
}
27402742

src/librustc/mir/interpret/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,14 @@ impl<'tcx> AllocMap<'tcx> {
470470
}
471471
}
472472

473+
/// Panics if the `AllocId` does not refer to a function
474+
pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> {
475+
match self.get(id) {
476+
Some(GlobalAlloc::Function(instance)) => instance,
477+
_ => bug!("expected allocation ID {} to point to a function", id),
478+
}
479+
}
480+
473481
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
474482
/// call this function twice, even with the same `Allocation` will ICE the compiler.
475483
pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {

src/librustc/ty/print/pretty.rs

+106-111
Original file line numberDiff line numberDiff line change
@@ -863,125 +863,120 @@ pub trait PrettyPrinter<'tcx>:
863863
}
864864

865865
let u8 = self.tcx().types.u8;
866-
if let ty::FnDef(did, substs) = ct.ty.kind {
867-
p!(print_value_path(did, substs));
868-
return Ok(self);
869-
}
870-
if let ConstValue::Unevaluated(did, substs) = ct.val {
871-
match self.tcx().def_kind(did) {
872-
| Some(DefKind::Static)
873-
| Some(DefKind::Const)
874-
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
875-
_ => if did.is_local() {
876-
let span = self.tcx().def_span(did);
877-
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
878-
p!(write("{}", snip))
866+
867+
match (ct.val, &ct.ty.kind) {
868+
(_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
869+
(ConstValue::Unevaluated(did, substs), _) => {
870+
match self.tcx().def_kind(did) {
871+
| Some(DefKind::Static)
872+
| Some(DefKind::Const)
873+
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
874+
_ => if did.is_local() {
875+
let span = self.tcx().def_span(did);
876+
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
877+
p!(write("{}", snip))
878+
} else {
879+
p!(write("_: "), print(ct.ty))
880+
}
879881
} else {
880882
p!(write("_: "), print(ct.ty))
881-
}
883+
},
884+
}
885+
},
886+
(ConstValue::Infer(..), _) => p!(write("_: "), print(ct.ty)),
887+
(ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
888+
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) =>
889+
p!(write("{}", if data == 0 { "false" } else { "true" })),
890+
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) =>
891+
p!(write("{}f32", Single::from_bits(data))),
892+
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) =>
893+
p!(write("{}f64", Double::from_bits(data))),
894+
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => {
895+
let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size();
896+
let max = truncate(u128::max_value(), bit_size);
897+
898+
if data == max {
899+
p!(write("std::{}::MAX", ui))
882900
} else {
883-
p!(write("_: "), print(ct.ty))
884-
},
885-
}
886-
return Ok(self);
887-
}
888-
if let ConstValue::Infer(..) = ct.val {
889-
p!(write("_: "), print(ct.ty));
890-
return Ok(self);
891-
}
892-
if let ConstValue::Param(ParamConst { name, .. }) = ct.val {
893-
p!(write("{}", name));
894-
return Ok(self);
895-
}
896-
if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val {
897-
match ct.ty.kind {
898-
ty::Bool => {
899-
p!(write("{}", if data == 0 { "false" } else { "true" }));
900-
return Ok(self);
901-
},
902-
ty::Float(ast::FloatTy::F32) => {
903-
p!(write("{}f32", Single::from_bits(data)));
904-
return Ok(self);
905-
},
906-
ty::Float(ast::FloatTy::F64) => {
907-
p!(write("{}f64", Double::from_bits(data)));
908-
return Ok(self);
909-
},
910-
ty::Uint(ui) => {
911-
let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(ui)).size();
912-
let max = truncate(u128::max_value(), bit_size);
901+
p!(write("{}{}", data, ui))
902+
};
903+
},
904+
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {
905+
let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i))
906+
.size().bits() as u128;
907+
let min = 1u128 << (bit_size - 1);
908+
let max = min - 1;
909+
910+
let ty = self.tcx().lift(&ct.ty).unwrap();
911+
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
912+
.unwrap()
913+
.size;
914+
match data {
915+
d if d == min => p!(write("std::{}::MIN", i)),
916+
d if d == max => p!(write("std::{}::MAX", i)),
917+
_ => p!(write("{}{}", sign_extend(data, size) as i128, i))
918+
}
919+
},
920+
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) =>
921+
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())),
922+
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {
923+
let instance = {
924+
let alloc_map = self.tcx().alloc_map.lock();
925+
alloc_map.unwrap_fn(ptr.alloc_id)
926+
};
927+
p!(print_value_path(instance.def_id(), instance.substs));
928+
},
929+
_ => {
930+
let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
931+
let byte_str = match (ct.val, &ref_ty.kind) {
932+
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
933+
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
934+
Some(self.tcx()
935+
.alloc_map.lock()
936+
.unwrap_memory(ptr.alloc_id)
937+
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
938+
},
939+
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
940+
// The `inspect` here is okay since we checked the bounds, and there are
941+
// no relocations (we have an active slice reference here). We don't use
942+
// this result to affect interpreter execution.
943+
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
944+
},
945+
_ => None,
946+
};
913947

914-
if data == max {
915-
p!(write("std::{}::MAX", ui))
948+
if let Some(byte_str) = byte_str {
949+
p!(write("b\""));
950+
for &c in byte_str {
951+
for e in std::ascii::escape_default(c) {
952+
self.write_char(e as char)?;
953+
}
954+
}
955+
p!(write("\""));
956+
true
957+
} else if let (ConstValue::Slice { data, start, end }, ty::Str) =
958+
(ct.val, &ref_ty.kind)
959+
{
960+
// The `inspect` here is okay since we checked the bounds, and there are no
961+
// relocations (we have an active `str` reference here). We don't use this
962+
// result to affect interpreter execution.
963+
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
964+
let s = ::std::str::from_utf8(slice)
965+
.expect("non utf8 str from miri");
966+
p!(write("{:?}", s));
967+
true
916968
} else {
917-
p!(write("{}{}", data, ui))
918-
};
919-
return Ok(self);
920-
},
921-
ty::Int(i) =>{
922-
let bit_size = Integer::from_attr(&self.tcx(), SignedInt(i))
923-
.size().bits() as u128;
924-
let min = 1u128 << (bit_size - 1);
925-
let max = min - 1;
926-
927-
let ty = self.tcx().lift(&ct.ty).unwrap();
928-
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
929-
.unwrap()
930-
.size;
931-
match data {
932-
d if d == min => p!(write("std::{}::MIN", i)),
933-
d if d == max => p!(write("std::{}::MAX", i)),
934-
_ => p!(write("{}{}", sign_extend(data, size) as i128, i))
935-
}
936-
return Ok(self);
937-
},
938-
ty::Char => {
939-
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()));
940-
return Ok(self);
941-
}
942-
_ => {},
943-
}
944-
}
945-
if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
946-
let byte_str = match (ct.val, &ref_ty.kind) {
947-
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
948-
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
949-
Some(self.tcx()
950-
.alloc_map.lock()
951-
.unwrap_memory(ptr.alloc_id)
952-
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
953-
},
954-
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
955-
// The `inspect` here is okay since we checked the bounds, and there are no
956-
// relocations (we have an active slice reference here). We don't use this
957-
// result to affect interpreter execution.
958-
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
959-
},
960-
(ConstValue::Slice { data, start, end }, ty::Str) => {
961-
// The `inspect` here is okay since we checked the bounds, and there are no
962-
// relocations (we have an active `str` reference here). We don't use this
963-
// result to affect interpreter execution.
964-
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
965-
let s = ::std::str::from_utf8(slice)
966-
.expect("non utf8 str from miri");
967-
p!(write("{:?}", s));
968-
return Ok(self);
969-
},
970-
_ => None,
971-
};
972-
if let Some(byte_str) = byte_str {
973-
p!(write("b\""));
974-
for &c in byte_str {
975-
for e in std::ascii::escape_default(c) {
976-
self.write_char(e as char)?;
969+
false
977970
}
971+
} else {
972+
false
973+
};
974+
if !printed {
975+
// fallback
976+
p!(write("{:?} : ", ct.val), print(ct.ty))
978977
}
979-
p!(write("\""));
980-
return Ok(self);
981978
}
982-
}
983-
p!(write("{:?} : ", ct.val), print(ct.ty));
984-
979+
};
985980
Ok(self)
986981
}
987982
}

0 commit comments

Comments
 (0)