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 b9ae796325023..ae629a3778e0f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -996,10 +996,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..0738b2df71e0c 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 { 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_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index f165a60336a6a..37902dddff46d 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -74,11 +74,10 @@ macro_rules! forward { }); }; - // Forward pattern for &mut self -> &mut Self, with S: Into - // type parameter. No obvious way to make this more generic. + // Forward pattern for &mut self -> &mut Self, with generic parameters. ( $(#[$attrs:meta])* - pub fn $n:ident>( + pub fn $n:ident<$($generic:ident: $bound:path),*>( &mut self, $($name:ident: $ty:ty),* $(,)? @@ -86,7 +85,7 @@ macro_rules! forward { ) => { $(#[$attrs])* forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") => - pub fn $n>(&mut self, $($name: $ty),*) -> &mut Self { + pub fn $n<$($generic: $bound),*>(&mut self, $($name: $ty),*) -> &mut Self { self.0.diagnostic.$n($($name),*); self }); @@ -398,6 +397,7 @@ impl<'a> DiagnosticBuilder<'a> { self } + forward!(pub fn set_primary_message>(&mut self, msg: M) -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); 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_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c4d867161386d..2778882adcf74 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -780,8 +780,20 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> pub struct CaptureInfo<'tcx> { /// Expr Id pointing to use that resulted in selecting the current capture kind /// + /// Eg: + /// ```rust,no_run + /// let mut t = (0,1); + /// + /// let c = || { + /// println!("{}",t); // L1 + /// t.1 = 4; // L2 + /// }; + /// ``` + /// `capture_kind_expr_id` will point to the use on L2 and `path_expr_id` will point to the + /// use on L1. + /// /// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is - /// possible that we don't see the use of a particular place resulting in expr_id being + /// possible that we don't see the use of a particular place resulting in capture_kind_expr_id being /// None. In such case we fallback on uvpars_mentioned for span. /// /// Eg: @@ -795,7 +807,12 @@ pub struct CaptureInfo<'tcx> { /// /// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured, /// but we won't see it being used during capture analysis, since it's essentially a discard. - pub expr_id: Option, + pub capture_kind_expr_id: Option, + /// Expr Id pointing to use that resulted the corresponding place being captured + /// + /// See `capture_kind_expr_id` for example. + /// + pub path_expr_id: Option, /// Capture mode that was selected pub capture_kind: UpvarCapture<'tcx>, 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_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 4234740b2b15f..6b7059eecf4e2 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -133,7 +133,15 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { - self.struct_span_err(path.span, "unexpected generic arguments in path").emit(); + self.struct_span_err( + path.segments + .iter() + .filter_map(|segment| segment.args.as_ref()) + .map(|arg| arg.span()) + .collect::>(), + "unexpected generic arguments in path", + ) + .emit(); } path }); 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_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7b90e5b611cd1..2e7c9701c0c67 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -622,6 +622,7 @@ symbols! { intel, into_iter, into_result, + into_trait, intra_doc_pointers, intrinsics, irrefutable_let_patterns, @@ -1159,6 +1160,8 @@ symbols! { truncf32, truncf64, try_blocks, + try_from_trait, + try_into_trait, try_trait, tt, tuple, 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/compiler/rustc_target/src/spec/wasm32_base.rs b/compiler/rustc_target/src/spec/wasm32_base.rs index a7957d84cbeef..bfef3d37228f0 100644 --- a/compiler/rustc_target/src/spec/wasm32_base.rs +++ b/compiler/rustc_target/src/spec/wasm32_base.rs @@ -55,15 +55,6 @@ pub fn options() -> TargetOptions { // to do so. arg("--no-demangle"); - // The symbol visibility story is a bit in flux right now with LLD. - // It's... not entirely clear to me what's going on, but this looks to - // make everything work when `export_symbols` isn't otherwise called for - // things like executables. - // - // This is really only here to get things working. If it can be removed and - // basic tests still work, then sounds like it should be removed! - arg("--export-dynamic"); - let mut pre_link_args = BTreeMap::new(); pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args); pre_link_args.insert(LinkerFlavor::Gcc, clang_args); diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index c12757b8f9812..9f69ce16c215d 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -2,6 +2,17 @@ use super::wasm32_base; use super::{LinkArgs, LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { + let mut options = wasm32_base::options(); + + let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + + // Rust really needs a way for users to specify exports and imports in + // the source code. --export-dynamic isn't the right tool for this job, + // however it does have the side effect of automatically exporting a lot + // of symbols, which approximates what people want when compiling for + // wasm32-unknown-unknown expect, so use it for now. + clang_args.push("--export-dynamic".to_string()); + let mut post_link_args = LinkArgs::new(); post_link_args.insert( LinkerFlavor::Em, @@ -28,7 +39,7 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Unwind, post_link_args, os_family: Some("unix".to_string()), - ..wasm32_base::options() + ..options }; Target { llvm_target: "wasm32-unknown-emscripten".to_string(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 6037aa5b4306e..5e89ba2520bdd 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -26,11 +26,18 @@ pub fn target() -> Target { // For now this target just never has an entry symbol no matter the output // type, so unconditionally pass this. clang_args.push("-Wl,--no-entry".to_string()); - options - .pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)) - .unwrap() - .push("--no-entry".to_string()); + + // Rust really needs a way for users to specify exports and imports in + // the source code. --export-dynamic isn't the right tool for this job, + // however it does have the side effect of automatically exporting a lot + // of symbols, which approximates what people want when compiling for + // wasm32-unknown-unknown expect, so use it for now. + clang_args.push("-Wl,--export-dynamic".to_string()); + + // Add the flags to wasm-ld's args too. + let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap(); + lld_args.push("--no-entry".to_string()); + lld_args.push("--export-dynamic".to_string()); Target { llvm_target: "wasm32-unknown-unknown".to_string(), diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index c553fda49c308..d49c7cae8222b 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -446,6 +446,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + let mut label_span_not_found = || { + if unsatisfied_predicates.is_empty() { + err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); + } else { + err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds")); + } + self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span); + }; + // If the method name is the name of a field with a function or closure type, // give a helping note that it has to be called as `(x.f)(...)`. if let SelfSource::MethodCall(expr) = source { @@ -501,12 +510,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_kind = if is_accessible { "field" } else { "private field" }; err.span_label(item_name.span, format!("{}, not a method", field_kind)); } else if lev_candidate.is_none() && static_sources.is_empty() { - err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str)); - self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span); + label_span_not_found(); } } else { - err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str)); - self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span); + label_span_not_found(); } if self.is_fn_ty(&rcvr_ty, span) { @@ -721,10 +728,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|(_, path)| path) .collect::>() .join("\n"); + let actual_prefix = actual.prefix_string(); + err.set_primary_message(&format!( + "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" + )); err.note(&format!( - "the method `{}` exists but the following trait bounds were not \ - satisfied:\n{}", - item_name, bound_list + "the following trait bounds were not satisfied:\n{bound_list}" )); } } @@ -742,7 +751,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if actual.is_enum() { + // Don't emit a suggestion if we found an actual method + // that had unsatisfied trait bounds + if unsatisfied_predicates.is_empty() && actual.is_enum() { let adt_def = actual.ty_adt_def().expect("enum is not an ADT"); if let Some(suggestion) = lev_distance::find_best_match_for_name( &adt_def.variants.iter().map(|s| s.ident.name).collect::>(), @@ -778,17 +789,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(span, msg); } } else if let Some(lev_candidate) = lev_candidate { - let def_kind = lev_candidate.kind.as_def_kind(); - err.span_suggestion( - span, - &format!( - "there is {} {} with a similar name", - def_kind.article(), - def_kind.descr(lev_candidate.def_id), - ), - lev_candidate.ident.to_string(), - Applicability::MaybeIncorrect, - ); + // Don't emit a suggestion if we found an actual method + // that had unsatisfied trait bounds + if unsatisfied_predicates.is_empty() { + let def_kind = lev_candidate.kind.as_def_kind(); + err.span_suggestion( + span, + &format!( + "there is {} {} with a similar name", + def_kind.article(), + def_kind.descr(lev_candidate.def_id), + ), + lev_candidate.ident.to_string(), + Applicability::MaybeIncorrect, + ); + } } return Some(err); diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index feda35daa617d..6b2cba62fa6b7 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -42,7 +42,7 @@ use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, ProjectionKind}; use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_span::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::{MultiSpan, Span, Symbol}; /// Describe the relationship between the paths of two places /// eg: @@ -135,7 +135,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let upvar_id = ty::UpvarId::new(var_hir_id, local_def_id); let capture_kind = self.init_capture_kind(capture_clause, upvar_id, span); - let info = ty::CaptureInfo { expr_id: None, capture_kind }; + let info = ty::CaptureInfo { + capture_kind_expr_id: None, + path_expr_id: None, + capture_kind, + }; capture_information.insert(place, info); } @@ -308,8 +312,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(capture_kind) = upvar_capture_map.get(&upvar_id) { // upvar_capture_map only stores the UpvarCapture (CaptureKind), // so we create a fake capture info with no expression. - let fake_capture_info = - ty::CaptureInfo { expr_id: None, capture_kind: *capture_kind }; + let fake_capture_info = ty::CaptureInfo { + capture_kind_expr_id: None, + path_expr_id: None, + capture_kind: *capture_kind, + }; determine_capture_info(fake_capture_info, capture_info).capture_kind } else { capture_info.capture_kind @@ -359,20 +366,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// ``` /// { - /// Place(base: hir_id_s, projections: [], ....) -> (hir_id_L5, ByValue), - /// Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> (hir_id_L2, ByRef(MutBorrow)) - /// Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> (hir_id_L3, ByRef(ImmutBorrow)) - /// Place(base: hir_id_p, projections: [], ...) -> (hir_id_L4, ByRef(ImmutBorrow)) + /// Place(base: hir_id_s, projections: [], ....) -> { + /// capture_kind_expr: hir_id_L5, + /// path_expr_id: hir_id_L5, + /// capture_kind: ByValue + /// }, + /// Place(base: hir_id_p, projections: [Field(0, 0)], ...) -> { + /// capture_kind_expr: hir_id_L2, + /// path_expr_id: hir_id_L2, + /// capture_kind: ByValue + /// }, + /// Place(base: hir_id_p, projections: [Field(1, 0)], ...) -> { + /// capture_kind_expr: hir_id_L3, + /// path_expr_id: hir_id_L3, + /// capture_kind: ByValue + /// }, + /// Place(base: hir_id_p, projections: [], ...) -> { + /// capture_kind_expr: hir_id_L4, + /// path_expr_id: hir_id_L4, + /// capture_kind: ByValue + /// }, /// ``` /// /// After the min capture analysis, we get: /// ``` /// { /// hir_id_s -> [ - /// Place(base: hir_id_s, projections: [], ....) -> (hir_id_L4, ByValue) + /// Place(base: hir_id_s, projections: [], ....) -> { + /// capture_kind_expr: hir_id_L5, + /// path_expr_id: hir_id_L5, + /// capture_kind: ByValue + /// }, /// ], /// hir_id_p -> [ - /// Place(base: hir_id_p, projections: [], ...) -> (hir_id_L2, ByRef(MutBorrow)), + /// Place(base: hir_id_p, projections: [], ...) -> { + /// capture_kind_expr: hir_id_L2, + /// path_expr_id: hir_id_L4, + /// capture_kind: ByValue + /// }, /// ], /// ``` fn compute_min_captures( @@ -425,8 +456,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // current place is ancestor of possible_descendant PlaceAncestryRelation::Ancestor => { descendant_found = true; + let backup_path_expr_id = updated_capture_info.path_expr_id; + updated_capture_info = determine_capture_info(updated_capture_info, possible_descendant.info); + + // we need to keep the ancestor's `path_expr_id` + updated_capture_info.path_expr_id = backup_path_expr_id; false } @@ -441,9 +477,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // current place is descendant of possible_ancestor PlaceAncestryRelation::Descendant => { ancestor_found = true; + let backup_path_expr_id = possible_ancestor.info.path_expr_id; possible_ancestor.info = determine_capture_info(possible_ancestor.info, capture_info); + // we need to keep the ancestor's `path_expr_id` + possible_ancestor.info.path_expr_id = backup_path_expr_id; + // Only one ancestor of the current place will be in the list. break; } @@ -518,7 +558,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let capture_str = construct_capture_info_string(self.tcx, place, capture_info); let output_str = format!("Capturing {}", capture_str); - let span = capture_info.expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); + let span = + capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); diag.span_note(span, &output_str); } diag.emit(); @@ -542,9 +583,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { construct_capture_info_string(self.tcx, place, capture_info); let output_str = format!("Min Capture {}", capture_str); - let span = - capture_info.expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); - diag.span_note(span, &output_str); + if capture.info.path_expr_id != capture.info.capture_kind_expr_id { + let path_span = capture_info + .path_expr_id + .map_or(closure_span, |e| self.tcx.hir().span(e)); + let capture_kind_span = capture_info + .capture_kind_expr_id + .map_or(closure_span, |e| self.tcx.hir().span(e)); + + let mut multi_span: MultiSpan = + MultiSpan::from_spans(vec![path_span, capture_kind_span]); + + let capture_kind_label = + construct_capture_kind_reason_string(self.tcx, place, capture_info); + let path_label = construct_path_string(self.tcx, place); + + multi_span.push_span_label(path_span, path_label); + multi_span.push_span_label(capture_kind_span, capture_kind_label); + + diag.span_note(multi_span, &output_str); + } else { + let span = capture_info + .path_expr_id + .map_or(closure_span, |e| self.tcx.hir().span(e)); + + diag.span_note(span, &output_str); + }; } } diag.emit(); @@ -642,7 +706,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { ); let capture_info = ty::CaptureInfo { - expr_id: Some(diag_expr_id), + capture_kind_expr_id: Some(diag_expr_id), + path_expr_id: Some(diag_expr_id), capture_kind: ty::UpvarCapture::ByValue(Some(usage_span)), }; @@ -762,7 +827,8 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { let new_upvar_borrow = ty::UpvarBorrow { kind, region: curr_upvar_borrow.region }; let capture_info = ty::CaptureInfo { - expr_id: Some(diag_expr_id), + capture_kind_expr_id: Some(diag_expr_id), + path_expr_id: Some(diag_expr_id), capture_kind: ty::UpvarCapture::ByRef(new_upvar_borrow), }; let updated_info = determine_capture_info(curr_capture_info, capture_info); @@ -824,7 +890,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { self.fcx.init_capture_kind(self.capture_clause, upvar_id, self.closure_span); let expr_id = Some(diag_expr_id); - let capture_info = ty::CaptureInfo { expr_id, capture_kind }; + let capture_info = ty::CaptureInfo { + capture_kind_expr_id: expr_id, + path_expr_id: expr_id, + capture_kind, + }; debug!("Capturing new place {:?}, capture_info={:?}", place_with_id, capture_info); @@ -890,11 +960,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } -fn construct_capture_info_string( - tcx: TyCtxt<'_>, - place: &Place<'tcx>, - capture_info: &ty::CaptureInfo<'tcx>, -) -> String { +fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let variable_name = match place.base { PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), @@ -914,11 +980,42 @@ fn construct_capture_info_string( projections_str.push_str(proj.as_str()); } + format!("{}[{}]", variable_name, projections_str) +} + +fn construct_capture_kind_reason_string( + tcx: TyCtxt<'_>, + place: &Place<'tcx>, + capture_info: &ty::CaptureInfo<'tcx>, +) -> String { + let place_str = construct_place_string(tcx, &place); + let capture_kind_str = match capture_info.capture_kind { ty::UpvarCapture::ByValue(_) => "ByValue".into(), ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind), }; - format!("{}[{}] -> {}", variable_name, projections_str, capture_kind_str) + + format!("{} captured as {} here", place_str, capture_kind_str) +} + +fn construct_path_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { + let place_str = construct_place_string(tcx, &place); + + format!("{} used here", place_str) +} + +fn construct_capture_info_string( + tcx: TyCtxt<'_>, + place: &Place<'tcx>, + capture_info: &ty::CaptureInfo<'tcx>, +) -> String { + let place_str = construct_place_string(tcx, &place); + + let capture_kind_str = match capture_info.capture_kind { + ty::UpvarCapture::ByValue(_) => "ByValue".into(), + ty::UpvarCapture::ByRef(borrow) => format!("{:?}", borrow.kind), + }; + format!("{} -> {}", place_str, capture_kind_str) } fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { @@ -930,7 +1027,9 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { /// (Note: CaptureInfo contains CaptureKind and an expression that led to capture it in that way) /// /// If both `CaptureKind`s are considered equivalent, then the CaptureInfo is selected based -/// on the `CaptureInfo` containing an associated expression id. +/// on the `CaptureInfo` containing an associated `capture_kind_expr_id`. +/// +/// It is the caller's duty to figure out which path_expr_id to use. /// /// If both the CaptureKind and Expression are considered to be equivalent, /// then `CaptureInfo` A is preferred. This can be useful in cases where we want to priortize @@ -981,7 +1080,7 @@ fn determine_capture_info( }; if eq_capture_kind { - match (capture_info_a.expr_id, capture_info_b.expr_id) { + match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) { (Some(_), _) | (None, None) => capture_info_a, (None, Some(_)) => capture_info_b, } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 9e6bf5ce52d8a..b6d740a4fdb57 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -348,7 +348,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let min_list_wb = min_list .iter() .map(|captured_place| { - let locatable = captured_place.info.expr_id.unwrap_or( + let locatable = captured_place.info.path_expr_id.unwrap_or( self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()), ); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 24364c6954e49..bd2c266d93dca 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { PlaceBase::Local(*var_hir_id) }; let place_with_id = PlaceWithHirId::new( - capture_info.expr_id.unwrap_or(closure_expr.hir_id), + capture_info.path_expr_id.unwrap_or(closure_expr.hir_id), place.base_ty, place_base, place.projections.clone(), diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index dde4a62ffbf3d..ad92d816c9836 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -60,6 +60,7 @@ This API is completely unstable and subject to change. #![feature(bool_to_option)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] +#![feature(format_args_capture)] #![feature(in_band_lifetimes)] #![feature(is_sorted)] #![feature(nll)] diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 139863bbe7f81..a6d3b5ef813f1 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -267,6 +267,7 @@ pub trait AsMut { /// /// [`String`]: ../../std/string/struct.String.html /// [`Vec`]: ../../std/vec/struct.Vec.html +#[rustc_diagnostic_item = "into_trait"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. @@ -382,6 +383,7 @@ pub trait From: Sized { /// /// This suffers the same restrictions and reasoning as implementing /// [`Into`], see there for details. +#[rustc_diagnostic_item = "try_into_trait"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. @@ -462,6 +464,7 @@ pub trait TryInto: Sized { /// /// [`try_from`]: TryFrom::try_from /// [`!`]: ../../std/primitive.never.html +#[rustc_diagnostic_item = "try_from_trait"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 465f3f8f99427..598fb670bb4bf 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -63,7 +63,7 @@ pub fn calc_result<'a>( )) } } - (&ShouldPanic::Yes, Ok(())) => { + (&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => { TestResult::TrFailedMsg("test did not panic as expected".to_string()) } _ if desc.allow_fail => TestResult::TrAllowedFail, diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 74313cc4438ed..a629829b88514 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -228,21 +228,30 @@ fn test_should_panic_non_string_message_type() { #[test] #[cfg(not(target_os = "emscripten"))] fn test_should_panic_but_succeeds() { - fn f() {} - let desc = TestDescAndFn { - desc: TestDesc { - name: StaticTestName("whatever"), - ignore: false, - should_panic: ShouldPanic::Yes, - allow_fail: false, - test_type: TestType::Unknown, - }, - testfn: DynTestFn(Box::new(f)), - }; - let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); - let result = rx.recv().unwrap().result; - assert_eq!(result, TrFailedMsg("test did not panic as expected".to_string())); + let should_panic_variants = [ShouldPanic::Yes, ShouldPanic::YesWithMessage("error message")]; + + for &should_panic in should_panic_variants.iter() { + fn f() {} + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic, + allow_fail: false, + test_type: TestType::Unknown, + }, + testfn: DynTestFn(Box::new(f)), + }; + let (tx, rx) = channel(); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + let result = rx.recv().unwrap().result; + assert_eq!( + result, + TrFailedMsg("test did not panic as expected".to_string()), + "should_panic == {:?}", + should_panic + ); + } } fn report_time_test_template(report_time: bool) -> Option { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 62065e27dd966..2f655e3b396f1 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"); + } } } 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/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/ui/associated-types/hr-associated-type-bound-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-2.rs index 7ff0fede28cfe..78ee28b17d4b3 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.rs +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.rs @@ -17,5 +17,5 @@ where fn main() { 1u32.f("abc"); - //~^ ERROR no method named `f` found for type `u32` in the current scope + //~^ ERROR the method } diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr index 20b6659bbc19b..043d1ac76de9a 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr @@ -1,10 +1,10 @@ -error[E0599]: no method named `f` found for type `u32` in the current scope +error[E0599]: the method `f` exists for type `u32`, but its trait bounds were not satisfied --> $DIR/hr-associated-type-bound-2.rs:19:10 | LL | 1u32.f("abc"); - | ^ method not found in `u32` + | ^ method cannot be called on `u32` due to unsatisfied trait bounds | - = note: the method `f` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `>::U: Clone` which is required by `u32: X` 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..72a21faa4e7ea --- /dev/null +++ b/src/test/ui/backtrace-apple-no-dsymutil.rs @@ -0,0 +1,30 @@ +// run-pass + +// compile-flags:-g -Csplit-debuginfo=off +// 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/2229_closure_analysis/capture-analysis-1.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs new file mode 100644 index 0000000000000..4368c830e1c61 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -0,0 +1,35 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let p = Point { x: 10, y: 10 }; + let q = Point { x: 10, y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ImmBorrow + println!("{:?}", p.x); + //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + + println!("{:?}", q.x); + //~^ NOTE: Capturing q[(0, 0)] -> ImmBorrow + println!("{:?}", q); + //~^ NOTE: Capturing q[] -> ImmBorrow + //~| NOTE: Min Capture q[] -> ImmBorrow + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr new file mode 100644 index 0000000000000..09255343af0e8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -0,0 +1,77 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-1.rs:17:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-1.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-1.rs:20:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", p); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:23:26 + | +LL | println!("{:?}", p); + | ^ +note: Capturing p[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:26:26 + | +LL | println!("{:?}", p.x); + | ^^^ +note: Capturing q[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:29:26 + | +LL | println!("{:?}", q.x); + | ^^^ +note: Capturing q[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:31:26 + | +LL | println!("{:?}", q); + | ^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-1.rs:20:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", p); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:23:26 + | +LL | println!("{:?}", p); + | ^ +note: Min Capture q[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:31:26 + | +LL | println!("{:?}", q); + | ^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs new file mode 100644 index 0000000000000..ab7fce6a43099 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -0,0 +1,30 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Point { + x: String, + y: i32, +} + +fn main() { + let mut p = Point { x: String::new(), y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = p.x; + //~^ NOTE: Capturing p[(0, 0)] -> ByValue + //~| NOTE: p[] captured as ByValue here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ByValue + //~| NOTE: p[] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr new file mode 100644 index 0000000000000..0e48d6b300b72 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -0,0 +1,65 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-2.rs:16:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-2.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-2.rs:19:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> ByValue + --> $DIR/capture-analysis-2.rs:22:18 + | +LL | let _x = p.x; + | ^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/capture-analysis-2.rs:25:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-2.rs:19:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ByValue + --> $DIR/capture-analysis-2.rs:22:18 + | +LL | let _x = p.x; + | ^^^ p[] captured as ByValue here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs new file mode 100644 index 0000000000000..817ade899e2a0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -0,0 +1,35 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Child { + c: String, + d: String, +} + +#[derive(Debug)] +struct Parent { + b: Child, +} + +fn main() { + let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = a.b.c; + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue + //~| NOTE: a[(0, 0)] captured as ByValue here + println!("{:?}", a.b); + //~^ NOTE: Capturing a[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture a[(0, 0)] -> ByValue + //~| NOTE: a[(0, 0)] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr new file mode 100644 index 0000000000000..263e9ca56ebf6 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -0,0 +1,65 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-3.rs:21:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-3.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-3.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b.c; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0),(0, 0)] -> ByValue + --> $DIR/capture-analysis-3.rs:27:18 + | +LL | let _x = a.b.c; + | ^^^^^ +note: Capturing a[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-3.rs:30:26 + | +LL | println!("{:?}", a.b); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-3.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b.c; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-3.rs:27:18 + | +LL | let _x = a.b.c; + | ^^^^^ a[(0, 0)] captured as ByValue here +... +LL | println!("{:?}", a.b); + | ^^^ a[(0, 0)] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs new file mode 100644 index 0000000000000..e8401299b30ad --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -0,0 +1,33 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Child { + c: String, + d: String, +} + +#[derive(Debug)] +struct Parent { + b: Child, +} + +fn main() { + let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = a.b; + //~^ NOTE: Capturing a[(0, 0)] -> ByValue + //~| NOTE: Min Capture a[(0, 0)] -> ByValue + println!("{:?}", a.b.c); + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr new file mode 100644 index 0000000000000..f4605c1d51b76 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -0,0 +1,62 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-4.rs:21:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/capture-analysis-4.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/capture-analysis-4.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-4.rs:27:18 + | +LL | let _x = a.b; + | ^^^ +note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-4.rs:30:26 + | +LL | println!("{:?}", a.b.c); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-4.rs:24:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-4.rs:27:18 + | +LL | let _x = a.b; + | ^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs new file mode 100644 index 0000000000000..f81866bb7e096 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -0,0 +1,52 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] +#![allow(unused)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +#[derive(Debug)] +struct Line { + p: Point, + q: Point +} +#[derive(Debug)] +struct Plane { + a: Line, + b: Line, +} + +fn main() { + let mut p = Plane { + a: Line { + p: Point { x: 1,y: 2 }, + q: Point { x: 3,y: 4 }, + }, + b: Line { + p: Point { x: 1,y: 2 }, + q: Point { x: 3,y: 4 }, + } + }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = &p.a.p.x; + //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + p.b.q.y = 9; + //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow + //~| NOTE: p[] captured as MutBorrow here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr new file mode 100644 index 0000000000000..863f1009131a1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -0,0 +1,70 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/deep-multilevel-struct.rs:36:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deep-multilevel-struct.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/deep-multilevel-struct.rs:39:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &p.a.p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/deep-multilevel-struct.rs:42:18 + | +LL | let x = &p.a.p.x; + | ^^^^^^^ +note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow + --> $DIR/deep-multilevel-struct.rs:44:9 + | +LL | p.b.q.y = 9; + | ^^^^^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/deep-multilevel-struct.rs:47:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/deep-multilevel-struct.rs:39:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &p.a.p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> MutBorrow + --> $DIR/deep-multilevel-struct.rs:44:9 + | +LL | p.b.q.y = 9; + | ^^^^^^^ p[] captured as MutBorrow here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs new file mode 100644 index 0000000000000..fb03a02efa09e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -0,0 +1,27 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| NOTE: `#[warn(incomplete_features)]` on by default +//~| NOTE: see issue #53488 +#![feature(rustc_attrs)] +#![allow(unused)] + +fn main() { + let mut t = (((1,2),(3,4)),((5,6),(7,8))); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = &t.0.0.0; + //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + t.1.1.1 = 9; + //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow + //~| NOTE: t[] captured as MutBorrow here + println!("{:?}", t); + //~^ NOTE: Min Capture t[] -> MutBorrow + //~| NOTE: Capturing t[] -> ImmBorrow + //~| NOTE: t[] used here + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr new file mode 100644 index 0000000000000..252db44473222 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -0,0 +1,70 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/deep-multilevel-tuple.rs:11:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deep-multilevel-tuple.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error: First Pass analysis includes: + --> $DIR/deep-multilevel-tuple.rs:14:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &t.0.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/deep-multilevel-tuple.rs:17:18 + | +LL | let x = &t.0.0.0; + | ^^^^^^^ +note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow + --> $DIR/deep-multilevel-tuple.rs:19:9 + | +LL | t.1.1.1 = 9; + | ^^^^^^^ +note: Capturing t[] -> ImmBorrow + --> $DIR/deep-multilevel-tuple.rs:22:26 + | +LL | println!("{:?}", t); + | ^ + +error: Min Capture analysis includes: + --> $DIR/deep-multilevel-tuple.rs:14:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &t.0.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[] -> MutBorrow + --> $DIR/deep-multilevel-tuple.rs:19:9 + | +LL | t.1.1.1 = 9; + | ^^^^^^^ t[] captured as MutBorrow here +... +LL | println!("{:?}", t); + | ^ t[] used here + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs index aaff3531e5850..a6b5e12d2ed78 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -32,9 +32,11 @@ fn main() { //~| ERROR: Min Capture analysis includes: p.x += 10; //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow - //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] captured as MutBorrow here println!("{:?}", p); //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] used here }; c(); diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index 30d3d5f504eb9..cbbc879219915 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -55,7 +55,10 @@ note: Min Capture p[] -> MutBorrow --> $DIR/simple-struct-min-capture.rs:33:9 | LL | p.x += 10; - | ^^^ + | ^^^ p[] captured as MutBorrow here +... +LL | println!("{:?}", p); + | ^ p[] used here error: aborting due to 3 previous errors; 1 warning emitted 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/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 92ba4f0704fef..ffee7004f8f8e 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `clone` found for struct `Bar` in the current scope +error[E0599]: the method `clone` exists for struct `Bar`, but its trait bounds were not satisfied --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { @@ -11,7 +11,7 @@ LL | struct NotClone; | ---------------- doesn't satisfy `NotClone: Clone` ... LL | Bar:: { x: 1 }.clone(); - | ^^^^^ method not found in `Bar` + | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/clone.rs:LL:COL | @@ -21,7 +21,7 @@ LL | fn clone(&self) -> Self; | the method is available for `Arc>` here | the method is available for `Rc>` here | - = note: the method `clone` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `NotClone: Clone` which is required by `Bar: Clone` = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index 90a7cadca41b7..a769872d83a52 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `filterx` found for struct `Map` in the current scope +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:128:22 | LL | pub struct Map { @@ -8,9 +8,9 @@ LL | pub struct Map { | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method not found in `Map` + | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds | - = note: the method `filterx` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `&'a mut Map: Stream` which is required by `Map: StreamExt` `&'a mut &Map: Stream` @@ -18,7 +18,7 @@ LL | let filter = map.filterx(|x: &_| true); `&'a mut &mut Map: Stream` which is required by `&mut Map: StreamExt` -error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope +error[E0599]: the method `countx` exists for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:141:24 | LL | pub struct Filter { @@ -28,9 +28,9 @@ LL | pub struct Filter { | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); - | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | ^^^^^^ method cannot be called on `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds | - = note: the method `countx` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index 90a7cadca41b7..a769872d83a52 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `filterx` found for struct `Map` in the current scope +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:128:22 | LL | pub struct Map { @@ -8,9 +8,9 @@ LL | pub struct Map { | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method not found in `Map` + | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds | - = note: the method `filterx` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `&'a mut Map: Stream` which is required by `Map: StreamExt` `&'a mut &Map: Stream` @@ -18,7 +18,7 @@ LL | let filter = map.filterx(|x: &_| true); `&'a mut &mut Map: Stream` which is required by `&mut Map: StreamExt` -error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope +error[E0599]: the method `countx` exists for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:141:24 | LL | pub struct Filter { @@ -28,9 +28,9 @@ LL | pub struct Filter { | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); - | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | ^^^^^^ method cannot be called on `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds | - = note: the method `countx` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index 8ce5c090b543e..278c5441ecfb7 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -126,8 +126,8 @@ fn variant1() { // guess. let map = source.mapx(|x: &_| x); let filter = map.filterx(|x: &_| true); - //[migrate]~^ ERROR no method named `filterx` - //[nll]~^^ ERROR no method named `filterx` + //[migrate]~^ ERROR the method + //[nll]~^^ ERROR the method } fn variant2() { @@ -139,8 +139,8 @@ fn variant2() { let map = source.mapx(identity); let filter = map.filterx(|x: &_| true); let count = filter.countx(); - //[migrate]~^ ERROR no method named `countx` - //[nll]~^^ ERROR no method named `countx` + //[migrate]~^ ERROR the method + //[nll]~^^ ERROR the method } fn main() {} diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index 70b975524e0c8..b0524f056ef7f 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -1,12 +1,12 @@ -error[E0599]: no method named `to_string` found for raw pointer `*const u8` in the current scope +error[E0599]: the method `to_string` exists for raw pointer `*const u8`, but its trait bounds were not satisfied --> $DIR/issue-21596.rs:4:22 | LL | println!("{}", z.to_string()); - | ^^^^^^^^^ method not found in `*const u8` + | ^^^^^^^^^ method cannot be called on `*const u8` due to unsatisfied trait bounds | = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior - = note: the method `to_string` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `*const u8: std::fmt::Display` which is required by `*const u8: ToString` diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs index 26195318380d2..40475426cff7a 100644 --- a/src/test/ui/issues/issue-31173.rs +++ b/src/test/ui/issues/issue-31173.rs @@ -11,7 +11,7 @@ pub fn get_tok(it: &mut IntoIter) { //~^ ERROR type mismatch resolving //~| expected type `u8` //~| found reference `&_` - .collect(); //~ ERROR no method named `collect` + .collect(); //~ ERROR the method } fn main() {} diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index d371703e29587..0b7ffc39646a6 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -7,11 +7,11 @@ LL | .cloned() = note: expected type `u8` found reference `&_` -error[E0599]: no method named `collect` found for struct `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>` in the current scope +error[E0599]: the method `collect` exists for struct `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>`, but its trait bounds were not satisfied --> $DIR/issue-31173.rs:14:10 | LL | .collect(); - | ^^^^^^^ method not found in `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>` + | ^^^^^^^ method cannot be called on `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL | @@ -23,7 +23,7 @@ LL | pub struct Cloned { LL | pub struct TakeWhile { | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_` | - = note: the method `collect` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item = &_` which is required by `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>: Iterator` `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>: Iterator` diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/issues/issue-35677.rs index ba2d503d7fcf1..15d139790625e 100644 --- a/src/test/ui/issues/issue-35677.rs +++ b/src/test/ui/issues/issue-35677.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; fn is_subset(this: &HashSet, other: &HashSet) -> bool { this.is_subset(other) - //~^ ERROR no method named + //~^ ERROR the method } fn main() {} diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr index afdc5d68ca39a..ab59e5d1acf6a 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/issues/issue-35677.stderr @@ -1,10 +1,10 @@ -error[E0599]: no method named `is_subset` found for reference `&HashSet` in the current scope +error[E0599]: the method `is_subset` exists for reference `&HashSet`, but its trait bounds were not satisfied --> $DIR/issue-35677.rs:4:10 | LL | this.is_subset(other) - | ^^^^^^^^^ method not found in `&HashSet` + | ^^^^^^^^^ method cannot be called on `&HashSet` due to unsatisfied trait bounds | - = note: the method `is_subset` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `T: Eq` `T: Hash` diff --git a/src/test/ui/issues/issue-43424.stderr b/src/test/ui/issues/issue-43424.stderr index 6274a7928ba04..8f59d7cc3aa77 100644 --- a/src/test/ui/issues/issue-43424.stderr +++ b/src/test/ui/issues/issue-43424.stderr @@ -1,8 +1,8 @@ error: unexpected generic arguments in path - --> $DIR/issue-43424.rs:10:4 + --> $DIR/issue-43424.rs:10:10 | LL | m!(inline); - | ^^^^^^^^^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs index 153ca0843d6a5..160cfc3d46c39 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs @@ -1,4 +1,4 @@ fn main() { let _result = &Some(42).as_deref(); -//~^ ERROR no method named `as_deref` found for enum `Option<{integer}>` +//~^ ERROR the method } diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index a8cd98b610784..21fc3b2bdd1f7 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -1,10 +1,10 @@ -error[E0599]: no method named `as_deref` found for enum `Option<{integer}>` in the current scope +error[E0599]: the method `as_deref` exists for enum `Option<{integer}>`, but its trait bounds were not satisfied --> $DIR/option-as_deref.rs:2:29 | LL | let _result = &Some(42).as_deref(); - | ^^^^^^^^ help: there is an associated function with a similar name: `as_ref` + | ^^^^^^^^ | - = note: the method `as_deref` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `{integer}: Deref` `<{integer} as Deref>::Target = _` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs index 11d5378fe304d..ff5095ce3d723 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs @@ -1,4 +1,4 @@ fn main() { let _result = &mut Some(42).as_deref_mut(); -//~^ ERROR no method named `as_deref_mut` found for enum `Option<{integer}>` +//~^ ERROR the method } diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 08399fcea7c97..c86b024de21a6 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -1,10 +1,10 @@ -error[E0599]: no method named `as_deref_mut` found for enum `Option<{integer}>` in the current scope +error[E0599]: the method `as_deref_mut` exists for enum `Option<{integer}>`, but its trait bounds were not satisfied --> $DIR/option-as_deref_mut.rs:2:33 | LL | let _result = &mut Some(42).as_deref_mut(); - | ^^^^^^^^^^^^ method not found in `Option<{integer}>` + | ^^^^^^^^^^^^ method cannot be called on `Option<{integer}>` due to unsatisfied trait bounds | - = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `{integer}: DerefMut` `<{integer} as Deref>::Target = _` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs index f713dee507f5b..4232f14d2d3d8 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs @@ -1,4 +1,4 @@ fn main() { let _result = &Ok(42).as_deref(); -//~^ ERROR no method named `as_deref` found +//~^ ERROR the method } diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 933e8a0c44bc5..e41c04ee89e0f 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -1,10 +1,10 @@ -error[E0599]: no method named `as_deref` found for enum `std::result::Result<{integer}, _>` in the current scope +error[E0599]: the method `as_deref` exists for enum `std::result::Result<{integer}, _>`, but its trait bounds were not satisfied --> $DIR/result-as_deref.rs:2:27 | LL | let _result = &Ok(42).as_deref(); - | ^^^^^^^^ help: there is an associated function with a similar name: `as_ref` + | ^^^^^^^^ | - = note: the method `as_deref` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `{integer}: Deref` `<{integer} as Deref>::Target = _` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs index 3af7033dd5dd3..3507d1d8e7e3e 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs @@ -1,4 +1,4 @@ fn main() { let _result = &mut Ok(42).as_deref_mut(); -//~^ ERROR no method named `as_deref_mut` found +//~^ ERROR the method } diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 69d85126f1006..372d056fc1908 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -1,10 +1,10 @@ -error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result<{integer}, _>` in the current scope +error[E0599]: the method `as_deref_mut` exists for enum `std::result::Result<{integer}, _>`, but its trait bounds were not satisfied --> $DIR/result-as_deref_mut.rs:2:31 | LL | let _result = &mut Ok(42).as_deref_mut(); - | ^^^^^^^^^^^^ method not found in `std::result::Result<{integer}, _>` + | ^^^^^^^^^^^^ method cannot be called on `std::result::Result<{integer}, _>` due to unsatisfied trait bounds | - = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `{integer}: DerefMut` `<{integer} as Deref>::Target = _` diff --git a/src/test/ui/issues/issue-57362-2.rs b/src/test/ui/issues/issue-57362-2.rs index 870d7f28ba953..a0b0ea1d03893 100644 --- a/src/test/ui/issues/issue-57362-2.rs +++ b/src/test/ui/issues/issue-57362-2.rs @@ -19,7 +19,7 @@ impl<'a> X for fn(&'a ()) { } fn g() { - let x = ::make_g(); //~ ERROR no function or associated item + let x = ::make_g(); //~ ERROR the function } fn main() {} diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 47cc64ec470a5..3b6cffeafe4c2 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,10 +1,10 @@ -error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope +error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'r> fn(&'r ())`, but its trait bounds were not satisfied --> $DIR/issue-57362-2.rs:22:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` + | ^^^^^^ function or associated item cannot be called on `for<'r> fn(&'r ())` due to unsatisfied trait bounds | - = note: the method `make_g` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `for<'r> fn(&'r ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/issues/issue-69725.rs index b8130b41f2167..7c77293945eb7 100644 --- a/src/test/ui/issues/issue-69725.rs +++ b/src/test/ui/issues/issue-69725.rs @@ -5,7 +5,7 @@ use issue_69725::Struct; fn crash() { let _ = Struct::::new().clone(); - //~^ ERROR: no method named `clone` found + //~^ ERROR: the method } fn main() {} diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr index 3f70dbcc2a0f4..48c71d76af097 100644 --- a/src/test/ui/issues/issue-69725.stderr +++ b/src/test/ui/issues/issue-69725.stderr @@ -1,8 +1,8 @@ -error[E0599]: no method named `clone` found for struct `Struct` in the current scope +error[E0599]: the method `clone` exists for struct `Struct`, but its trait bounds were not satisfied --> $DIR/issue-69725.rs:7:32 | LL | let _ = Struct::::new().clone(); - | ^^^^^ method not found in `Struct` + | ^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds | ::: $DIR/auxiliary/issue-69725.rs:2:1 | @@ -17,7 +17,7 @@ LL | fn clone(&self) -> Self; | the method is available for `Arc>` here | the method is available for `Rc>` here | - = note: the method `clone` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `A: Clone` which is required by `Struct: Clone` diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs index 9bfacc7babf2e..86d00ca376026 100644 --- a/src/test/ui/methods/method-call-err-msg.rs +++ b/src/test/ui/methods/method-call-err-msg.rs @@ -16,7 +16,7 @@ fn main() { let y = Foo; y.zero() - .take() //~ ERROR no method named `take` found + .take() //~ ERROR the method .one(0); y.three::(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied } diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 60f9eeeca27fe..ffeacfe15dd06 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -40,7 +40,7 @@ note: associated function defined here LL | fn two(self, _: isize, _: isize) -> Foo { self } | ^^^ ---- -------- -------- -error[E0599]: no method named `take` found for struct `Foo` in the current scope +error[E0599]: the method `take` exists for struct `Foo`, but its trait bounds were not satisfied --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; @@ -50,9 +50,9 @@ LL | pub struct Foo; | doesn't satisfy `Foo: Iterator` ... LL | .take() - | ^^^^ method not found in `Foo` + | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds | - = note: the method `take` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `Foo: Iterator` which is required by `&mut Foo: Iterator` = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9035e3380b0c5..17d2292baaf68 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -5,6 +5,6 @@ use std::iter::once; fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); - //~^ ERROR no method named `count` + //~^ ERROR the method //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 2efd37b4738a5..69ae3d8cbd0e5 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -6,11 +6,11 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected signature of `for<'r> fn(&'r &str) -> _` -error[E0599]: no method named `count` found for struct `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope +error[E0599]: the method `count` exists for struct `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied --> $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | -------------- ^^^^^ method not found in `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` + | -------------- ^^^^^ method cannot be called on `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds | | | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` | doesn't satisfy `_: FnMut<(&&str,)>` @@ -20,7 +20,7 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); LL | pub struct Filter { | ----------------------- doesn't satisfy `_: Iterator` | - = note: the method `count` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `<[closure@$DIR/issue-36053-2.rs:7:39: 7:53] as FnOnce<(&&str,)>>::Output = bool` which is required by `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` `[closure@$DIR/issue-36053-2.rs:7:39: 7:53]: FnMut<(&&str,)>` diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs index 58ceaffc96400..f85c10d78c54d 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs @@ -3,5 +3,5 @@ struct Foo; fn main() { let a: Result<(), Foo> = Ok(()); a.unwrap(); - //~^ ERROR no method named `unwrap` found + //~^ ERROR the method } diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 67f79a8147b9b..92a88cbdb34a3 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -1,13 +1,13 @@ -error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope +error[E0599]: the method `unwrap` exists for enum `std::result::Result<(), Foo>`, but its trait bounds were not satisfied --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | struct Foo; | ----------- doesn't satisfy `Foo: Debug` ... LL | a.unwrap(); - | ^^^^^^ method not found in `std::result::Result<(), Foo>` + | ^^^^^^ method cannot be called on `std::result::Result<(), Foo>` due to unsatisfied trait bounds | - = note: the method `unwrap` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `Foo: Debug` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-57642-higher-ranked-subtype.rs b/src/test/ui/nll/issue-57642-higher-ranked-subtype.rs index 36c54628317e9..b222b90e4af24 100644 --- a/src/test/ui/nll/issue-57642-higher-ranked-subtype.rs +++ b/src/test/ui/nll/issue-57642-higher-ranked-subtype.rs @@ -31,7 +31,7 @@ impl Y for fn(T) { } fn higher_ranked_region_has_lost_its_binder() { - let x = ::make_g(); //~ ERROR no function + let x = ::make_g(); //~ ERROR the function } fn magical() { diff --git a/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr b/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr index f69098193429c..95811ea05b873 100644 --- a/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr +++ b/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr @@ -1,10 +1,10 @@ -error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope +error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'r> fn(&'r ())`, but its trait bounds were not satisfied --> $DIR/issue-57642-higher-ranked-subtype.rs:34:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` + | ^^^^^^ function or associated item cannot be called on `for<'r> fn(&'r ())` due to unsatisfied trait bounds | - = note: the method `make_g` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `for<'r> fn(&'r ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it diff --git a/src/test/ui/span/import-ty-params.rs b/src/test/ui/span/import-ty-params.rs index 850bbd857ffec..313cd227b7c27 100644 --- a/src/test/ui/span/import-ty-params.rs +++ b/src/test/ui/span/import-ty-params.rs @@ -16,5 +16,8 @@ fn f1() { fn f2() { import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path } +fn f3() { + import! { a::b<>::c::S<> } //~ ERROR unexpected generic arguments in path +} fn main() {} diff --git a/src/test/ui/span/import-ty-params.stderr b/src/test/ui/span/import-ty-params.stderr index a02a1edc13499..701cd0c04bd1f 100644 --- a/src/test/ui/span/import-ty-params.stderr +++ b/src/test/ui/span/import-ty-params.stderr @@ -1,14 +1,20 @@ error: unexpected generic arguments in path - --> $DIR/import-ty-params.rs:14:15 + --> $DIR/import-ty-params.rs:14:25 | LL | import! { a::b::c::S } - | ^^^^^^^^^^^^^^ + | ^^^^ error: unexpected generic arguments in path - --> $DIR/import-ty-params.rs:17:15 + --> $DIR/import-ty-params.rs:17:25 | LL | import! { a::b::c::S<> } - | ^^^^^^^^^^^^ + | ^^ -error: aborting due to 2 previous errors +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:20:19 + | +LL | import! { a::b<>::c::S<> } + | ^^ ^^^^ ^^ + +error: aborting due to 3 previous errors diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr index d3fa1d7732e72..067893fd22d34 100644 --- a/src/test/ui/span/visibility-ty-params.stderr +++ b/src/test/ui/span/visibility-ty-params.stderr @@ -1,8 +1,8 @@ error: unexpected generic arguments in path - --> $DIR/visibility-ty-params.rs:6:5 + --> $DIR/visibility-ty-params.rs:6:6 | LL | m!{ S } - | ^^^^^ + | ^^^^ error[E0577]: expected module, found struct `S` --> $DIR/visibility-ty-params.rs:6:5 @@ -11,10 +11,10 @@ LL | m!{ S } | ^^^^^ not a module error: unexpected generic arguments in path - --> $DIR/visibility-ty-params.rs:10:9 + --> $DIR/visibility-ty-params.rs:10:10 | LL | m!{ m<> } - | ^^^ + | ^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs index 35e3b8725a82a..6834d57362991 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs @@ -20,5 +20,5 @@ default impl Foo for T { fn main() { println!("{}", MyStruct.foo_one()); - //~^ ERROR no method named `foo_one` found + //~^ ERROR the method } diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index fb623c97f4209..16ffc661fe0a3 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -8,7 +8,7 @@ LL | #![feature(specialization)] = note: see issue #31844 for more information = help: consider using `min_specialization` instead, which is more stable and complete -error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope +error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | struct MyStruct; @@ -18,9 +18,9 @@ LL | struct MyStruct; | doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); - | ^^^^^^^ method not found in `MyStruct` + | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds | - = note: the method `foo_one` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope note: `Foo` defines an item `foo_one`, perhaps you need to implement it diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs index fefdf149f556c..afd47f71c2cbf 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs @@ -12,7 +12,7 @@ impl Bar for Foo {} impl Foo { fn bar(&self) { self.foo(); - //~^ ERROR no method named `foo` found for reference `&Foo` in the current scope + //~^ ERROR the method } } @@ -25,7 +25,7 @@ impl Bar for Fin {} impl Fin { fn bar(&self) { self.foo(); - //~^ ERROR no method named `foo` found for reference `&Fin` in the current scope + //~^ ERROR the method } } fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index eb695379b580d..c7376b0007f97 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -1,13 +1,13 @@ -error[E0599]: no method named `foo` found for reference `&Foo` in the current scope +error[E0599]: the method `foo` exists for reference `&Foo`, but its trait bounds were not satisfied --> $DIR/missing-trait-bounds-for-method-call.rs:14:14 | LL | struct Foo { | ------------- doesn't satisfy `Foo: Bar` ... LL | self.foo(); - | ^^^ method not found in `&Foo` + | ^^^ method cannot be called on `&Foo` due to unsatisfied trait bounds | - = note: the method `foo` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `T: Bar` which is required by `Foo: Bar` `T: Default` @@ -17,16 +17,16 @@ help: consider restricting the type parameters to satisfy the trait bounds LL | struct Foo where T: Bar, T: Default { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0599]: no method named `foo` found for reference `&Fin` in the current scope +error[E0599]: the method `foo` exists for reference `&Fin`, but its trait bounds were not satisfied --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 | LL | struct Fin where T: Bar { | -------------------------- doesn't satisfy `Fin: Bar` ... LL | self.foo(); - | ^^^ method not found in `&Fin` + | ^^^ method cannot be called on `&Fin` due to unsatisfied trait bounds | - = note: the method `foo` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `T: Default` which is required by `Fin: Bar` help: consider restricting the type parameter to satisfy the trait bound diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs index f8b86377187c5..924bfd82eb832 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -19,5 +19,5 @@ fn main() { //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for struct + writeln!(fp, "hello world").unwrap(); //~ ERROR the method } diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 8a9a1e5793588..3120b739c0295 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -33,18 +33,18 @@ LL | pub struct BufWriter { | = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` -error[E0599]: no method named `write_fmt` found for struct `BufWriter<&dyn std::io::Write>` in the current scope +error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied --> $DIR/mut-borrow-needed-by-trait.rs:22:5 | LL | writeln!(fp, "hello world").unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `BufWriter<&dyn std::io::Write>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds | ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL | LL | pub struct BufWriter { | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write` | - = note: the method `write_fmt` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `&dyn std::io::Write: std::io::Write` which is required by `BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) 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/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs index 753a9f74d03e4..7ab19edb47179 100644 --- a/src/test/ui/union/union-derive-clone.rs +++ b/src/test/ui/union/union-derive-clone.rs @@ -32,5 +32,5 @@ struct CloneNoCopy; fn main() { let u = U5 { a: ManuallyDrop::new(CloneNoCopy) }; - let w = u.clone(); //~ ERROR no method named `clone` found for union `U5` + let w = u.clone(); //~ ERROR the method } diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index e18f457a8b6f5..a793bf58d23e2 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,7 +11,7 @@ LL | pub struct AssertParamIsCopy { | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0599]: no method named `clone` found for union `U5` in the current scope +error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied --> $DIR/union-derive-clone.rs:35:15 | LL | union U5 { @@ -24,7 +24,7 @@ LL | struct CloneNoCopy; | ------------------- doesn't satisfy `CloneNoCopy: Copy` ... LL | let w = u.clone(); - | ^^^^^ method not found in `U5` + | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/clone.rs:LL:COL | @@ -34,7 +34,7 @@ LL | fn clone(&self) -> Self; | the method is available for `Arc>` here | the method is available for `Rc>` here | - = note: the method `clone` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index dd38a7190aa0e..d243b8f34dbcf 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -21,5 +21,5 @@ impl Foo for Bar { fn main() { let x = box Bar { x: 10 }; let y: Box = x as Box; - let _z = y.clone(); //~ ERROR no method named `clone` found + let _z = y.clone(); //~ ERROR the method } diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 09cbb8753387a..4bbacfc0a8b60 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `clone` found for struct `Box` in the current scope +error[E0599]: the method `clone` exists for struct `Box`, but its trait bounds were not satisfied --> $DIR/unique-object-noncopyable.rs:24:16 | LL | trait Foo { @@ -8,7 +8,7 @@ LL | trait Foo { | doesn't satisfy `dyn Foo: Sized` ... LL | let _z = y.clone(); - | ^^^^^ method not found in `Box` + | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/clone.rs:LL:COL | @@ -26,7 +26,7 @@ LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator LL | | >(Unique, A); | |________________- doesn't satisfy `Box: Clone` | - = note: the method `clone` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `dyn Foo: Sized` which is required by `Box: Clone` `dyn Foo: Clone` diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs index 4c30450c70455..8edaeef51e061 100644 --- a/src/test/ui/unique-pinned-nocopy.rs +++ b/src/test/ui/unique-pinned-nocopy.rs @@ -9,6 +9,6 @@ impl Drop for R { fn main() { let i = Box::new(R { b: true }); - let _j = i.clone(); //~ ERROR no method named `clone` found + let _j = i.clone(); //~ ERROR the method println!("{:?}", i); } diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index bc081024182af..dd0b7fc5489ce 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,11 +1,11 @@ -error[E0599]: no method named `clone` found for struct `Box` in the current scope +error[E0599]: the method `clone` exists for struct `Box`, but its trait bounds were not satisfied --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { | -------- doesn't satisfy `R: Clone` ... LL | let _j = i.clone(); - | ^^^^^ method not found in `Box` + | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/clone.rs:LL:COL | @@ -23,7 +23,7 @@ LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator LL | | >(Unique, A); | |________________- doesn't satisfy `Box: Clone` | - = note: the method `clone` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `R: Clone` which is required by `Box: Clone` = help: items from traits can only be used if the trait is implemented and in scope 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/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 9f389c8d2f9e7..527905e375d28 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -1,7 +1,4 @@ -use crate::utils::paths::FROM_TRAIT; -use crate::utils::{ - is_expn_of, is_type_diagnostic_item, match_def_path, match_panic_def_id, method_chain_args, span_lint_and_then, -}; +use crate::utils::{is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, span_lint_and_then}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -59,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); - if match_def_path(cx, impl_trait_ref.def_id, &FROM_TRAIT); + if cx.tcx.is_diagnostic_item(sym::from_trait, impl_trait_ref.def_id); then { lint_impl_body(cx, item.span, impl_.items); } 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 3b5a83d2a0bec..624ea16f585d2 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 9b262517a9834..023fb0a7112c1 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -370,19 +370,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/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index c0b203b5388dc..432cc5b59f684 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -48,7 +48,6 @@ pub const FN_MUT: [&str; 3] = ["core", "ops", "FnMut"]; pub const FN_ONCE: [&str; 3] = ["core", "ops", "FnOnce"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"]; -pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; pub const HASH: [&str; 3] = ["core", "hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; 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) {