diff --git a/Cargo.lock b/Cargo.lock index fb5ae6ce66303..a4ba7704426e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3746,6 +3746,7 @@ dependencies = [ "rustc_errors", "rustc_feature", "rustc_lexer", + "rustc_lint_defs", "rustc_macros", "rustc_parse", "rustc_serialize", @@ -4391,12 +4392,20 @@ dependencies = [ "pulldown-cmark 0.8.0", "regex", "rustc-rayon", + "rustdoc-json-types", "serde", "serde_json", "smallvec 1.4.2", "tempfile", ] +[[package]] +name = "rustdoc-json-types" +version = "0.1.0" +dependencies = [ + "serde", +] + [[package]] name = "rustdoc-themes" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 5bd1147cad554..f3b2e0f740d61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "compiler/rustc", "library/std", "library/test", + "src/rustdoc-json-types", "src/tools/cargotest", "src/tools/clippy", "src/tools/compiletest", diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index beff84fb2e217..5702832bcb67d 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -134,11 +134,9 @@ pub(crate) fn codegen_constant<'tcx>( { Ok(const_val) => const_val, Err(_) => { - if promoted.is_none() { - fx.tcx - .sess - .span_err(constant.span, "erroneous constant encountered"); - } + fx.tcx + .sess + .span_err(constant.span, "erroneous constant encountered"); return crate::trap::trap_unreachable_ret_value( fx, fx.layout_of(const_.ty), diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 29415973ed073..5effe68752808 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -732,10 +732,7 @@ pub unsafe fn optimize_thin_module( let diag_handler = cgcx.create_diag_handler(); let module_name = &thin_module.shared.module_names[thin_module.idx]; - let split_dwarf_file = cgcx - .output_filenames - .split_dwarf_filename(cgcx.split_dwarf_kind, Some(module_name.to_str().unwrap())); - let tm_factory_config = TargetMachineFactoryConfig { split_dwarf_file }; + let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap()); let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, &e))?; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index e225730dce061..326ae354ccf48 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -23,13 +23,11 @@ use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{ - self, Lto, OutputType, Passes, SanitizerSet, SplitDwarfKind, SwitchWithOptPath, -}; +use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::InnerSpan; -use rustc_target::spec::{CodeModel, RelocModel}; +use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo}; use tracing::debug; use libc::{c_char, c_int, c_uint, c_void, size_t}; @@ -93,9 +91,12 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm: } pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine { - let split_dwarf_file = tcx - .output_filenames(LOCAL_CRATE) - .split_dwarf_filename(tcx.sess.opts.debugging_opts.split_dwarf, Some(mod_name)); + let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { + tcx.output_filenames(LOCAL_CRATE) + .split_dwarf_filename(tcx.sess.split_debuginfo(), Some(mod_name)) + } else { + None + }; let config = TargetMachineFactoryConfig { split_dwarf_file }; target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))(config) .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise()) @@ -838,11 +839,17 @@ pub(crate) unsafe fn codegen( .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name); - let dwo_out = match cgcx.split_dwarf_kind { + let dwo_out = match cgcx.split_debuginfo { // Don't change how DWARF is emitted in single mode (or when disabled). - SplitDwarfKind::None | SplitDwarfKind::Single => None, + SplitDebuginfo::Off | SplitDebuginfo::Packed => None, // Emit (a subset of the) DWARF into a separate file in split mode. - SplitDwarfKind::Split => Some(dwo_out.as_path()), + SplitDebuginfo::Unpacked => { + if cgcx.target_can_use_split_dwarf { + Some(dwo_out.as_path()) + } else { + None + } + } }; with_codegen(tm, llmod, config.no_builtins, |cpm| { @@ -880,7 +887,7 @@ pub(crate) unsafe fn codegen( Ok(module.into_compiled_module( config.emit_obj != EmitObj::None, - cgcx.split_dwarf_kind == SplitDwarfKind::Split, + cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked, config.emit_bc, &cgcx.output_filenames, )) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 3a4e1492af337..6e7c0b3e3478a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -995,10 +995,13 @@ pub fn compile_unit_metadata( let flags = "\0"; let out_dir = &tcx.output_filenames(LOCAL_CRATE).out_directory; - let split_name = tcx - .output_filenames(LOCAL_CRATE) - .split_dwarf_filename(tcx.sess.opts.debugging_opts.split_dwarf, Some(codegen_unit_name)) - .unwrap_or_default(); + let split_name = if tcx.sess.target_can_use_split_dwarf() { + tcx.output_filenames(LOCAL_CRATE) + .split_dwarf_filename(tcx.sess.split_debuginfo(), Some(codegen_unit_name)) + } else { + None + } + .unwrap_or_default(); let out_dir = out_dir.to_str().unwrap(); let split_name = split_name.to_str().unwrap(); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 92ac770aca554..d11c1592f99d1 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -351,12 +351,7 @@ impl ModuleLlvm { unsafe { let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?; - - let split_dwarf_file = cgcx - .output_filenames - .split_dwarf_filename(cgcx.split_dwarf_kind, Some(name.to_str().unwrap())); - let tm_factory_config = TargetMachineFactoryConfig { split_dwarf_file }; - + let tm_factory_config = TargetMachineFactoryConfig::new(&cgcx, name.to_str().unwrap()); let tm = match (cgcx.tm_factory)(tm_factory_config) { Ok(m) => m, Err(e) => { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 72e049b6d7469..8bc4e64422370 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -14,7 +14,7 @@ use rustc_session::utils::NativeLibKind; use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; -use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor}; +use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target}; use super::archive::ArchiveBuilder; @@ -99,9 +99,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( path.as_ref(), target_cpu, ); - if sess.opts.debugging_opts.split_dwarf == config::SplitDwarfKind::Split { - link_dwarf_object(sess, &out_filename); - } } } if sess.opts.json_artifact_notifications { @@ -828,29 +825,43 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( } } - // On macOS, debuggers need this utility to get run to do some munging of - // the symbols. Note, though, that if the object files are being preserved - // for their debug information there's no need for us to run dsymutil. - if sess.target.is_like_osx - && sess.opts.debuginfo != DebugInfo::None - && !preserve_objects_for_their_debuginfo(sess) - { - let prog = Command::new("dsymutil").arg(out_filename).output(); - match prog { - Ok(prog) => { - if !prog.status.success() { - let mut output = prog.stderr.clone(); - output.extend_from_slice(&prog.stdout); - sess.struct_warn(&format!( - "processing debug info with `dsymutil` failed: {}", - prog.status - )) - .note(&escape_string(&output)) - .emit(); + match sess.split_debuginfo() { + // If split debug information is disabled or located in individual files + // there's nothing to do here. + SplitDebuginfo::Off | SplitDebuginfo::Unpacked => {} + + // If packed split-debuginfo is requested, but the final compilation + // doesn't actually have any debug information, then we skip this step. + SplitDebuginfo::Packed if sess.opts.debuginfo == DebugInfo::None => {} + + // On macOS the external `dsymutil` tool is used to create the packed + // debug information. Note that this will read debug information from + // the objects on the filesystem which we'll clean up later. + SplitDebuginfo::Packed if sess.target.is_like_osx => { + let prog = Command::new("dsymutil").arg(out_filename).output(); + match prog { + Ok(prog) => { + if !prog.status.success() { + let mut output = prog.stderr.clone(); + output.extend_from_slice(&prog.stdout); + sess.struct_warn(&format!( + "processing debug info with `dsymutil` failed: {}", + prog.status + )) + .note(&escape_string(&output)) + .emit(); + } } + Err(e) => sess.fatal(&format!("unable to run `dsymutil`: {}", e)), } - Err(e) => sess.fatal(&format!("unable to run `dsymutil`: {}", e)), } + + // On MSVC packed debug information is produced by the linker itself so + // there's no need to do anything else here. + SplitDebuginfo::Packed if sess.target.is_like_msvc => {} + + // ... and otherwise we're processing a `*.dwp` packed dwarf file. + SplitDebuginfo::Packed => link_dwarf_object(sess, &out_filename), } } @@ -1050,28 +1061,9 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { return false; } - // Single mode keeps debuginfo in the same object file, but in such a way that it it skipped - // by the linker - so it's expected that when codegen units are linked together that this - // debuginfo would be lost without keeping around the temps. - if sess.opts.debugging_opts.split_dwarf == config::SplitDwarfKind::Single { - return true; - } - - // If we're on OSX then the equivalent of split dwarf is turned on by - // default. The final executable won't actually have any debug information - // except it'll have pointers to elsewhere. Historically we've always run - // `dsymutil` to "link all the dwarf together" but this is actually sort of - // a bummer for incremental compilation! (the whole point of split dwarf is - // that you don't do this sort of dwarf link). - // - // Basically as a result this just means that if we're on OSX and we're - // *not* running dsymutil then the object files are the only source of truth - // for debug information, so we must preserve them. - if sess.target.is_like_osx { - return !sess.opts.debugging_opts.run_dsymutil; - } - - false + // "unpacked" split debuginfo means that we leave object files as the + // debuginfo is found in the original object files themselves + sess.split_debuginfo() == SplitDebuginfo::Unpacked } pub fn archive_search_paths(sess: &Session) -> Vec { @@ -2211,8 +2203,13 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { return; } }; - let arch_name = llvm_target.split('-').next().expect("LLVM target must have a hyphen"); - cmd.args(&["-arch", arch_name, "-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]); + if llvm_target.contains("macabi") { + cmd.args(&["-target", llvm_target]) + } else { + let arch_name = llvm_target.split('-').next().expect("LLVM target must have a hyphen"); + cmd.args(&["-arch", arch_name]) + } + cmd.args(&["-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]); } fn get_apple_sdk_root(sdk_name: &str) -> Result { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c84b87964b845..6aef5cb535a1f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -282,6 +282,20 @@ pub struct TargetMachineFactoryConfig { pub split_dwarf_file: Option, } +impl TargetMachineFactoryConfig { + pub fn new( + cgcx: &CodegenContext, + module_name: &str, + ) -> TargetMachineFactoryConfig { + let split_dwarf_file = if cgcx.target_can_use_split_dwarf { + cgcx.output_filenames.split_dwarf_filename(cgcx.split_debuginfo, Some(module_name)) + } else { + None + }; + TargetMachineFactoryConfig { split_dwarf_file } + } +} + pub type TargetMachineFactoryFn = Arc< dyn Fn(TargetMachineFactoryConfig) -> Result<::TargetMachine, String> + Send @@ -311,10 +325,11 @@ pub struct CodegenContext { pub tm_factory: TargetMachineFactoryFn, pub msvc_imps_needed: bool, pub is_pe_coff: bool, + pub target_can_use_split_dwarf: bool, pub target_pointer_width: u32, pub target_arch: String, pub debuginfo: config::DebugInfo, - pub split_dwarf_kind: config::SplitDwarfKind, + pub split_debuginfo: rustc_target::spec::SplitDebuginfo, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -1035,10 +1050,11 @@ fn start_executing_work( total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), is_pe_coff: tcx.sess.target.is_like_windows, + target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), target_pointer_width: tcx.sess.target.pointer_width, target_arch: tcx.sess.target.arch.clone(), debuginfo: tcx.sess.opts.debuginfo, - split_dwarf_kind: tcx.sess.opts.debugging_opts.split_dwarf, + split_debuginfo: tcx.sess.split_debuginfo(), }; // This is the "main loop" of parallel work happening for parallel codegen. diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 3a85c268e0ea9..b79a221a0e74a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -30,12 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .tcx() .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) .map_err(|err| { - if promoted.is_none() { - self.cx - .tcx() - .sess - .span_err(constant.span, "erroneous constant encountered"); - } + self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); err }), ty::ConstKind::Value(value) => Ok(value), diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 25c2851f6de59..7413b0d9431f9 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -18,6 +18,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_lexer = { path = "../rustc_lexer" } rustc_parse = { path = "../rustc_parse" } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index e8c711cae64ef..73fbde70bda9f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -11,12 +11,14 @@ use crate::mbe::transcribe::transcribe; use rustc_ast as ast; use rustc_ast::token::{self, NonterminalKind, NtTT, Token, TokenKind::*}; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; +use rustc_ast::NodeId; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_feature::Features; +use rustc_lint_defs::builtin::SEMICOLON_IN_EXPRESSIONS_FROM_MACROS; use rustc_parse::parser::Parser; use rustc_session::parse::ParseSess; use rustc_session::Session; @@ -37,6 +39,7 @@ crate struct ParserAnyMacro<'a> { site_span: Span, /// The ident of the macro we're parsing macro_ident: Ident, + lint_node_id: NodeId, arm_span: Span, } @@ -110,7 +113,8 @@ fn emit_frag_parse_err( impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { - let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; + let ParserAnyMacro { site_span, macro_ident, ref mut parser, lint_node_id, arm_span } = + *self; let snapshot = &mut parser.clone(); let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, @@ -124,6 +128,12 @@ impl<'a> ParserAnyMacro<'a> { // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, // but `m!()` is allowed in expression positions (cf. issue #34706). if kind == AstFragmentKind::Expr && parser.token == token::Semi { + parser.sess.buffer_lint( + SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, + parser.token.span, + lint_node_id, + "trailing semicolon in macro used in expression position", + ); parser.bump(); } @@ -276,6 +286,7 @@ fn generic_extension<'cx>( let mut p = Parser::new(sess, tts, false, None); p.last_type_ascription = cx.current_expansion.prior_type_ascription; + let lint_node_id = cx.resolver.lint_node_id(cx.current_expansion.id); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. @@ -287,6 +298,7 @@ fn generic_extension<'cx>( // macro leaves unparsed tokens. site_span: sp, macro_ident: name, + lint_node_id, arm_span, }); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 55d521a9b5ff5..305ae23669bbf 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -17,7 +17,7 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, TlsModel}; +use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::path::PathBuf; @@ -446,6 +446,7 @@ fn test_codegen_options_tracking_hash() { tracked!(profile_use, Some(PathBuf::from("abc"))); tracked!(relocation_model, Some(RelocModel::Pic)); tracked!(soft_float, true); + tracked!(split_debuginfo, Some(SplitDebuginfo::Packed)); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); } @@ -579,7 +580,6 @@ fn test_debugging_options_tracking_hash() { tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(report_delayed_bugs, true); - tracked!(run_dsymutil, false); tracked!(sanitizer, SanitizerSet::ADDRESS); tracked!(sanitizer_memory_track_origins, 2); tracked!(sanitizer_recover, SanitizerSet::ADDRESS); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index b17765998807f..8bd9dad785c4b 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -746,6 +746,14 @@ impl<'tcx> LateContext<'tcx> { hir::QPath::Resolved(_, ref path) => path.res, hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self .maybe_typeck_results() + .filter(|typeck_results| typeck_results.hir_owner == id.owner) + .or_else(|| { + if self.tcx.has_typeck_results(id.owner.to_def_id()) { + Some(self.tcx.typeck(id.owner)) + } else { + None + } + }) .and_then(|typeck_results| typeck_results.type_dependent_def(id)) .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 015e109871182..3821a393efb8b 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -140,6 +140,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let generics = self.context.generics.take(); self.context.generics = it.kind.generics(); + let old_cached_typeck_results = self.context.cached_typeck_results.take(); + let old_enclosing_body = self.context.enclosing_body.take(); self.with_lint_attrs(it.hir_id, &it.attrs, |cx| { cx.with_param_env(it.hir_id, |cx| { lint_callback!(cx, check_item, it); @@ -147,6 +149,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas lint_callback!(cx, check_item_post, it); }); }); + self.context.enclosing_body = old_enclosing_body; + self.context.cached_typeck_results.set(old_cached_typeck_results); self.context.generics = generics; } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 658372ac336a8..a8bf1ce51bb74 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! Some lints that are built in to the compiler. //! //! These are the built-in lints that are emitted direct in the main @@ -2833,6 +2834,52 @@ declare_lint! { "detects `#[unstable]` on stable trait implementations for stable types" } +declare_lint! { + /// The `semicolon_in_expressions_from_macros` lint detects trailing semicolons + /// in macro bodies when the macro is invoked in expression position. + /// This was previous accepted, but is being phased out. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(semicolon_in_expressions_from_macros)] + /// macro_rules! foo { + /// () => { true; } + /// } + /// + /// fn main() { + /// let val = match true { + /// true => false, + /// _ => foo!() + /// }; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous, Rust ignored trailing semicolon in a macro + /// body when a macro was invoked in expression position. + /// However, this makes the treatment of semicolons in the language + /// inconsistent, and could lead to unexpected runtime behavior + /// in some circumstances (e.g. if the macro author expects + /// a value to be dropped). + /// + /// This is a [future-incompatible] lint to transition this + /// to a hard error in the future. See [issue #79813] for more details. + /// + /// [issue #79813]: https://github.com/rust-lang/rust/issues/79813 + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, + Allow, + "trailing semicolon in macro body used as expression", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #79813 ", + edition: None, + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -2920,6 +2967,7 @@ declare_lint_pass! { USELESS_DEPRECATED, UNSUPPORTED_NAKED_FUNCTIONS, MISSING_ABI, + SEMICOLON_IN_EXPRESSIONS_FROM_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 e1af6fc07cf8f..73196c732f5bb 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -1,9 +1,12 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; -use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location}; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{ + hir::place::PlaceBase, + mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location}, +}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; @@ -241,6 +244,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("mut {}", self.local_names[local].unwrap()), Applicability::MachineApplicable, ); + let tcx = self.infcx.tcx; + if let ty::Closure(id, _) = the_place_err.ty(self.body, tcx).ty.kind() { + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + } } // Also suggest adding mut for upvars @@ -271,6 +278,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } } + + let tcx = self.infcx.tcx; + if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind() + { + if let ty::Closure(id, _) = ty.kind() { + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + } + } } // complete hack to approximate old AST-borrowck @@ -463,6 +478,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.buffer(&mut self.errors_buffer); } + // point to span of upvar making closure call require mutable borrow + fn show_mutating_upvar( + &self, + tcx: TyCtxt<'_>, + id: &hir::def_id::DefId, + the_place_err: PlaceRef<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ) { + let id = id.expect_local(); + let tables = tcx.typeck(id); + let hir_id = tcx.hir().local_def_id_to_hir_id(id); + let (span, place) = &tables.closure_kind_origins()[hir_id]; + let reason = if let PlaceBase::Upvar(upvar_id) = place.base { + let upvar = ty::place_to_string_for_capture(tcx, place); + match tables.upvar_capture(upvar_id) { + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: ty::BorrowKind::MutBorrow, + .. + }) => { + format!("mutable borrow of `{}`", upvar) + } + ty::UpvarCapture::ByValue(_) => { + format!("possible mutation of `{}`", upvar) + } + _ => bug!("upvar `{}` borrowed, but not mutably", upvar), + } + } else { + bug!("not an upvar") + }; + err.span_label( + *span, + format!( + "calling `{}` requires mutable binding due to {}", + self.describe_place(the_place_err).unwrap(), + reason + ), + ); + } + /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { err.span_label(sp, format!("cannot {}", act)); diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index df163f6562842..252f5e7ef2ff2 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -298,6 +298,8 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx.def_span(def.did), key.param_env, CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), + // Statics (and promoteds inside statics) may access other statics, because unlike consts + // they do not have to behave "as if" they were evaluated at runtime. MemoryExtra { can_access_statics: is_static }, ); @@ -305,83 +307,35 @@ pub fn eval_to_allocation_raw_provider<'tcx>( match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { Err(error) => { let err = ConstEvalErr::new(&ecx, error, None); - // errors in statics are always emitted as fatal errors - if is_static { - // Ensure that if the above error was either `TooGeneric` or `Reported` - // an error must be reported. - let v = err.report_as_error( - ecx.tcx.at(ecx.cur_span()), - "could not evaluate static initializer", - ); - - // If this is `Reveal:All`, then we need to make sure an error is reported but if - // this is `Reveal::UserFacing`, then it's expected that we could get a - // `TooGeneric` error. When we fall back to `Reveal::All`, then it will either - // succeed or we'll report this error then. - if key.param_env.reveal() == Reveal::All { - tcx.sess.delay_span_bug( - err.span, - &format!("static eval failure did not emit an error: {:#?}", v), - ); - } - - Err(v) - } else if let Some(def) = def.as_local() { - // constant defined in this crate, we can figure out a lint level! - match tcx.def_kind(def.did.to_def_id()) { - // constants never produce a hard error at the definition site. Anything else is - // a backwards compatibility hazard (and will break old versions of winapi for - // sure) - // - // note that validation may still cause a hard error on this very same constant, - // because any code that existed before validation could not have failed - // validation thus preventing such a hard error from being a backwards - // compatibility hazard - DefKind::Const | DefKind::AssocConst => { - let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - Err(err.report_as_lint( - tcx.at(tcx.def_span(def.did)), - "any use of this value will cause an error", - hir_id, - Some(err.span), - )) - } - // promoting runtime code is only allowed to error if it references broken - // constants any other kind of error will be reported to the user as a - // deny-by-default lint - _ => { - if let Some(p) = cid.promoted { - let span = tcx.promoted_mir_opt_const_arg(def.to_global())[p].span; - if let err_inval!(ReferencedConstant) = err.error { - Err(err.report_as_error( - tcx.at(span), - "evaluation of constant expression failed", - )) - } else { - Err(err.report_as_lint( - tcx.at(span), - "reaching this expression at runtime will panic or abort", - tcx.hir().local_def_id_to_hir_id(def.did), - Some(err.span), - )) - } - // anything else (array lengths, enum initializers, constant patterns) are - // reported as hard errors - } else { - Err(err.report_as_error( - ecx.tcx.at(ecx.cur_span()), - "evaluation of constant value failed", - )) - } - } - } + // Some CTFE errors raise just a lint, not a hard error; see + // . + let emit_as_lint = if let Some(def) = def.as_local() { + // (Associated) consts only emit a lint, since they might be unused. + matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst) } else { - // use of broken constant from other crate - Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")) + // use of broken constant from other crate: always an error + false + }; + if emit_as_lint { + let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did); + Err(err.report_as_lint( + tcx.at(tcx.def_span(def.did)), + "any use of this value will cause an error", + hir_id, + Some(err.span), + )) + } else { + let msg = if is_static { + "could not evaluate static initializer" + } else { + "evaluation of constant value failed" + }; + Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), msg)) } } Ok(mplace) => { - // Since evaluation had no errors, valiate the resulting constant: + // Since evaluation had no errors, validate the resulting constant. + // This is a separate `try` block to provide more targeted error reporting. let validation = try { let mut ref_tracking = RefTracking::new(mplace); let mut inner = false; @@ -399,7 +353,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( } }; if let Err(error) = validation { - // Validation failed, report an error + // Validation failed, report an error. This is always a hard error. let err = ConstEvalErr::new(&ecx, error, None); Err(err.struct_error( ecx.tcx, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 5d6120cd31076..d0adee2429d9a 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -344,6 +344,8 @@ impl<'a> ResolverExpand for Resolver<'a> { } fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId { + // FIXME - make this more precise. This currently returns the NodeId of the + // nearest closing item - we should try to return the closest parent of the ExpnId self.invocation_parents .get(&expn_id) .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[*id]) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 6e269e9e1264c..f9e40919149d9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -13,7 +13,7 @@ use rustc_data_structures::impl_stable_hash_via_hash; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_target::abi::{Align, TargetDataLayout}; -use rustc_target::spec::{Target, TargetTriple}; +use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple}; use crate::parse::CrateConfig; use rustc_feature::UnstableFeatures; @@ -221,23 +221,6 @@ pub enum DebugInfo { Full, } -/// Some debuginfo requires link-time relocation and some does not. LLVM can partition the debuginfo -/// into sections depending on whether or not it requires link-time relocation. Split DWARF -/// provides a mechanism which allows the linker to skip the sections which don't require link-time -/// relocation - either by putting those sections into DWARF object files, or keeping them in the -/// object file in such a way that the linker will skip them. -#[derive(Clone, Copy, Debug, PartialEq, Hash)] -pub enum SplitDwarfKind { - /// Disabled. - None, - /// Sections which do not require relocation are written into the object file but ignored - /// by the linker. - Single, - /// Sections which do not require relocation are written into a DWARF object (`.dwo`) file, - /// which is skipped by the linker by virtue of being a different file. - Split, -} - #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] #[derive(Encodable, Decodable)] pub enum OutputType { @@ -635,10 +618,10 @@ impl OutputFilenames { /// mode is being used, which is the logic that this function is intended to encapsulate. pub fn split_dwarf_filename( &self, - split_dwarf_kind: SplitDwarfKind, + split_debuginfo_kind: SplitDebuginfo, cgu_name: Option<&str>, ) -> Option { - self.split_dwarf_path(split_dwarf_kind, cgu_name) + self.split_dwarf_path(split_debuginfo_kind, cgu_name) .map(|path| path.strip_prefix(&self.out_directory).unwrap_or(&path).to_path_buf()) } @@ -646,19 +629,19 @@ impl OutputFilenames { /// mode is being used, which is the logic that this function is intended to encapsulate. pub fn split_dwarf_path( &self, - split_dwarf_kind: SplitDwarfKind, + split_debuginfo_kind: SplitDebuginfo, cgu_name: Option<&str>, ) -> Option { let obj_out = self.temp_path(OutputType::Object, cgu_name); let dwo_out = self.temp_path_dwo(cgu_name); - match split_dwarf_kind { - SplitDwarfKind::None => None, + match split_debuginfo_kind { + SplitDebuginfo::Off => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes // (pointing at the path which is being determined here). Use the path to the current // object file. - SplitDwarfKind::Single => Some(obj_out), + SplitDebuginfo::Packed => Some(obj_out), // Split mode emits the DWARF into a different file, use that path. - SplitDwarfKind::Split => Some(dwo_out), + SplitDebuginfo::Unpacked => Some(dwo_out), } } } @@ -1910,6 +1893,15 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let pretty = parse_pretty(matches, &debugging_opts, error_format); + if !debugging_opts.unstable_options + && !target_triple.triple().contains("apple") + && cg.split_debuginfo.is_some() + { + { + early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform"); + } + } + Options { crate_types, optimize: opt_level, @@ -2191,7 +2183,7 @@ crate mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; - use rustc_target::spec::{RelroLevel, TargetTriple, TlsModel}; + use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2263,6 +2255,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_via_hash!(TargetTriple); impl_dep_tracking_hash_via_hash!(Edition); impl_dep_tracking_hash_via_hash!(LinkerPluginLto); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(SwitchWithOptPath); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 30af65e49a075..2aaab84585d07 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -6,7 +6,7 @@ use crate::search_paths::SearchPath; use crate::utils::NativeLibKind; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, TargetTriple, TlsModel}; +use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; @@ -269,7 +269,6 @@ macro_rules! options { pub const parse_switch_with_opt_path: &str = "an optional path to the profiling data output directory"; pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; - pub const parse_split_dwarf_kind: &str = "one of: `none`, `single` or `split`"; pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)"; pub const parse_src_file_hash: &str = "either `md5` or `sha1`"; pub const parse_relocation_model: &str = @@ -280,6 +279,8 @@ macro_rules! options { "one of supported TLS models (`rustc --print tls-models`)"; pub const parse_target_feature: &str = parse_string; pub const parse_wasi_exec_model: &str = "either `command` or `reactor`"; + pub const parse_split_debuginfo: &str = + "one of supported split-debuginfo modes (`off` or `dsymutil`)"; } #[allow(dead_code)] @@ -678,19 +679,6 @@ macro_rules! options { true } - fn parse_split_dwarf_kind( - slot: &mut SplitDwarfKind, - v: Option<&str>, - ) -> bool { - *slot = match v { - Some("none") => SplitDwarfKind::None, - Some("split") => SplitDwarfKind::Split, - Some("single") => SplitDwarfKind::Single, - _ => return false, - }; - true - } - fn parse_symbol_mangling_version( slot: &mut Option, v: Option<&str>, @@ -732,6 +720,14 @@ macro_rules! options { } true } + + fn parse_split_debuginfo(slot: &mut Option, v: Option<&str>) -> bool { + match v.and_then(|s| SplitDebuginfo::from_str(s).ok()) { + Some(e) => *slot = Some(e), + _ => return false, + } + true + } } ) } @@ -830,6 +826,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "save all temporary output files during compilation (default: no)"), soft_float: bool = (false, parse_bool, [TRACKED], "use soft float ABI (*eabihf targets only) (default: no)"), + split_debuginfo: Option = (None, parse_split_debuginfo, [TRACKED], + "how to handle split-debuginfo, a platform-specific option"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], @@ -1073,11 +1071,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "choose which RELRO level to use"), report_delayed_bugs: bool = (false, parse_bool, [TRACKED], "immediately print bugs registered with `delay_span_bug` (default: no)"), - // The default historical behavior was to always run dsymutil, so we're - // preserving that temporarily, but we're likely to switch the default - // soon. - run_dsymutil: bool = (true, parse_bool, [TRACKED], - "if on Mac, run `dsymutil` and delete intermediate object files (default: yes)"), sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], "use a sanitizer"), sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED], @@ -1112,8 +1105,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), - split_dwarf: SplitDwarfKind = (SplitDwarfKind::None, parse_split_dwarf_kind, [UNTRACKED], - "enable generation of split dwarf"), split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], "provide minimal debug info in the object/executable to facilitate online \ symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 6d01854228662..dad21e59502de 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -28,7 +28,7 @@ use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, S use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; -use rustc_target::spec::{Target, TargetTriple, TlsModel}; +use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel}; use std::cell::{self, RefCell}; use std::env; @@ -804,6 +804,14 @@ impl Session { ) } + pub fn split_debuginfo(&self) -> SplitDebuginfo { + self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) + } + + pub fn target_can_use_split_dwarf(&self) -> bool { + !self.target.is_like_windows && !self.target.is_like_osx + } + pub fn must_not_eliminate_frame_pointers(&self) -> bool { // "mcount" function relies on stack pointer. // See . diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 8842239521643..3b458962b3d07 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{LinkArgs, TargetOptions}; +use crate::spec::{LinkArgs, SplitDebuginfo, TargetOptions}; pub fn opts(os: &str) -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -36,6 +36,10 @@ pub fn opts(os: &str) -> TargetOptions { emit_debug_gdb_scripts: false, eh_frame_header: false, + // The historical default for macOS targets is to run `dsymutil` which + // generates a packed version of debuginfo split from the main file. + split_debuginfo: SplitDebuginfo::Packed, + // This environment variable is pretty magical but is intended for // producing deterministic builds. This was first discovered to be used // by the `ar` tool as a way to control whether or not mtime entries in diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 90d35efaa25bd..0227febd294a0 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -448,6 +448,69 @@ impl fmt::Display for LinkOutputKind { pub type LinkArgs = BTreeMap>; +#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)] +pub enum SplitDebuginfo { + /// Split debug-information is disabled, meaning that on supported platforms + /// you can find all debug information in the executable itself. This is + /// only supported for ELF effectively. + /// + /// * Windows - not supported + /// * macOS - don't run `dsymutil` + /// * ELF - `.dwarf_*` sections + Off, + + /// Split debug-information can be found in a "packed" location separate + /// from the final artifact. This is supported on all platforms. + /// + /// * Windows - `*.pdb` + /// * macOS - `*.dSYM` (run `dsymutil`) + /// * ELF - `*.dwp` (run `rust-llvm-dwp`) + Packed, + + /// Split debug-information can be found in individual object files on the + /// filesystem. The main executable may point to the object files. + /// + /// * Windows - not supported + /// * macOS - supported, scattered object files + /// * ELF - supported, scattered `*.dwo` files + Unpacked, +} + +impl SplitDebuginfo { + fn as_str(&self) -> &'static str { + match self { + SplitDebuginfo::Off => "off", + SplitDebuginfo::Packed => "packed", + SplitDebuginfo::Unpacked => "unpacked", + } + } +} + +impl FromStr for SplitDebuginfo { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "off" => SplitDebuginfo::Off, + "unpacked" => SplitDebuginfo::Unpacked, + "packed" => SplitDebuginfo::Packed, + _ => return Err(()), + }) + } +} + +impl ToJson for SplitDebuginfo { + fn to_json(&self) -> Json { + self.as_str().to_json() + } +} + +impl fmt::Display for SplitDebuginfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -1085,6 +1148,10 @@ pub struct TargetOptions { /// Is true if the target is an ARM architecture using thumb v1 which allows for /// thumb and arm interworking. pub has_thumb_interworking: bool, + + /// How to handle split debug information, if at all. Specifying `None` has + /// target-specific meaning. + pub split_debuginfo: SplitDebuginfo, } impl Default for TargetOptions { @@ -1184,6 +1251,7 @@ impl Default for TargetOptions { use_ctors_section: false, eh_frame_header: true, has_thumb_interworking: false, + split_debuginfo: SplitDebuginfo::Off, } } } @@ -1382,6 +1450,18 @@ impl Target { Some(Ok(())) })).unwrap_or(Ok(())) } ); + ($key_name:ident, SplitDebuginfo) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s.parse::() { + Ok(level) => base.$key_name = level, + _ => return Some(Err(format!("'{}' is not a valid value for \ + split-debuginfo. Use 'off' or 'dsymutil'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, list) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(v) = obj.find(&name).and_then(Json::as_array) { @@ -1627,6 +1707,7 @@ impl Target { key!(use_ctors_section, bool); key!(eh_frame_header, bool); key!(has_thumb_interworking, bool); + key!(split_debuginfo, SplitDebuginfo)?; // NB: The old name is deprecated, but support for it is retained for // compatibility. @@ -1862,6 +1943,7 @@ impl ToJson for Target { target_option_val!(use_ctors_section); target_option_val!(eh_frame_header); target_option_val!(has_thumb_interworking); + target_option_val!(split_debuginfo); if default.unsupported_abis != self.unsupported_abis { d.insert( diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs index 8cd6735a8c1ec..39c0d5f0bb4ff 100644 --- a/compiler/rustc_target/src/spec/msvc_base.rs +++ b/compiler/rustc_target/src/spec/msvc_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions}; pub fn opts() -> TargetOptions { let pre_link_args_msvc = vec![ @@ -27,6 +27,10 @@ pub fn opts() -> TargetOptions { abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, + // Currently this is the only supported method of debuginfo on MSVC + // where `*.pdb` files show up next to the final artifact. + split_debuginfo: SplitDebuginfo::Packed, + ..Default::default() } } diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 29e191db0f62f..081f282edcf89 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -265,7 +265,13 @@ where } } match self.iter.next() { - None => return self.backiter.as_mut()?.next(), + None => match self.backiter.as_mut()?.next() { + None => { + self.backiter = None; + return None; + } + elt @ Some(_) => return elt, + }, Some(inner) => self.frontiter = Some(inner.into_iter()), } } @@ -353,7 +359,13 @@ where } } match self.iter.next_back() { - None => return self.frontiter.as_mut()?.next_back(), + None => match self.frontiter.as_mut()?.next_back() { + None => { + self.frontiter = None; + return None; + } + elt @ Some(_) => return elt, + }, next => self.backiter = next.map(IntoIterator::into_iter), } } diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index bd2c6fd9252df..4bbae6947bf66 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -64,6 +64,14 @@ fn test_flatten_non_fused_outer() { assert_eq!(iter.next_back(), Some(1)); assert_eq!(iter.next(), Some(0)); assert_eq!(iter.next(), None); + assert_eq!(iter.next(), None); + + let mut iter = NonFused::new(once(0..2)).flatten(); + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next_back(), Some(1)); + assert_eq!(iter.next_back(), None); + assert_eq!(iter.next_back(), None); } #[test] @@ -74,6 +82,15 @@ fn test_flatten_non_fused_inner() { assert_eq!(iter.next(), Some(0)); assert_eq!(iter.next(), Some(1)); assert_eq!(iter.next(), None); + assert_eq!(iter.next(), None); + + let mut iter = once(0..1).chain(once(1..3)).flat_map(NonFused::new); + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.next_back(), Some(1)); + assert_eq!(iter.next_back(), None); + assert_eq!(iter.next_back(), None); } #[test] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5350c9eefe753..8576f57959a6f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -833,6 +833,7 @@ def build_bootstrap(self): target_linker = self.get_toml("linker", build_section) if target_linker is not None: env["RUSTFLAGS"] += " -C linker=" + target_linker + # cfg(bootstrap): Add `-Wsemicolon_in_expressions_from_macros` after the next beta bump env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" if self.get_toml("deny-warnings", "rust") != "false": env["RUSTFLAGS"] += " -Dwarnings" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 62065e27dd966..f1a160250dbe1 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1139,10 +1139,18 @@ impl<'a> Builder<'a> { // itself, we skip it by default since we know it's safe to do so in that case. // See https://github.com/rust-lang/rust/issues/79361 for more info on this flag. if target.contains("apple") { - if self.config.rust_run_dsymutil { - rustflags.arg("-Zrun-dsymutil=yes"); + if stage == 0 { + if self.config.rust_run_dsymutil { + rustflags.arg("-Zrun-dsymutil=yes"); + } else { + rustflags.arg("-Zrun-dsymutil=no"); + } } else { - rustflags.arg("-Zrun-dsymutil=no"); + if self.config.rust_run_dsymutil { + rustflags.arg("-Csplit-debuginfo=packed"); + } else { + rustflags.arg("-Csplit-debuginfo=unpacked"); + } } } @@ -1250,6 +1258,12 @@ impl<'a> Builder<'a> { // some code doesn't go through this `rustc` wrapper. lint_flags.push("-Wrust_2018_idioms"); lint_flags.push("-Wunused_lifetimes"); + // cfg(bootstrap): unconditionally enable this warning after the next beta bump + // This is currently disabled for the stage1 libstd, since build scripts + // will end up using the bootstrap compiler (which doesn't yet support this lint) + if compiler.stage != 0 && mode != Mode::Std { + lint_flags.push("-Wsemicolon_in_expressions_from_macros"); + } if self.config.deny_warnings { lint_flags.push("-Dwarnings"); diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f6493e49c3c3e..51e7d987d9d82 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -492,6 +492,34 @@ point instructions in software. It takes one of the following values: * `y`, `yes`, `on`, or no value: use soft floats. * `n`, `no`, or `off`: use hardware floats (the default). +## split-debuginfo + +This option controls the emission of "split debuginfo" for debug information +that `rustc` generates. The default behavior of this option is +platform-specific, and not all possible values for this option work on all +platform. Possible values are: + +* `off` - This is the default for platforms with ELF binaries and windows-gnu + (not Windows MSVC and not macOS). This typically means that dwarf debug + information can be found in the final artifact in sections of the executable. + This option is not supported on Windows MSVC. On macOS this options prevents + the final execution of `dsymutil` to generate debuginfo. + +* `packed` - This is the default for Windows MSVC and macOS platforms. The term + "packed" here means that all the debug information is packed into a separate + file from the main executable. On Windows MSVC this is a `*.pdb` file, on + macOS this is a `*.dSYM` folder, and on other platforms this is a `*.dwp` + files. + +* `unpacked` - This means that debug information will be found in separate + files for each compilation unit (object file). This is not supported on + Windows MSVC. On macOS this means the original object files will contain + debug information. On other Unix platforms this means that `*.dwo` files will + contain debug information. + +Note that `packed` and `unpacked` gated behind `-Zunstable-options` on +non-macOS platforms at this time. + ## target-cpu This instructs `rustc` to generate code specifically for a particular processor. @@ -499,7 +527,7 @@ This instructs `rustc` to generate code specifically for a particular processor. You can run `rustc --print target-cpus` to see the valid options to pass here. Each target has a default base CPU. Special values include: -* `native` can be passed to use the processor of the host machine. +* `native` can be passed to use the processor of the host machine. * `generic` refers to an LLVM target with minimal features but modern tuning. ## target-feature diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index b0f5bac6abd0f..db64b31f31cfc 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -17,6 +17,7 @@ smallvec = "1.0" tempfile = "3" itertools = "0.9" regex = "1" +rustdoc-json-types = { path = "../rustdoc-json-types" } [dev-dependencies] expect-test = "1.0" diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 01915c33a07ad..74b61f1555c6f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -659,6 +659,8 @@ fn fmt_type( use_absolute: bool, cache: &Cache, ) -> fmt::Result { + debug!("fmt_type(t = {:?})", t); + match *t { clean::Generic(name) => write!(f, "{}", name), clean::ResolvedPath { did, ref param_names, ref path, is_generic } => { @@ -675,21 +677,22 @@ fn fmt_type( if f.alternate() { write!( f, - "{}{:#}fn{:#}{:#}", + "{:#}{}{:#}fn{:#}", + decl.print_hrtb_with_space(cache), decl.unsafety.print_with_space(), print_abi_with_space(decl.abi), - decl.print_generic_params(cache), decl.decl.print(cache) ) } else { write!( f, - "{}{}", + "{}{}{}", + decl.print_hrtb_with_space(cache), decl.unsafety.print_with_space(), print_abi_with_space(decl.abi) )?; primitive_link(f, PrimitiveType::Fn, "fn", cache)?; - write!(f, "{}{}", decl.print_generic_params(cache), decl.decl.print(cache)) + write!(f, "{}", decl.decl.print(cache)) } } clean::Tuple(ref typs) => { @@ -992,8 +995,14 @@ impl clean::FnRetTy { } impl clean::BareFunctionDecl { - fn print_generic_params<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { - comma_sep(self.generic_params.iter().map(move |g| g.print(cache))) + fn print_hrtb_with_space<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + display_fn(move |f| { + if !self.generic_params.is_empty() { + write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cache)))) + } else { + Ok(()) + } + }) } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index bb9a7be590e87..df3701487d797 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1345,6 +1345,7 @@ impl AllTypes { write!( f, "

\ + List of all items\ \ \ \ - List of all items\

" ); print_entries(f, &self.structs, "Structs", "structs"); @@ -1711,36 +1711,7 @@ where fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top - write!(buf, "

"); - render_stability_since_raw( - buf, - item.stable_since(cx.tcx()).as_deref(), - item.const_stable_since(cx.tcx()).as_deref(), - None, - None, - ); - write!( - buf, - "\ - \ - []\ - \ - " - ); - - // Write `src` tag - // - // When this item is part of a `crate use` in a downstream crate, the - // [src] link in the downstream documentation will actually come back to - // this page, and this link will be auto-clicked. The `id` attribute is - // used to find the link to auto-click. - if cx.shared.include_sources && !item.is_primitive() { - write_srclink(cx, item, buf); - } - - write!(buf, ""); // out-of-band - write!(buf, ""); + write!(buf, "

"); let name = match *item.kind { clean::ModuleItem(ref m) => { if m.is_crate { @@ -1788,7 +1759,36 @@ fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { } write!(buf, "{}", item.type_(), item.name.as_ref().unwrap()); - write!(buf, "

"); // in-band + write!(buf, "
"); // in-band + write!(buf, ""); + render_stability_since_raw( + buf, + item.stable_since(cx.tcx()).as_deref(), + item.const_stable_since(cx.tcx()).as_deref(), + None, + None, + ); + write!( + buf, + "\ + \ + []\ + \ + " + ); + + // Write `src` tag + // + // When this item is part of a `crate use` in a downstream crate, the + // [src] link in the downstream documentation will actually come back to + // this page, and this link will be auto-clicked. The `id` attribute is + // used to find the link to auto-click. + if cx.shared.include_sources && !item.is_primitive() { + write_srclink(cx, item, buf); + } + + write!(buf, "

"); // out-of-band match *item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bfd2141d9a174..b2e5c8834b8ff 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -9,9 +9,10 @@ use rustc_hir::def::CtorKind; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_span::Pos; +use rustdoc_json_types::*; + use crate::clean; use crate::formats::item_type::ItemType; -use crate::json::types::*; use crate::json::JsonRenderer; impl JsonRenderer<'_> { @@ -22,7 +23,7 @@ impl JsonRenderer<'_> { match *kind { clean::StrippedItem(_) => None, kind => Some(Item { - id: def_id.into(), + id: from_def_id(def_id), crate_id: def_id.krate.as_u32(), name: name.map(|sym| sym.to_string()), source: self.convert_span(source), @@ -32,7 +33,7 @@ impl JsonRenderer<'_> { .links .into_iter() .filter_map(|clean::ItemLink { link, did, .. }| { - did.map(|did| (link, did.into())) + did.map(|did| (link, from_def_id(did))) }) .collect(), attrs: attrs @@ -40,7 +41,7 @@ impl JsonRenderer<'_> { .iter() .map(rustc_ast_pretty::pprust::attribute_to_string) .collect(), - deprecation: deprecation.map(Into::into), + deprecation: deprecation.map(from_deprecation), kind: item_type.into(), inner: kind.into(), }), @@ -74,19 +75,17 @@ impl JsonRenderer<'_> { Inherited => Visibility::Default, Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate, Restricted(did) => Visibility::Restricted { - parent: did.into(), + parent: from_def_id(did), path: self.tcx.def_path(did).to_string_no_crate_verbose(), }, } } } -impl From for Deprecation { - fn from(deprecation: rustc_attr::Deprecation) -> Self { - #[rustfmt::skip] - let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation; - Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) } - } +crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation { + #[rustfmt::skip] + let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation; + Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) } } impl From for GenericArgs { @@ -141,10 +140,8 @@ impl From for TypeBindingKind { } } -impl From for Id { - fn from(did: DefId) -> Self { - Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))) - } +crate fn from_def_id(did: DefId) -> Id { + Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))) } impl From for ItemEnum { @@ -199,7 +196,7 @@ impl From for Struct { fn from(struct_: clean::Struct) -> Self { let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_; Struct { - struct_type: struct_type.into(), + struct_type: from_ctor_kind(struct_type), generics: generics.into(), fields_stripped, fields: ids(fields), @@ -221,13 +218,11 @@ impl From for Struct { } } -impl From for StructType { - fn from(struct_type: CtorKind) -> Self { - match struct_type { - CtorKind::Fictive => StructType::Plain, - CtorKind::Fn => StructType::Tuple, - CtorKind::Const => StructType::Unit, - } +crate fn from_ctor_kind(struct_type: CtorKind) -> StructType { + match struct_type { + CtorKind::Fictive => StructType::Plain, + CtorKind::Fn => StructType::Tuple, + CtorKind::Const => StructType::Unit, } } @@ -310,7 +305,7 @@ impl From for GenericBound { GenericBound::TraitBound { trait_: trait_.into(), generic_params: generic_params.into_iter().map(Into::into).collect(), - modifier: modifier.into(), + modifier: from_trait_bound_modifier(modifier), } } Outlives(lifetime) => GenericBound::Outlives(lifetime.0.to_string()), @@ -318,14 +313,12 @@ impl From for GenericBound { } } -impl From for TraitBoundModifier { - fn from(modifier: rustc_hir::TraitBoundModifier) -> Self { - use rustc_hir::TraitBoundModifier::*; - match modifier { - None => TraitBoundModifier::None, - Maybe => TraitBoundModifier::Maybe, - MaybeConst => TraitBoundModifier::MaybeConst, - } +crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> TraitBoundModifier { + use rustc_hir::TraitBoundModifier::*; + match modifier { + None => TraitBoundModifier::None, + Maybe => TraitBoundModifier::Maybe, + MaybeConst => TraitBoundModifier::MaybeConst, } } @@ -335,7 +328,7 @@ impl From for Type { match ty { ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath { name: path.whole_name(), - id: did.into(), + id: from_def_id(did), args: path.segments.last().map(|args| Box::new(args.clone().args.into())), param_names: param_names .map(|v| v.into_iter().map(Into::into).collect()) @@ -470,7 +463,7 @@ impl From for Struct { fn from(struct_: clean::VariantStruct) -> Self { let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_; Struct { - struct_type: struct_type.into(), + struct_type: from_ctor_kind(struct_type), generics: Default::default(), fields_stripped, fields: ids(fields), @@ -497,13 +490,13 @@ impl From for Import { Simple(s) => Import { span: import.source.path.whole_name(), name: s.to_string(), - id: import.source.did.map(Into::into), + id: import.source.did.map(from_def_id), glob: false, }, Glob => Import { span: import.source.path.whole_name(), name: import.source.path.last_name().to_string(), - id: import.source.did.map(Into::into), + id: import.source.did.map(from_def_id), glob: true, }, } @@ -513,20 +506,18 @@ impl From for Import { impl From for ProcMacro { fn from(mac: clean::ProcMacro) -> Self { ProcMacro { - kind: mac.kind.into(), + kind: from_macro_kind(mac.kind), helpers: mac.helpers.iter().map(|x| x.to_string()).collect(), } } } -impl From for MacroKind { - fn from(kind: rustc_span::hygiene::MacroKind) -> Self { - use rustc_span::hygiene::MacroKind::*; - match kind { - Bang => MacroKind::Bang, - Attr => MacroKind::Attr, - Derive => MacroKind::Derive, - } +crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind { + use rustc_span::hygiene::MacroKind::*; + match kind { + Bang => MacroKind::Bang, + Attr => MacroKind::Attr, + Derive => MacroKind::Derive, } } @@ -599,5 +590,5 @@ impl From for ItemKind { } fn ids(items: impl IntoIterator) -> Vec { - items.into_iter().filter(|x| !x.is_stripped()).map(|i| i.def_id.into()).collect() + items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect() } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index a8a4b74b818b6..a7c875fb7480b 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -5,7 +5,6 @@ //! docs for usage and details. mod conversions; -pub mod types; use std::cell::RefCell; use std::fs::File; @@ -17,12 +16,15 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; +use rustdoc_json_types as types; + use crate::clean; use crate::config::{RenderInfo, RenderOptions}; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::FormatRenderer; use crate::html::render::cache::ExternalLocation; +use crate::json::conversions::from_def_id; #[derive(Clone)] crate struct JsonRenderer<'tcx> { @@ -50,7 +52,7 @@ impl JsonRenderer<'_> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - item.def_id.into() + from_def_id(item.def_id) }) .collect() }) @@ -68,7 +70,7 @@ impl JsonRenderer<'_> { let item = &i.impl_item; if item.def_id.is_local() { self.item(item.clone()).unwrap(); - Some(item.def_id.into()) + Some(from_def_id(item.def_id)) } else { None } @@ -87,9 +89,9 @@ impl JsonRenderer<'_> { if !id.is_local() { trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap()); Some(( - id.into(), + from_def_id(id), types::Item { - id: id.into(), + id: from_def_id(id), crate_id: id.krate.as_u32(), name: self .cache @@ -163,7 +165,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { } else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner { e.impls = self.get_impls(id) } - let removed = self.index.borrow_mut().insert(id.into(), new_item.clone()); + let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone()); // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check // to make sure the items are unique. if let Some(old_item) = removed { @@ -203,11 +205,14 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { debug!("Done with crate"); let mut index = (*self.index).clone().into_inner(); index.extend(self.get_trait_items()); + // This needs to be the default HashMap for compatibility with the public interface for + // rustdoc-json + #[allow(rustc::default_hash_types)] let output = types::Crate { root: types::Id(String::from("0:0")), crate_version: krate.version.clone(), includes_private: self.cache.document_private, - index, + index: index.into_iter().collect(), paths: self .cache .paths @@ -216,7 +221,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { .chain(self.cache.external_paths.clone().into_iter()) .map(|(k, (path, kind))| { ( - k.into(), + from_def_id(k), types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() }, ) }) diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml new file mode 100644 index 0000000000000..7bba16a68b96c --- /dev/null +++ b/src/rustdoc-json-types/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rustdoc-json-types" +version = "0.1.0" +authors = ["The Rust Project Developers"] +edition = "2018" + +[lib] +path = "lib.rs" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } diff --git a/src/rustdoc-json-types/README.md b/src/rustdoc-json-types/README.md new file mode 100644 index 0000000000000..1e67d37655c6e --- /dev/null +++ b/src/rustdoc-json-types/README.md @@ -0,0 +1,12 @@ +# Rustdoc JSON Types + +This crate exposes the Rustdoc JSON API as a set of types with serde implementations. +These types are part of the public interface of the rustdoc JSON output, and making them +their own crate allows them to be versioned and distributed without having to depend on +any rustc/rustdoc internals. This way, consumers can rely on this crate for both documentation +of the output, and as a way to read the output easily, and its versioning is intended to +follow semver guarantees about the version of the format. JSON format X will always be +compatible with rustdoc-json-types version N. + +Currently, this crate is only used by rustdoc itself. Upon the stabilization of +rustdoc-json, it may be distributed separately for consumers of the API. diff --git a/src/librustdoc/json/types.rs b/src/rustdoc-json-types/lib.rs similarity index 98% rename from src/librustdoc/json/types.rs rename to src/rustdoc-json-types/lib.rs index 66cf12954dd0b..3fb2a32d5a0a3 100644 --- a/src/librustdoc/json/types.rs +++ b/src/rustdoc-json-types/lib.rs @@ -3,9 +3,9 @@ //! 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::path::PathBuf; -use rustc_data_structures::fx::FxHashMap; use serde::{Deserialize, Serialize}; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information @@ -21,11 +21,11 @@ pub struct Crate { pub includes_private: bool, /// A collection of all items in the local crate as well as some external traits and their /// items that are referenced locally. - pub index: FxHashMap, + pub index: HashMap, /// Maps IDs to fully qualified paths and other info helpful for generating links. - pub paths: FxHashMap, + pub paths: HashMap, /// Maps `crate_id` of items to a crate name and html_root_url if it exists. - pub external_crates: FxHashMap, + pub external_crates: HashMap, /// A single version number to be used in the future when making backwards incompatible changes /// to the JSON output. pub format_version: u32, @@ -72,7 +72,7 @@ pub struct Item { /// Some("") if there is some documentation but it is empty (EG `#[doc = ""]`). pub docs: Option, /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs - pub links: FxHashMap, + pub links: HashMap, /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`) pub attrs: Vec, pub deprecation: Option, diff --git a/src/test/run-make-fulldeps/split-debuginfo/Makefile b/src/test/run-make-fulldeps/split-debuginfo/Makefile new file mode 100644 index 0000000000000..e8e62efe01c14 --- /dev/null +++ b/src/test/run-make-fulldeps/split-debuginfo/Makefile @@ -0,0 +1,59 @@ +-include ../tools.mk + +all: off packed unpacked + +ifeq ($(UNAME),Darwin) +# If disabled, don't run dsymutil +off: + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs -g -C split-debuginfo=off + [ ! -d $(TMPDIR)/foo.dSYM ] + +# Packed by default, but only if debuginfo is requested +packed: + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs + [ ! -d $(TMPDIR)/foo.dSYM ] + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs -g + [ -d $(TMPDIR)/foo.dSYM ] + rm -rf $(TMPDIR)/*.dSYM + $(RUSTC) foo.rs -g -C split-debuginfo=packed + [ -d $(TMPDIR)/foo.dSYM ] + rm -rf $(TMPDIR)/*.dSYM + +# Object files are preserved with unpacked and `dsymutil` isn't run +unpacked: + $(RUSTC) foo.rs -g -C split-debuginfo=unpacked + ls $(TMPDIR)/*.o + [ ! -d $(TMPDIR)/foo.dSYM ] +else +ifdef IS_WINDOWS +# Windows only supports =off +off: +packed: +unpacked: +else +# If disabled, don't run dsymutil +off: + $(RUSTC) foo.rs -g -C split-debuginfo=off -Z unstable-options + [ ! -f $(TMPDIR)/*.dwp ] + [ ! -f $(TMPDIR)/*.dwo ] + + $(RUSTC) foo.rs -g + [ ! -f $(TMPDIR)/*.dwp ] + [ ! -f $(TMPDIR)/*.dwo ] + +packed: + $(RUSTC) foo.rs -g -C split-debuginfo=packed -Z unstable-options + ls $(TMPDIR)/*.dwp + ls $(TMPDIR)/*.dwo && exit 1 || exit 0 + rm -rf $(TMPDIR)/*.dwp + +unpacked: + $(RUSTC) foo.rs -g -C split-debuginfo=unpacked -Z unstable-options + ls $(TMPDIR)/*.dwp && exit 1 || exit 0 + ls $(TMPDIR)/*.dwo + rm -rf $(TMPDIR)/*.dwo +endif +endif diff --git a/src/test/run-make-fulldeps/split-debuginfo/foo.rs b/src/test/run-make-fulldeps/split-debuginfo/foo.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/src/test/run-make-fulldeps/split-debuginfo/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make-fulldeps/split-dwarf/Makefile b/src/test/run-make-fulldeps/split-dwarf/Makefile index e1a78e2edfc44..93dfc8e76a961 100644 --- a/src/test/run-make-fulldeps/split-dwarf/Makefile +++ b/src/test/run-make-fulldeps/split-dwarf/Makefile @@ -3,6 +3,6 @@ # only-linux all: - $(RUSTC) -Z split-dwarf=split foo.rs + $(RUSTC) -Z unstable-options -C split-debuginfo=packed foo.rs -g rm $(TMPDIR)/foo.dwp rm $(TMPDIR)/$(call BIN,foo) diff --git a/src/test/rustdoc/fn-type.rs b/src/test/rustdoc/fn-type.rs new file mode 100644 index 0000000000000..f5e123aed9c47 --- /dev/null +++ b/src/test/rustdoc/fn-type.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#![crate_name = "foo"] +#![crate_type = "lib"] + +pub struct Foo<'a, T> { + pub generic: fn(val: &T) -> T, + + pub lifetime: fn(val: &'a i32) -> i32, + pub hrtb_lifetime: for<'b, 'c> fn(one: &'b i32, two: &'c &'b i32) -> (&'b i32, &'c i32), +} + +// @has 'foo/struct.Foo.html' '//span[@id="structfield.generic"]' "generic: fn(val: &T) -> T" +// @has 'foo/struct.Foo.html' '//span[@id="structfield.lifetime"]' "lifetime: fn(val: &'a i32) -> i32" +// @has 'foo/struct.Foo.html' '//span[@id="structfield.hrtb_lifetime"]' "hrtb_lifetime: for<'b, 'c> fn(one: &'b i32, two: &'c &'b i32) -> (&'b i32, &'c i32)" diff --git a/src/test/rustdoc/for-lifetime.rs b/src/test/rustdoc/for-lifetime.rs new file mode 100644 index 0000000000000..299794b63b2ea --- /dev/null +++ b/src/test/rustdoc/for-lifetime.rs @@ -0,0 +1,14 @@ +// ignore-tidy-linelength + +#![crate_name = "foo"] +#![crate_type = "lib"] + +pub struct Foo { + pub some_func: for<'a> fn(val: &'a i32) -> i32, + pub some_trait: dyn for<'a> Trait<'a>, +} + +// @has foo/struct.Foo.html '//span[@id="structfield.some_func"]' "some_func: for<'a> fn(val: &'a i32) -> i32" +// @has foo/struct.Foo.html '//span[@id="structfield.some_trait"]' "some_trait: dyn Trait<'a>" + +pub trait Trait<'a> {} diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.rs b/src/test/ui/associated-consts/defaults-not-assumed-fail.rs index d7a48cbd63ecc..b0a4c7722e3ce 100644 --- a/src/test/ui/associated-consts/defaults-not-assumed-fail.rs +++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.rs @@ -31,7 +31,7 @@ impl Tr for u32 { fn main() { assert_eq!(<() as Tr>::A, 255); assert_eq!(<() as Tr>::B, 0); // causes the error above - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed //~| ERROR erroneous constant used assert_eq!(::A, 254); diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr index 1497633c26af9..cbaaed0508b98 100644 --- a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -8,15 +8,11 @@ LL | const B: u8 = Self::A + 1; | = note: `#[deny(const_err)]` on by default -error[E0080]: evaluation of constant expression failed - --> $DIR/defaults-not-assumed-fail.rs:33:5 +error[E0080]: evaluation of constant value failed + --> $DIR/defaults-not-assumed-fail.rs:33:16 | LL | assert_eq!(<() as Tr>::B, 0); // causes the error above - | ^^^^^^^^^^^-------------^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^^^^^^^^^^ referenced constant has errors error: erroneous constant used --> $DIR/defaults-not-assumed-fail.rs:33:5 diff --git a/src/test/ui/backtrace-apple-no-dsymutil.rs b/src/test/ui/backtrace-apple-no-dsymutil.rs new file mode 100644 index 0000000000000..492ff6356bcaf --- /dev/null +++ b/src/test/ui/backtrace-apple-no-dsymutil.rs @@ -0,0 +1,30 @@ +// run-pass + +// compile-flags:-g -Csplit-debuginfo=unpacked +// only-macos + +#![feature(backtrace)] + +use std::process::Command; +use std::str; + +#[inline(never)] +fn main() { + let args: Vec = std::env::args().collect(); + if args.len() >= 2 { + println!("{}", std::backtrace::Backtrace::force_capture()); + return; + } + let out = Command::new(&args[0]).env("RUST_BACKTRACE", "1").arg("foo").output().unwrap(); + let output = format!( + "{}\n{}", + str::from_utf8(&out.stdout).unwrap(), + str::from_utf8(&out.stderr).unwrap(), + ); + if out.status.success() && output.contains(file!()) { + return; + } + println!("status: {}", out.status); + println!("child output:\n\t{}", output.replace("\n", "\n\t")); + panic!("failed to find {:?} in output", file!()); +} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr index 44dde0fd80b0d..ea74fb966846f 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -20,7 +20,9 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable | LL | let f = || { | - help: consider changing this to be mutable: `mut f` -... +LL | let y = &raw mut x; + | - calling `f` requires mutable binding due to mutable borrow of `x` +LL | }; LL | f(); | ^ cannot borrow as mutable diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs new file mode 100644 index 0000000000000..ff210ae06a3bd --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr new file mode 100644 index 0000000000000..bf9e1febdbba4 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5 + | +LL | let callback = || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow 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/issue-80313-mutable-borrow-in-move-closure.rs b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs new file mode 100644 index 0000000000000..8f2d8a676302c --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr new file mode 100644 index 0000000000000..b67cec6a609f0 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5 + | +LL | let callback = move || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow 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/issue-80313-mutation-in-closure.rs b/src/test/ui/closures/issue-80313-mutation-in-closure.rs new file mode 100644 index 0000000000000..e082ea562ef22 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr new file mode 100644 index 0000000000000..6e98549f6b84f --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-closure.rs:6:5 + | +LL | let callback = || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow 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/issue-80313-mutation-in-move-closure.rs b/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs new file mode 100644 index 0000000000000..f66bf4e062831 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr new file mode 100644 index 0000000000000..edd55422a0bd4 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-move-closure.rs:6:5 + | +LL | let callback = move || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr index 65dfbd8097e76..c2adff116ef20 100644 --- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![warn(const_err)] | ^^^^^^^^^ -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/conditional_array_execution.rs:11:20 | LL | println!("{}", FOO); diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index 39803c8f257e0..cbfeca2402666 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -21,6 +21,6 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error fn main() { let x: &'static i32 = &X; - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed println!("x={}", x); } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 0016d301e598c..3e727b84aed10 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -12,13 +12,11 @@ note: the lint level is defined here LL | #[warn(const_err)] | ^^^^^^^^^ -error[E0080]: evaluation of constant expression failed - --> $DIR/const-eval-query-stack.rs:23:27 +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-query-stack.rs:23:28 | LL | let x: &'static i32 = &X; - | ^- - | | - | referenced constant has errors + | ^ referenced constant has errors query stack during panic: #0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]` #1 [optimized_mir] optimizing MIR for `main` diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs index f67871e6142ef..0a2532973f423 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -18,7 +18,7 @@ const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday fn main() { assert_eq!(Y, 4); - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed assert_eq!(Z, 4); - //~^ ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr index 822d4af83064e..2afedf30563a6 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -1,22 +1,14 @@ -error[E0080]: evaluation of constant expression failed - --> $DIR/const_fn_ptr_fail2.rs:20:5 +error[E0080]: evaluation of constant value failed + --> $DIR/const_fn_ptr_fail2.rs:20:16 | LL | assert_eq!(Y, 4); - | ^^^^^^^^^^^-^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^ referenced constant has errors -error[E0080]: evaluation of constant expression failed - --> $DIR/const_fn_ptr_fail2.rs:22:5 +error[E0080]: evaluation of constant value failed + --> $DIR/const_fn_ptr_fail2.rs:22:16 | LL | assert_eq!(Z, 4); - | ^^^^^^^^^^^-^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^ referenced constant has errors warning: skipping const checks | diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs index 9109307632b59..7d1d33288a907 100644 --- a/src/test/ui/consts/const-eval/issue-43197.rs +++ b/src/test/ui/consts/const-eval/issue-43197.rs @@ -12,8 +12,8 @@ fn main() { const Y: u32 = foo(0 - 1); //~^ WARN any use of this value will cause println!("{} {}", X, Y); - //~^ ERROR evaluation of constant expression failed - //~| ERROR evaluation of constant expression failed + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed //~| WARN erroneous constant used [const_err] //~| WARN erroneous constant used [const_err] } diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr index 27e067cedbb5c..8c72b59141687 100644 --- a/src/test/ui/consts/const-eval/issue-43197.stderr +++ b/src/test/ui/consts/const-eval/issue-43197.stderr @@ -20,7 +20,7 @@ LL | const Y: u32 = foo(0 - 1); | | | attempt to compute `0_u32 - 1_u32`, which would overflow -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/issue-43197.rs:14:23 | LL | println!("{} {}", X, Y); @@ -32,7 +32,7 @@ warning: erroneous constant used LL | println!("{} {}", X, Y); | ^ referenced constant has errors -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/issue-43197.rs:14:26 | LL | println!("{} {}", X, Y); diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs index f9194709dc0b7..79f1301a2f944 100644 --- a/src/test/ui/consts/const-eval/issue-44578.rs +++ b/src/test/ui/consts/const-eval/issue-44578.rs @@ -25,5 +25,5 @@ impl Foo for u16 { fn main() { println!("{}", as Foo>::AMT); - //~^ ERROR evaluation of constant expression failed [E0080] + //~^ ERROR evaluation of constant value failed [E0080] } diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr index f4323713e682b..bff9f40f82b35 100644 --- a/src/test/ui/consts/const-eval/issue-44578.stderr +++ b/src/test/ui/consts/const-eval/issue-44578.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of constant expression failed +error[E0080]: evaluation of constant value failed --> $DIR/issue-44578.rs:27:20 | LL | println!("{}", as Foo>::AMT); diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr index ca8885e935090..f929f500cf9fb 100644 --- a/src/test/ui/consts/const-eval/issue-50814-2.stderr +++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr @@ -8,13 +8,11 @@ LL | const BAR: usize = [5, 6, 7][T::BOO]; | = note: `#[deny(const_err)]` on by default -error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814-2.rs:18:5 +error[E0080]: evaluation of constant value failed + --> $DIR/issue-50814-2.rs:18:6 | LL | & as Foo>::BAR - | ^--------------------- - | | - | referenced constant has errors + | ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index 7327138627648..307fb3c8c9de1 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -8,13 +8,11 @@ LL | const MAX: u8 = A::MAX + B::MAX; | = note: `#[deny(const_err)]` on by default -error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814.rs:20:5 +error[E0080]: evaluation of constant value failed + --> $DIR/issue-50814.rs:20:6 | LL | &Sum::::MAX - | ^----------------- - | | - | referenced constant has errors + | ^^^^^^^^^^^^^^^^^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr index 31090be090833..6dddc7ff6e9d2 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr @@ -20,15 +20,11 @@ note: the lint level is defined here LL | #[warn(const_err)] | ^^^^^^^^^ -error[E0080]: evaluation of constant expression failed - --> $DIR/const_unsafe_unreachable_ub.rs:17:3 +error[E0080]: evaluation of constant value failed + --> $DIR/const_unsafe_unreachable_ub.rs:17:14 | LL | assert_eq!(BAR, true); - | ^^^^^^^^^^^---^^^^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^ referenced constant has errors error: erroneous constant used --> $DIR/const_unsafe_unreachable_ub.rs:17:3 diff --git a/src/test/ui/consts/issue-55878.stderr b/src/test/ui/consts/issue-55878.stderr index 924910e9cb6df..ede5487b65d39 100644 --- a/src/test/ui/consts/issue-55878.stderr +++ b/src/test/ui/consts/issue-55878.stderr @@ -2,15 +2,12 @@ error[E0080]: values of the type `[u8; SIZE]` are too big for the current archit --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | LL | intrinsics::size_of::() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL - | inside `main` at $DIR/issue-55878.rs:7:26 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL | ::: $DIR/issue-55878.rs:7:26 | LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); - | ---------------------------------------------- + | ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26 error: erroneous constant used --> $DIR/issue-55878.rs:7:26 diff --git a/src/test/ui/lint/semicolon-in-expressions-from-macros/allow-semicolon-in-expressions-from-macros.rs b/src/test/ui/lint/semicolon-in-expressions-from-macros/allow-semicolon-in-expressions-from-macros.rs new file mode 100644 index 0000000000000..6f9e6ec0a57ff --- /dev/null +++ b/src/test/ui/lint/semicolon-in-expressions-from-macros/allow-semicolon-in-expressions-from-macros.rs @@ -0,0 +1,15 @@ +// check-pass +// Ensure that trailing semicolons are allowed by default + +macro_rules! foo { + () => { + true; + } +} + +fn main() { + let val = match true { + true => false, + _ => foo!() + }; +} diff --git a/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs new file mode 100644 index 0000000000000..605d5a0309cfc --- /dev/null +++ b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs @@ -0,0 +1,30 @@ +// check-pass +#![warn(semicolon_in_expressions_from_macros)] + +#[allow(dead_code)] +macro_rules! foo { + ($val:ident) => { + true; //~ WARN trailing + //~| WARN this was previously + //~| WARN trailing + //~| WARN this was previously + } +} + +fn main() { + // This `allow` doesn't work + #[allow(semicolon_in_expressions_from_macros)] + let _ = { + foo!(first) + }; + + // This 'allow' doesn't work either + #[allow(semicolon_in_expressions_from_macros)] + let _ = foo!(second); + + // But this 'allow' does + #[allow(semicolon_in_expressions_from_macros)] + fn inner() { + let _ = foo!(third); + } +} diff --git a/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr new file mode 100644 index 0000000000000..6f9f879661a41 --- /dev/null +++ b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr @@ -0,0 +1,33 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:7:13 + | +LL | true; + | ^ +... +LL | foo!(first) + | ----------- in this macro invocation + | +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:2:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:7:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(second); + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 2 warnings emitted + diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr index 5dea424596e9c..a0ed56d4bcf7b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -3,6 +3,8 @@ error[E0596]: cannot borrow `tick1` as mutable, as it is not declared as mutable | LL | let tick1 = || { | ----- help: consider changing this to be mutable: `mut tick1` +LL | counter += 1; + | ------- calling `tick1` requires mutable binding due to mutable borrow of `counter` ... LL | tick1(); | ^^^^^ cannot borrow as mutable @@ -12,6 +14,8 @@ error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable | LL | let tick2 = || { | ----- help: consider changing this to be mutable: `mut tick2` +LL | tick1(); + | ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1` ... LL | tick2(); | ^^^^^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index eb398628846dd..27d23e3fa044b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5 | LL | let tick = || counter += 1; - | ---- help: consider changing this to be mutable: `mut tick` + | ---- ------- calling `tick` requires mutable binding due to mutable borrow of `counter` + | | + | help: consider changing this to be mutable: `mut tick` LL | tick(); | ^^^^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index b9d76d9a752ce..c00f986c397a7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5 | LL | let tick = move || counter += 1; - | ---- help: consider changing this to be mutable: `mut tick` + | ---- ------- calling `tick` requires mutable binding due to possible mutation of `counter` + | | + | help: consider changing this to be mutable: `mut tick` LL | tick(); | ^^^^ cannot borrow as mutable diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index f7224811e6e79..6fa1378b8c73d 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -1,5 +1,5 @@ use crate::utils::{ - any_parent_is_automatically_derived, contains_name, match_def_path, paths, qpath_res, snippet_with_macro_callsite, + any_parent_is_automatically_derived, contains_name, match_def_path, paths, snippet_with_macro_callsite, }; use crate::utils::{span_lint_and_note, span_lint_and_sugg}; use if_chain::if_chain; @@ -231,7 +231,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool if_chain! { if let ExprKind::Call(ref fn_expr, _) = &expr.kind; if let ExprKind::Path(qpath) = &fn_expr.kind; - if let Res::Def(_, def_id) = qpath_res(cx, qpath, fn_expr.hir_id); + if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); then { // right hand side of assignment is `Default::default` match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD) diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index cf528d189b4b1..a84f9c4628716 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note}; +use crate::utils::{is_copy, match_def_path, paths, span_lint_and_note}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { if let ExprKind::Call(ref path, ref args) = expr.kind; if let ExprKind::Path(ref qpath) = path.kind; if args.len() == 1; - if let Some(def_id) = qpath_res(cx, qpath, path.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); then { let lint; let msg; diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index 7337d98c8be37..915859270009b 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_entrypoint_fn, match_def_path, paths, qpath_res, span_lint}; +use crate::utils::{is_entrypoint_fn, match_def_path, paths, span_lint}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; @@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit { if_chain! { if let ExprKind::Call(ref path_expr, ref _args) = e.kind; if let ExprKind::Path(ref path) = path_expr.kind; - if let Some(def_id) = qpath_res(cx, path, path_expr.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::EXIT); then { let parent = cx.tcx.hir().get_parent_item(e.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs index fd93548b55c6d..8795425461033 100644 --- a/src/tools/clippy/clippy_lints/src/functions.rs +++ b/src/tools/clippy/clippy_lints/src/functions.rs @@ -1,7 +1,7 @@ use crate::utils::{ attr_by_name, attrs::is_proc_macro, is_must_use_ty, is_trait_impl_item, is_type_diagnostic_item, iter_input_pats, - last_path_segment, match_def_path, must_use_attr, qpath_res, return_ty, snippet, snippet_opt, span_lint, - span_lint_and_help, span_lint_and_then, trait_ref_of_method, type_is_unsafe_function, + last_path_segment, match_def_path, must_use_attr, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help, + span_lint_and_then, trait_ref_of_method, type_is_unsafe_function, }; use if_chain::if_chain; use rustc_ast::ast::Attribute; @@ -659,7 +659,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { impl<'a, 'tcx> DerefVisitor<'a, 'tcx> { fn check_arg(&self, ptr: &hir::Expr<'_>) { if let hir::ExprKind::Path(ref qpath) = ptr.kind { - if let Res::Local(id) = qpath_res(self.cx, qpath, ptr.hir_id) { + if let Res::Local(id) = self.cx.qpath_res(qpath, ptr.hir_id) { if self.ptrs.contains(&id) { span_lint( self.cx, @@ -722,7 +722,7 @@ fn is_mutated_static(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { use hir::ExprKind::{Field, Index, Path}; match e.kind { - Path(ref qpath) => !matches!(qpath_res(cx, qpath, e.hir_id), Res::Local(_)), + Path(ref qpath) => !matches!(cx.qpath_res(qpath, e.hir_id), Res::Local(_)), Field(ref inner, _) | Index(ref inner, _) => is_mutated_static(cx, inner), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index db717cd1240a4..5886c2360e362 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,4 @@ -use crate::utils::{qpath_res, snippet, span_lint_and_then, visitors::LocalUsedVisitor}; +use crate::utils::{snippet, span_lint_and_then, visitors::LocalUsedVisitor}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -145,7 +145,7 @@ fn check_assign<'tcx>( if let hir::StmtKind::Semi(ref expr) = expr.kind; if let hir::ExprKind::Assign(ref var, ref value, _) = expr.kind; if let hir::ExprKind::Path(ref qpath) = var.kind; - if let Res::Local(local_id) = qpath_res(cx, qpath, var.hir_id); + if let Res::Local(local_id) = cx.qpath_res(qpath, var.hir_id); if decl == local_id; then { let mut v = LocalUsedVisitor::new(decl); diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index bbcea387de2cb..f89075005bc7a 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -6,9 +6,9 @@ use crate::utils::visitors::LocalUsedVisitor; use crate::utils::{ contains_name, get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, indent_of, is_in_panic_handler, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, - last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, qpath_res, single_segment_path, - snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, - span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq, + last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, single_segment_path, snippet, + snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, + span_lint_and_then, sugg, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast; @@ -848,7 +848,7 @@ fn same_var<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, var: HirId) -> bool { if let ExprKind::Path(qpath) = &expr.kind; if let QPath::Resolved(None, path) = qpath; if path.segments.len() == 1; - if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id); + if let Res::Local(local_id) = cx.qpath_res(qpath, expr.hir_id); then { // our variable! local_id == var @@ -1420,7 +1420,7 @@ fn detect_same_item_push<'tcx>( // Make sure that the push does not involve possibly mutating values match pushed_item.kind { ExprKind::Path(ref qpath) => { - match qpath_res(cx, qpath, pushed_item.hir_id) { + match cx.qpath_res(qpath, pushed_item.hir_id) { // immutable bindings that are initialized with literal or constant Res::Local(hir_id) => { if_chain! { @@ -1437,7 +1437,7 @@ fn detect_same_item_push<'tcx>( ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item), // immutable bindings that are initialized with constant ExprKind::Path(ref path) => { - if let Res::Def(DefKind::Const, ..) = qpath_res(cx, path, init.hir_id) { + if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { emit_lint(cx, vec, pushed_item); } } @@ -2028,7 +2028,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option if let ExprKind::Path(ref qpath) = bound.kind; if let QPath::Resolved(None, _) = *qpath; then { - let res = qpath_res(cx, qpath, bound.hir_id); + let res = cx.qpath_res(qpath, bound.hir_id); if let Res::Local(hir_id) = res { let node_str = cx.tcx.hir().get(hir_id); if_chain! { @@ -2120,7 +2120,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if self.prefer_mutable { self.indexed_mut.insert(seqvar.segments[0].ident.name); } - let res = qpath_res(self.cx, seqpath, seqexpr.hir_id); + let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); match res { Res::Local(hir_id) => { let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); @@ -2184,7 +2184,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; then { - if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id) { + if let Res::Local(local_id) = self.cx.qpath_res(qpath, expr.hir_id) { if local_id == self.var { self.nonindex = true; } else { @@ -2589,7 +2589,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn var_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { if let ExprKind::Path(ref qpath) = expr.kind { - let path_res = qpath_res(cx, qpath, expr.hir_id); + let path_res = cx.qpath_res(qpath, expr.hir_id); if let Res::Local(hir_id) = path_res { return Some(hir_id); } @@ -2819,7 +2819,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { if_chain! { if let ExprKind::Path(ref qpath) = ex.kind; if let QPath::Resolved(None, _) = *qpath; - let res = qpath_res(self.cx, qpath, ex.hir_id); + let res = self.cx.qpath_res(qpath, ex.hir_id); then { match res { Res::Local(hir_id) => { diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index a0cfe145a301c..42a92104a4919 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -1,7 +1,7 @@ use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{ - eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then, + eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, snippet, span_lint_and_then, }; use if_chain::if_chain; @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { } else { return; }; - let target_res = qpath_res(cx, &target_path, target_arg.hir_id); + let target_res = cx.qpath_res(&target_path, target_arg.hir_id); if target_res == Res::Err { return; }; @@ -221,7 +221,7 @@ fn find_stripping<'tcx>( if let ExprKind::Index(indexed, index) = &unref.kind; if let Some(higher::Range { start, end, .. }) = higher::range(index); if let ExprKind::Path(path) = &indexed.kind; - if qpath_res(self.cx, path, ex.hir_id) == self.target; + if self.cx.qpath_res(path, ex.hir_id) == self.target; then { match (self.strip_kind, start, end) { (StripKind::Prefix, Some(start), None) => { @@ -235,7 +235,7 @@ fn find_stripping<'tcx>( if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind; if let Some(left_arg) = len_arg(self.cx, left); if let ExprKind::Path(left_path) = &left_arg.kind; - if qpath_res(self.cx, left_path, left_arg.hir_id) == self.target; + if self.cx.qpath_res(left_path, left_arg.hir_id) == self.target; if eq_pattern_length(self.cx, self.pattern, right); then { self.results.push(ex.span); diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs index 8c6fd10f98a1e..d34f9761e26f9 100644 --- a/src/tools/clippy/clippy_lints/src/mem_forget.rs +++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_def_path, paths, qpath_res, span_lint}; +use crate::utils::{match_def_path, paths, span_lint}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Call(ref path_expr, ref args) = e.kind { if let ExprKind::Path(ref qpath) = path_expr.kind { - if let Some(def_id) = qpath_res(cx, qpath, path_expr.hir_id).opt_def_id() { + if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { if match_def_path(cx, def_id, &paths::MEM_FORGET) { let forgot_ty = cx.typeck_results().expr_ty(&args[0]); diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index b1b5b3439a0e3..69302d695ce0a 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,4 +1,4 @@ -use crate::utils::{has_drop, qpath_res, snippet_opt, span_lint, span_lint_and_sugg}; +use crate::utils::{has_drop, snippet_opt, span_lint, span_lint_and_sugg}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; @@ -67,7 +67,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { }, ExprKind::Call(ref callee, ref args) => { if let ExprKind::Path(ref qpath) = callee.kind { - let res = qpath_res(cx, qpath, callee.hir_id); + let res = cx.qpath_res(qpath, callee.hir_id); match res { Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) => { !has_drop(cx, cx.typeck_results().expr_ty(expr)) @@ -146,7 +146,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option { if let ExprKind::Path(ref qpath) = callee.kind { - let res = qpath_res(cx, qpath, callee.hir_id); + let res = cx.qpath_res(qpath, callee.hir_id); match res { Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) if !has_drop(cx, cx.typeck_results().expr_ty(expr)) => diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 3a9aa6ced03ba..f57d753631755 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -18,7 +18,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_typeck::hir_ty_to_ty; -use crate::utils::{in_constant, qpath_res, span_lint_and_then}; +use crate::utils::{in_constant, span_lint_and_then}; use if_chain::if_chain; // FIXME: this is a correctness problem but there's no suitable @@ -339,7 +339,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { } // Make sure it is a const item. - let item_def_id = match qpath_res(cx, qpath, expr.hir_id) { + let item_def_id = match cx.qpath_res(qpath, expr.hir_id) { Res::Def(DefKind::Const | DefKind::AssocConst, did) => did, _ => return, }; diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs index c53727ba16004..fa508df865e48 100644 --- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs +++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint}; +use crate::utils::{match_def_path, match_trait_method, paths, span_lint}; use if_chain::if_chain; use rustc_hir::def::Res; use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind}; @@ -94,7 +94,7 @@ impl LateLintPass<'_> for ToStringInDisplay { if match_trait_method(cx, expr, &paths::TO_STRING); if self.in_display_impl; if let ExprKind::Path(ref qpath) = args[0].kind; - if let Res::Local(hir_id) = qpath_res(cx, qpath, args[0].hir_id); + if let Res::Local(hir_id) = cx.qpath_res(qpath, args[0].hir_id); if let Some(self_hir_id) = self.self_hir_id; if hir_id == self_hir_id; then { diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs index 17cef0af3e9c9..04c32ce9e8f2c 100644 --- a/src/tools/clippy/clippy_lints/src/types.rs +++ b/src/tools/clippy/clippy_lints/src/types.rs @@ -34,7 +34,7 @@ use crate::utils::sugg::Sugg; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_hir_ty_cfg_dependant, is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args, - multispan_sugg, numeric_literal::NumericLiteral, qpath_res, reindent_multiline, sext, snippet, snippet_opt, + multispan_sugg, numeric_literal::NumericLiteral, reindent_multiline, sext, snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, unsext, }; @@ -298,7 +298,7 @@ fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) _ => None, }); if let TyKind::Path(ref qpath) = ty.kind; - if let Some(did) = qpath_res(cx, qpath, ty.hir_id).opt_def_id(); + if let Some(did) = cx.qpath_res(qpath, ty.hir_id).opt_def_id(); if match_def_path(cx, did, path); then { return Some(ty.span); @@ -365,7 +365,7 @@ impl Types { match hir_ty.kind { TyKind::Path(ref qpath) if !is_local => { let hir_id = hir_ty.hir_id; - let res = qpath_res(cx, qpath, hir_id); + let res = cx.qpath_res(qpath, hir_id); if let Some(def_id) = res.opt_def_id() { if Some(def_id) == cx.tcx.lang_items().owned_box() { if let Some(span) = match_borrows_parameter(cx, qpath) { @@ -535,7 +535,7 @@ impl Types { }); // ty is now _ at this point if let TyKind::Path(ref ty_qpath) = ty.kind; - let res = qpath_res(cx, ty_qpath, ty.hir_id); + let res = cx.qpath_res(ty_qpath, ty.hir_id); if let Some(def_id) = res.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); // At this point, we know ty is Box, now get T @@ -652,7 +652,7 @@ impl Types { match mut_ty.ty.kind { TyKind::Path(ref qpath) => { let hir_id = mut_ty.ty.hir_id; - let def = qpath_res(cx, qpath, hir_id); + let def = cx.qpath_res(qpath, hir_id); if_chain! { if let Some(def_id) = def.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); @@ -739,7 +739,7 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool { fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option> { if_chain! { - if let Some(did) = qpath_res(cx, qpath, id).opt_def_id(); + if let Some(did) = cx.qpath_res(qpath, id).opt_def_id(); if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; if synthetic == Some(SyntheticTyParamKind::ImplTrait); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index 7aa17520ba79f..822863ca3e279 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::{ - is_expn_of, match_def_path, match_qpath, match_type, method_calls, path_to_res, paths, qpath_res, run_lints, - snippet, span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq, + is_expn_of, match_def_path, match_qpath, match_type, method_calls, path_to_res, paths, run_lints, snippet, + span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, NodeId}; @@ -787,7 +787,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option return path_to_matched_type(cx, expr), - ExprKind::Path(qpath) => match qpath_res(cx, qpath, expr.hir_id) { + ExprKind::Path(qpath) => match cx.qpath_res(qpath, expr.hir_id) { Res::Local(hir_id) => { let parent_id = cx.tcx.hir().get_parent_node(hir_id); if let Some(Node::Local(local)) = cx.tcx.hir().find(parent_id) { diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 46b2b06d1a280..0bbb6a52a2046 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -369,19 +369,6 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option { } } -pub fn qpath_res(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { - match qpath { - hir::QPath::Resolved(_, path) => path.res, - hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { - if cx.tcx.has_typeck_results(id.owner.to_def_id()) { - cx.tcx.typeck(id.owner).qpath_res(qpath, id) - } else { - Res::Err - } - }, - } -} - /// Convenience function to get the `DefId` of a trait by path. /// It could be a trait or trait alias. pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 5608ff98417cd..52aed57fc76af 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2015,10 +2015,10 @@ impl<'test> TestCx<'test> { rustc.args(&["-Zchalk"]); } Some(CompareMode::SplitDwarf) => { - rustc.args(&["-Zsplit-dwarf=split"]); + rustc.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]); } Some(CompareMode::SplitDwarfSingle) => { - rustc.args(&["-Zsplit-dwarf=single"]); + rustc.args(&["-Csplit-debuginfo=packed", "-Zunstable-options"]); } None => {} } diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index e687901f212b6..21d05226fb42c 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -7,7 +7,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 1458; +const ROOT_ENTRY_LIMIT: usize = 1459; const ISSUES_ENTRY_LIMIT: usize = 2669; fn check_entries(path: &Path, bad: &mut bool) {