diff --git a/Cargo.lock b/Cargo.lock index a9e65ffc39107..c1011c0f479cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -593,7 +593,7 @@ dependencies = [ "rustc-semver", "semver 0.11.0", "serde", - "smallvec 1.4.2", + "smallvec 1.6.1", "syn", "toml", "unicode-normalization", @@ -2086,7 +2086,7 @@ checksum = "22bf8d885d073610aee20e7fa205c4341ed32a761dbde96da5fd96301a8d3e82" dependencies = [ "parking_lot", "rustc-hash", - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] @@ -2236,7 +2236,7 @@ dependencies = [ "rustc-workspace-hack", "rustc_version", "shell-escape", - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] @@ -2459,7 +2459,7 @@ dependencies = [ "instant", "libc", "redox_syscall", - "smallvec 1.4.2", + "smallvec 1.6.1", "winapi 0.3.9", ] @@ -3110,7 +3110,7 @@ version = "705.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93575affa286089b92c8208aea4e60fe9fdd251a619a09b566d6e4e2cc123212" dependencies = [ - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] @@ -3126,7 +3126,7 @@ dependencies = [ "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3201,7 +3201,7 @@ dependencies = [ "rustc-hash", "rustc-rayon", "rustc-rayon-core", - "smallvec 1.4.2", + "smallvec 1.6.1", "stable_deref_trait", "stacker", "tempfile", @@ -3249,7 +3249,7 @@ dependencies = [ "rustc-ap-rustc_serialize", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3337,7 +3337,7 @@ dependencies = [ "rustc-ap-rustc_lexer", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", "unicode-normalization", ] @@ -3349,7 +3349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc232e2a351d8131c8f1386ce372ee22ef7b1b0b897bbf817a8ce4792029a564" dependencies = [ "indexmap", - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] @@ -3497,8 +3497,8 @@ dependencies = [ "quote", "serde", "serde_json", - "smallvec 0.6.13", - "smallvec 1.4.2", + "smallvec 0.6.14", + "smallvec 1.6.1", "syn", "url 2.1.1", "winapi 0.3.9", @@ -3509,14 +3509,14 @@ name = "rustc_apfloat" version = "0.0.0" dependencies = [ "bitflags", - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] name = "rustc_arena" version = "0.0.0" dependencies = [ - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] @@ -3530,7 +3530,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3548,7 +3548,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3611,7 +3611,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3639,7 +3639,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "snap", "tracing", ] @@ -3697,7 +3697,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", - "smallvec 1.4.2", + "smallvec 1.6.1", "stable_deref_trait", "stacker", "tempfile", @@ -3778,7 +3778,7 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3810,7 +3810,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3868,7 +3868,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -3909,7 +3909,7 @@ dependencies = [ "rustc_traits", "rustc_ty_utils", "rustc_typeck", - "smallvec 1.4.2", + "smallvec 1.6.1", "tempfile", "tracing", "winapi 0.3.9", @@ -3999,7 +3999,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "snap", "stable_deref_trait", "tracing", @@ -4031,7 +4031,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_type_ir", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4062,7 +4062,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4085,7 +4085,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4102,7 +4102,7 @@ dependencies = [ "rustc_lexer", "rustc_session", "rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", "unicode-normalization", ] @@ -4178,7 +4178,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4202,7 +4202,7 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4231,7 +4231,7 @@ version = "0.0.0" dependencies = [ "indexmap", "rustc_macros", - "smallvec 1.4.2", + "smallvec 1.6.1", ] [[package]] @@ -4328,7 +4328,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4348,7 +4348,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_trait_selection", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4398,7 +4398,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.4.2", + "smallvec 1.6.1", "tracing", ] @@ -4425,7 +4425,7 @@ dependencies = [ "rustdoc-json-types", "serde", "serde_json", - "smallvec 1.4.2", + "smallvec 1.6.1", "tempfile", ] @@ -4759,18 +4759,18 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" dependencies = [ "maybe-uninit", ] [[package]] name = "smallvec" -version = "1.4.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "snap" @@ -5237,7 +5237,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec 1.4.2", + "smallvec 1.6.1", "thread_local", "tracing", "tracing-core", diff --git a/compiler/rustc_apfloat/Cargo.toml b/compiler/rustc_apfloat/Cargo.toml index 306513f1a7eaf..103e64be5ac0b 100644 --- a/compiler/rustc_apfloat/Cargo.toml +++ b/compiler/rustc_apfloat/Cargo.toml @@ -6,4 +6,4 @@ edition = "2018" [dependencies] bitflags = "1.2.1" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_arena/Cargo.toml b/compiler/rustc_arena/Cargo.toml index 29caa852ed47e..f2d039c82ab7f 100644 --- a/compiler/rustc_arena/Cargo.toml +++ b/compiler/rustc_arena/Cargo.toml @@ -5,4 +5,4 @@ version = "0.0.0" edition = "2018" [dependencies] -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 13e17a807c484..6b9b9e8155ed2 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -15,5 +15,5 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } bitflags = "1.2.1" diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 177a9066edf5d..0cced00189eb5 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -19,4 +19,4 @@ rustc_span = { path = "../rustc_span" } rustc_errors = { path = "../rustc_errors" } rustc_session = { path = "../rustc_session" } rustc_ast = { path = "../rustc_ast" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index eb022b5b2b16e..962dfbac934c7 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -19,7 +19,7 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_parse = { path = "../rustc_parse" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_expand = { path = "../rustc_expand" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index f9373640dce5e..ebbb852f21cc8 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -29,6 +29,6 @@ rustc_llvm = { path = "../rustc_llvm" } rustc_session = { path = "../rustc_session" } rustc_serialize = { path = "../rustc_serialize" } rustc_target = { path = "../rustc_target" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 23e689fcae796..e3476517de583 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -22,7 +22,7 @@ stable_deref_trait = "1.0.0" rayon = { version = "0.3.0", package = "rustc-rayon" } rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } rustc-hash = "1.1.0" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_index = { path = "../rustc_index", package = "rustc_index" } bitflags = "1.2.1" measureme = "9.0.0" diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 7413b0d9431f9..59c1604e8444c 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -23,5 +23,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_lexer = { path = "../rustc_lexer" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index c14165454ed8f..d41b81f8f217d 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -17,4 +17,4 @@ rustc_span = { path = "../rustc_span" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } tracing = "0.1" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 6dbcfb963ee0e..473477bf22da2 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -54,6 +54,7 @@ pub enum Target { ForeignTy, GenericParam(GenericParamKind), MacroDef, + Param, } impl Display for Target { @@ -96,6 +97,7 @@ impl Display for Target { GenericParamKind::Const => "const parameter", }, Target::MacroDef => "macro def", + Target::Param => "function param", } ) } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 5dba4106c9423..a75ad7b31a64e 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -20,5 +20,5 @@ rustc_session = { path = "../rustc_session" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 2481a27dee795..f3e4aab941b7e 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -11,7 +11,7 @@ doctest = false libc = "0.2" tracing = "0.1" rayon = { version = "0.3.0", package = "rustc-rayon" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index f1975e78801ef..2aabc2c407b1a 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -12,7 +12,7 @@ libc = "0.2" snap = "1" tracing = "0.1" memmap = "0.7" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_middle = { path = "../rustc_middle" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index d33aad3b71040..7de398a1898e5 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -27,7 +27,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } chalk-ir = "0.55.0" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } measureme = "9.0.0" rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_mir/Cargo.toml b/compiler/rustc_mir/Cargo.toml index 10dbf35fedcc9..59a0c9a5dd5b9 100644 --- a/compiler/rustc_mir/Cargo.toml +++ b/compiler/rustc_mir/Cargo.toml @@ -31,7 +31,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_apfloat = { path = "../rustc_apfloat" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } [dev-dependencies] coverage_test_macros = { path = "src/transform/coverage/test_macros" } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs index 98450f5a547da..0400431a542ee 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -1,6 +1,7 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; +use rustc_middle::hir::map::Map; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{ @@ -543,13 +544,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Attempt to search similar mutable associated items for suggestion. // In the future, attempt in all path but initially for RHS of for_loop fn suggest_similar_mut_method_for_for_loop(&self, err: &mut DiagnosticBuilder<'_>) { - let hir = self.infcx.tcx.hir(); - let node = hir.item(self.mir_hir_id()); use hir::{ - Expr, + BodyId, Expr, ExprKind::{Block, Call, DropTemps, Match, MethodCall}, + HirId, ImplItem, ImplItemKind, Item, ItemKind, }; - if let hir::ItemKind::Fn(_, _, body_id) = node.kind { + + fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option { + match hir_map.find(id) { + Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) + | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { + Some(*body_id) + } + _ => None, + } + } + let hir_map = self.infcx.tcx.hir(); + let mir_body_hir_id = self.mir_hir_id(); + if let Some(fn_body_id) = maybe_body_id_of_fn(&hir_map, mir_body_hir_id) { if let Block( hir::Block { expr: @@ -579,7 +591,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. }, _, - ) = hir.body(body_id).value.kind + ) = hir_map.body(fn_body_id).value.kind { let opt_suggestions = path_segment .hir_id diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 1635a95f46ec8..f4f69fc8ac62b 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -159,7 +159,7 @@ impl Inliner<'tcx> { } } - #[instrument(skip(self, caller_body))] + #[instrument(level = "debug", skip(self, caller_body))] fn is_mir_available(&self, callee: Instance<'tcx>, caller_body: &Body<'tcx>) -> bool { match callee.def { InstanceDef::Item(_) => { @@ -258,7 +258,7 @@ impl Inliner<'tcx> { None } - #[instrument(skip(self, callee_body))] + #[instrument(level = "debug", skip(self, callee_body))] fn should_inline(&self, callsite: CallSite<'tcx>, callee_body: &Body<'tcx>) -> bool { let tcx = self.tcx; diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir/src/transform/inline/cycle.rs index e4d403fbf60c0..4c24bec0ce3ad 100644 --- a/compiler/rustc_mir/src/transform/inline/cycle.rs +++ b/compiler/rustc_mir/src/transform/inline/cycle.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt}; // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking // this query riddiculously often. -#[instrument(skip(tcx, root, target))] +#[instrument(level = "debug", skip(tcx, root, target))] crate fn mir_callgraph_reachable( tcx: TyCtxt<'tcx>, (root, target): (ty::Instance<'tcx>, LocalDefId), @@ -27,7 +27,10 @@ crate fn mir_callgraph_reachable( !tcx.is_constructor(root.def_id()), "you should not call `mir_callgraph_reachable` on enum/struct constructor functions" ); - #[instrument(skip(tcx, param_env, target, stack, seen, recursion_limiter, caller))] + #[instrument( + level = "debug", + skip(tcx, param_env, target, stack, seen, recursion_limiter, caller) + )] fn process( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 7fc1c3a73af91..f46e94eea96c7 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -289,19 +289,19 @@ pub fn write_mir_pretty<'tcx>( } Ok(()) }; - match tcx.hir().body_const_context(def_id.expect_local()) { - None => render_body(w, tcx.optimized_mir(def_id))?, - // For `const fn` we want to render the optimized MIR. If you want the mir used in - // ctfe, you can dump the MIR after the `Deaggregator` optimization pass. - Some(rustc_hir::ConstContext::ConstFn) => { - render_body(w, tcx.optimized_mir(def_id))?; - writeln!(w)?; - writeln!(w, "// MIR FOR CTFE")?; - // Do not use `render_body`, as that would render the promoteds again, but these - // are shared between mir_for_ctfe and optimized_mir - write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?; - } - Some(_) => render_body(w, tcx.mir_for_ctfe(def_id))?, + + // For `const fn` we want to render both the optimized MIR and the MIR for ctfe. + if tcx.is_const_fn_raw(def_id) { + render_body(w, tcx.optimized_mir(def_id))?; + writeln!(w)?; + writeln!(w, "// MIR FOR CTFE")?; + // Do not use `render_body`, as that would render the promoteds again, but these + // are shared between mir_for_ctfe and optimized_mir + write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?; + } else { + let instance_mir = + tcx.instance_mir(ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id))); + render_body(w, instance_mir)?; } } Ok(()) diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 2dd894a67a6a1..b75221bb5d5cd 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -24,4 +24,4 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ast = { path = "../rustc_ast" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index f3f21b903ea08..010fe4fd524d4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -1079,7 +1079,10 @@ impl<'tcx> Witness<'tcx> { /// `is_under_guard` is used to inform if the pattern has a guard. If it /// has one it must not be inserted into the matrix. This shouldn't be /// relied on for soundness. -#[instrument(skip(cx, matrix, witness_preference, hir_id, is_under_guard, is_top_level))] +#[instrument( + level = "debug", + skip(cx, matrix, witness_preference, hir_id, is_under_guard, is_top_level) +)] fn is_useful<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, matrix: &Matrix<'p, 'tcx>, diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 52835e5c8a94d..c887729c35570 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -19,4 +19,4 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_ast = { path = "../rustc_ast" } unicode-normalization = "0.1.11" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0e3a722e082f2..2c79eeeb0e6d2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1101,17 +1101,6 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { intravisit::walk_arm(self, arm); } - fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) { - self.check_attributes( - macro_def.hir_id, - ¯o_def.attrs, - ¯o_def.span, - Target::MacroDef, - None, - ); - intravisit::walk_macro_def(self, macro_def); - } - fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) { let target = Target::from_foreign_item(f_item); self.check_attributes( @@ -1157,6 +1146,23 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { self.check_attributes(variant.id, variant.attrs, &variant.span, Target::Variant, None); intravisit::walk_variant(self, variant, generics, item_id) } + + fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) { + self.check_attributes( + macro_def.hir_id, + macro_def.attrs, + ¯o_def.span, + Target::MacroDef, + None, + ); + intravisit::walk_macro_def(self, macro_def); + } + + fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { + self.check_attributes(param.hir_id, param.attrs, ¶m.span, Target::Param, None); + + intravisit::walk_param(self, param); + } } fn is_c_like_enum(item: &Item<'_>) -> bool { diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index f38d62dec0046..d18a2a6faed6c 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -18,4 +18,4 @@ rustc_index = { path = "../rustc_index" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } parking_lot = "0.11" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 821f9ea4738fe..7441f4a9f22a4 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -26,4 +26,4 @@ rustc_index = { path = "../rustc_index" } rustc_metadata = { path = "../rustc_metadata" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 16c5dff734126..05fc6a4e11d43 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] indexmap = "1" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } [dev-dependencies] rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 9f265f37f35f6..4ccf657335fed 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1405,8 +1405,8 @@ fn update_disambiguator(expn_id: ExpnId) { }); if modified { - info!("Set disambiguator for {:?} (hash {:?})", expn_id, first_hash); - info!("expn_data = {:?}", expn_id.expn_data()); + debug!("Set disambiguator for {:?} (hash {:?})", expn_id, first_hash); + debug!("expn_data = {:?}", expn_id.expn_data()); // Verify that the new disambiguator makes the hash unique #[cfg(debug_assertions)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1c37a6b2aca18..ef062da3f6e89 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1604,6 +1604,7 @@ pub mod sym { use super::Symbol; use std::convert::TryInto; + #[doc(inline)] pub use super::sym_generated::*; // Used from a macro in `librustc_feature/accepted.rs` diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index a72c172918bb0..c5d4c2400f82a 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -22,4 +22,4 @@ rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 657d5c123e8e4..45853a66efc2a 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -91,7 +91,7 @@ pub fn codegen_fulfill_obligation<'tcx>( }); let impl_source = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, impl_source); - info!("Cache miss: {:?} => {:?}", trait_ref, impl_source); + debug!("Cache miss: {:?} => {:?}", trait_ref, impl_source); Ok(impl_source) }) } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index d4ced20f86319..95f79147efd43 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -647,7 +647,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ProcessResult::Unchanged } Err(selection_err) => { - info!("selecting trait at depth {} yielded Err", obligation.recursion_depth); + debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth); ProcessResult::Error(CodeSelectionError(selection_err)) } diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 8fdbc3b76b459..a7ce14afaa362 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -16,6 +16,6 @@ rustc_span = { path = "../rustc_span" } chalk-ir = "0.55.0" chalk-solve = "0.55.0" chalk-engine = "0.55.0" -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 2827163d854d5..cfcbc77c172fd 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -80,7 +80,7 @@ fn dropck_outlives<'tcx>( let cause = ObligationCause::dummy(); let mut constraints = DtorckConstraint::empty(); while let Some((ty, depth)) = ty_stack.pop() { - info!( + debug!( "{} kinds, {} overflows, {} ty_stack", result.kinds.len(), result.overflows.len(), diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml index e3ba0bea7e8e2..d92d317e34ad6 100644 --- a/compiler/rustc_typeck/Cargo.toml +++ b/compiler/rustc_typeck/Cargo.toml @@ -20,7 +20,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } -smallvec = { version = "1.0", features = ["union", "may_dangle"] } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 244eba8ad5e02..c9cc47b83e3d6 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2191,12 +2191,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::BareFn(ref bf) => { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); + tcx.mk_fn_ptr(self.ty_of_fn( bf.unsafety, bf.abi, &bf.decl, &hir::Generics::empty(), None, + Some(ast_ty), )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { @@ -2336,6 +2338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>, ident_span: Option, + hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); @@ -2367,12 +2370,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // only want to emit an error complaining about them if infer types (`_`) are not // allowed. `allow_ty_infer` gates this behavior. We check for the presence of // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. + crate::collect::placeholder_type_error( tcx, ident_span.map(|sp| sp.shrink_to_hi()), &generics.params[..], visitor.0, true, + hir_ty, ); } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 229127e95d93c..fce7ae8119e17 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -502,6 +502,7 @@ fn typeck_with_fallback<'tcx>( decl, &hir::Generics::empty(), None, + None, ) } else { tcx.fn_sig(def_id) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index c666cd774c478..d097f863ad2f9 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -40,13 +40,16 @@ use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::UpvarRegion; -use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, ProjectionKind}; +use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults, UpvarSubsts}; use rustc_session::lint; use rustc_span::sym; use rustc_span::{MultiSpan, Span, Symbol}; +use rustc_index::vec::Idx; +use rustc_target::abi::VariantIdx; + /// Describe the relationship between the paths of two places /// eg: /// - `foo` is ancestor of `foo.bar.baz` @@ -535,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, body: &'tcx hir::Body<'tcx>, ) { - let need_migrations = self.compute_2229_migrations_first_pass( + let need_migrations = self.compute_2229_migrations( closure_def_id, span, capture_clause, @@ -544,9 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if !need_migrations.is_empty() { - let need_migrations_hir_id = need_migrations.iter().map(|m| m.0).collect::>(); - - let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations_hir_id); + let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations); let local_def_id = closure_def_id.expect_local(); let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); @@ -573,15 +574,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - It would have been moved into the closure when `capture_disjoint_fields` wasn't /// enabled, **and** /// - It wasn't completely captured by the closure, **and** - /// - The type of the root variable needs Drop. - fn compute_2229_migrations_first_pass( + /// - One of the paths starting at this root variable, that is not captured needs Drop. + fn compute_2229_migrations( &self, closure_def_id: DefId, closure_span: Span, closure_clause: hir::CaptureBy, body: &'tcx hir::Body<'tcx>, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, - ) -> Vec<(hir::HirId, Ty<'tcx>)> { + ) -> Vec { fn resolve_ty>( fcx: &FnCtxt<'_, 'tcx>, span: Span, @@ -617,7 +618,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match closure_clause { // Only migrate if closure is a move closure - hir::CaptureBy::Value => need_migrations.push((var_hir_id, ty)), + hir::CaptureBy::Value => need_migrations.push(var_hir_id), hir::CaptureBy::Ref => {} } @@ -625,21 +626,277 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; }; - let is_moved = root_var_min_capture_list + let projections_list = root_var_min_capture_list .iter() - .any(|capture| matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue(_))); + .filter_map(|captured_place| match captured_place.info.capture_kind { + // Only care about captures that are moved into the closure + ty::UpvarCapture::ByValue(..) => { + Some(captured_place.place.projections.as_slice()) + } + ty::UpvarCapture::ByRef(..) => None, + }) + .collect::>(); + + let is_moved = !projections_list.is_empty(); let is_not_completely_captured = root_var_min_capture_list.iter().any(|capture| capture.place.projections.len() > 0); - if is_moved && is_not_completely_captured { - need_migrations.push((var_hir_id, ty)); + if is_moved + && is_not_completely_captured + && self.has_significant_drop_outside_of_captures( + closure_def_id, + closure_span, + ty, + projections_list, + ) + { + need_migrations.push(var_hir_id); } } need_migrations } + /// This is a helper function to `compute_2229_migrations_precise_pass`. Provided the type + /// of a root variable and a list of captured paths starting at this root variable (expressed + /// using list of `Projection` slices), it returns true if there is a path that is not + /// captured starting at this root variable that implements Drop. + /// + /// FIXME(project-rfc-2229#35): This should return true only for significant drops. + /// A drop is significant if it's implemented by the user or does + /// anything that will have any observable behavior (other than + /// freeing up memory). + /// + /// The way this function works is at a given call it looks at type `base_path_ty` of some base + /// path say P and then list of projection slices which represent the different captures moved + /// into the closure starting off of P. + /// + /// This will make more sense with an example: + /// + /// ```rust + /// #![feature(capture_disjoint_fields)] + /// + /// struct FancyInteger(i32); // This implements Drop + /// + /// struct Point { x: FancyInteger, y: FancyInteger } + /// struct Color; + /// + /// struct Wrapper { p: Point, c: Color } + /// + /// fn f(w: Wrapper) { + /// let c = || { + /// // Closure captures w.p.x and w.c by move. + /// }; + /// + /// c(); + /// } + /// ``` + /// + /// If `capture_disjoint_fields` wasn't enabled the closure would've moved `w` instead of the + /// precise paths. If we look closely `w.p.y` isn't captured which implements Drop and + /// therefore Drop ordering would change and we want this function to return true. + /// + /// Call stack to figure out if we need to migrate for `w` would look as follows: + /// + /// Our initial base path is just `w`, and the paths captured from it are `w[p, x]` and + /// `w[c]`. + /// Notation: + /// - Ty(place): Type of place + /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_projs` + /// respectively. + /// ``` + /// (Ty(w), [ &[p, x], &[c] ]) + /// | + /// ---------------------------- + /// | | + /// v v + /// (Ty(w.p), [ &[x] ]) (Ty(w.c), [ &[] ]) // I(1) + /// | | + /// v v + /// (Ty(w.p), [ &[x] ]) false + /// | + /// | + /// ------------------------------- + /// | | + /// v v + /// (Ty((w.p).x), [ &[] ]) (Ty((w.p).y), []) // IMP 2 + /// | | + /// v v + /// false NeedsDrop(Ty(w.p.y)) + /// | + /// v + /// true + /// ``` + /// + /// IMP 1 `(Ty(w.c), [ &[] ])`: Notice the single empty slice inside `captured_projs`. + /// This implies that the `w.c` is completely captured by the closure. + /// Since drop for this path will be called when the closure is + /// dropped we don't need to migrate for it. + /// + /// IMP 2 `(Ty((w.p).y), [])`: Notice that `captured_projs` is empty. This implies that this + /// path wasn't captured by the closure. Also note that even + /// though we didn't capture this path, the function visits it, + /// which is kind of the point of this function. We then return + /// if the type of `w.p.y` implements Drop, which in this case is + /// true. + /// + /// Consider another example: + /// + /// ```rust + /// struct X; + /// impl Drop for X {} + /// + /// struct Y(X); + /// impl Drop for Y {} + /// + /// fn foo() { + /// let y = Y(X); + /// let c = || move(y.0); + /// } + /// ``` + /// + /// Note that `y.0` is captured by the closure. When this function is called for `y`, it will + /// return true, because even though all paths starting at `y` are captured, `y` itself + /// implements Drop which will be affected since `y` isn't completely captured. + fn has_significant_drop_outside_of_captures( + &self, + closure_def_id: DefId, + closure_span: Span, + base_path_ty: Ty<'tcx>, + captured_projs: Vec<&[Projection<'tcx>]>, + ) -> bool { + let needs_drop = |ty: Ty<'tcx>| { + ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) + }; + + let is_drop_defined_for_ty = |ty: Ty<'tcx>| { + let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); + let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]); + self.tcx.type_implements_trait(( + drop_trait, + ty, + ty_params, + self.tcx.param_env(closure_def_id.expect_local()), + )) + }; + + let is_drop_defined_for_ty = is_drop_defined_for_ty(base_path_ty); + + // If there is a case where no projection is applied on top of current place + // then there must be exactly one capture corresponding to such a case. Note that this + // represents the case of the path being completely captured by the variable. + // + // eg. If `a.b` is captured and we are processing `a.b`, then we can't have the closure also + // capture `a.b.c`, because that voilates min capture. + let is_completely_captured = captured_projs.iter().any(|projs| projs.is_empty()); + + assert!(!is_completely_captured || (captured_projs.len() == 1)); + + if is_completely_captured { + // The place is captured entirely, so doesn't matter if needs dtor, it will be drop + // when the closure is dropped. + return false; + } + + if is_drop_defined_for_ty { + // If drop is implemented for this type then we need it to be fully captured, + // which we know it is not because of the previous check. Therefore we need to + // do migrate. + return true; + } + + if captured_projs.is_empty() { + return needs_drop(base_path_ty); + } + + match base_path_ty.kind() { + // Observations: + // - `captured_projs` is not empty. Therefore we can call + // `captured_projs.first().unwrap()` safely. + // - All entries in `captured_projs` have atleast one projection. + // Therefore we can call `captured_projs.first().unwrap().first().unwrap()` safely. + + // We don't capture derefs in case of move captures, which would have be applied to + // access any further paths. + ty::Adt(def, _) if def.is_box() => unreachable!(), + ty::Ref(..) => unreachable!(), + ty::RawPtr(..) => unreachable!(), + + ty::Adt(def, substs) => { + // Multi-varaint enums are captured in entirety, + // which would've been handled in the case of single empty slice in `captured_projs`. + assert_eq!(def.variants.len(), 1); + + // Only Field projections can be applied to a non-box Adt. + assert!( + captured_projs.iter().all(|projs| matches!( + projs.first().unwrap().kind, + ProjectionKind::Field(..) + )) + ); + def.variants.get(VariantIdx::new(0)).unwrap().fields.iter().enumerate().any( + |(i, field)| { + let paths_using_field = captured_projs + .iter() + .filter_map(|projs| { + if let ProjectionKind::Field(field_idx, _) = + projs.first().unwrap().kind + { + if (field_idx as usize) == i { Some(&projs[1..]) } else { None } + } else { + unreachable!(); + } + }) + .collect(); + + let after_field_ty = field.ty(self.tcx, substs); + self.has_significant_drop_outside_of_captures( + closure_def_id, + closure_span, + after_field_ty, + paths_using_field, + ) + }, + ) + } + + ty::Tuple(..) => { + // Only Field projections can be applied to a tuple. + assert!( + captured_projs.iter().all(|projs| matches!( + projs.first().unwrap().kind, + ProjectionKind::Field(..) + )) + ); + + base_path_ty.tuple_fields().enumerate().any(|(i, element_ty)| { + let paths_using_field = captured_projs + .iter() + .filter_map(|projs| { + if let ProjectionKind::Field(field_idx, _) = projs.first().unwrap().kind + { + if (field_idx as usize) == i { Some(&projs[1..]) } else { None } + } else { + unreachable!(); + } + }) + .collect(); + + self.has_significant_drop_outside_of_captures( + closure_def_id, + closure_span, + element_ty, + paths_using_field, + ) + }) + } + + // Anything else would be completely captured and therefore handled already. + _ => unreachable!(), + } + } + fn init_capture_kind( &self, capture_clause: hir::CaptureBy, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 2598f3e38ce00..e24aa7d76f194 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -143,6 +143,7 @@ crate fn placeholder_type_error( generics: &[hir::GenericParam<'_>], placeholder_types: Vec, suggest: bool, + hir_ty: Option<&hir::Ty<'_>>, ) { if placeholder_types.is_empty() { return; @@ -173,12 +174,40 @@ crate fn placeholder_type_error( } let mut err = bad_placeholder_type(tcx, placeholder_types); + + // Suggest, but only if it is not a function in const or static if suggest { - err.multipart_suggestion( - "use type parameters instead", - sugg, - Applicability::HasPlaceholders, - ); + let mut is_fn = false; + let mut is_const = false; + let mut is_static = false; + + if let Some(hir_ty) = hir_ty { + if let hir::TyKind::BareFn(_) = hir_ty.kind { + is_fn = true; + + // Check if parent is const or static + let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); + let parent_node = tcx.hir().get(parent_id); + + if let hir::Node::Item(item) = parent_node { + if let hir::ItemKind::Const(_, _) = item.kind { + is_const = true; + } else if let hir::ItemKind::Static(_, _, _) = item.kind { + is_static = true; + } + } + } + } + + // if function is wrapped around a const or static, + // then don't show the suggestion + if !(is_fn && (is_const || is_static)) { + err.multipart_suggestion( + "use type parameters instead", + sugg, + Applicability::HasPlaceholders, + ); + } } err.emit(); } @@ -200,7 +229,14 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_item(item); - placeholder_type_error(tcx, Some(generics.span), &generics.params[..], visitor.0, suggest); + placeholder_type_error( + tcx, + Some(generics.span), + &generics.params[..], + visitor.0, + suggest, + None, + ); } impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { @@ -682,6 +718,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { let it = tcx.hir().expect_item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id); let def_id = tcx.hir().local_def_id(item_id); + match it.kind { // These don't define types. hir::ItemKind::ExternCrate(_) @@ -787,7 +824,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { // Account for `const C: _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } hir::TraitItemKind::Type(_, Some(_)) => { @@ -796,7 +833,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { // Account for `type T = _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } hir::TraitItemKind::Type(_, None) => { @@ -805,7 +842,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { // even if there is no concrete type. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } }; @@ -826,7 +864,8 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { // Account for `type T = _;` let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_impl_item(impl_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } hir::ImplItemKind::Const(..) => {} } @@ -1654,6 +1693,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { &sig.decl, &generics, Some(ident.span), + None, ), } } @@ -1663,9 +1703,15 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ident, generics, .. - }) => { - AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span)) - } + }) => AstConv::ty_of_fn( + &icx, + header.unsafety, + header.abi, + decl, + &generics, + Some(ident.span), + None, + ), ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), @@ -2335,6 +2381,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( decl, &hir::Generics::empty(), Some(ident.span), + None, ); // Feature gate SIMD types in FFI, since I am not sure that the diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index 43838578ca21f..783c802448199 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -103,7 +103,8 @@ where } } -/// Equivalent to `range_search(k, v, ..)` but without the `Ord` bound. +/// Equivalent to `range_search(root1, root2, ..)` but without the `Ord` bound. +/// Equivalent to `(root1.first_leaf_edge(), root2.last_leaf_edge())` but more efficient. fn full_range( root1: NodeRef, root2: NodeRef, @@ -130,7 +131,7 @@ fn full_range( } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { - /// Creates a pair of leaf edges delimiting a specified range in or underneath a node. + /// Finds the pair of leaf edges delimiting a specific range in a tree. /// /// The result is meaningful only if the tree is ordered by key, like the tree /// in a `BTreeMap` is. @@ -149,7 +150,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> range_search(self, self, range) } - /// Returns (self.first_leaf_edge(), self.last_leaf_edge()), but more efficiently. + /// Finds the pair of leaf edges delimiting an entire tree. pub fn full_range( self, ) -> ( diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 50d6fb11b11ce..4fc32305f1e30 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -181,7 +181,7 @@ impl NodeRef { NodeRef { height: self.height, node: self.node, _marker: PhantomData } } - /// Irreversibly transistions to a reference that offers traversal, + /// Irreversibly transitions to a reference that permits traversal and offers /// destructive methods and little else. pub fn into_dying(self) -> NodeRef { NodeRef { height: self.height, node: self.node, _marker: PhantomData } diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index c7ca0134f9ce1..7572b8c6f4a8c 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -108,7 +108,7 @@ def check_type(ty): elif ty["kind"] == "function_pointer": for param in ty["inner"]["generic_params"]: check_generic_param(param) - check_decl(ty["inner"]["inner"]) + check_decl(ty["inner"]["decl"]) elif ty["kind"] == "qualified_path": check_type(ty["inner"]["self_type"]) check_type(ty["inner"]["trait"]) diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index b6965898b4e44..1b9a35e649172 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,7 +14,7 @@ minifier = "0.0.33" rayon = { version = "0.3.0", package = "rustc-rayon" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -smallvec = "1.0" +smallvec = "1.6.1" tempfile = "3" itertools = "0.9" regex = "1" diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f96f6d52088a4..e2652ca378a81 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -2,6 +2,8 @@ //! the `clean` types but with some fields removed or stringified to simplify the output and not //! expose unstable compiler internals. +#![allow(rustc::default_hash_types)] + use std::convert::From; use rustc_ast::ast; @@ -16,6 +18,7 @@ use crate::clean; use crate::clean::utils::print_const_expr; use crate::formats::item_type::ItemType; use crate::json::JsonRenderer; +use std::collections::HashSet; impl JsonRenderer<'_> { pub(super) fn convert_item(&self, item: clean::Item) -> Option { @@ -225,15 +228,22 @@ crate fn from_ctor_kind(struct_type: CtorKind) -> StructType { } } -fn stringify_header(header: &rustc_hir::FnHeader) -> String { - let mut s = String::from(header.unsafety.prefix_str()); - if header.asyncness == rustc_hir::IsAsync::Async { - s.push_str("async ") +crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet { + let mut v = HashSet::new(); + + if let rustc_hir::Unsafety::Unsafe = header.unsafety { + v.insert(Qualifiers::Unsafe); + } + + if let rustc_hir::IsAsync::Async = header.asyncness { + v.insert(Qualifiers::Async); } - if header.constness == rustc_hir::Constness::Const { - s.push_str("const ") + + if let rustc_hir::Constness::Const = header.constness { + v.insert(Qualifiers::Const); } - s + + v } impl From for Function { @@ -242,7 +252,7 @@ impl From for Function { Function { decl: decl.into(), generics: generics.into(), - header: stringify_header(&header), + header: from_fn_header(&header), abi: header.abi.to_string(), } } @@ -364,7 +374,13 @@ impl From for FunctionPointer { fn from(bare_decl: clean::BareFunctionDecl) -> Self { let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl; FunctionPointer { - is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, + header: if let rustc_hir::Unsafety::Unsafe = unsafety { + let mut hs = HashSet::new(); + hs.insert(Qualifiers::Unsafe); + hs + } else { + HashSet::new() + }, generic_params: generic_params.into_iter().map(Into::into).collect(), decl: decl.into(), abi: abi.to_string(), @@ -439,7 +455,7 @@ crate fn from_function_method(function: clean::Function, has_body: bool) -> Meth Method { decl: decl.into(), generics: generics.into(), - header: stringify_header(&header), + header: from_fn_header(&header), abi: header.abi.to_string(), has_body, } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 876b1b56dee6d..b31276c9dcb7f 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -243,7 +243,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), - format_version: 3, + format_version: 4, }; let mut p = self.out_path.clone(); p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 297fc95006b02..6188b87d2c617 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -3,7 +3,7 @@ //! These types are the public API exposed through the `--output-format json` flag. The [`Crate`] //! struct is the root of the JSON blob and all other items are contained within. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use serde::{Deserialize, Serialize}; @@ -281,11 +281,20 @@ pub enum StructType { Unit, } +#[non_exhaustive] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[serde(rename_all = "snake_case")] +pub enum Qualifiers { + Const, + Unsafe, + Async, +} + #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Function { pub decl: FnDecl, pub generics: Generics, - pub header: String, + pub header: HashSet, pub abi: String, } @@ -293,7 +302,7 @@ pub struct Function { pub struct Method { pub decl: FnDecl, pub generics: Generics, - pub header: String, + pub header: HashSet, pub abi: String, pub has_body: bool, } @@ -404,9 +413,9 @@ pub enum Type { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct FunctionPointer { - pub is_unsafe: bool, - pub generic_params: Vec, pub decl: FnDecl, + pub generic_params: Vec, + pub header: HashSet, pub abi: String, } diff --git a/src/test/rustdoc-json/fn_pointer/header.rs b/src/test/rustdoc-json/fn_pointer/header.rs new file mode 100644 index 0000000000000..a5038e0cd2aa8 --- /dev/null +++ b/src/test/rustdoc-json/fn_pointer/header.rs @@ -0,0 +1,5 @@ +// @has header.json "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header" "[]" +pub type FnPointer = fn(); + +// @has - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header" '["unsafe"]' +pub type UnsafePointer = unsafe fn(); diff --git a/src/test/rustdoc-json/fns/header.rs b/src/test/rustdoc-json/fns/header.rs new file mode 100644 index 0000000000000..29741dd50dadc --- /dev/null +++ b/src/test/rustdoc-json/fns/header.rs @@ -0,0 +1,22 @@ +// edition:2018 + +// @has header.json "$.index[*][?(@.name=='nothing_fn')].inner.header" "[]" +pub fn nothing_fn() {} + +// @has - "$.index[*][?(@.name=='const_fn')].inner.header" '["const"]' +pub const fn const_fn() {} + +// @has - "$.index[*][?(@.name=='async_fn')].inner.header" '["async"]' +pub async fn async_fn() {} + +// @count - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" 2 +// @has - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" '"async"' +// @has - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header[*]" '"unsafe"' +pub async unsafe fn async_unsafe_fn() {} + +// @count - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" 2 +// @has - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" '"const"' +// @has - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header[*]" '"unsafe"' +pub const unsafe fn const_unsafe_fn() {} + +// It's impossible for a function to be both const and async, so no test for that diff --git a/src/test/rustdoc-json/methods/header.rs b/src/test/rustdoc-json/methods/header.rs new file mode 100644 index 0000000000000..50a3db75ef395 --- /dev/null +++ b/src/test/rustdoc-json/methods/header.rs @@ -0,0 +1,26 @@ +// edition:2018 + +pub struct Foo; + +impl Foo { + // @has header.json "$.index[*][?(@.name=='nothing_meth')].inner.header" "[]" + pub fn nothing_meth() {} + + // @has - "$.index[*][?(@.name=='const_meth')].inner.header" '["const"]' + pub const fn const_meth() {} + + // @has - "$.index[*][?(@.name=='async_meth')].inner.header" '["async"]' + pub async fn async_meth() {} + + // @count - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" 2 + // @has - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" '"async"' + // @has - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header[*]" '"unsafe"' + pub async unsafe fn async_unsafe_meth() {} + + // @count - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" 2 + // @has - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" '"const"' + // @has - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header[*]" '"unsafe"' + pub const unsafe fn const_unsafe_meth() {} + + // It's impossible for a method to be both const and async, so no test for that +} diff --git a/src/test/ui/attributes/attrs-on-params.rs b/src/test/ui/attributes/attrs-on-params.rs new file mode 100644 index 0000000000000..0e606eac1e8b6 --- /dev/null +++ b/src/test/ui/attributes/attrs-on-params.rs @@ -0,0 +1,8 @@ +// This checks that incorrect params on function parameters are caught + +fn function(#[inline] param: u32) { + //~^ ERROR attribute should be applied to function or closure + //~| ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes +} + +fn main() {} diff --git a/src/test/ui/attributes/attrs-on-params.stderr b/src/test/ui/attributes/attrs-on-params.stderr new file mode 100644 index 0000000000000..003f43d371a35 --- /dev/null +++ b/src/test/ui/attributes/attrs-on-params.stderr @@ -0,0 +1,17 @@ +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/attrs-on-params.rs:3:13 + | +LL | fn function(#[inline] param: u32) { + | ^^^^^^^^^ + +error[E0518]: attribute should be applied to function or closure + --> $DIR/attrs-on-params.rs:3:13 + | +LL | fn function(#[inline] param: u32) { + | ^^^^^^^^^----------- + | | + | not a function or closure + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0518`. diff --git a/src/test/ui/borrowck/issue-82032.rs b/src/test/ui/borrowck/issue-82032.rs new file mode 100644 index 0000000000000..4a01b60c1f62b --- /dev/null +++ b/src/test/ui/borrowck/issue-82032.rs @@ -0,0 +1,16 @@ +use std::{fs, io::*}; +use std::collections::HashMap; + +type Handle = BufWriter; +struct Thing(HashMap); + +impl Thing { + pub fn die_horribly(&mut self) { + for v in self.0.values() { + v.flush(); + //~^ ERROR cannot borrow + } + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-82032.stderr b/src/test/ui/borrowck/issue-82032.stderr new file mode 100644 index 0000000000000..f272477a9f5b3 --- /dev/null +++ b/src/test/ui/borrowck/issue-82032.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference + --> $DIR/issue-82032.rs:10:13 + | +LL | for v in self.0.values() { + | --------------- + | | | + | | help: use mutable method: `values_mut()` + | this iterator yields `&` references +LL | v.flush(); + | ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs new file mode 100644 index 0000000000000..79702cc6b56f3 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs @@ -0,0 +1,78 @@ +#![deny(disjoint_capture_drop_reorder)] +//~^ NOTE: the lint level is defined here + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +struct ConstainsDropField(Foo, Foo); + +#[derive(Debug)] +struct ContainsAndImplsDrop(Foo); +impl Drop for ContainsAndImplsDrop { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +// Test that even if all paths starting at root variable that implement Drop are captured, +// the lint is triggered if the root variable implements drop and isn't captured. +fn test_precise_analysis_parent_root_impl_drop_not_captured() { + let t = ContainsAndImplsDrop(Foo(10)); + + let c = || { + //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| NOTE: drop(&(t)); + let _t = t.0; + }; + + c(); +} + +// Test that lint is triggered if a path that implements Drop is not captured by move +fn test_precise_analysis_drop_paths_not_captured_by_move() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| NOTE: drop(&(t)); + let _t = t.0; + let _t = &t.1; + }; + + c(); +} + +struct S; +impl Drop for S { + fn drop(&mut self) { + } +} + +struct T(S, S); +struct U(T, T); + +// Test precise analysis for the lint works with paths longer than one. +fn test_precise_analysis_long_path_missing() { + let u = U(T(S, S), T(S, S)); + + let c = || { + //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| NOTE: drop(&(u)); + let _x = u.0.0; + let _x = u.0.1; + let _x = u.1.0; + }; + + c(); +} + +fn main() { + test_precise_analysis_parent_root_impl_drop_not_captured(); + test_precise_analysis_drop_paths_not_captured_by_move(); + test_precise_analysis_long_path_missing(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr new file mode 100644 index 0000000000000..968ca395f946e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr @@ -0,0 +1,49 @@ +error: drop order affected for closure because of `capture_disjoint_fields` + --> $DIR/precise.rs:27:13 + | +LL | let c = || { + | _____________^ +LL | | +LL | | +LL | | let _t = t.0; +LL | | }; + | |_____^ + | +note: the lint level is defined here + --> $DIR/precise.rs:1:9 + | +LL | #![deny(disjoint_capture_drop_reorder)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: drop(&(t)); + +error: drop order affected for closure because of `capture_disjoint_fields` + --> $DIR/precise.rs:40:13 + | +LL | let c = || { + | _____________^ +LL | | +LL | | +LL | | let _t = t.0; +LL | | let _t = &t.1; +LL | | }; + | |_____^ + | + = note: drop(&(t)); + +error: drop order affected for closure because of `capture_disjoint_fields` + --> $DIR/precise.rs:63:13 + | +LL | let c = || { + | _____________^ +LL | | +LL | | +LL | | let _x = u.0.0; +LL | | let _x = u.0.1; +LL | | let _x = u.1.0; +LL | | }; + | |_____^ + | + = note: drop(&(u)); + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs new file mode 100644 index 0000000000000..8af48501ca295 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs @@ -0,0 +1,105 @@ +// run-pass + +#![deny(disjoint_capture_drop_reorder)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +struct ConstainsDropField(Foo, Foo); + +// Test that if all paths starting at root variable that implement Drop are captured +// then it doesn't trigger the lint. +fn test_precise_analysis_simple_1() { + let t = (Foo(10), Foo(20), Foo(30)); + + let c = || { + let _t = t.0; + let _t = t.1; + let _t = t.2; + }; + + c(); +} + +// Test that if all paths starting at root variable that implement Drop are captured +// then it doesn't trigger the lint. +fn test_precise_analysis_simple_2() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + let _t = t.0; + let _t = t.1; + }; + + c(); +} + +#[derive(Debug)] +struct ContainsAndImplsDrop(Foo); +impl Drop for ContainsAndImplsDrop { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +// If a path isn't directly captured but requires Drop, then this tests that migrations aren't +// needed if the a parent to that path is captured. +fn test_precise_analysis_parent_captured_1() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + let _t = t; + }; + + c(); +} + +// If a path isn't directly captured but requires Drop, then this tests that migrations aren't +// needed if the a parent to that path is captured. +fn test_precise_analysis_parent_captured_2() { + let t = ContainsAndImplsDrop(Foo(10)); + + let c = || { + let _t = t; + }; + + c(); +} + +struct S; +impl Drop for S { + fn drop(&mut self) { + } +} + +struct T(S, S); +struct U(T, T); + +// Test that if the path is longer than just one element, precise analysis works correctly. +fn test_precise_analysis_long_path() { + let u = U(T(S, S), T(S, S)); + + let c = || { + let _x = u.0.0; + let _x = u.0.1; + let _x = u.1.0; + let _x = u.1.1; + }; + + c(); +} + +fn main() { + test_precise_analysis_simple_1(); + test_precise_analysis_simple_2(); + + test_precise_analysis_parent_captured_1(); + test_precise_analysis_parent_captured_2(); + + test_precise_analysis_long_path(); +} diff --git a/src/test/ui/generics/issue-32498.rs b/src/test/ui/generics/issue-32498.rs new file mode 100644 index 0000000000000..1b54401097ea9 --- /dev/null +++ b/src/test/ui/generics/issue-32498.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +// Making sure that no overflow occurs. + +struct L { + n: Option, +} +type L8 = L>>>>>>>; +type L64 = L8>>>; + +fn main() { + use std::mem::size_of; + assert_eq!(size_of::>>(), 1); + assert_eq!(size_of::>>>(), 1); +} diff --git a/src/test/ui/issues/issue-74086.stderr b/src/test/ui/issues/issue-74086.stderr index 4127f48a093f4..e602425059e1b 100644 --- a/src/test/ui/issues/issue-74086.stderr +++ b/src/test/ui/issues/issue-74086.stderr @@ -2,10 +2,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/issue-74086.rs:2:20 | LL | static BUG: fn(_) -> u8 = |_| 8; - | ^ - | | - | not allowed in type signatures - | help: use type parameters instead: `T` + | ^ not allowed in type signatures error: aborting due to previous error diff --git a/src/test/ui/issues/issue-81885.rs b/src/test/ui/issues/issue-81885.rs new file mode 100644 index 0000000000000..86c39d4a48c05 --- /dev/null +++ b/src/test/ui/issues/issue-81885.rs @@ -0,0 +1,10 @@ +const TEST4: fn() -> _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item + //signatures + +fn main() { + const TEST5: fn() -> _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item + //signatures + +} diff --git a/src/test/ui/issues/issue-81885.stderr b/src/test/ui/issues/issue-81885.stderr new file mode 100644 index 0000000000000..955b428387442 --- /dev/null +++ b/src/test/ui/issues/issue-81885.stderr @@ -0,0 +1,15 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-81885.rs:1:22 + | +LL | const TEST4: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-81885.rs:6:26 + | +LL | const TEST5: fn() -> _ = 42; + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs index a6e9ed14ff13e..65d8bcd9972e6 100644 --- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -3,8 +3,8 @@ #![feature(decl_macro)] //~ ERROR `feature` is ambiguous extern crate builtin_attrs; -use builtin_attrs::{test, bench}; use builtin_attrs::*; +use builtin_attrs::{bench, test}; #[repr(C)] //~ ERROR `repr` is ambiguous struct S; diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr index 31959248a68c2..1ad991db3be44 100644 --- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -12,7 +12,7 @@ LL | #[repr(C)] | = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:7:5 + --> $DIR/ambiguous-builtin-attrs.rs:6:5 | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | #[cfg_attr(all(), repr(C))] | = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:7:5 + --> $DIR/ambiguous-builtin-attrs.rs:6:5 | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | fn non_macro_expanded_location<#[repr(C)] T>() { | = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:7:5 + --> $DIR/ambiguous-builtin-attrs.rs:6:5 | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | #[repr(C)] | = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:7:5 + --> $DIR/ambiguous-builtin-attrs.rs:6:5 | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | #![feature(decl_macro)] | = note: `feature` could refer to a built-in attribute note: `feature` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:7:5 + --> $DIR/ambiguous-builtin-attrs.rs:6:5 | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr index 0121e18631676..f868c8d483486 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -29,10 +29,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/typeck_type_placeholder_item_help.rs:13:22 | LL | const TEST4: fn() -> _ = 42; - | ^ - | | - | not allowed in type signatures - | help: use type parameters instead: `T` + | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:17:18 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 1cde0e25cedca..8da7db2dfddb4 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -71,8 +71,8 @@ proc-macro2 = { version = "1", features = ["default"] } quote = { version = "1", features = ["default"] } serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] } -smallvec-0_6 = { package = "smallvec", version = "0.6", features = ['union', 'may_dangle'] } -smallvec = { version = "1.0", features = ['union', 'may_dangle'] } +smallvec-0_6 = { package = "smallvec", version = "0.6.14", features = ['union', 'may_dangle'] } +smallvec = { version = "1.6.1", features = ['union', 'may_dangle'] } syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit', 'visit-mut'] } url = { version = "2.0", features = ['serde'] }