From dd2356fe7d8500a2b555a8b43761625e17223860 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 6 Oct 2019 21:57:23 +0800 Subject: [PATCH 01/26] add testcase for generator move suggestion --- .../async-borrowck-escaping-block-error.rs | 9 ++++++++ ...async-borrowck-escaping-block-error.stderr | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.rs create mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.stderr diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs new file mode 100644 index 0000000000000..49f59e4149313 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(async_closure,async_await)] +fn foo() -> Box> { + let x = 0u32; + Box::new(async { x } ) + //~^ ERROR E0373 +} + +fn main() {} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr new file mode 100644 index 0000000000000..5771ccbcf9d1e --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -0,0 +1,22 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-block-error.rs:5:20 + | +LL | Box::new(async { x } ) + | ^^-^^ + | | | + | | `x` is borrowed here + | may outlive borrowed value `x` + | +note: generator is returned here + --> $DIR/async-borrowck-escaping-block-error.rs:3:13 + | +LL | fn foo() -> Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new(async move { x } ) + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. From 50932ea1dae96a15e8f457e4e038d0e5218d2cad Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sun, 6 Oct 2019 23:58:07 +0200 Subject: [PATCH 02/26] add more info in debug traces for gcu merging --- src/librustc_mir/monomorphize/partitioning.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index c193911247e2b..61868b24c0b8a 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -494,6 +494,9 @@ fn merge_codegen_units<'tcx>( for (k, v) in smallest.items_mut().drain() { second_smallest.items_mut().insert(k, v); } + debug!("CodegenUnit {} merged in to CodegenUnit {}", + smallest.name(), + second_smallest.name()); } let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); @@ -774,7 +777,7 @@ where if cfg!(debug_assertions) { debug!("{}", label); for cgu in cgus { - debug!("CodegenUnit {}:", cgu.name()); + debug!("CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate()); for (mono_item, linkage) in cgu.items() { let symbol_name = mono_item.symbol_name(tcx).name.as_str(); @@ -782,10 +785,11 @@ where let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); - debug!(" - {} [{:?}] [{}]", + debug!(" - {} [{:?}] [{}] estimated size {}", mono_item.to_string(tcx, true), linkage, - symbol_hash); + symbol_hash, + mono_item.size_estimate(tcx)); } debug!(""); From 543449d4fdf7bb7fd4a12c2fea96dafbe26eea90 Mon Sep 17 00:00:00 2001 From: Ayose Date: Sat, 20 Jul 2019 00:55:58 +0000 Subject: [PATCH 03/26] [RFC 2091] Add #[track_caller] attribute. - The attribute is behind a feature gate. - Error if both #[naked] and #[track_caller] are applied to the same function. - Error if #[track_caller] is applied to a non-function item. - Error if ABI is not "rust" - Error if #[track_caller] is applied to a trait function. Error codes and descriptions are pending. --- .../src/language-features/track-caller.md | 5 +++ src/librustc/error_codes.rs | 10 ++++++ src/librustc/hir/check_attr.rs | 34 +++++++++++++++++++ src/librustc/hir/mod.rs | 4 ++- src/librustc_typeck/check/wfcheck.rs | 12 +++++++ src/librustc_typeck/collect.rs | 10 ++++++ src/librustc_typeck/error_codes.rs | 11 ++++++ src/libsyntax/feature_gate/active.rs | 3 ++ src/libsyntax/feature_gate/builtin_attrs.rs | 4 +++ src/libsyntax_pos/symbol.rs | 1 + .../feature-gate-track_caller.rs | 6 ++++ .../feature-gate-track_caller.stderr | 12 +++++++ .../rfc-2091-track-caller/error-odd-syntax.rs | 7 ++++ .../error-odd-syntax.stderr | 8 +++++ .../error-with-invalid-abi.rs | 7 ++++ .../error-with-invalid-abi.stderr | 9 +++++ .../rfc-2091-track-caller/error-with-naked.rs | 8 +++++ .../error-with-naked.stderr | 9 +++++ .../error-with-trait-fns.rs | 13 +++++++ .../error-with-trait-fns.stderr | 9 +++++ .../ui/rfc-2091-track-caller/only-for-fns.rs | 7 ++++ .../rfc-2091-track-caller/only-for-fns.stderr | 11 ++++++ 22 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/language-features/track-caller.md create mode 100644 src/test/ui/feature-gates/feature-gate-track_caller.rs create mode 100644 src/test/ui/feature-gates/feature-gate-track_caller.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-naked.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-naked.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/only-for-fns.rs create mode 100644 src/test/ui/rfc-2091-track-caller/only-for-fns.stderr diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md new file mode 100644 index 0000000000000..afc11a2b9492c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/track-caller.md @@ -0,0 +1,5 @@ +# `track_caller` + +The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809). + +------------------------ diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 502172db91c9b..959a06c2e32f6 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1640,6 +1640,16 @@ each method; it is not possible to annotate the entire impl with an `#[inline]` attribute. "##, +E0900: r##" +TODO: change error number +TODO: track_caller: invalid syntax +"##, + +E0901: r##" +TODO: change error number +TODO: track_caller: no naked functions +"##, + E0522: r##" The lang attribute is intended for marking special items that are built-in to Rust itself. This includes special traits (like `Copy` and `Sized`) that affect diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index d5e956555bdfb..31a09645d1691 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -94,6 +94,7 @@ impl CheckAttrVisitor<'tcx> { /// Checks any attribute. fn check_attributes(&self, item: &hir::Item, target: Target) { let mut is_valid = true; + let mut track_caller_span = None; for attr in &item.attrs { is_valid &= if attr.check_name(sym::inline) { self.check_inline(attr, &item.span, target) @@ -103,6 +104,9 @@ 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) { + track_caller_span = Some(attr.span); + self.check_track_caller(attr, &item, target) } else { true }; @@ -118,6 +122,19 @@ impl CheckAttrVisitor<'tcx> { self.check_repr(item, target); self.check_used(item, target); + + // Checks if `#[track_caller]` and `#[naked]` are both used. + if let Some(span) = track_caller_span { + if item.attrs.iter().any(|attr| attr.check_name(sym::naked)) { + struct_span_err!( + self.tcx.sess, + span, + E0901, + "cannot use `#[track_caller]` with `#[naked]`", + ) + .emit(); + } + } } /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. @@ -135,6 +152,23 @@ impl CheckAttrVisitor<'tcx> { } } + /// Checks if a `#[target_feature]` can be applied. + 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, + E0900, + "attribute should be applied to function" + ) + .span_label(item.span, "not a function") + .emit(); + false + } else { + true + } + } + /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid. fn check_non_exhaustive( &self, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30b0503668877..f7240d6bf820e 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2721,7 +2721,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; } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e736a55a5f51c..3c9010de5cb77 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -172,6 +172,18 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { _ => None }; check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig); + + // Prohibits applying `#[track_caller]` to trait methods + for attr in &trait_item.attrs { + if attr.check_name(sym::track_caller) { + struct_span_err!( + tcx.sess, + attr.span, + E0903, + "`#[track_caller]` is not supported for trait items yet." + ).emit(); + } + } } pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 64eca1371447b..0b98e4b781d77 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2594,6 +2594,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; } else if attr.check_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; + } else if attr.check_name(sym::track_caller) { + if tcx.fn_sig(id).abi() != abi::Abi::Rust { + struct_span_err!( + tcx.sess, + attr.span, + E0902, + "rust ABI is required to use `#[track_caller]`" + ).emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } else if attr.check_name(sym::export_name) { if let Some(s) = attr.value_str() { if s.as_str().contains("\0") { diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 3a07171b12fb8..f698427c78add 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4907,6 +4907,17 @@ fn foo_recursive(n: usize) -> Pin>> { The `Box<...>` ensures that the result is of known size, and the pin is required to keep it in the same place in memory. "##, + +E0902: r##" +TODO: change error number +TODO: track_caller: require Rust ABI to use track_caller +"##, + +E0903: r##" +TODO: change error number +TODO: track_caller: can't apply in traits +"##, + ; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 19ef430318d3e..312a9bf6e755f 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -525,6 +525,9 @@ declare_features! ( // Allows the use of raw-dylibs (RFC 2627). (active, raw_dylib, "1.40.0", Some(58713), None), + /// Enable accurate caller location reporting during panic (RFC 2091). + (active, track_caller, "1.37.0", Some(47809), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index c12d0ce06ffef..d6a6450e471bd 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -499,6 +499,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(no_debug) ) ), + gated!( + track_caller, Whitelisted, template!(Word), + "the `#[track_caller]` attribute is an experimental feature", + ), gated!( // Used in resolve: prelude_import, Whitelisted, template!(Word), diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c7230d5ca1522..2b005c3fc421a 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -674,6 +674,7 @@ symbols! { tool_attributes, tool_lints, trace_macros, + track_caller, trait_alias, transmute, transparent, diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs new file mode 100644 index 0000000000000..458df0b2b0281 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-track_caller.rs @@ -0,0 +1,6 @@ + +#[track_caller] +fn f() {} +//~^^ ERROR the `#[track_caller]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr new file mode 100644 index 0000000000000..9a058736e5080 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-track_caller.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[track_caller]` attribute is an experimental feature + --> $DIR/feature-gate-track_caller.rs:2:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/47809 + = help: add `#![feature(track_caller)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs new file mode 100644 index 0000000000000..d6560231871c9 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -0,0 +1,7 @@ +#![feature(track_caller)] + +#[track_caller(1)] +fn f() {} +//~^^ ERROR malformed `track_caller` attribute input + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr new file mode 100644 index 0000000000000..8906fa59506a7 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -0,0 +1,8 @@ +error: malformed `track_caller` attribute input + --> $DIR/error-odd-syntax.rs:3:1 + | +LL | #[track_caller(1)] + | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs new file mode 100644 index 0000000000000..5c42a1b3faa2d --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -0,0 +1,7 @@ +#![feature(track_caller)] + +#[track_caller] +extern "C" fn f() {} +//~^^ ERROR rust ABI is required to use `#[track_caller]` + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr new file mode 100644 index 0000000000000..fc6f4d17dcc42 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -0,0 +1,9 @@ +error[E0902]: rust ABI is required to use `#[track_caller]` + --> $DIR/error-with-invalid-abi.rs:3:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0902`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs new file mode 100644 index 0000000000000..dd9e5d0413585 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -0,0 +1,8 @@ +#![feature(naked_functions, track_caller)] + +#[track_caller] +#[naked] +fn f() {} +//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]` + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr new file mode 100644 index 0000000000000..3566d288ed10b --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -0,0 +1,9 @@ +error[E0901]: cannot use `#[track_caller]` with `#[naked]` + --> $DIR/error-with-naked.rs:3:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0901`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs new file mode 100644 index 0000000000000..c00cf7367ce54 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs @@ -0,0 +1,13 @@ +#![feature(track_caller)] + +trait Trait { + #[track_caller] + fn unwrap(&self); + //~^^ ERROR: `#[track_caller]` is not supported for trait items yet. +} + +impl Trait for u64 { + fn unwrap(&self) {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr new file mode 100644 index 0000000000000..bd3d4043a642b --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr @@ -0,0 +1,9 @@ +error[E0903]: `#[track_caller]` is not supported for trait items yet. + --> $DIR/error-with-trait-fns.rs:4:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0903`. diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs new file mode 100644 index 0000000000000..0fd59b4bf4918 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs @@ -0,0 +1,7 @@ +#![feature(track_caller)] + +#[track_caller] +struct S; +//~^^ ERROR attribute should be applied to function + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr new file mode 100644 index 0000000000000..9ddc99c02bf9c --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -0,0 +1,11 @@ +error[E0900]: attribute should be applied to function + --> $DIR/only-for-fns.rs:3:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | struct S; + | --------- not a function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0900`. From 6c04c8eb8e361649fb541f918e373b23d2d7f772 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 18:24:10 -0700 Subject: [PATCH 04/26] track_caller run-pass test, lint cleanup, PR review. --- src/librustc/error_codes.rs | 8 +++--- src/librustc/hir/check_attr.rs | 28 ++++++++----------- src/librustc_typeck/error_codes.rs | 8 +++--- src/libsyntax/feature_gate/active.rs | 2 +- src/libsyntax/feature_gate/builtin_attrs.rs | 5 +--- .../feature-gate-track_caller.rs | 1 - .../feature-gate-track_caller.stderr | 2 +- src/test/ui/rfc-2091-track-caller/pass.rs | 9 ++++++ 8 files changed, 31 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/rfc-2091-track-caller/pass.rs diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 959a06c2e32f6..b2671e48be684 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1641,13 +1641,13 @@ attribute. "##, E0900: r##" -TODO: change error number -TODO: track_caller: invalid syntax +FIXME(anp): change error number +FIXME(anp): track_caller: invalid syntax "##, E0901: r##" -TODO: change error number -TODO: track_caller: no naked functions +FIXME(anp): change error number +FIXME(anp): track_caller: no naked functions "##, E0522: r##" diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 31a09645d1691..66415e26281b3 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -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)] @@ -94,7 +94,6 @@ impl CheckAttrVisitor<'tcx> { /// Checks any attribute. fn check_attributes(&self, item: &hir::Item, target: Target) { let mut is_valid = true; - let mut track_caller_span = None; for attr in &item.attrs { is_valid &= if attr.check_name(sym::inline) { self.check_inline(attr, &item.span, target) @@ -105,7 +104,6 @@ impl CheckAttrVisitor<'tcx> { } else if attr.check_name(sym::target_feature) { self.check_target_feature(attr, item, target) } else if attr.check_name(sym::track_caller) { - track_caller_span = Some(attr.span); self.check_track_caller(attr, &item, target) } else { true @@ -122,19 +120,6 @@ impl CheckAttrVisitor<'tcx> { self.check_repr(item, target); self.check_used(item, target); - - // Checks if `#[track_caller]` and `#[naked]` are both used. - if let Some(span) = track_caller_span { - if item.attrs.iter().any(|attr| attr.check_name(sym::naked)) { - struct_span_err!( - self.tcx.sess, - span, - E0901, - "cannot use `#[track_caller]` with `#[naked]`", - ) - .emit(); - } - } } /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. @@ -152,7 +137,7 @@ impl CheckAttrVisitor<'tcx> { } } - /// Checks if a `#[target_feature]` can be applied. + /// 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!( @@ -164,6 +149,15 @@ impl CheckAttrVisitor<'tcx> { .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, + E0901, + "cannot use `#[track_caller]` with `#[naked]`", + ) + .emit(); + false } else { true } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index f698427c78add..1ebae19c7d90b 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4909,13 +4909,13 @@ and the pin is required to keep it in the same place in memory. "##, E0902: r##" -TODO: change error number -TODO: track_caller: require Rust ABI to use track_caller +FIXME(anp): change error number +FIXME(anp): track_caller: require Rust ABI to use track_caller "##, E0903: r##" -TODO: change error number -TODO: track_caller: can't apply in traits +FIXME(anp): change error number +FIXME(anp): track_caller: can't apply in traits "##, ; diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 312a9bf6e755f..c90b18fc3976f 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -526,7 +526,7 @@ declare_features! ( (active, raw_dylib, "1.40.0", Some(58713), None), /// Enable accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.37.0", Some(47809), None), + (active, track_caller, "1.39.0", Some(47809), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index d6a6450e471bd..ae23cc5cb933c 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -324,6 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), + gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: @@ -499,10 +500,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(no_debug) ) ), - gated!( - track_caller, Whitelisted, template!(Word), - "the `#[track_caller]` attribute is an experimental feature", - ), gated!( // Used in resolve: prelude_import, Whitelisted, template!(Word), diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs index 458df0b2b0281..5865cf0a4f754 100644 --- a/src/test/ui/feature-gates/feature-gate-track_caller.rs +++ b/src/test/ui/feature-gates/feature-gate-track_caller.rs @@ -1,4 +1,3 @@ - #[track_caller] fn f() {} //~^^ ERROR the `#[track_caller]` attribute is an experimental feature diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr index 9a058736e5080..b890019ee4f3c 100644 --- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr +++ b/src/test/ui/feature-gates/feature-gate-track_caller.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[track_caller]` attribute is an experimental feature - --> $DIR/feature-gate-track_caller.rs:2:1 + --> $DIR/feature-gate-track_caller.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs new file mode 100644 index 0000000000000..eef83b3d68f97 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/pass.rs @@ -0,0 +1,9 @@ +// run-pass +#![feature(track_caller)] + +#[track_caller] +fn f() {} + +fn main() { + f(); +} From 43d4b70417bb24f08584902e2f91e4eb0c703768 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 21:32:59 -0700 Subject: [PATCH 05/26] track_caller feature gate starts in 1.40.0. Co-Authored-By: Mazdak Farrokhzad --- src/libsyntax/feature_gate/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index c90b18fc3976f..6c0d76de751bb 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -526,7 +526,7 @@ declare_features! ( (active, raw_dylib, "1.40.0", Some(58713), None), /// Enable accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.39.0", Some(47809), None), + (active, track_caller, "1.40.0", Some(47809), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates From d931afe47061cb27dfdb44727b0a6707868ea326 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 22:09:18 -0700 Subject: [PATCH 06/26] Mark #![feature(track_caller)] as incomplete. --- src/libsyntax/feature_gate/active.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 6c0d76de751bb..94f0995566f52 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -543,4 +543,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::or_patterns, sym::let_chains, sym::raw_dylib, + sym::track_caller, ]; From 9900211ea07a419289037b77eda218030dc32db3 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 22:35:58 -0700 Subject: [PATCH 07/26] track_caller error numbers and text. --- src/librustc/error_codes.rs | 20 +++++++++---------- src/librustc/hir/check_attr.rs | 4 ++-- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/error_codes.rs | 16 +++++++++------ .../error-with-invalid-abi.stderr | 4 ++-- .../error-with-naked.stderr | 4 ++-- .../error-with-trait-fns.stderr | 4 ++-- .../rfc-2091-track-caller/only-for-fns.stderr | 4 ++-- 9 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index b2671e48be684..6be1b6a54fb3f 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1640,16 +1640,6 @@ each method; it is not possible to annotate the entire impl with an `#[inline]` attribute. "##, -E0900: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: invalid syntax -"##, - -E0901: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: no naked functions -"##, - E0522: r##" The lang attribute is intended for marking special items that are built-in to Rust itself. This includes special traits (like `Copy` and `Sized`) that affect @@ -2085,6 +2075,15 @@ 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. + +This is primarily due to ABI incompatibilities between the two attributes. +See [RFC 2091] for details on this and other limitations. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md +"##, + ; // E0006, // merged with E0005 // E0101, // replaced with E0282 @@ -2146,4 +2145,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 + E0735, // invalid track_caller application/syntax } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 66415e26281b3..35c7ffbf14ef3 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -143,7 +143,7 @@ impl CheckAttrVisitor<'tcx> { struct_span_err!( self.tcx.sess, attr.span, - E0900, + E0735, "attribute should be applied to function" ) .span_label(item.span, "not a function") @@ -153,7 +153,7 @@ impl CheckAttrVisitor<'tcx> { struct_span_err!( self.tcx.sess, attr.span, - E0901, + E0736, "cannot use `#[track_caller]` with `#[naked]`", ) .emit(); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 3c9010de5cb77..b8d1da2bbed85 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -179,7 +179,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { struct_span_err!( tcx.sess, attr.span, - E0903, + E0738, "`#[track_caller]` is not supported for trait items yet." ).emit(); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0b98e4b781d77..7f34aa354c9e8 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2599,7 +2599,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { struct_span_err!( tcx.sess, attr.span, - E0902, + E0737, "rust ABI is required to use `#[track_caller]`" ).emit(); } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 1ebae19c7d90b..be1e34661fd1a 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4908,14 +4908,18 @@ The `Box<...>` ensures that the result is of known size, and the pin is required to keep it in the same place in memory. "##, -E0902: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: require Rust ABI to use track_caller +E0737: r##" +#[track_caller] requires functions to have the "Rust" ABI for passing caller +location. See [RFC 2091] for details on this and other restrictions. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, -E0903: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: can't apply in traits +E0738: r##" +#[track_caller] cannot be applied to trait methods. See [RFC 2091] +for details on this and other restrictions. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, ; diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr index fc6f4d17dcc42..e39e4bee5cf9c 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -1,4 +1,4 @@ -error[E0902]: rust ABI is required to use `#[track_caller]` +error[E0737]: rust ABI is required to use `#[track_caller]` --> $DIR/error-with-invalid-abi.rs:3:1 | LL | #[track_caller] @@ -6,4 +6,4 @@ LL | #[track_caller] error: aborting due to previous error -For more information about this error, try `rustc --explain E0902`. +For more information about this error, try `rustc --explain E0737`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 3566d288ed10b..2f5003cfdb7a5 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -1,4 +1,4 @@ -error[E0901]: cannot use `#[track_caller]` with `#[naked]` +error[E0736]: cannot use `#[track_caller]` with `#[naked]` --> $DIR/error-with-naked.rs:3:1 | LL | #[track_caller] @@ -6,4 +6,4 @@ LL | #[track_caller] error: aborting due to previous error -For more information about this error, try `rustc --explain E0901`. +For more information about this error, try `rustc --explain E0736`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr index bd3d4043a642b..e3f3135cd7366 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr @@ -1,4 +1,4 @@ -error[E0903]: `#[track_caller]` is not supported for trait items yet. +error[E0738]: `#[track_caller]` is not supported for trait items yet. --> $DIR/error-with-trait-fns.rs:4:5 | LL | #[track_caller] @@ -6,4 +6,4 @@ LL | #[track_caller] error: aborting due to previous error -For more information about this error, try `rustc --explain E0903`. +For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index 9ddc99c02bf9c..ac5ba0bfbaac6 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -1,4 +1,4 @@ -error[E0900]: attribute should be applied to function +error[E0735]: attribute should be applied to function --> $DIR/only-for-fns.rs:3:1 | LL | #[track_caller] @@ -8,4 +8,4 @@ LL | struct S; error: aborting due to previous error -For more information about this error, try `rustc --explain E0900`. +For more information about this error, try `rustc --explain E0735`. From 53096c575d0e17449e3b86919b96aa0e66ca9c48 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 23:01:52 -0700 Subject: [PATCH 08/26] track_caller tests account for incomplete feature warning. --- src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs | 2 +- .../ui/rfc-2091-track-caller/error-odd-syntax.stderr | 8 ++++++++ .../ui/rfc-2091-track-caller/error-with-invalid-abi.rs | 2 +- .../rfc-2091-track-caller/error-with-invalid-abi.stderr | 8 ++++++++ src/test/ui/rfc-2091-track-caller/error-with-naked.rs | 2 +- .../ui/rfc-2091-track-caller/error-with-naked.stderr | 8 ++++++++ .../ui/rfc-2091-track-caller/error-with-trait-fns.rs | 2 +- .../ui/rfc-2091-track-caller/error-with-trait-fns.stderr | 8 ++++++++ src/test/ui/rfc-2091-track-caller/only-for-fns.rs | 2 +- src/test/ui/rfc-2091-track-caller/only-for-fns.stderr | 9 ++++++++- src/test/ui/rfc-2091-track-caller/pass.rs | 2 +- src/test/ui/rfc-2091-track-caller/pass.stderr | 8 ++++++++ 12 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/rfc-2091-track-caller/pass.stderr diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs index d6560231871c9..d400db8575e0a 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller(1)] fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr index 8906fa59506a7..a53a8ee2bedc6 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -4,5 +4,13 @@ error: malformed `track_caller` attribute input LL | #[track_caller(1)] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-odd-syntax.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error: aborting due to previous error diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs index 5c42a1b3faa2d..2994f3c06212f 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] extern "C" fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr index e39e4bee5cf9c..a34acf3fc6142 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-invalid-abi.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0737]: rust ABI is required to use `#[track_caller]` --> $DIR/error-with-invalid-abi.rs:3:1 | diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index dd9e5d0413585..bbbcec30e8d51 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -1,4 +1,4 @@ -#![feature(naked_functions, track_caller)] +#![feature(naked_functions, track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] #[naked] diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 2f5003cfdb7a5..93e6f7a4cd32c 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-naked.rs:1:29 + | +LL | #![feature(naked_functions, track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0736]: cannot use `#[track_caller]` with `#[naked]` --> $DIR/error-with-naked.rs:3:1 | diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs index c00cf7367ce54..e42568076b9dc 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete trait Trait { #[track_caller] diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr index e3f3135cd7366..c5c2f136a3a81 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-trait-fns.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0738]: `#[track_caller]` is not supported for trait items yet. --> $DIR/error-with-trait-fns.rs:4:5 | diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs index 0fd59b4bf4918..01ebf13b521b2 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] struct S; diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index ac5ba0bfbaac6..e2d3d57f0adf4 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/only-for-fns.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0735]: attribute should be applied to function --> $DIR/only-for-fns.rs:3:1 | @@ -8,4 +16,3 @@ LL | struct S; error: aborting due to previous error -For more information about this error, try `rustc --explain E0735`. diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs index eef83b3d68f97..f2c3f0dc59e01 100644 --- a/src/test/ui/rfc-2091-track-caller/pass.rs +++ b/src/test/ui/rfc-2091-track-caller/pass.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/pass.stderr b/src/test/ui/rfc-2091-track-caller/pass.stderr new file mode 100644 index 0000000000000..b1fd23a6a9ddb --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/pass.stderr @@ -0,0 +1,8 @@ +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 + From 8992c30db41ceda8eb07c36080f2f1926013c2ac Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 3 Oct 2019 18:49:35 -0700 Subject: [PATCH 09/26] E0735 -> E0739 Prevents number collision with another approved PR. --- src/librustc/error_codes.rs | 2 +- src/librustc/hir/check_attr.rs | 2 +- src/test/ui/rfc-2091-track-caller/only-for-fns.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 6be1b6a54fb3f..8bc472aa0284e 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2145,5 +2145,5 @@ See [RFC 2091] for details on this and other limitations. 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 - E0735, // invalid track_caller application/syntax + E0739, // invalid track_caller application/syntax } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 35c7ffbf14ef3..c37fec982b116 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -143,7 +143,7 @@ impl CheckAttrVisitor<'tcx> { struct_span_err!( self.tcx.sess, attr.span, - E0735, + E0739, "attribute should be applied to function" ) .span_label(item.span, "not a function") diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index e2d3d57f0adf4..3301da7ff47bf 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -6,7 +6,7 @@ LL | #![feature(track_caller)] | = note: `#[warn(incomplete_features)]` on by default -error[E0735]: attribute should be applied to function +error[E0739]: attribute should be applied to function --> $DIR/only-for-fns.rs:3:1 | LL | #[track_caller] From bdc4bd142b3a452d5e7456cf30e9fc67106ec01b Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 4 Oct 2019 14:19:05 -0700 Subject: [PATCH 10/26] E073[6-8] include failing code examples. --- src/librustc/error_codes.rs | 10 ++++++++ src/librustc_typeck/error_codes.rs | 37 ++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 8bc472aa0284e..e3ef58a0f81f4 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2078,6 +2078,16 @@ 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. diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index be1e34661fd1a..1fb5b59261631 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4909,15 +4909,44 @@ and the pin is required to keep it in the same place in memory. "##, E0737: r##" -#[track_caller] requires functions to have the "Rust" ABI for passing caller -location. See [RFC 2091] for details on this and other restrictions. +#[track_caller] requires functions to have the "Rust" ABI for implicitly +receiving caller location. See [RFC 2091] for details on this and other +restrictions. + +Erroneous code example: + +```compile_fail,E0737 +#![feature(track_caller)] + +#[track_caller] +extern "C" fn foo() {} +``` [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, E0738: r##" -#[track_caller] cannot be applied to trait methods. See [RFC 2091] -for details on this and other restrictions. +#[track_caller] cannot be applied to trait methods. + +This is due to limitations in the compiler which are likely to be temporary. +See [RFC 2091] for details on this and other restrictions. + +Erroneous code example: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { + fn bar(&self); +} + +struct Bar; + +impl Foo for Bar { + #[track_caller] + fn bar(&self) {} +} +``` [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, From 130be6d4b8015b32a3e68678dd75459b2a3de3ab Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 4 Oct 2019 15:55:39 -0700 Subject: [PATCH 11/26] Expand E0738 to cover different cases. --- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/error_codes.rs | 39 +++++++++++++++---- ...-trait-fns.rs => error-with-trait-decl.rs} | 2 +- .../error-with-trait-decl.stderr | 17 ++++++++ .../error-with-trait-default-impl.rs | 9 +++++ .../error-with-trait-default-impl.stderr | 17 ++++++++ .../error-with-trait-fn-impl.rs | 13 +++++++ ...stderr => error-with-trait-fn-impl.stderr} | 6 +-- 8 files changed, 93 insertions(+), 12 deletions(-) rename src/test/ui/rfc-2091-track-caller/{error-with-trait-fns.rs => error-with-trait-decl.rs} (72%) create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs rename src/test/ui/rfc-2091-track-caller/{error-with-trait-fns.stderr => error-with-trait-fn-impl.stderr} (71%) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b8d1da2bbed85..4f9c686bd39c6 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -180,7 +180,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { tcx.sess, attr.span, E0738, - "`#[track_caller]` is not supported for trait items yet." + "`#[track_caller]` is not supported in trait declarations." ).emit(); } } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 1fb5b59261631..026aff7a96468 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4926,12 +4926,11 @@ extern "C" fn foo() {} "##, E0738: r##" -#[track_caller] cannot be applied to trait methods. +#[track_caller] cannot be used in traits yet. This is due to limitations in the +compiler which are likely to be temporary. See [RFC 2091] for details on this +and other restrictions. -This is due to limitations in the compiler which are likely to be temporary. -See [RFC 2091] for details on this and other restrictions. - -Erroneous code example: +Erroneous example with a trait method implementation: ```compile_fail,E0738 #![feature(track_caller)] @@ -4940,14 +4939,40 @@ trait Foo { fn bar(&self); } -struct Bar; +impl Foo for u64 { + #[track_caller] + fn bar(&self) {} +} +``` -impl Foo for Bar { +Erroneous example with a blanket trait method implementation: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { #[track_caller] fn bar(&self) {} + fn baz(&self); +} +``` + +Erroneous example with a trait method declaration: + +```compile_fail,E0738 +#[!feature(track_caller)] + +trait Foo { + fn bar(&self) {} + + #[track_caller] + fn baz(&self); } ``` +Note that while the compiler may be able to support the attribute in traits in +the future, [RFC 2091] prohibits their implementation without a follow-up RFC. + [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs similarity index 72% rename from src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs rename to src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs index e42568076b9dc..72f690777da21 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs @@ -3,7 +3,7 @@ trait Trait { #[track_caller] fn unwrap(&self); - //~^^ ERROR: `#[track_caller]` is not supported for trait items yet. + //~^^ ERROR: `#[track_caller]` is not supported in traits yet. } impl Trait for u64 { diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr new file mode 100644 index 0000000000000..fb3732b597083 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr @@ -0,0 +1,17 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-trait-decl.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0738]: `#[track_caller]` is not supported in trait declarations. + --> $DIR/error-with-trait-decl.rs:4:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs new file mode 100644 index 0000000000000..0f2020d6fb26b --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs @@ -0,0 +1,9 @@ +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete + +trait Trait { + #[track_caller] + fn unwrap(&self) {} + //~^^ ERROR: `#[track_caller]` is not supported in trait declarations. +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr new file mode 100644 index 0000000000000..f7faeba189b5e --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr @@ -0,0 +1,17 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-trait-default-impl.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0738]: `#[track_caller]` is not supported in traits yet. + --> $DIR/error-with-trait-default-impl.rs:4:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs new file mode 100644 index 0000000000000..1378ebaa03ffa --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs @@ -0,0 +1,13 @@ +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete + +trait Trait { + fn unwrap(&self); +} + +impl Trait for u64 { + #[track_caller] + fn unwrap(&self) {} + //~^^ ERROR: `#[track_caller]` is not supported in traits yet. +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr similarity index 71% rename from src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr rename to src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr index c5c2f136a3a81..1e6c2eeca4736 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr @@ -1,13 +1,13 @@ warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-trait-fns.rs:1:12 + --> $DIR/error-with-trait-fn-impl.rs:1:12 | LL | #![feature(track_caller)] | ^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default -error[E0738]: `#[track_caller]` is not supported for trait items yet. - --> $DIR/error-with-trait-fns.rs:4:5 +error[E0738]: `#[track_caller]` is not supported in traits yet. + --> $DIR/error-with-trait-fn-impl.rs:4:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ From f70ed29fbd2b58dd1ebfcff878134fd3876a0dea Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 08:12:48 -0700 Subject: [PATCH 12/26] Update expected error output. --- src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs | 2 +- .../rfc-2091-track-caller/error-with-trait-default-impl.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs index 72f690777da21..1cd45c8cdbc91 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs @@ -3,7 +3,7 @@ trait Trait { #[track_caller] fn unwrap(&self); - //~^^ ERROR: `#[track_caller]` is not supported in traits yet. + //~^^ ERROR: `#[track_caller]` is not supported in trait declarations. } impl Trait for u64 { diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr index f7faeba189b5e..c212a716c2024 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr @@ -6,7 +6,7 @@ LL | #![feature(track_caller)] | = note: `#[warn(incomplete_features)]` on by default -error[E0738]: `#[track_caller]` is not supported in traits yet. +error[E0738]: `#[track_caller]` is not supported in trait declarations. --> $DIR/error-with-trait-default-impl.rs:4:5 | LL | #[track_caller] From 190212c6bf1588fb4349a16caa9c2796f9a795f4 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 08:21:30 -0700 Subject: [PATCH 13/26] Prohibit #[track_caller] within trait impls as well as decls. --- src/librustc_typeck/check/wfcheck.rs | 27 ++++++++++++++++++- .../error-with-trait-fn-impl.stderr | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4f9c686bd39c6..051bd671d445b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -173,7 +173,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { }; check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig); - // Prohibits applying `#[track_caller]` to trait methods + // Prohibits applying `#[track_caller]` to trait decls for attr in &trait_item.attrs { if attr.check_name(sym::track_caller) { struct_span_err!( @@ -194,6 +194,31 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { hir::ImplItemKind::Method(ref sig, _) => Some(sig), _ => None }; + + // Prohibits applying `#[track_caller]` to trait impls + if method_sig.is_some() { + let track_caller_attr = impl_item.attrs.iter() + .find(|a| a.check_name(sym::track_caller)); + if let Some(tc_attr) = track_caller_attr { + let parent_hir_id = tcx.hir().get_parent_item(hir_id); + let containing_item = tcx.hir().expect_item(parent_hir_id); + let containing_impl_trait_ref = match &containing_item.kind { + hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr, + _ => bug!("parent of an ImplItem must be an Impl"), + }; + + // if the impl block this item is within is for a trait... + if containing_impl_trait_ref.is_some() { + struct_span_err!( + tcx.sess, + tc_attr.span, + E0738, + "`#[track_caller]` is not supported in traits yet." + ).emit(); + } + } + } + check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig); } diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr index 1e6c2eeca4736..2662fbff7a2c2 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr @@ -7,7 +7,7 @@ LL | #![feature(track_caller)] = note: `#[warn(incomplete_features)]` on by default error[E0738]: `#[track_caller]` is not supported in traits yet. - --> $DIR/error-with-trait-fn-impl.rs:4:5 + --> $DIR/error-with-trait-fn-impl.rs:8:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ From c49966bb1bc66cb14d66e2c116d187e781ee6776 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 08:28:38 -0700 Subject: [PATCH 14/26] Clarify variable names when checking track_caller methods. --- src/librustc_typeck/check/wfcheck.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 051bd671d445b..fa283904fe474 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -196,19 +196,18 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { }; // Prohibits applying `#[track_caller]` to trait impls - if method_sig.is_some() { + if method_sig.is_some() { let track_caller_attr = impl_item.attrs.iter() .find(|a| a.check_name(sym::track_caller)); if let Some(tc_attr) = track_caller_attr { let parent_hir_id = tcx.hir().get_parent_item(hir_id); let containing_item = tcx.hir().expect_item(parent_hir_id); - let containing_impl_trait_ref = match &containing_item.kind { - hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr, + let containing_impl_is_for_trait = match &containing_item.kind { + hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(), _ => bug!("parent of an ImplItem must be an Impl"), }; - // if the impl block this item is within is for a trait... - if containing_impl_trait_ref.is_some() { + if containing_impl_is_for_trait { struct_span_err!( tcx.sess, tc_attr.span, From cca58d1321b6de3098884d4af7bbff57f0f65101 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Mon, 7 Oct 2019 08:04:26 -0700 Subject: [PATCH 15/26] Fix syntax typo in error message. --- src/librustc_typeck/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 026aff7a96468..0736d69a731e1 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4960,7 +4960,7 @@ trait Foo { Erroneous example with a trait method declaration: ```compile_fail,E0738 -#[!feature(track_caller)] +#![feature(track_caller)] trait Foo { fn bar(&self) {} From d1d256592bcd3f05d00fe7ad80d1a1ed22c9e7d7 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 6 Oct 2019 21:58:32 +0800 Subject: [PATCH 16/26] suggest to add move keyword for generator --- .../borrow_check/conflict_errors.rs | 26 +++++++++++++++++++ .../borrow_check/nll/explain_borrow/mod.rs | 3 ++- .../async-borrowck-escaping-block-error.fixed | 12 +++++++++ .../async-borrowck-escaping-block-error.rs | 7 +++-- ...async-borrowck-escaping-block-error.stderr | 4 +-- 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.fixed diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index ef459ef0c1b70..2f9df7bd77e84 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -750,6 +750,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0)); let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place); + debug!( + "report_borrowed_value_does_not_live_long_enough(place_desc: {:?}, explanation: {:?})", + place_desc, + explanation + ); let err = match (place_desc, explanation) { (Some(_), _) if self.is_place_thread_local(root_place) => { self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) @@ -790,6 +795,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span, &format!("`{}`", name), ), + ( + Some(ref name), + BorrowExplanation::MustBeValidFor { + category: category @ ConstraintCategory::OpaqueType, + from_closure: false, + ref region_name, + span, + .. + }, + + ) if borrow_spans.for_generator() => self.report_escaping_closure_capture( + borrow_spans.args_or_use(), + borrow_span, + region_name, + category, + span, + &format!("`{}`", name), + ), ( ref name, BorrowExplanation::MustBeValidFor { @@ -1214,6 +1237,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ConstraintCategory::Return => { err.span_note(constraint_span, "closure is returned here"); } + ConstraintCategory::OpaqueType => { + err.span_note(constraint_span, "generator is returned here"); + } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); err.span_note( diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index ff4243df6e9b8..5354b45f92d0a 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -17,6 +17,7 @@ use syntax_pos::Span; mod find_use; +#[derive(Debug)] pub(in crate::borrow_check) enum BorrowExplanation { UsedLater(LaterUseKind, Span), UsedLaterInLoop(LaterUseKind, Span), @@ -35,7 +36,7 @@ pub(in crate::borrow_check) enum BorrowExplanation { Unexplained, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub(in crate::borrow_check) enum LaterUseKind { TraitCapture, ClosureCapture, diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed new file mode 100644 index 0000000000000..f004b4180ddc9 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed @@ -0,0 +1,12 @@ +// edition:2018 +// run-rustfix + +fn foo() -> Box> { + let x = 0u32; + Box::new(async move { x } ) + //~^ ERROR E0373 +} + +fn main() { + let _foo = foo(); +} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs index 49f59e4149313..4f35fd52ca39b 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs @@ -1,9 +1,12 @@ // edition:2018 -#![feature(async_closure,async_await)] +// run-rustfix + fn foo() -> Box> { let x = 0u32; Box::new(async { x } ) //~^ ERROR E0373 } -fn main() {} +fn main() { + let _foo = foo(); +} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index 5771ccbcf9d1e..af17ecc86fbf9 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -1,5 +1,5 @@ error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-block-error.rs:5:20 + --> $DIR/async-borrowck-escaping-block-error.rs:6:20 | LL | Box::new(async { x } ) | ^^-^^ @@ -8,7 +8,7 @@ LL | Box::new(async { x } ) | may outlive borrowed value `x` | note: generator is returned here - --> $DIR/async-borrowck-escaping-block-error.rs:3:13 + --> $DIR/async-borrowck-escaping-block-error.rs:4:13 | LL | fn foo() -> Box> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 2afd277bc3ad53ddb6064b7f2a739583e8b4820a Mon Sep 17 00:00:00 2001 From: ben Date: Tue, 1 Oct 2019 17:55:26 +1300 Subject: [PATCH 17/26] Fix calling function pointer const parameters. Also fixes inference of function pointer const parameters. --- src/librustc/ty/relate.rs | 66 +++++++++++-------- src/librustc_mir/monomorphize/collector.rs | 10 ++- .../ui/const-generics/fn-const-param-call.rs | 20 ++++++ .../const-generics/fn-const-param-call.stderr | 8 +++ .../ui/const-generics/fn-const-param-infer.rs | 26 ++++++++ .../fn-const-param-infer.stderr | 45 +++++++++++++ 6 files changed, 145 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/const-generics/fn-const-param-call.rs create mode 100644 src/test/ui/const-generics/fn-const-param-call.stderr create mode 100644 src/test/ui/const-generics/fn-const-param-infer.rs create mode 100644 src/test/ui/const-generics/fn-const-param-infer.stderr diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 5489c6f5d5afb..2d811a83c10c1 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,7 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar}; +use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar, GlobalAlloc}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -561,37 +561,47 @@ pub fn super_relate_consts>( // implement both `PartialEq` and `Eq`, corresponding to // `structural_match` types. // FIXME(const_generics): check for `structural_match` synthetic attribute. - match (eagerly_eval(a), eagerly_eval(b)) { + let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) } (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => { - Ok(a) + return Ok(a); } (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => { - Ok(a) + return Ok(a); } - (a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _) - if a.ty == b.ty && a_val == b_val => - { - Ok(tcx.mk_const(ty::Const { - val: a_val, - ty: a.ty, - })) + (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => { + if a_val == b_val { + Ok(ConstValue::Scalar(a_val)) + } else if let ty::FnPtr(_) = a.ty.kind { + let alloc_map = tcx.alloc_map.lock(); + let get_fn_instance = |val: Scalar| { + let ptr = val.to_ptr().unwrap(); + if let Some(GlobalAlloc::Function(instance)) = alloc_map.get(ptr.alloc_id) { + instance + } else { + bug!("Allocation for FnPtr isn't a function"); + } + }; + let a_instance = get_fn_instance(a_val); + let b_instance = get_fn_instance(b_val); + if a_instance == b_instance { + Ok(ConstValue::Scalar(a_val)) + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } } - // FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment - // saying that we're not handling it intentionally. - (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => { let a_bytes = get_slice_bytes(&tcx, a_val); let b_bytes = get_slice_bytes(&tcx, b_val); if a_bytes == b_bytes { - Ok(tcx.mk_const(ty::Const { - val: a_val, - ty: a.ty, - })) + Ok(a_val) } else { Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) } @@ -602,16 +612,16 @@ pub fn super_relate_consts>( // FIXME(const_generics): this is wrong, as it is a projection (ConstValue::Unevaluated(a_def_id, a_substs), ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = - relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(tcx.mk_const(ty::Const { - val: ConstValue::Unevaluated(a_def_id, &substs), - ty: a.ty, - })) - } - - _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), - } + let substs = + relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; + Ok(ConstValue::Unevaluated(a_def_id, &substs)) + } + _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), + }; + new_const_val.map(|val| tcx.mk_const(ty::Const { + val, + ty: a.ty, + })) } impl<'tcx> Relate<'tcx> for &'tcx ty::List> { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 3ac837dd330fd..a0c3ae82bcc38 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1265,7 +1265,13 @@ fn collect_const<'tcx>( ) { debug!("visiting const {:?}", constant); - match constant.val { + let substituted_constant = if let ConstValue::Param(param) = constant.val { + param_substs.const_at(param.index as usize) + } else { + constant + }; + + match substituted_constant.val { ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), ConstValue::Slice { data: alloc, start: _, end: _ } | @@ -1297,7 +1303,7 @@ fn collect_const<'tcx>( tcx.def_span(def_id), "collection encountered polymorphic constant", ), } - } + }, _ => {}, } } diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs new file mode 100644 index 0000000000000..9f64d4bd086dd --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn function() -> u32 { + 17 +} + +struct Wrapper u32>; + +impl u32> Wrapper<{F}> { + fn call() -> u32 { + F() + } +} + +fn main() { + assert_eq!(Wrapper::<{function}>::call(), 17); +} \ No newline at end of file diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr new file mode 100644 index 0000000000000..88d7700680b19 --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/fn-const-param-call.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs new file mode 100644 index 0000000000000..ac48ccc26e136 --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -0,0 +1,26 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Checked bool>; + +fn not_one(val: usize) -> bool { val != 1 } +fn not_two(val: usize) -> bool { val != 2 } + +fn generic_arg(val: T) -> bool { true } + +fn generic(val: usize) -> bool { val != 1 } + +fn main() { + let _: Option> = None; + let _: Checked<{not_one}> = Checked::<{not_one}>; + let _: Checked<{not_one}> = Checked::<{not_two}>; //~ mismatched types + + let _ = Checked::<{generic_arg}>; + let _ = Checked::<{generic_arg::}>; + let _ = Checked::<{generic_arg::}>; //~ mismatched types + + let _ = Checked::<{generic}>; //~ type annotations needed + let _ = Checked::<{generic::}>; + let _: Checked<{generic::}> = Checked::<{generic::}>; + let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types +} \ No newline at end of file diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr new file mode 100644 index 0000000000000..4ef55fd22d46e --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -0,0 +1,45 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/fn-const-param-infer.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/fn-const-param-infer.rs:16:33 + | +LL | let _: Checked<{not_one}> = Checked::<{not_two}>; + | ^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(1).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(10).0x0) : fn(usize) -> bool` + | + = note: expected type `Checked<>` + found type `Checked<>` + +error[E0308]: mismatched types + --> $DIR/fn-const-param-infer.rs:20:24 + | +LL | let _ = Checked::<{generic_arg::}>; + | ^^^^^^^^^^^^^^^^^^ expected usize, found u32 + | + = note: expected type `fn(usize) -> bool` + found type `fn(u32) -> bool {generic_arg::}` + +error[E0282]: type annotations needed + --> $DIR/fn-const-param-infer.rs:22:24 + | +LL | let _ = Checked::<{generic}>; + | ^^^^^^^ cannot infer type for `T` + +error[E0308]: mismatched types + --> $DIR/fn-const-param-infer.rs:25:40 + | +LL | let _: Checked<{generic::}> = Checked::<{generic::}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(7).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(20).0x0) : fn(usize) -> bool` + | + = note: expected type `Checked<>` + found type `Checked<>` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. From a59eb6d55483e68f790c048efcfc8cdec26db32c Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 2 Oct 2019 20:29:16 +1300 Subject: [PATCH 18/26] Pretty print function pointer const values. --- src/librustc/mir/interpret/mod.rs | 8 ++++++++ src/librustc/ty/print/pretty.rs | 12 ++++++++++++ src/librustc/ty/relate.rs | 14 +++----------- src/test/ui/const-generics/fn-const-param-call.rs | 2 +- src/test/ui/const-generics/fn-const-param-infer.rs | 2 +- .../ui/const-generics/fn-const-param-infer.stderr | 4 ++-- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index e925d7429fff4..6c31d54e081c4 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -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) { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 07c63a92b39dd..7694d529aa3cb 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -980,6 +980,18 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } } + + if let ty::FnPtr(_) = ct.ty.kind { + if let ConstValue::Scalar(Scalar::Ptr(ptr)) = ct.val { + 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)); + return Ok(self); + } + } + p!(write("{:?} : ", ct.val), print(ct.ty)); Ok(self) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2d811a83c10c1..41f34703622e7 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,7 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar, GlobalAlloc}; +use crate::mir::interpret::{ConstValue, get_slice_bytes}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -577,16 +577,8 @@ pub fn super_relate_consts>( Ok(ConstValue::Scalar(a_val)) } else if let ty::FnPtr(_) = a.ty.kind { let alloc_map = tcx.alloc_map.lock(); - let get_fn_instance = |val: Scalar| { - let ptr = val.to_ptr().unwrap(); - if let Some(GlobalAlloc::Function(instance)) = alloc_map.get(ptr.alloc_id) { - instance - } else { - bug!("Allocation for FnPtr isn't a function"); - } - }; - let a_instance = get_fn_instance(a_val); - let b_instance = get_fn_instance(b_val); + let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id); + let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id); if a_instance == b_instance { Ok(ConstValue::Scalar(a_val)) } else { diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index 9f64d4bd086dd..1fb57897e286d 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -17,4 +17,4 @@ impl u32> Wrapper<{F}> { fn main() { assert_eq!(Wrapper::<{function}>::call(), 17); -} \ No newline at end of file +} diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index ac48ccc26e136..65a1523a3547e 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -23,4 +23,4 @@ fn main() { let _ = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types -} \ No newline at end of file +} diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 4ef55fd22d46e..8598cd95b8169 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:16:33 | LL | let _: Checked<{not_one}> = Checked::<{not_two}>; - | ^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(1).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(10).0x0) : fn(usize) -> bool` + | ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` | = note: expected type `Checked<>` found type `Checked<>` @@ -34,7 +34,7 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:25:40 | LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(7).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(20).0x0) : fn(usize) -> bool` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` | = note: expected type `Checked<>` found type `Checked<>` From cf3b561cea59f0063c9f51c9b058a6f2462bb31d Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 10:49:24 +1300 Subject: [PATCH 19/26] Gate use of raw and function pointers in const generics behind const_compare_raw_pointers. --- src/librustc_typeck/collect.rs | 26 +++++++++++-- .../ui/const-generics/fn-const-param-call.rs | 2 +- .../const-generics/fn-const-param-call.stderr | 2 +- .../ui/const-generics/fn-const-param-infer.rs | 2 +- .../fn-const-param-infer.stderr | 2 +- .../raw-ptr-const-param-deref.rs | 19 +++++++++ .../raw-ptr-const-param-deref.stderr | 8 ++++ .../ui/const-generics/raw-ptr-const-param.rs | 9 +++++ .../const-generics/raw-ptr-const-param.stderr | 20 ++++++++++ .../feature-gate-const_generics-ptr.rs | 9 +++++ .../feature-gate-const_generics-ptr.stderr | 39 +++++++++++++++++++ 11 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/const-generics/raw-ptr-const-param-deref.rs create mode 100644 src/test/ui/const-generics/raw-ptr-const-param-deref.stderr create mode 100644 src/test/ui/const-generics/raw-ptr-const-param.rs create mode 100644 src/test/ui/const-generics/raw-ptr-const-param.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 64eca1371447b..84fb8461c6a17 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1508,9 +1508,29 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option match ¶m.kind { - hir::GenericParamKind::Type { default: Some(ref ty), .. } | - hir::GenericParamKind::Const { ref ty, .. } => { - icx.to_ty(ty) + hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), + hir::GenericParamKind::Const { ty: ref hir_ty, .. } => { + let ty = icx.to_ty(hir_ty); + if !tcx.features().const_compare_raw_pointers { + let err = match ty.peel_refs().kind { + ty::FnPtr(_) => Some("function pointers"), + ty::RawPtr(_) => Some("raw pointers"), + _ => None, + }; + if let Some(unsupported_type) = err { + feature_gate::emit_feature_err( + &tcx.sess.parse_sess, + sym::const_compare_raw_pointers, + hir_ty.span, + feature_gate::GateIssue::Language, + &format!( + "use of {} as const generic arguments are unstable", + unsupported_type + ), + ); + }; + } + ty } x => { if !fail { diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index 1fb57897e286d..84615386d2995 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(const_generics)] +#![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash fn function() -> u32 { diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr index 88d7700680b19..c677d70374931 100644 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -1,7 +1,7 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/fn-const-param-call.rs:3:12 | -LL | #![feature(const_generics)] +LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index 65a1523a3547e..78fb10e8cb904 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -1,4 +1,4 @@ -#![feature(const_generics)] +#![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash struct Checked bool>; diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 8598cd95b8169..408786f98e1c7 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -1,7 +1,7 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/fn-const-param-infer.rs:1:12 | -LL | #![feature(const_generics)] +LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs new file mode 100644 index 0000000000000..672092a377934 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(const_generics, const_compare_raw_pointers)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +const A: u32 = 3; + +struct Const; + +impl Const<{P}> { + fn get() -> u32 { + unsafe { + *P + } + } +} + +fn main() { + assert_eq!(Const::<{&A as *const _}>::get(), 3) +} \ No newline at end of file diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr new file mode 100644 index 0000000000000..73221596c8e87 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/raw-ptr-const-param-deref.rs:2:12 + | +LL | #![feature(const_generics, const_compare_raw_pointers)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs new file mode 100644 index 0000000000000..435b6c874f4f0 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_compare_raw_pointers)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Const; + +fn main() { + let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types + let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; +} \ No newline at end of file diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr new file mode 100644 index 0000000000000..e432afd9e9d69 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -0,0 +1,20 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/raw-ptr-const-param.rs:1:12 + | +LL | #![feature(const_generics, const_compare_raw_pointers)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/raw-ptr-const-param.rs:7:38 + | +LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(0x000000000000000f) : *const u32`, found `Scalar(0x000000000000000a) : *const u32` + | + = note: expected type `Const<>` + found type `Const<>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs new file mode 100644 index 0000000000000..db5290bdf3be2 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -0,0 +1,9 @@ +struct ConstFn; +//~^ ERROR const generics are unstable +//~^^ ERROR use of function pointers as const generic arguments are unstable + +struct ConstPtr; +//~^ ERROR const generics are unstable +//~^^ ERROR use of raw pointers as const generic arguments are unstable + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr new file mode 100644 index 0000000000000..0afaf4f8e49e6 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -0,0 +1,39 @@ +error[E0658]: const generics are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:1:22 + | +LL | struct ConstFn; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: const generics are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:5:23 + | +LL | struct ConstPtr; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: use of function pointers as const generic arguments are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:1:25 + | +LL | struct ConstFn; + | ^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/53020 + = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable + +error[E0658]: use of raw pointers as const generic arguments are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:5:26 + | +LL | struct ConstPtr; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/53020 + = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. From 43badf9b1d02f0e79341a93a442b0bad9312dc54 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 11:19:24 +1300 Subject: [PATCH 20/26] Substitute and normalize all types of consts within collect const --- src/librustc_mir/monomorphize/collector.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a0c3ae82bcc38..1fc8a865c1894 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1265,11 +1265,12 @@ fn collect_const<'tcx>( ) { debug!("visiting const {:?}", constant); - let substituted_constant = if let ConstValue::Param(param) = constant.val { - param_substs.const_at(param.index as usize) - } else { - constant - }; + let param_env = ty::ParamEnv::reveal_all(); + let substituted_constant = tcx.subst_and_normalize_erasing_regions( + param_substs, + param_env, + &constant, + ); match substituted_constant.val { ConstValue::Scalar(Scalar::Ptr(ptr)) => @@ -1281,12 +1282,6 @@ fn collect_const<'tcx>( } } ConstValue::Unevaluated(def_id, substs) => { - let param_env = ty::ParamEnv::reveal_all(); - let substs = tcx.subst_and_normalize_erasing_regions( - param_substs, - param_env, - &substs, - ); let instance = ty::Instance::resolve(tcx, param_env, def_id, From 9677cbe82e4b317c63e4459d90f7a1f2498c16ae Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 12:57:12 +1300 Subject: [PATCH 21/26] Refactor pretty print const to use a big match statement --- src/librustc/ty/print/pretty.rs | 225 ++++++++---------- .../raw-ptr-const-param-deref.rs | 2 +- .../ui/const-generics/raw-ptr-const-param.rs | 2 +- 3 files changed, 106 insertions(+), 123 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7694d529aa3cb..8cd637468ccd6 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -863,137 +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)) - } else { - p!(write("_: "), print(ct.ty)) - } - } 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); - if data == max { - p!(write("std::{}::MAX", ui)) + 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("{}{}", 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); + p!(write("_: "), print(ct.ty)) + }, } - _ => {}, - } - } - 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)?; - } + }, + (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("{}{}", 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)) } - p!(write("\"")); - return Ok(self); - } - } - - if let ty::FnPtr(_) = ct.ty.kind { - if let ConstValue::Scalar(Scalar::Ptr(ptr)) = ct.val { + }, + (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)); - return Ok(self); - } - } - - p!(write("{:?} : ", ct.val), print(ct.ty)); + }, + _ => { + 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 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 { + false + } + } else { + false + }; + if !printed { + // fallback + p!(write("{:?} : ", ct.val), print(ct.ty)) + } + } + }; Ok(self) } } diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index 672092a377934..d26ab8be4c3fe 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -16,4 +16,4 @@ impl Const<{P}> { fn main() { assert_eq!(Const::<{&A as *const _}>::get(), 3) -} \ No newline at end of file +} diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index 435b6c874f4f0..f69c37fbb8f3d 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -6,4 +6,4 @@ struct Const; fn main() { let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; -} \ No newline at end of file +} From 50ea5f45356b645e44a03d809fa86c78c264ae28 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 14:03:41 +1300 Subject: [PATCH 22/26] Fix reify_fn_ptr test as we now pretty print const function pointers. --- src/test/mir-opt/const_prop/reify_fn_ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs index e9b61690cf89e..ad7f195676a68 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs @@ -16,7 +16,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const Scalar(AllocId(0).0x0) : fn(); +// _3 = const main; // _2 = move _3 as usize (Misc); // ... // _1 = move _2 as *const fn() (Misc); From 16b7f44b070994cc450ae7a85c3e886656dd8fb5 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Tue, 8 Oct 2019 07:55:47 +1300 Subject: [PATCH 23/26] Update feature gate error message Co-Authored-By: varkor --- src/librustc_typeck/collect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 84fb8461c6a17..6992f8c5b7f77 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1524,7 +1524,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option Date: Wed, 9 Oct 2019 06:58:39 +1300 Subject: [PATCH 24/26] Update ui tests --- src/test/ui/const-generics/fn-const-param-infer.stderr | 8 ++++---- src/test/ui/const-generics/raw-ptr-const-param.stderr | 4 ++-- .../ui/feature-gates/feature-gate-const_generics-ptr.rs | 4 ++-- .../feature-gates/feature-gate-const_generics-ptr.stderr | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 408786f98e1c7..de0916b26bfef 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | let _: Checked<{not_one}> = Checked::<{not_two}>; | ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` | - = note: expected type `Checked<>` - found type `Checked<>` + = note: expected type `Checked` + found type `Checked` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:20:24 @@ -36,8 +36,8 @@ error[E0308]: mismatched types LL | let _: Checked<{generic::}> = Checked::<{generic::}>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` | - = note: expected type `Checked<>` - found type `Checked<>` + = note: expected type `Checked>` + found type `Checked>` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index e432afd9e9d69..31db64d30a7da 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(0x000000000000000f) : *const u32`, found `Scalar(0x000000000000000a) : *const u32` | - = note: expected type `Const<>` - found type `Const<>` + = note: expected type `Const` + found type `Const` error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs index db5290bdf3be2..1ab11ce3b4423 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -1,9 +1,9 @@ struct ConstFn; //~^ ERROR const generics are unstable -//~^^ ERROR use of function pointers as const generic arguments are unstable +//~^^ ERROR using function pointers as const generic parameters is unstable struct ConstPtr; //~^ ERROR const generics are unstable -//~^^ ERROR use of raw pointers as const generic arguments are unstable +//~^^ ERROR using raw pointers as const generic parameters is unstable fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr index 0afaf4f8e49e6..935f84b9163d3 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -16,7 +16,7 @@ LL | struct ConstPtr; = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0658]: use of function pointers as const generic arguments are unstable +error[E0658]: using function pointers as const generic parameters is unstable --> $DIR/feature-gate-const_generics-ptr.rs:1:25 | LL | struct ConstFn; @@ -25,7 +25,7 @@ LL | struct ConstFn; = note: for more information, see https://github.com/rust-lang/rust/issues/53020 = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable -error[E0658]: use of raw pointers as const generic arguments are unstable +error[E0658]: using raw pointers as const generic parameters is unstable --> $DIR/feature-gate-const_generics-ptr.rs:5:26 | LL | struct ConstPtr; From 2c81089425660c78c066c650c44aea25c5d58543 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 8 Oct 2019 13:07:27 -0700 Subject: [PATCH 25/26] Update LLVM for Emscripten exception handling support Updates LLVM to pick up the cherry-picked support for correctly handling exception handling with aggregates passed by value. This will be necessary to continue to support Emscripten's exception handling once we switch using Emscripten's LLVM backend. See #63649. --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 8473db5f2af9d..14a3b123074e0 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 8473db5f2af9dc36aaf6f9b053fcc2e0e6ac8026 +Subproject commit 14a3b123074e066d64a99886941473058e52197d From bdcc21cbc4dabe73662634ffada8d0f353bc1ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Saparelli?= Date: Sat, 21 Sep 2019 22:56:05 +1200 Subject: [PATCH 26/26] Implement (HashMap) Entry::insert as per #60142 --- Cargo.lock | 21 +++++++++++-- src/libstd/Cargo.toml | 2 +- src/libstd/collections/hash/map.rs | 47 ++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80364515a7cca..6c05efcbec5e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ dependencies = [ "winapi 0.3.6", ] +[[package]] +name = "autocfg" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" + [[package]] name = "backtrace" version = "0.3.37" @@ -1259,7 +1265,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d" dependencies = [ - "hashbrown", + "hashbrown 0.5.0", "lazy_static 1.3.0", "log", "pest", @@ -1276,10 +1282,19 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" dependencies = [ + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +dependencies = [ + "autocfg", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", - "serde", ] [[package]] @@ -4073,7 +4088,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown", + "hashbrown 0.6.1", "libc", "panic_abort", "panic_unwind", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index ee4b367b5c5b9..5309af6f4c342 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,7 +23,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.6.1", default-features = false, features = ['rustc-dep-of-std'] } [dependencies.backtrace_rs] package = "backtrace" diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ff50051ef5040..fcca112563d2d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2030,6 +2030,31 @@ impl<'a, K, V> Entry<'a, K, V> { Vacant(entry) => Vacant(entry), } } + + /// Sets the value of the entry, and returns an OccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// #![feature(entry_insert)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, String> = HashMap::new(); + /// let entry = map.entry("poneyland").insert("hoho".to_string()); + /// + /// assert_eq!(entry.key(), &"poneyland"); + /// ``` + #[inline] + #[unstable(feature = "entry_insert", issue = "65225")] + pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V> { + match self { + Occupied(mut entry) => { + entry.insert(value); + entry + }, + Vacant(entry) => entry.insert_entry(value), + } + } } impl<'a, K, V: Default> Entry<'a, K, V> { @@ -2347,6 +2372,28 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { pub fn insert(self, value: V) -> &'a mut V { self.base.insert(value) } + + /// Sets the value of the entry with the VacantEntry's key, + /// and returns an OccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// use std::collections::hash_map::Entry; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// + /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// o.insert(37); + /// } + /// assert_eq!(map["poneyland"], 37); + /// ``` + #[inline] + fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { + let base = self.base.insert_entry(value); + OccupiedEntry { base } + } } #[stable(feature = "rust1", since = "1.0.0")]