From 23d3ff1b9756c768c4412dcd1d80cff0617fd5c5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 6 Oct 2019 23:45:25 +0200 Subject: [PATCH 01/20] Fix zero-size uninitialized boxes Requesting a zero-size allocation is not allowed, return a dangling pointer instead. CC https://github.com/rust-lang/rust/issues/63291#issuecomment-538692745 --- src/liballoc/boxed.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9b5d9431ae2..2693a64e13b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,6 +141,9 @@ impl Box { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { + if mem::size_of::() == 0 { + return Box(NonNull::dangling().into()) + } let layout = alloc::Layout::new::>(); let ptr = unsafe { Global.alloc(layout) @@ -181,10 +184,17 @@ impl Box<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - let layout = alloc::Layout::array::>(len).unwrap(); - let ptr = unsafe { alloc::alloc(layout) }; - let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); - let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + let ptr = if mem::size_of::() == 0 || len == 0 { + NonNull::dangling() + } else { + let layout = alloc::Layout::array::>(len).unwrap(); + unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + .cast() + } + }; + let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) }; Box(Unique::from(slice)) } } From ca1cfdab78d1966efd492cd550a3684f3b95527c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 16 Oct 2019 20:32:58 +0200 Subject: [PATCH 02/20] Uninitialized boxes: check for zero-size allocation based on Layout::size --- src/liballoc/boxed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2693a64e13b..567b8ea7224 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,10 +141,10 @@ impl Box { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { - if mem::size_of::() == 0 { + let layout = alloc::Layout::new::>(); + if layout.size() == 0 { return Box(NonNull::dangling().into()) } - let layout = alloc::Layout::new::>(); let ptr = unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) @@ -184,10 +184,10 @@ impl Box<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - let ptr = if mem::size_of::() == 0 || len == 0 { + let layout = alloc::Layout::array::>(len).unwrap(); + let ptr = if layout.size() == 0 { NonNull::dangling() } else { - let layout = alloc::Layout::array::>(len).unwrap(); unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) From 75f4dac5f38cfe46cf9ccd3b2c602a5e1336453c Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 16 Oct 2019 18:00:44 -0700 Subject: [PATCH 03/20] Add regression test for #65394 --- src/test/ui/consts/const-eval/issue-65394.rs | 13 +++++++++++++ src/test/ui/consts/const-eval/issue-65394.stderr | 11 +++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/consts/const-eval/issue-65394.rs create mode 100644 src/test/ui/consts/const-eval/issue-65394.stderr diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs new file mode 100644 index 00000000000..978e227bcc8 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-65394.rs @@ -0,0 +1,13 @@ +// Test for absence of validation mismatch ICE in #65394 + +#![feature(rustc_attrs)] + +#[rustc_mir(borrowck_graphviz_postflow="hello.dot")] +const _: Vec = { + let mut x = Vec::::new(); + let r = &mut x; //~ ERROR references in constants may only refer to immutable values + let y = x; + y +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr new file mode 100644 index 00000000000..f48c551cb50 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -0,0 +1,11 @@ +error[E0017]: references in constants may only refer to immutable values + --> $DIR/issue-65394.rs:8:13 + | +LL | let r = &mut x; + | ^^^^^^ constants require immutable values + +[ERROR rustc_mir::transform::qualify_consts] old validator: [($DIR/issue-65394.rs:8:13: 8:19, "MutBorrow(Mut { allow_two_phase_borrow: false })")] +[ERROR rustc_mir::transform::qualify_consts] new validator: [($DIR/issue-65394.rs:8:13: 8:19, "MutBorrow(Mut { allow_two_phase_borrow: false })"), ($DIR/issue-65394.rs:7:9: 7:14, "LiveDrop")] +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. From 22a0856641dec573ab3b83b09c57aa597ca87b19 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 16 Oct 2019 18:01:01 -0700 Subject: [PATCH 04/20] Enable `drain_filter` --- src/librustc_mir/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a837c34e8d4..98d5487870a 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,6 +14,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(core_intrinsics)] #![feature(const_fn)] #![feature(decl_macro)] +#![feature(drain_filter)] #![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(specialization)] From af691de9c1d9923e8a6b7965d1eebf21e1d87ad2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 16 Oct 2019 18:01:26 -0700 Subject: [PATCH 05/20] Suppress validation mismatch ICE in the presence of mut borrows --- src/librustc_mir/transform/qualify_consts.rs | 75 +++++++++++++++----- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index fbcf9c8cb5e..da1abb9747c 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1024,23 +1024,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { new_errors.dedup(); if self.errors != new_errors { - error!("old validator: {:?}", self.errors); - error!("new validator: {:?}", new_errors); - - // ICE on nightly if the validators do not emit exactly the same errors. - // Users can supress this panic with an unstable compiler flag (hopefully after - // filing an issue). - let opts = &self.tcx.sess.opts; - let trigger_ice = opts.unstable_features.is_nightly_build() - && !opts.debugging_opts.suppress_const_validation_back_compat_ice; - - if trigger_ice { - span_bug!( - body.span, - "{}", - VALIDATOR_MISMATCH_ERR, - ); - } + validator_mismatch( + self.tcx, + body, + std::mem::replace(&mut self.errors, vec![]), + new_errors, + ); } } @@ -1870,6 +1859,58 @@ fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option, + body: &Body<'tcx>, + mut old_errors: Vec<(Span, String)>, + mut new_errors: Vec<(Span, String)>, +) { + error!("old validator: {:?}", old_errors); + error!("new validator: {:?}", new_errors); + + // ICE on nightly if the validators do not emit exactly the same errors. + // Users can supress this panic with an unstable compiler flag (hopefully after + // filing an issue). + let opts = &tcx.sess.opts; + let strict_validation_enabled = opts.unstable_features.is_nightly_build() + && !opts.debugging_opts.suppress_const_validation_back_compat_ice; + + if !strict_validation_enabled { + return; + } + + // If this difference would cause a regression from the old to the new or vice versa, trigger + // the ICE. + if old_errors.is_empty() || new_errors.is_empty() { + span_bug!(body.span, "{}", VALIDATOR_MISMATCH_ERR); + } + + // HACK: Borrows that would allow mutation are forbidden in const contexts, but they cause the + // new validator to be more conservative about when a dropped local has been moved out of. + // + // Supress the mismatch ICE in cases where the validators disagree only on the number of + // `LiveDrop` errors and both observe the same sequence of `MutBorrow`s. + + let is_live_drop = |(_, s): &mut (_, String)| s.starts_with("LiveDrop"); + let is_mut_borrow = |(_, s): &&(_, String)| s.starts_with("MutBorrow"); + + let old_live_drops: Vec<_> = old_errors.drain_filter(is_live_drop).collect(); + let new_live_drops: Vec<_> = new_errors.drain_filter(is_live_drop).collect(); + + let only_live_drops_differ = old_live_drops != new_live_drops && old_errors == new_errors; + + let old_mut_borrows = old_errors.iter().filter(is_mut_borrow); + let new_mut_borrows = new_errors.iter().filter(is_mut_borrow); + + let at_least_one_mut_borrow = old_mut_borrows.clone().next().is_some(); + + if only_live_drops_differ && at_least_one_mut_borrow && old_mut_borrows.eq(new_mut_borrows) { + return; + } + + span_bug!(body.span, "{}", VALIDATOR_MISMATCH_ERR); +} + const VALIDATOR_MISMATCH_ERR: &str = r"Disagreement between legacy and dataflow-based const validators. After filing an issue, use `-Zsuppress-const-validation-back-compat-ice` to compile your code."; From b25e3238c76a4df767b4a929011ed47c479ed115 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 17 Oct 2019 16:09:32 -0700 Subject: [PATCH 06/20] Don't add `argc` and `argv` arguments to `main` on WASI. Add a target setting to allow targets to specify whether the generated `main` function should be passed `argc` and `argv` arguments. Set it to false on wasm32-wasi, since WASI's `args::args()` calls into the WASI APIs itself. This will allow the WASI toolchain to avoid linking and running command-line argument initialization code when the arguments aren't actually needed. --- src/librustc_codegen_ssa/base.rs | 25 ++++++++++++++++++------- src/librustc_target/spec/mod.rs | 6 ++++++ src/librustc_target/spec/wasm32_wasi.rs | 4 ++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 1c441ca7cbf..546972903e9 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -414,8 +414,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' rust_main_def_id: DefId, use_start_lang_item: bool, ) { - let llfty = - cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()); + let llfty = if cx.sess().target.target.options.main_needs_argc_argv { + cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) + } else { + cx.type_func(&[], cx.type_int()) + }; let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -445,11 +448,19 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' bx.insert_reference_to_gdb_debug_scripts_section_global(); - // Params from native main() used as args for rust start function - let param_argc = bx.get_param(0); - let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); - let arg_argv = param_argv; + let (arg_argc, arg_argv) = if cx.sess().target.target.options.main_needs_argc_argv { + // Params from native main() used as args for rust start function + let param_argc = bx.get_param(0); + let param_argv = bx.get_param(1); + let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argv = param_argv; + (arg_argc, arg_argv) + } else { + // The Rust start function doesn't need argc and argv, so just pass zeros. + let arg_argc = bx.const_int(cx.type_int(), 0); + let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); + (arg_argc, arg_argv) + }; let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index cf1a84dec97..c5277c4f90e 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -691,6 +691,9 @@ pub struct TargetOptions { /// defined in libgcc. If this option is enabled, the target must provide /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, + /// Whether the runtime startup code requires the `main` function be passed + /// `argc` and `argv` values. + pub main_needs_argc_argv: bool, /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for /// this target. @@ -849,6 +852,7 @@ impl Default for TargetOptions { link_env_remove: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, + main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, @@ -1159,6 +1163,7 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); + key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); @@ -1376,6 +1381,7 @@ impl ToJson for Target { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); + target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(no_integrated_as); diff --git a/src/librustc_target/spec/wasm32_wasi.rs b/src/librustc_target/spec/wasm32_wasi.rs index 86978c05b15..d5ef230dcf7 100644 --- a/src/librustc_target/spec/wasm32_wasi.rs +++ b/src/librustc_target/spec/wasm32_wasi.rs @@ -101,6 +101,10 @@ pub fn target() -> Result { // without a main function. options.crt_static_allows_dylibs = true; + // WASI's `sys::args::init` function ignores its arguments; instead, + // `args::args()` makes the WASI API calls itself. + options.main_needs_argc_argv = false; + Ok(Target { llvm_target: "wasm32-wasi".to_string(), target_endian: "little".to_string(), From 11011013f2b609b6cf58c96555b9e31dfd19d7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 17 Oct 2019 19:00:19 -0700 Subject: [PATCH 07/20] Refer to "associated functions" instead of "static methods" --- src/librustc_resolve/error_codes.rs | 22 ++++++++++++++-------- src/librustc_resolve/late/diagnostics.rs | 22 ++++++++++------------ src/libsyntax_ext/deriving/clone.rs | 22 +++++++++------------- src/libsyntax_ext/deriving/default.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +--- src/test/ui/error-codes/E0424.stderr | 2 +- src/test/ui/resolve/issue-2356.stderr | 4 ++-- 7 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index ab3d95dd8ed..29ca797fc06 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1013,7 +1013,12 @@ fn h1() -> i32 { "##, E0424: r##" -The `self` keyword was used in a static method. +The `self` keyword was used inside of an associated function instead of inside +of a method. Associated functions have no "`self` receiver" argument, and are +equivalent to regular functions which exist in the namespace of a trait. +Methods, on the other hand, have a `self` reciver argument, like `self`, +`&self`, `&mut self` or `self: &mut Pin` (this last one is an example of +an ["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). Erroneous code example: @@ -1021,25 +1026,26 @@ Erroneous code example: struct Foo; impl Foo { - fn bar(self) {} + // `bar` is a method, because it has a receiver argument. + fn bar(&self) {} + // `foo` is an associated function, because it has no receiver argument. fn foo() { - self.bar(); // error: `self` is not available in a static method. + self.bar(); // error: `self` is not available in an associated function } } ``` -Please check if the method's argument list should have contained `self`, -`&self`, or `&mut self` (in case you didn't want to create a static -method), and add it if so. Example: +Check if the associated function's argument list should have contained a `self` +receiver for it to be a method, and add it if so. Example: ``` struct Foo; impl Foo { - fn bar(self) {} + fn bar(&self) {} - fn foo(self) { + fn foo(self) { // `foo` is now a method. self.bar(); // ok! } } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 412734eabe0..dba4226e983 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -115,8 +115,10 @@ impl<'a> LateResolutionVisitor<'a, '_> { if is_self_type(path, ns) { syntax::diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); - err.span_label(span, format!("`Self` is only available in impls, traits, \ - and type definitions")); + err.span_label( + span, + format!("`Self` is only available in impls, traits, and type definitions"), + ); return (err, Vec::new()); } if is_self_value(path, ns) { @@ -125,16 +127,12 @@ impl<'a> LateResolutionVisitor<'a, '_> { syntax::diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); err.span_label(span, match source { - PathSource::Pat => { - format!("`self` value is a keyword \ - and may not be bound to \ - variables or shadowed") - } - _ => { - format!("`self` value is a keyword \ - only available in methods \ - with `self` parameter") - } + PathSource::Pat => format!( + "`self` value is a keyword and may not be bound to variables or shadowed", + ), + _ => format!( + "`self` value is a keyword only available in methods with a `self` parameter", + ), }); return (err, Vec::new()); } diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index eb7d480aa98..67ef69babdc 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -174,14 +174,12 @@ fn cs_clone(name: &str, all_fields = af; vdata = &variant.data; } - EnumNonMatchingCollapsed(..) => { - cx.span_bug(trait_span, - &format!("non-matching enum variants in \ - `derive({})`", - name)) - } + EnumNonMatchingCollapsed(..) => cx.span_bug(trait_span, &format!( + "non-matching enum variants in `derive({})`", + name, + )), StaticEnum(..) | StaticStruct(..) => { - cx.span_bug(trait_span, &format!("static method in `derive({})`", name)) + cx.span_bug(trait_span, &format!("associated function in `derive({})`", name)) } } @@ -191,12 +189,10 @@ fn cs_clone(name: &str, .map(|field| { let ident = match field.name { Some(i) => i, - None => { - cx.span_bug(trait_span, - &format!("unnamed field in normal struct in \ - `derive({})`", - name)) - } + None => cx.span_bug(trait_span, &format!( + "unnamed field in normal struct in `derive({})`", + name, + )), }; let call = subcall(cx, field); cx.field_imm(field.span, ident, call) diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index 6176791c31b..cfc0f3cd6cb 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -75,6 +75,6 @@ fn default_substructure(cx: &mut ExtCtxt<'_>, // let compilation continue DummyResult::raw_expr(trait_span, true) } - _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"), + _ => cx.span_bug(trait_span, "method in `derive(Default)`"), }; } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1886a5154b7..fd2c1552d32 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1055,9 +1055,7 @@ impl<'a> MethodDef<'a> { }) .collect() } else { - cx.span_bug(trait_.span, - "no self arguments to non-static method in generic \ - `derive`") + cx.span_bug(trait_.span, "no self arguments for method in generic `derive`") }; // body of the inner most destructuring match diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index d67a2660dac..99b5e01abb1 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -2,7 +2,7 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | LL | self.bar(); - | ^^^^ `self` value is a keyword only available in methods with `self` parameter + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0424]: expected unit struct/variant or constant, found module `self` --> $DIR/E0424.rs:12:9 diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 7790383843e..e0a2088ab8b 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -62,7 +62,7 @@ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | LL | if self.whiskers > 3 { - | ^^^^ `self` value is a keyword only available in methods with `self` parameter + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -98,7 +98,7 @@ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | LL | self += 1; - | ^^^^ `self` value is a keyword only available in methods with `self` parameter + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error: aborting due to 17 previous errors From d8fca9ee4ea9399dc8244f744f0198821d233ecf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 09:24:56 +1100 Subject: [PATCH 08/20] Use `with` in `Symbol` trait methods. Instead of `as_str()`, which unnecessarily involves `LocalInternedString`. --- src/libsyntax_pos/symbol.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 8845b66a7ce..e4f309259e7 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -934,19 +934,19 @@ impl Symbol { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) + self.with(|str| fmt::Display::fmt(&str, f)) } } impl fmt::Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.as_str(), f) + self.with(|str| fmt::Display::fmt(&str, f)) } } impl Encodable for Symbol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) + self.with(|string| s.emit_str(string)) } } From 3532863a96499df049589aa5120db149498ab544 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 10:06:23 +1100 Subject: [PATCH 09/20] Change how `Symbol::Debug` works. Currently, `Symbol::Debug` and `Symbol::Display` produce the same output; neither wraps the symbol in double quotes. This commit changes `Symbol::Debug` so it wraps the symbol in quotes. This change brings `Symbol`'s behaviour in line with `String` and `InternedString`. The change requires a couple of trivial test output adjustments. --- src/libsyntax_pos/symbol.rs | 2 +- src/test/ui/hygiene/unpretty-debug.stdout | 2 +- .../lint/redundant-semicolon/redundant-semi-proc-macro.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index e4f309259e7..efb01ff84dc 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -934,7 +934,7 @@ impl Symbol { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.with(|str| fmt::Display::fmt(&str, f)) + self.with(|str| fmt::Debug::fmt(&str, f)) } } diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index 6971873ba60..acd852103ca 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -17,7 +17,7 @@ fn y /* 0#0 */() { } /* Expansions: 0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root -1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo) +1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo") SyntaxContexts: #0: parent: #0, outer_mark: (ExpnId(0), Opaque) diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index 5f289c0914d..2160df51a83 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | From f65a492afcd9cd892a1a5591f938efd41b5e0d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 17 Oct 2019 20:26:21 -0700 Subject: [PATCH 10/20] Point at enclosing function without `self` receiver --- src/librustc_resolve/late.rs | 8 +++++++- src/librustc_resolve/late/diagnostics.rs | 3 +++ src/test/ui/error-codes/E0424.stderr | 14 ++++++++++---- src/test/ui/resolve/issue-2356.stderr | 18 ++++++++++++++---- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index bb9f895c5f3..73a282b1a0e 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -345,6 +345,9 @@ struct LateResolutionVisitor<'a, 'b> { /// The current self item if inside an ADT (used for better errors). current_self_item: Option, + /// The current enclosing funciton (used for better errors). + current_function: Option, + /// A list of labels as of yet unused. Labels will be removed from this map when /// they are used (in a `break` or `continue` statement) unused_labels: FxHashMap, @@ -415,7 +418,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { } } } - fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) { + fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, sp: Span, _: NodeId) { + let previous_value = replace(&mut self.current_function, Some(sp)); debug!("(resolving function) entering function"); let rib_kind = match fn_kind { FnKind::ItemFn(..) => FnItemRibKind, @@ -441,6 +445,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { debug!("(resolving function) leaving function"); }) }); + self.current_function = previous_value; } fn visit_generics(&mut self, generics: &'tcx Generics) { @@ -546,6 +551,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { current_trait_assoc_types: Vec::new(), current_self_type: None, current_self_item: None, + current_function: None, unused_labels: Default::default(), current_type_ascription: Vec::new(), } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index dba4226e983..2721df4c687 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -134,6 +134,9 @@ impl<'a> LateResolutionVisitor<'a, '_> { "`self` value is a keyword only available in methods with a `self` parameter", ), }); + if let Some(span) = &self.current_function { + err.span_label(*span, "this function doesn't have a `self` parameter"); + } return (err, Vec::new()); } diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index 99b5e01abb1..567d1b3cc75 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -1,14 +1,20 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | -LL | self.bar(); - | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | / fn foo() { +LL | | self.bar(); + | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | | } + | |_____- this function doesn't have a `self` parameter error[E0424]: expected unit struct/variant or constant, found module `self` --> $DIR/E0424.rs:12:9 | -LL | let self = "self"; - | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed +LL | / fn main () { +LL | | let self = "self"; + | | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed +LL | | } + | |_- this function doesn't have a `self` parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index e0a2088ab8b..329543114a6 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -61,8 +61,14 @@ LL | purr(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | -LL | if self.whiskers > 3 { - | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | / fn meow() { +LL | | if self.whiskers > 3 { + | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | | +LL | | println!("MEOW"); +LL | | } +LL | | } + | |___- this function doesn't have a `self` parameter error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -97,8 +103,12 @@ LL | purr_louder(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | -LL | self += 1; - | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | / fn main() { +LL | | self += 1; + | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | | +LL | | } + | |_- this function doesn't have a `self` parameter error: aborting due to 17 previous errors From 0879f630741550f0d4989e908071de0bb05a50f1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 16:05:14 +1100 Subject: [PATCH 11/20] Remove `Copy` and `Clone` impls for `LocalInternedString`. They aren't used. --- src/libsyntax_pos/symbol.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index efb01ff84dc..fa9567fb62c 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1106,8 +1106,8 @@ fn with_interner T>(f: F) -> T { } /// An alternative to `Symbol` and `InternedString`, useful when the chars -/// within the symbol need to be accessed. It is best used for temporary -/// values. +/// within the symbol need to be accessed. It deliberately has limited +/// functionality and should only be used for temporary values. /// /// Because the interner outlives any thread which uses this type, we can /// safely treat `string` which points to interner data, as an immortal string, @@ -1116,7 +1116,7 @@ fn with_interner T>(f: F) -> T { // FIXME: ensure that the interner outlives any thread which uses // `LocalInternedString`, by creating a new thread right after constructing the // interner. -#[derive(Clone, Copy, Eq, PartialOrd, Ord)] +#[derive(Eq, PartialOrd, Ord)] pub struct LocalInternedString { string: &'static str, } From d343ee839b6fe26c992d0609281443776839039c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 16:36:17 +1100 Subject: [PATCH 12/20] Remove `Hash` impls for `DefPath`, `DisambiguatedDefPathData`, and `DefKey`. They aren't used. --- src/librustc/hir/map/definitions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index cc099fcc40f..d2732c92d26 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -111,7 +111,7 @@ pub struct Definitions { /// A unique identifier that we can use to lookup a definition /// precisely. It combines the index of the definition's parent (if /// any) with a `DisambiguatedDefPathData`. -#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub struct DefKey { /// The parent path. pub parent: Option, @@ -162,13 +162,13 @@ impl DefKey { /// between them. This introduces some artificial ordering dependency /// but means that if you have, e.g., two impls for the same type in /// the same module, they do get distinct `DefId`s. -#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { pub data: DefPathData, pub disambiguator: u32 } -#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct DefPath { /// The path leading from the crate root to the item. pub data: Vec, From 865c4bcff6b52f69b4122e3a0f02f647cf588553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Oct 2019 08:36:46 -0700 Subject: [PATCH 13/20] review comments: help wording --- src/librustc_resolve/error_codes.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 29ca797fc06..ee207025e0c 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1013,12 +1013,12 @@ fn h1() -> i32 { "##, E0424: r##" -The `self` keyword was used inside of an associated function instead of inside -of a method. Associated functions have no "`self` receiver" argument, and are -equivalent to regular functions which exist in the namespace of a trait. -Methods, on the other hand, have a `self` reciver argument, like `self`, -`&self`, `&mut self` or `self: &mut Pin` (this last one is an example of -an ["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). +The `self` keyword was used inside of an associated function without a "`self` +receiver" parameter. The `self` keyword can only be used inside methods, which +are associated functions (functions defined inside of a `trait` or `impl` block) +that have a `self` receiver as its first parameter, like `self`, `&self`, +`&mut self` or `self: &mut Pin` (this last one is an example of an +["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). Erroneous code example: @@ -1026,17 +1026,18 @@ Erroneous code example: struct Foo; impl Foo { - // `bar` is a method, because it has a receiver argument. + // `bar` is a method, because it has a receiver parameter. fn bar(&self) {} - // `foo` is an associated function, because it has no receiver argument. + // `foo` is not a method, because it has no receiver parameter. fn foo() { - self.bar(); // error: `self` is not available in an associated function + self.bar(); // error: `self` value is a keyword only available in + // methods with a `self` parameter } } ``` -Check if the associated function's argument list should have contained a `self` +Check if the associated function's parameter list should have contained a `self` receiver for it to be a method, and add it if so. Example: ``` From bd813bf1acbef7643a06278af48603397c7eb5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Oct 2019 08:38:08 -0700 Subject: [PATCH 14/20] review comment: span bug label --- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index fd2c1552d32..216338c1a88 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1055,7 +1055,7 @@ impl<'a> MethodDef<'a> { }) .collect() } else { - cx.span_bug(trait_.span, "no self arguments for method in generic `derive`") + cx.span_bug(trait_.span, "no `self` parameter for method in generic `derive`") }; // body of the inner most destructuring match From 2b76c8b95ff866d8806fdc82fe270c4df02efc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Oct 2019 13:00:14 -0700 Subject: [PATCH 15/20] review comments --- src/librustc_resolve/error_codes.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index ee207025e0c..2288aab3c27 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1014,11 +1014,7 @@ fn h1() -> i32 { E0424: r##" The `self` keyword was used inside of an associated function without a "`self` -receiver" parameter. The `self` keyword can only be used inside methods, which -are associated functions (functions defined inside of a `trait` or `impl` block) -that have a `self` receiver as its first parameter, like `self`, `&self`, -`&mut self` or `self: &mut Pin` (this last one is an example of an -["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). +receiver" parameter. Erroneous code example: @@ -1037,6 +1033,12 @@ impl Foo { } ``` +The `self` keyword can only be used inside methods, which are associated +functions (functions defined inside of a `trait` or `impl` block) that have a +`self` receiver as its first parameter, like `self`, `&self`, `&mut self` or +`self: &mut Pin` (this last one is an example of an ["abitrary `self` +type"](https://github.com/rust-lang/rust/issues/44874)). + Check if the associated function's parameter list should have contained a `self` receiver for it to be a method, and add it if so. Example: From 2d3c17a609e672120305e084314cba2f98308399 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Oct 2019 01:08:17 +0300 Subject: [PATCH 16/20] resolve: Mark macros starting with an underscore as used --- src/librustc_resolve/build_reduced_graph.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index eadae52c250..50ff01b3913 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1064,8 +1064,17 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { None } + // Mark the given macro as unused unless its name starts with `_`. + // Macro uses will remove items from this set, and the remaining + // items will be reported as `unused_macros`. + fn insert_unused_macro(&mut self, ident: Ident, node_id: NodeId, span: Span) { + if !ident.as_str().starts_with("_") { + self.r.unused_macros.insert(node_id, span); + } + } + fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { - let parent_scope = &self.parent_scope; + let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let (ext, ident, span, is_legacy) = match &item.kind { ItemKind::MacroDef(def) => { @@ -1105,7 +1114,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { (res, vis, span, expansion, IsMacroExport)); } else { self.r.check_reserved_macro_name(ident, res); - self.r.unused_macros.insert(item.id, span); + self.insert_unused_macro(ident, item.id, span); } LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding { parent_legacy_scope: parent_scope.legacy, binding, ident @@ -1114,7 +1123,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let module = parent_scope.module; let vis = self.resolve_visibility(&item.vis); if vis != ty::Visibility::Public { - self.r.unused_macros.insert(item.id, span); + self.insert_unused_macro(ident, item.id, span); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.parent_scope.legacy From 7ce85f2dca545c9012fdc13c90cb2b058e58d3dd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Oct 2019 01:41:47 +0300 Subject: [PATCH 17/20] expand: Simplify expansion of derives And make it more uniform with other macros. By merging placeholders for future derives' outputs into the derive container's output fragment early. --- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 10 ------- src/librustc_resolve/macros.rs | 8 ++--- src/libsyntax/lib.rs | 1 + src/libsyntax_expand/base.rs | 3 +- src/libsyntax_expand/expand.rs | 33 ++++++++++++++------- src/libsyntax_expand/placeholders.rs | 11 +------ 7 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index fbef95fec7d..9be339be703 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -90,7 +90,7 @@ impl<'a> DefCollector<'a> { } } - pub fn visit_macro_invoc(&mut self, id: NodeId) { + fn visit_macro_invoc(&mut self, id: NodeId) { self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 50ff01b3913..e261d3af61f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -163,25 +163,15 @@ impl<'a> Resolver<'a> { Some(ext) } - // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. crate fn build_reduced_graph( &mut self, fragment: &AstFragment, - extra_placeholders: &[NodeId], parent_scope: ParentScope<'a>, ) -> LegacyScope<'a> { let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); fragment.visit_with(&mut def_collector); - for placeholder in extra_placeholders { - def_collector.visit_macro_invoc(*placeholder); - } - let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); - for placeholder in extra_placeholders { - visitor.parent_scope.legacy = visitor.visit_invoc(*placeholder); - } - visitor.parent_scope.legacy } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c91a0b2ed98..94fe0cc5740 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -108,15 +108,11 @@ impl<'a> base::Resolver for Resolver<'a> { }); } - // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. - fn visit_ast_fragment_with_placeholders( - &mut self, expansion: ExpnId, fragment: &AstFragment, extra_placeholders: &[NodeId] - ) { + fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) { // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; - let output_legacy_scope = - self.build_reduced_graph(fragment, extra_placeholders, parent_scope); + let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); self.output_legacy_scopes.insert(expansion, output_legacy_scope); parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index a68b7fdf931..261cc53e158 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -11,6 +11,7 @@ #![feature(const_fn)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] +#![feature(decl_macro)] #![feature(label_break_value)] #![feature(nll)] #![feature(try_trait)] diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index 593e06f29b9..c222e7357ac 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -851,8 +851,7 @@ pub trait Resolver { fn next_node_id(&mut self) -> NodeId; fn resolve_dollar_crates(&mut self); - fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - extra_placeholders: &[NodeId]); + fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn expansion_for_ast_pass( diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index 47b4bca314a..f03d464eafb 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -26,7 +26,6 @@ use errors::{Applicability, FatalError}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, DUMMY_SP, FileName}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::io::ErrorKind; use std::{iter, mem, slice}; @@ -75,6 +74,22 @@ macro_rules! ast_fragments { } impl AstFragment { + pub fn add_placeholders(&mut self, placeholders: &[NodeId]) { + if placeholders.is_empty() { + return; + } + match self { + $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| { + // We are repeating through arguments with `many`, to do that we have to + // mention some macro variable from those arguments even if it's not used. + #[cfg_attr(bootstrap, allow(unused_macros))] + macro _repeating($flat_map_ast_elt) {} + placeholder(AstFragmentKind::$Kind, *id).$make_ast() + })),)?)* + _ => panic!("unexpected AST fragment kind") + } + } + pub fn make_opt_expr(self) -> Option> { match self { AstFragment::OptExpr(expr) => expr, @@ -342,7 +357,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); - let mut all_derive_placeholders: FxHashMap> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -420,9 +434,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.resolver.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); } - let derive_placeholders = - all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); - derive_placeholders.reserve(derives.len()); + let mut derive_placeholders = Vec::with_capacity(derives.len()); invocations.reserve(derives.len()); for path in derives { let expn_id = ExpnId::fresh(None); @@ -438,7 +450,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } let fragment = invoc.fragment_kind .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derive_placeholders) + self.collect_invocations(fragment, &derive_placeholders) } }; @@ -457,10 +469,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derive_placeholders = - all_derive_placeholders.remove(&expn_id).unwrap_or_else(Vec::new); placeholder_expander.add(NodeId::placeholder_from_expn_id(expn_id), - expanded_fragment, derive_placeholders); + expanded_fragment); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -493,13 +503,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { monotonic: self.monotonic, }; fragment.mut_visit_with(&mut collector); + fragment.add_placeholders(extra_placeholders); collector.invocations }; - // FIXME: Merge `extra_placeholders` into the `fragment` as regular placeholders. if self.monotonic { self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.id, &fragment, extra_placeholders); + self.cx.current_expansion.id, &fragment + ); } (fragment, invocations) diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index f2c89e14b53..21d8a21aa39 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -171,17 +171,8 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec) { + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); - if let AstFragment::Items(mut items) = fragment { - for placeholder in placeholders { - match self.remove(placeholder) { - AstFragment::Items(derived_items) => items.extend(derived_items), - _ => unreachable!(), - } - } - fragment = AstFragment::Items(items); - } self.expanded_fragments.insert(id, fragment); } From 25cc99fca0650f54828e8ba7ad2bab341b231fcc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 16 Oct 2019 00:01:47 +0300 Subject: [PATCH 18/20] privacy: Avoid one more `unwrap` causing an ICE in rustdoc The issue is rustdoc-specific because its root cause if the `everybody_loops` pass makes some def-ids to not have local hir-ids --- src/librustc_privacy/lib.rs | 10 +++++----- src/test/rustdoc/macro-in-closure.rs | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/macro-in-closure.rs diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f44692b7aea..a3a4ccf5d65 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -880,11 +880,11 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { self.tcx, self.tcx.hir().local_def_id(md.hir_id) ).unwrap(); - let mut module_id = self.tcx.hir().as_local_hir_id(macro_module_def_id).unwrap(); - if !self.tcx.hir().is_hir_id_module(module_id) { - // `module_id` doesn't correspond to a `mod`, return early (#63164). - return; - } + let mut module_id = match self.tcx.hir().as_local_hir_id(macro_module_def_id) { + Some(module_id) if self.tcx.hir().is_hir_id_module(module_id) => module_id, + // `module_id` doesn't correspond to a `mod`, return early (#63164, #65252). + _ => return, + }; let level = if md.vis.node.is_pub() { self.get(module_id) } else { None }; let new_level = self.update(md.hir_id, level); if new_level.is_none() { diff --git a/src/test/rustdoc/macro-in-closure.rs b/src/test/rustdoc/macro-in-closure.rs new file mode 100644 index 00000000000..298ff601de8 --- /dev/null +++ b/src/test/rustdoc/macro-in-closure.rs @@ -0,0 +1,9 @@ +// Regression issue for rustdoc ICE encountered in PR #65252. + +#![feature(decl_macro)] + +fn main() { + || { + macro m() {} + }; +} From 7f89f04b41d4d1de85df2fd3ede61e4fc97d9e69 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 19 Oct 2019 00:54:17 +0300 Subject: [PATCH 19/20] Fix rebase --- src/libsyntax/lib.rs | 1 - src/libsyntax_expand/lib.rs | 1 + src/libsyntax_expand/placeholders.rs | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 261cc53e158..a68b7fdf931 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -11,7 +11,6 @@ #![feature(const_fn)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] -#![feature(decl_macro)] #![feature(label_break_value)] #![feature(nll)] #![feature(try_trait)] diff --git a/src/libsyntax_expand/lib.rs b/src/libsyntax_expand/lib.rs index 88e69d79397..db292b619be 100644 --- a/src/libsyntax_expand/lib.rs +++ b/src/libsyntax_expand/lib.rs @@ -1,4 +1,5 @@ #![feature(crate_visibility_modifier)] +#![feature(decl_macro)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index 21d8a21aa39..e595888dae7 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -1,7 +1,7 @@ use crate::base::ExtCtxt; use crate::expand::{AstFragment, AstFragmentKind}; -use syntax::ast::{self, NodeId}; +use syntax::ast; use syntax::source_map::{DUMMY_SP, dummy_spanned}; use syntax::tokenstream::TokenStream; use syntax::mut_visit::*; From 227db40a98e5bd903aa3658c16f19a3d6f694deb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 16 Oct 2019 20:33:55 +0200 Subject: [PATCH 20/20] Uninitialized boxes: add test for zero-size allocations --- src/liballoc/tests/boxed.rs | 18 ++++++++++++++++++ src/liballoc/tests/lib.rs | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 src/liballoc/tests/boxed.rs diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs new file mode 100644 index 00000000000..bc3d53bf30d --- /dev/null +++ b/src/liballoc/tests/boxed.rs @@ -0,0 +1,18 @@ +use std::ptr::NonNull; +use std::mem::MaybeUninit; + +#[test] +fn unitialized_zero_size_box() { + assert_eq!( + &*Box::<()>::new_uninit() as *const _, + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[()]>::new_uninit_slice(4).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[String]>::new_uninit_slice(0).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); +} diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 5723a30c0f3..59f5c8dfb8a 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -2,6 +2,7 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] +#![feature(new_uninit)] #![feature(option_flattening)] #![feature(pattern)] #![feature(repeat_generic_slice)] @@ -15,6 +16,7 @@ use std::collections::hash_map::DefaultHasher; mod arc; mod binary_heap; +mod boxed; mod btree; mod cow_str; mod fmt;