From 3a4f45d728014ef419aa210c9581c31b6b5be28d Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 08:25:41 -0700 Subject: [PATCH 1/6] core::panic::Location is a lang item. For #[track_caller], passing Location as an implicit argument makes it effectively part of the ABI, and type lookup for it must be done for many functions without imports in the file or modifications to the prelude. --- src/libcore/panic.rs | 1 + src/librustc/middle/lang_items.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 989fc96732a5a..9428ff3ef15c4 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -162,6 +162,7 @@ impl fmt::Display for PanicInfo<'_> { /// /// panic!("Normal panic"); /// ``` +#[cfg_attr(not(bootstrap), lang = "panic_location")] #[derive(Debug)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index cab929389d6a4..a17b5a115b86b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -366,6 +366,7 @@ language_item_table! { PanicFnLangItem, "panic", panic_fn, Target::Fn; PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn; PanicInfoLangItem, "panic_info", panic_info, Target::Struct; + PanicLocationLangItem, "panic_location", panic_location, Target::Struct; PanicImplLangItem, "panic_impl", panic_impl, Target::Fn; // Libstd panic entry point. Necessary for const eval to be able to catch it BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn; From ba3b6edfaaf8a0f95988cb9362b1fa2a0e256b2b Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 20:13:38 -0700 Subject: [PATCH 2/6] Add implicit argument to MIR of #[track_caller] functions. --- src/librustc_mir/build/mod.rs | 23 ++++++++++++++++++- src/test/ui/rfc-2091-track-caller/pass.rs | 9 -------- src/test/ui/rfc-2091-track-caller/pass.stderr | 8 ------- .../ui/rfc-2091-track-caller/should-pass.rs | 12 ++++++++++ .../rfc-2091-track-caller/should-pass.stderr | 21 +++++++++++++++++ 5 files changed, 55 insertions(+), 18 deletions(-) delete mode 100644 src/test/ui/rfc-2091-track-caller/pass.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/pass.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/should-pass.rs create mode 100644 src/test/ui/rfc-2091-track-caller/should-pass.stderr diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index ffb70180bbb4b..e5072fc2c1db9 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -89,6 +89,25 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { _ => None, }; + // if this fn has #[track_caller], it will receive an implicit argument with a location + let has_track_caller = tcx.codegen_fn_attrs(def_id).flags + .contains(hir::CodegenFnAttrFlags::TRACK_CALLER); + let location_argument = if has_track_caller { + #[cfg(not(bootstrap))] + { + use rustc::middle::lang_items::PanicLocationLangItem; + let panic_loc_item = tcx.require_lang_item(PanicLocationLangItem, None); + let panic_loc_ty = tcx.type_of(panic_loc_item); + Some(ArgInfo(panic_loc_ty, None, None, None)) + } + #[cfg(bootstrap)] + { + bug!("#[track_caller] can't be used during a bootstrap build (yet)."); + } + } else { + None + }; + let safety = match fn_sig.unsafety { hir::Unsafety::Normal => Safety::Safe, hir::Unsafety::Unsafe => Safety::FnUnsafe, @@ -141,7 +160,9 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { ArgInfo(ty, opt_ty_info, Some(&arg), self_arg) }); - let arguments = implicit_argument.into_iter().chain(explicit_arguments); + let arguments = implicit_argument.into_iter() + .chain(location_argument) + .chain(explicit_arguments); let (yield_ty, return_ty) = if body.generator_kind.is_some() { let gen_sig = match ty.kind { diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs deleted file mode 100644 index f2c3f0dc59e01..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/pass.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller] -fn f() {} - -fn main() { - f(); -} diff --git a/src/test/ui/rfc-2091-track-caller/pass.stderr b/src/test/ui/rfc-2091-track-caller/pass.stderr deleted file mode 100644 index b1fd23a6a9ddb..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/pass.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/pass.rs:2:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/rfc-2091-track-caller/should-pass.rs b/src/test/ui/rfc-2091-track-caller/should-pass.rs new file mode 100644 index 0000000000000..6faeadacb6936 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/should-pass.rs @@ -0,0 +1,12 @@ +// failure-status: 101 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" + +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete + +#[track_caller] +fn f() {} + +fn main() { + f(); +} diff --git a/src/test/ui/rfc-2091-track-caller/should-pass.stderr b/src/test/ui/rfc-2091-track-caller/should-pass.stderr new file mode 100644 index 0000000000000..1160ddc890ee2 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/should-pass.stderr @@ -0,0 +1,21 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/should-pass.rs:5:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +thread 'rustc' panicked at 'index out of bounds: the len is 0 but the index is 0', $SRC_DIR/libcore/slice/mod.rs:LL:COL +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc VERSION running on TARGET + +note: compiler flags: FLAGS + From 9961fa6eccccdc99ada45878e1e538f35365da89 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 22:38:06 -0700 Subject: [PATCH 3/6] ty::Instance::fn_sig inserts caller location arg. --- src/librustc/ty/instance.rs | 19 +++++++++++++++++++ .../rfc-2091-track-caller/should-pass.stderr | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 5139c8085a583..a2b2848b256dc 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -121,6 +121,25 @@ impl<'tcx> Instance<'tcx> { fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); fn_sig }); + } else if let InstanceDef::ReifyShim(..) = self.def { + // Modify fn(...) to fn(_location: &core::panic::Location, ...) + #[cfg(not(bootstrap))] + { + use rustc::middle::lang_items::PanicLocationLangItem; + let panic_loc_item = tcx.require_lang_item(PanicLocationLangItem, None); + let panic_loc_ty = tcx.type_of(panic_loc_item); + + fn_sig = fn_sig.map_bound(|mut fn_sig| { + let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); + inputs_and_output.insert(0, panic_loc_ty); + fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + fn_sig + }); + } + #[cfg(bootstrap)] + { + bug!("#[track_caller] isn't supported during bootstrap (yet)."); + } } fn_sig } diff --git a/src/test/ui/rfc-2091-track-caller/should-pass.stderr b/src/test/ui/rfc-2091-track-caller/should-pass.stderr index 1160ddc890ee2..3cc441fd2487d 100644 --- a/src/test/ui/rfc-2091-track-caller/should-pass.stderr +++ b/src/test/ui/rfc-2091-track-caller/should-pass.stderr @@ -6,7 +6,7 @@ LL | #![feature(track_caller)] | = note: `#[warn(incomplete_features)]` on by default -thread 'rustc' panicked at 'index out of bounds: the len is 0 but the index is 0', $SRC_DIR/libcore/slice/mod.rs:LL:COL +thread 'rustc' panicked at 'assertion failed: !value.needs_subst()', src/librustc/traits/query/normalize_erasing_regions.rs:59:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic From 77784dec577917879203eb6735b26af378dbc94f Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 10 Oct 2019 21:16:01 -0700 Subject: [PATCH 4/6] Consolidate type generation for #[track_caller]. --- src/librustc/ty/instance.rs | 44 +++++++++++++++++++++-------------- src/librustc_mir/build/mod.rs | 32 ++++++++++--------------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index a2b2848b256dc..1b2cb0faa0fe9 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -123,26 +123,36 @@ impl<'tcx> Instance<'tcx> { }); } else if let InstanceDef::ReifyShim(..) = self.def { // Modify fn(...) to fn(_location: &core::panic::Location, ...) - #[cfg(not(bootstrap))] - { - use rustc::middle::lang_items::PanicLocationLangItem; - let panic_loc_item = tcx.require_lang_item(PanicLocationLangItem, None); - let panic_loc_ty = tcx.type_of(panic_loc_item); - - fn_sig = fn_sig.map_bound(|mut fn_sig| { - let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); - inputs_and_output.insert(0, panic_loc_ty); - fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); - fn_sig - }); - } - #[cfg(bootstrap)] - { - bug!("#[track_caller] isn't supported during bootstrap (yet)."); - } + fn_sig = fn_sig.map_bound(|mut fn_sig| { + let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); + inputs_and_output.insert(0, Self::track_caller_ty(tcx)); + fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + fn_sig + }); } fn_sig } + + /// Returns `&'static core::panic::Location`, for args of functions with #[track_caller]. + pub fn track_caller_ty(_tcx: TyCtxt<'_>) -> Ty<'_> { + #[cfg(bootstrap)] + { bug!("#[track_caller] isn't supported during bootstrap (yet)."); } + + #[cfg(not(bootstrap))] + { + use crate::hir::Mutability; + use rustc::middle::lang_items::PanicLocationLangItem; + + let panic_loc_item = _tcx.require_lang_item(PanicLocationLangItem, None); + _tcx.mk_ref( + _tcx.mk_region(ty::RegionKind::ReStatic), + ty::TypeAndMut { + mutbl: Mutability::MutImmutable, + ty: _tcx.type_of(panic_loc_item), + }, + ) + } + } } impl<'tcx> InstanceDef<'tcx> { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index e5072fc2c1db9..8654da5f8c946 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -89,25 +89,6 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { _ => None, }; - // if this fn has #[track_caller], it will receive an implicit argument with a location - let has_track_caller = tcx.codegen_fn_attrs(def_id).flags - .contains(hir::CodegenFnAttrFlags::TRACK_CALLER); - let location_argument = if has_track_caller { - #[cfg(not(bootstrap))] - { - use rustc::middle::lang_items::PanicLocationLangItem; - let panic_loc_item = tcx.require_lang_item(PanicLocationLangItem, None); - let panic_loc_ty = tcx.type_of(panic_loc_item); - Some(ArgInfo(panic_loc_ty, None, None, None)) - } - #[cfg(bootstrap)] - { - bug!("#[track_caller] can't be used during a bootstrap build (yet)."); - } - } else { - None - }; - let safety = match fn_sig.unsafety { hir::Unsafety::Normal => Safety::Safe, hir::Unsafety::Unsafe => Safety::FnUnsafe, @@ -161,7 +142,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { }); let arguments = implicit_argument.into_iter() - .chain(location_argument) + .chain(track_caller_argument(tcx, def_id)) .chain(explicit_arguments); let (yield_ty, return_ty) = if body.generator_kind.is_some() { @@ -206,6 +187,17 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { }) } +/// Returns the appropriate `ArgInfo` if the provided function has #[track_caller]. +fn track_caller_argument(tcx: TyCtxt<'_>, fn_def_id: DefId) -> Option> { + let codegen_flags = tcx.codegen_fn_attrs(fn_def_id).flags; + let has_track_caller = codegen_flags.contains(hir::CodegenFnAttrFlags::TRACK_CALLER); + if has_track_caller { + Some(ArgInfo(ty::Instance::track_caller_ty(tcx), None, None, None)) + } else { + None + } +} + /////////////////////////////////////////////////////////////////////////// // BuildMir -- walks a crate, looking for fn items and methods to build MIR from From 41bfc971023099f90e780cf1283fb7cdc6e2cae3 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 12 Oct 2019 08:05:00 -0700 Subject: [PATCH 5/6] Remove unnecessary feature flagging. --- src/librustc/ty/instance.rs | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 1b2cb0faa0fe9..e163f887a0297 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,4 +1,5 @@ use crate::hir::CodegenFnAttrFlags; +use crate::hir::Mutability; use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; @@ -6,6 +7,7 @@ use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; use crate::ty::print::{FmtPrinter, Printer}; use crate::traits; use crate::middle::lang_items::DropInPlaceFnLangItem; +use rustc::middle::lang_items::PanicLocationLangItem; use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; @@ -134,24 +136,15 @@ impl<'tcx> Instance<'tcx> { } /// Returns `&'static core::panic::Location`, for args of functions with #[track_caller]. - pub fn track_caller_ty(_tcx: TyCtxt<'_>) -> Ty<'_> { - #[cfg(bootstrap)] - { bug!("#[track_caller] isn't supported during bootstrap (yet)."); } - - #[cfg(not(bootstrap))] - { - use crate::hir::Mutability; - use rustc::middle::lang_items::PanicLocationLangItem; - - let panic_loc_item = _tcx.require_lang_item(PanicLocationLangItem, None); - _tcx.mk_ref( - _tcx.mk_region(ty::RegionKind::ReStatic), - ty::TypeAndMut { - mutbl: Mutability::MutImmutable, - ty: _tcx.type_of(panic_loc_item), - }, - ) - } + pub fn track_caller_ty(tcx: TyCtxt<'_>) -> Ty<'_> { + let panic_loc_item = tcx.require_lang_item(PanicLocationLangItem, None); + tcx.mk_ref( + tcx.mk_region(ty::RegionKind::ReStatic), + ty::TypeAndMut { + mutbl: Mutability::MutImmutable, + ty: tcx.type_of(panic_loc_item), + }, + ) } } From 9bdbe1b5d36a3f21201d5dda81dcd291598d68ff Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 12 Oct 2019 21:20:06 -0700 Subject: [PATCH 6/6] Update error message. --- src/test/ui/rfc-2091-track-caller/should-pass.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/rfc-2091-track-caller/should-pass.stderr b/src/test/ui/rfc-2091-track-caller/should-pass.stderr index 3cc441fd2487d..1160ddc890ee2 100644 --- a/src/test/ui/rfc-2091-track-caller/should-pass.stderr +++ b/src/test/ui/rfc-2091-track-caller/should-pass.stderr @@ -6,7 +6,7 @@ LL | #![feature(track_caller)] | = note: `#[warn(incomplete_features)]` on by default -thread 'rustc' panicked at 'assertion failed: !value.needs_subst()', src/librustc/traits/query/normalize_erasing_regions.rs:59:9 +thread 'rustc' panicked at 'index out of bounds: the len is 0 but the index is 0', $SRC_DIR/libcore/slice/mod.rs:LL:COL note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic