diff options
558 files changed, 5758 insertions, 4274 deletions
diff --git a/Cargo.lock b/Cargo.lock index d4b3e063140..86936b25d8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3869,6 +3869,7 @@ name = "rustc_hir" version = "0.0.0" dependencies = [ "odht", + "rustc_arena", "rustc_ast", "rustc_data_structures", "rustc_error_messages", @@ -4009,6 +4010,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_macros", "rustc_middle", "rustc_parse_format", "rustc_session", diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 62995dfd2e2..a5f1cbc96da 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -19,6 +19,7 @@ #![feature(rustc_attrs)] #![cfg_attr(test, feature(test))] #![feature(strict_provenance)] +#![feature(ptr_const_cast)] use smallvec::SmallVec; @@ -27,7 +28,7 @@ use std::cell::{Cell, RefCell}; use std::cmp; use std::marker::{PhantomData, Send}; use std::mem::{self, MaybeUninit}; -use std::ptr; +use std::ptr::{self, NonNull}; use std::slice; #[inline(never)] @@ -55,15 +56,24 @@ pub struct TypedArena<T> { struct ArenaChunk<T = u8> { /// The raw storage for the arena chunk. - storage: Box<[MaybeUninit<T>]>, + storage: NonNull<[MaybeUninit<T>]>, /// The number of valid entries in the chunk. entries: usize, } +unsafe impl<#[may_dangle] T> Drop for ArenaChunk<T> { + fn drop(&mut self) { + unsafe { Box::from_raw(self.storage.as_mut()) }; + } +} + impl<T> ArenaChunk<T> { #[inline] unsafe fn new(capacity: usize) -> ArenaChunk<T> { - ArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 } + ArenaChunk { + storage: NonNull::new(Box::into_raw(Box::new_uninit_slice(capacity))).unwrap(), + entries: 0, + } } /// Destroys this arena chunk. @@ -72,14 +82,15 @@ impl<T> ArenaChunk<T> { // The branch on needs_drop() is an -O1 performance optimization. // Without the branch, dropping TypedArena<u8> takes linear time. if mem::needs_drop::<T>() { - ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut self.storage[..len])); + let slice = &mut *(self.storage.as_mut()); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len])); } } // Returns a pointer to the first allocated object. #[inline] fn start(&mut self) -> *mut T { - MaybeUninit::slice_as_mut_ptr(&mut self.storage) + self.storage.as_ptr() as *mut T } // Returns a pointer to the end of the allocated space. @@ -90,7 +101,7 @@ impl<T> ArenaChunk<T> { // A pointer as large as possible for zero-sized elements. ptr::invalid_mut(!0) } else { - self.start().add(self.storage.len()) + self.start().add((*self.storage.as_ptr()).len()) } } } @@ -274,7 +285,7 @@ impl<T> TypedArena<T> { // If the previous chunk's len is less than HUGE_PAGE // bytes, then this chunk will be least double the previous // chunk's size. - new_cap = last_chunk.storage.len().min(HUGE_PAGE / elem_size / 2); + new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / elem_size / 2); new_cap *= 2; } else { new_cap = PAGE / elem_size; @@ -382,7 +393,7 @@ impl DroplessArena { // If the previous chunk's len is less than HUGE_PAGE // bytes, then this chunk will be least double the previous // chunk's size. - new_cap = last_chunk.storage.len().min(HUGE_PAGE / 2); + new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / 2); new_cap *= 2; } else { new_cap = PAGE; diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs index 911e577c1ed..ad61464343a 100644 --- a/compiler/rustc_arena/src/tests.rs +++ b/compiler/rustc_arena/src/tests.rs @@ -79,7 +79,11 @@ fn test_arena_alloc_nested() { #[test] pub fn test_copy() { let arena = TypedArena::default(); - for _ in 0..100000 { + #[cfg(not(miri))] + const N: usize = 100000; + #[cfg(miri)] + const N: usize = 1000; + for _ in 0..N { arena.alloc(Point { x: 1, y: 2, z: 3 }); } } @@ -106,7 +110,11 @@ struct Noncopy { #[test] pub fn test_noncopy() { let arena = TypedArena::default(); - for _ in 0..100000 { + #[cfg(not(miri))] + const N: usize = 100000; + #[cfg(miri)] + const N: usize = 1000; + for _ in 0..N { arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }); } } @@ -114,7 +122,11 @@ pub fn test_noncopy() { #[test] pub fn test_typed_arena_zero_sized() { let arena = TypedArena::default(); - for _ in 0..100000 { + #[cfg(not(miri))] + const N: usize = 100000; + #[cfg(miri)] + const N: usize = 1000; + for _ in 0..N { arena.alloc(()); } } @@ -124,7 +136,11 @@ pub fn test_typed_arena_clear() { let mut arena = TypedArena::default(); for _ in 0..10 { arena.clear(); - for _ in 0..10000 { + #[cfg(not(miri))] + const N: usize = 10000; + #[cfg(miri)] + const N: usize = 100; + for _ in 0..N { arena.alloc(Point { x: 1, y: 2, z: 3 }); } } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e5b61d7000a..2820d5e6e0c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2667,13 +2667,16 @@ impl Item { #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub enum Extern { None, - Implicit, - Explicit(StrLit), + Implicit(Span), + Explicit(StrLit, Span), } impl Extern { - pub fn from_abi(abi: Option<StrLit>) -> Extern { - abi.map_or(Extern::Implicit, Extern::Explicit) + pub fn from_abi(abi: Option<StrLit>, span: Span) -> Extern { + match abi { + Some(name) => Extern::Explicit(name, span), + None => Extern::Implicit(span), + } } } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index aab9b90e4b7..0e395d70335 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -24,10 +24,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> &'hir hir::InlineAsm<'hir> { // Rustdoc needs to support asm! from foreign architectures: don't try // lowering the register constraints in this case. - let asm_arch = if self.sess.opts.actually_rustdoc { None } else { self.sess.asm_arch }; - if asm_arch.is_none() && !self.sess.opts.actually_rustdoc { - struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target") - .emit(); + let asm_arch = + if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch }; + if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc { + struct_span_err!( + self.tcx.sess, + sp, + E0472, + "inline assembly is unsupported on this target" + ) + .emit(); } if let Some(asm_arch) = asm_arch { // Inline assembly is currently only stable for these architectures. @@ -40,9 +46,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | asm::InlineAsmArch::RiscV32 | asm::InlineAsmArch::RiscV64 ); - if !is_stable && !self.sess.features_untracked().asm_experimental_arch { + if !is_stable && !self.tcx.features().asm_experimental_arch { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::asm_experimental_arch, sp, "inline assembly is not stable yet on this architecture", @@ -52,17 +58,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) - && !self.sess.opts.actually_rustdoc + && !self.tcx.sess.opts.actually_rustdoc { - self.sess + self.tcx + .sess .struct_span_err(sp, "the `att_syntax` option is only supported on x86") .emit(); } - if asm.options.contains(InlineAsmOptions::MAY_UNWIND) - && !self.sess.features_untracked().asm_unwind - { + if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable", @@ -73,12 +78,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut clobber_abis = FxHashMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { Some((prev_name, prev_sp)) => { - let mut err = self.sess.struct_span_err( + let mut err = self.tcx.sess.struct_span_err( *abi_span, &format!("`{}` ABI specified multiple times", prev_name), ); @@ -86,7 +91,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Multiple different abi names may actually be the same ABI // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI - let source_map = self.sess.source_map(); + let source_map = self.tcx.sess.source_map(); if source_map.span_to_snippet(*prev_sp) != source_map.span_to_snippet(*abi_span) { @@ -101,7 +106,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } Err(&[]) => { - self.sess + self.tcx + .sess .struct_span_err( *abi_span, "`clobber_abi` is not supported on this target", @@ -109,8 +115,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .emit(); } Err(supported_abis) => { - let mut err = - self.sess.struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); + let mut err = self + .tcx + .sess + .struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); let mut abis = format!("`{}`", supported_abis[0]); for m in &supported_abis[1..] { let _ = write!(abis, ", `{}`", m); @@ -128,7 +136,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Lower operands to HIR. We use dummy register classes if an error // occurs during lowering because we still need to be able to produce a // valid HIR. - let sess = self.sess; + let sess = self.tcx.sess; let mut operands: Vec<_> = asm .operands .iter() @@ -184,9 +192,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } InlineAsmOperand::Const { ref anon_const } => { - if !self.sess.features_untracked().asm_const { + if !self.tcx.features().asm_const { feature_err( - &self.sess.parse_sess, + &sess.parse_sess, sym::asm_const, *op_sp, "const operands for inline assembly are unstable", @@ -198,9 +206,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } InlineAsmOperand::Sym { ref sym } => { - if !self.sess.features_untracked().asm_sym { + if !self.tcx.features().asm_sym { feature_err( - &self.sess.parse_sess, + &sess.parse_sess, sym::asm_sym, *op_sp, "sym operands for inline assembly are unstable", diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 3a7e0a70585..9444fffc331 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -159,9 +159,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)), }); - if !self.sess.features_untracked().let_else { + if !self.tcx.features().let_else { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::let_else, local.span, "`let...else` statements are unstable", diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3babe73030a..9e02e7ed3b9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -46,7 +46,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(e.id); return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; } else { - self.sess + self.tcx.sess .struct_span_err( e.span, "#[rustc_box] requires precisely one argument \ @@ -207,8 +207,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims) } ExprKind::Underscore => { - self.sess - .struct_span_err( + self.tcx + .sess.struct_span_err( e.span, "in expressions, `_` can only be used on the left-hand side of an assignment", ) @@ -245,7 +245,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Rest(sp) => { - self.sess + self.tcx + .sess .struct_span_err(*sp, "base expression required after `..`") .span_label(*sp, "add a base expression here") .emit(); @@ -474,7 +475,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } else { let try_span = this.mark_span_with_reason( DesugaringKind::TryBlock, - this.sess.source_map().end_point(body.span), + this.tcx.sess.source_map().end_point(body.span), this.allow_try_trait.clone(), ); @@ -653,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { let mut err = struct_span_err!( - self.sess, + self.tcx.sess, dot_await_span, E0728, "`await` is only allowed inside `async` functions and blocks" @@ -878,7 +879,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Gen) => { if decl.inputs.len() > 1 { struct_span_err!( - self.sess, + self.tcx.sess, fn_decl_span, E0628, "too many parameters for a generator (expected 0 or 1 parameters)" @@ -892,8 +893,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } None => { if movability == Movability::Static { - struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static") - .emit(); + struct_span_err!( + self.tcx.sess, + fn_decl_span, + E0697, + "closures cannot be static" + ) + .emit(); } None } @@ -916,7 +922,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { struct_span_err!( - this.sess, + this.tcx.sess, fn_decl_span, E0708, "`async` non-`move` closures with parameters are not currently supported", @@ -1163,7 +1169,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let fields_omitted = match &se.rest { StructRest::Base(e) => { - self.sess + self.tcx + .sess .struct_span_err( e.span, "functional record updates are not allowed in destructuring \ @@ -1371,7 +1378,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Gen) => {} Some(hir::GeneratorKind::Async(_)) => { struct_span_err!( - self.sess, + self.tcx.sess, span, E0727, "`async` generators are not yet supported" @@ -1516,7 +1523,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, self.allow_try_trait.clone(), ); - let try_span = self.sess.source_map().end_point(span); + let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 0ef21371694..7da49143b46 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,7 +1,6 @@ use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; -use super::{LoweringContext, ParamMode}; -use crate::{Arena, FnDeclKind}; +use super::{FnDeclKind, LoweringContext, ParamMode}; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; @@ -12,12 +11,9 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; -use rustc_hir::definitions::Definitions; use rustc_hir::PredicateOrigin; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::ty::{ResolverAstLowering, ResolverOutputs}; -use rustc_session::cstore::CrateStoreDyn; -use rustc_session::Session; +use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -27,12 +23,8 @@ use smallvec::{smallvec, SmallVec}; use std::iter; pub(super) struct ItemLowerer<'a, 'hir> { - pub(super) sess: &'a Session, - pub(super) definitions: &'a mut Definitions, - pub(super) cstore: &'a CrateStoreDyn, - pub(super) resolutions: &'a ResolverOutputs, + pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, - pub(super) arena: &'hir Arena<'hir>, pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>, pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>, } @@ -65,12 +57,9 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { ) { let mut lctx = LoweringContext { // Pseudo-globals. - sess: &self.sess, - definitions: self.definitions, - cstore: self.cstore, - resolutions: self.resolutions, + tcx: self.tcx, resolver: self.resolver, - arena: self.arena, + arena: self.tcx.hir_arena, // HirId handling. bodies: Vec::new(), @@ -144,12 +133,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = { - let parent = self.definitions.def_key(def_id).parent; - let local_def_index = parent.unwrap(); - LocalDefId { local_def_index } - }; - + let parent_id = self.tcx.local_parent(def_id); let parent_hir = self.lower_node(parent_id).unwrap(); self.with_lctx(item.id, |lctx| { // Evaluate with the lifetimes in `params` in-scope. @@ -1272,13 +1256,13 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi { match ext { Extern::None => abi::Abi::Rust, - Extern::Implicit => abi::Abi::FALLBACK, - Extern::Explicit(abi) => self.lower_abi(abi), + Extern::Implicit(_) => abi::Abi::FALLBACK, + Extern::Explicit(abi, _) => self.lower_abi(abi), } } fn error_on_invalid_abi(&self, abi: StrLit) { - struct_span_err!(self.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol) + struct_span_err!(self.tcx.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol) .span_label(abi.span, "invalid ABI") .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) .emit(); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e8b92eaad5c..2dcbd0782ef 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -49,18 +49,15 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, Handler}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; -use rustc_hir::definitions::{DefPathData, Definitions}; +use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::ty::{ResolverAstLowering, ResolverOutputs}; -use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::CrateStoreDyn; +use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::feature_err; -use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -83,19 +80,12 @@ mod item; mod pat; mod path; -rustc_hir::arena_types!(rustc_arena::declare_arena); - -struct LoweringContext<'a, 'hir: 'a> { - /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. - sess: &'a Session, - - definitions: &'a mut Definitions, - cstore: &'a CrateStoreDyn, - resolutions: &'a ResolverOutputs, +struct LoweringContext<'a, 'hir> { + tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering, /// Used to allocate HIR nodes. - arena: &'hir Arena<'hir>, + arena: &'hir hir::Arena<'hir>, /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, @@ -391,61 +381,58 @@ fn index_crate<'a>( /// Compute the hash for the HIR of the full crate. /// This hash will then be part of the crate_hash which is stored in the metadata. fn compute_hir_hash( - sess: &Session, - definitions: &Definitions, - cstore: &CrateStoreDyn, - resolver: &ResolverOutputs, + tcx: TyCtxt<'_>, owners: &IndexVec<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>, ) -> Fingerprint { let mut hir_body_nodes: Vec<_> = owners .iter_enumerated() .filter_map(|(def_id, info)| { let info = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); + let def_path_hash = tcx.hir().def_path_hash(def_id); Some((def_path_hash, info)) }) .collect(); hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - let mut stable_hasher = StableHasher::new(); - let mut hcx = StableHashingContext::new(sess, definitions, cstore, &resolver.source_span); - hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() + tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }) } -pub fn lower_crate<'hir>( - sess: &Session, - krate: &Crate, - definitions: &mut Definitions, - cstore: &CrateStoreDyn, - resolutions: &ResolverOutputs, - mut resolver: ResolverAstLowering, - arena: &'hir Arena<'hir>, -) -> &'hir hir::Crate<'hir> { - let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); +pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { + let sess = tcx.sess; + let krate = tcx.untracked_crate.steal(); + let mut resolver = tcx.resolver_for_lowering(()).steal(); - let ast_index = index_crate(&resolver.node_id_to_def_id, krate); - - let mut owners = - IndexVec::from_fn_n(|_| hir::MaybeOwner::Phantom, definitions.def_index_count()); + let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); + let mut owners = IndexVec::from_fn_n( + |_| hir::MaybeOwner::Phantom, + tcx.definitions_untracked().def_index_count(), + ); for def_id in ast_index.indices() { item::ItemLowerer { - sess, - definitions, - cstore, - resolutions, + tcx, resolver: &mut resolver, - arena, ast_index: &ast_index, owners: &mut owners, } .lower_node(def_id); } - let hir_hash = compute_hir_hash(sess, definitions, cstore, resolutions, &owners); - let krate = hir::Crate { owners, hir_hash }; - arena.alloc(krate) + // Drop AST to free memory + std::mem::drop(ast_index); + sess.time("drop_ast", || std::mem::drop(krate)); + + // Discard hygiene data, which isn't required after lowering to HIR. + if !sess.opts.debugging_opts.keep_hygiene_data { + rustc_span::hygiene::clear_syntax_context_map(); + } + + let hir_hash = compute_hir_hash(tcx, &owners); + hir::Crate { owners, hir_hash } } #[derive(Copy, Clone, PartialEq, Debug)] @@ -464,38 +451,25 @@ enum ParenthesizedGenericArgs { } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - StableHashingContext::new( - self.sess, - self.definitions, - self.cstore, - &self.resolutions.source_span, - ) - } - fn create_def( &mut self, parent: LocalDefId, node_id: ast::NodeId, data: DefPathData, ) -> LocalDefId { + debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( self.opt_local_def_id(node_id).is_none(), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.definitions.def_key(self.local_def_id(node_id)), + self.tcx.hir().def_key(self.local_def_id(node_id)), ); - let def_id = self.definitions.create_def(parent, data); + let def_id = self.tcx.create_def(parent, data); - // Some things for which we allocate `LocalDefId`s don't correspond to - // anything in the AST, so they don't have a `NodeId`. For these cases - // we don't need a mapping from `NodeId` to `LocalDefId`. - if node_id != ast::DUMMY_NODE_ID { - debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); - self.resolver.node_id_to_def_id.insert(node_id, def_id); - } + debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); + self.resolver.node_id_to_def_id.insert(node_id, def_id); def_id } @@ -515,6 +489,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) } + /// Freshen the `LoweringContext` and ready it to lower a nested item. + /// The lowered item is registered into `self.children`. + /// + /// This function sets up `HirId` lowering infrastructure, + /// and stashes the shared mutable state to avoid pollution by the closure. #[instrument(level = "debug", skip(self, f))] fn with_hir_id_owner( &mut self, @@ -533,8 +512,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); let current_impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds); - // Do not reset `next_node_id` and `node_id_to_def_id` as we want to refer to the - // subdefinitions' nodes. + + // Do not reset `next_node_id` and `node_id_to_def_id`: + // we want `f` to be able to refer to the `LocalDefId`s that the caller created. + // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s. // Always allocate the first `HirId` for the owner itself. let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::new(0)); @@ -578,7 +559,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bodies.sort_by_key(|(k, _)| *k); let bodies = SortedMap::from_presorted_elements(bodies); let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies); - let (nodes, parenting) = index::index_hir(self.sess, self.definitions, node, &bodies); + let (nodes, parenting) = + index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies); let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, @@ -587,10 +569,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { local_id_to_def_id, }; let attrs = { - let mut hcx = self.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - attrs.hash_stable(&mut hcx, &mut stable_hasher); - let hash = stable_hasher.finish(); + let hash = self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + attrs.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); hir::AttributeMap { map: attrs, hash } }; @@ -604,18 +587,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node: hir::OwnerNode<'hir>, bodies: &SortedMap<hir::ItemLocalId, &'hir hir::Body<'hir>>, ) -> (Fingerprint, Fingerprint) { - let mut hcx = self.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); - let hash_including_bodies = stable_hasher.finish(); - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); - let hash_without_bodies = stable_hasher.finish(); - (hash_including_bodies, hash_without_bodies) + self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let hash_including_bodies = stable_hasher.finish(); + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let hash_without_bodies = stable_hasher.finish(); + (hash_including_bodies, hash_without_bodies) + }) } /// This method allocates a new `HirId` for the given `NodeId` and stores it in @@ -656,9 +640,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + /// Generate a new `HirId` without a backing `NodeId`. fn next_id(&mut self) -> hir::HirId { - let node_id = self.next_node_id(); - self.lower_node_id(node_id) + let owner = self.current_hir_id_owner; + let local_id = self.item_local_id_counter; + assert_ne!(local_id, hir::ItemLocalId::new(0)); + self.item_local_id_counter.increment_by(1); + hir::HirId { owner, local_id } } #[instrument(level = "trace", skip(self))] @@ -691,8 +679,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_import_res(id).present_items() } - fn diagnostic(&self) -> &rustc_errors::Handler { - self.sess.diagnostic() + fn diagnostic(&self) -> &Handler { + self.tcx.sess.diagnostic() } /// Reuses the span but adds information like the kind of the desugaring and features that are @@ -703,18 +691,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, allow_internal_unstable: Option<Lrc<[Symbol]>>, ) -> Span { - span.mark_with_reason( - allow_internal_unstable, - reason, - self.sess.edition(), - self.create_stable_hashing_context(), - ) + self.tcx.with_stable_hashing_context(|hcx| { + span.mark_with_reason(allow_internal_unstable, reason, self.tcx.sess.edition(), hcx) + }) } /// Intercept all spans entering HIR. /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { - if self.sess.opts.debugging_opts.incremental_relative_spans { + if self.tcx.sess.opts.debugging_opts.incremental_relative_spans { span.with_parent(Some(self.current_hir_id_owner)) } else { // Do not make spans relative when not using incremental compilation. @@ -1061,7 +1046,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) { - let mut err = self.sess.struct_span_err( + let mut err = self.tcx.sess.struct_span_err( data.span, "parenthesized generic arguments cannot be used in associated type constraints", ); @@ -1106,7 +1091,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { match ty.kind { - TyKind::Infer if self.sess.features_untracked().generic_arg_infer => { + TyKind::Infer if self.tcx.features().generic_arg_infer => { return GenericArg::Infer(hir::InferArg { hir_id: self.lower_node_id(ty.id), span: self.lower_span(ty.span), @@ -1203,7 +1188,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.next_node_id() }; - let span = self.sess.source_map().next_point(t.span.shrink_to_lo()); + let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo()); Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); let lifetime = self.lower_lifetime(®ion); @@ -1307,7 +1292,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::Disallowed(position) => { let mut err = struct_span_err!( - self.sess, + self.tcx.sess, t.span, E0562, "`impl Trait` only allowed in function and inherent method return types, not in {}", @@ -1320,7 +1305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::CVarArgs => { - self.sess.delay_span_bug( + self.tcx.sess.delay_span_bug( t.span, "`TyKind::CVarArgs` should have been handled elsewhere", ); @@ -1925,7 +1910,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir_id, name, span: self.lower_span(param.span()), - pure_wrt_drop: self.sess.contains_name(¶m.attrs, sym::may_dangle), + pure_wrt_drop: self.tcx.sess.contains_name(¶m.attrs, sym::may_dangle), kind, colon_span: param.colon_span.map(|s| self.lower_span(s)), } @@ -2067,11 +2052,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { match c.value.kind { ExprKind::Underscore => { - if self.sess.features_untracked().generic_arg_infer { + if self.tcx.features().generic_arg_infer { hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span) } else { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::generic_arg_infer, c.value.span, "using `_` for array lengths is unstable", diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 52ba5daf014..393be3b454c 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -133,7 +133,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We should've returned in the for loop above. - self.sess.diagnostic().span_bug( + self.diagnostic().span_bug( p.span, &format!( "lower_qpath: no final extension segment in {}..{}", @@ -193,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Err => { - let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg); + let mut err = struct_span_err!(self.tcx.sess, data.span, E0214, "{}", msg); err.span_label(data.span, "only `Fn` traits may use parentheses"); // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` if !data.inputs.is_empty() { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 503bdbad258..3942062656f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -13,7 +13,9 @@ use rustc_ast::walk_list; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{error_code, pluralize, struct_span_err, Applicability}; +use rustc_errors::{ + error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, +}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -476,6 +478,17 @@ impl<'a> AstValidator<'a> { } fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) { + self.error_item_without_body_with_help(sp, ctx, msg, sugg, |_| ()); + } + + fn error_item_without_body_with_help( + &self, + sp: Span, + ctx: &str, + msg: &str, + sugg: &str, + help: impl FnOnce(&mut DiagnosticBuilder<'_, ErrorGuaranteed>), + ) { let source_map = self.session.source_map(); let end = source_map.end_point(sp); let replace_span = if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) { @@ -483,15 +496,15 @@ impl<'a> AstValidator<'a> { } else { sp.shrink_to_hi() }; - self.err_handler() - .struct_span_err(sp, msg) - .span_suggestion( - replace_span, - &format!("provide a definition for the {}", ctx), - sugg, - Applicability::HasPlaceholders, - ) - .emit(); + let mut err = self.err_handler().struct_span_err(sp, msg); + err.span_suggestion( + replace_span, + &format!("provide a definition for the {}", ctx), + sugg, + Applicability::HasPlaceholders, + ); + help(&mut err); + err.emit(); } fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) { @@ -630,7 +643,8 @@ impl<'a> AstValidator<'a> { match (fk.ctxt(), fk.header()) { (Some(FnCtxt::Foreign), _) => return, (Some(FnCtxt::Free), Some(header)) => match header.ext { - Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit + Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _) + | Extern::Implicit(_) if matches!(header.unsafety, Unsafe::Yes(_)) => { return; @@ -842,7 +856,7 @@ impl<'a> AstValidator<'a> { .emit(); }); self.check_late_bound_lifetime_defs(&bfty.generic_params); - if let Extern::Implicit = bfty.ext { + if let Extern::Implicit(_) = bfty.ext { let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo()); self.maybe_lint_missing_abi(sig_span, ty.id); } @@ -1190,8 +1204,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if body.is_none() { let msg = "free function without a body"; - self.error_item_without_body(item.span, "function", msg, " { <body> }"); + let ext = sig.header.ext; + + let f = |e: &mut DiagnosticBuilder<'_, _>| { + if let Extern::Implicit(start_span) | Extern::Explicit(_, start_span) = &ext + { + let start_suggestion = if let Extern::Explicit(abi, _) = ext { + format!("extern \"{}\" {{", abi.symbol_unescaped) + } else { + "extern {".to_owned() + }; + + let end_suggestion = " }".to_owned(); + let end_span = item.span.shrink_to_hi(); + + e + .multipart_suggestion( + "if you meant to declare an externally defined function, use an `extern` block", + vec![(*start_span, start_suggestion), (end_span, end_suggestion)], + Applicability::MaybeIncorrect, + ); + } + }; + + self.error_item_without_body_with_help( + item.span, + "function", + msg, + " { <body> }", + f, + ); } + self.visit_vis(&item.vis); self.visit_ident(item.ident); let kind = @@ -1556,7 +1600,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let FnKind::Fn( _, _, - FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. }, + FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit(_), .. }, .. }, _, _, _, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 37c4f665415..fd2dd6cf6c7 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -283,7 +283,7 @@ impl<'a> PostExpansionVisitor<'a> { } fn check_extern(&self, ext: ast::Extern, constness: ast::Const) { - if let ast::Extern::Explicit(abi) = ext { + if let ast::Extern::Explicit(abi, _) = ext { self.check_abi(abi, constness); } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index ad8dbfd506d..c9e3a7edfa6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1734,10 +1734,10 @@ impl<'a> State<'a> { match header.ext { ast::Extern::None => {} - ast::Extern::Implicit => { + ast::Extern::Implicit(_) => { self.word_nbsp("extern"); } - ast::Extern::Explicit(abi) => { + ast::Extern::Explicit(abi, _) => { self.word_nbsp("extern"); self.print_literal(&abi.as_lit()); self.nbsp(); diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index a5d9a2bc597..08ea00d71ef 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -33,22 +33,6 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { err } - pub(crate) fn cannot_act_on_uninitialized_variable( - &self, - span: Span, - verb: &str, - desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { - struct_span_err!( - self, - span, - E0381, - "{} of possibly-uninitialized variable: `{}`", - verb, - desc, - ) - } - pub(crate) fn cannot_mutably_borrow_multiply( &self, new_loan_span: Span, @@ -175,8 +159,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0501, - "cannot borrow {}{} as {} because previous closure \ - requires unique access", + "cannot borrow {}{} as {} because previous closure requires unique access", desc_new, opt_via, kind_new, @@ -453,9 +436,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { self, closure_span, E0373, - "{} may outlive the current function, \ - but it borrows {}, \ - which is owned by the current function", + "{} may outlive the current function, but it borrows {}, which is owned by the current \ + function", closure_kind, borrowed_path, ); @@ -479,7 +461,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { } #[rustc_lint_diagnostics] - fn struct_span_err_with_code<S: Into<MultiSpan>>( + pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, msg: impl Into<DiagnosticMessage>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 73c0bf16a1f..b9cfc3732dc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2,9 +2,12 @@ use either::Either; use rustc_const_eval::util::CallKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ + struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; @@ -18,6 +21,7 @@ use rustc_middle::ty::{ self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty, }; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; +use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::sym; use rustc_span::{BytePos, Span}; use rustc_trait_selection::infer::InferCtxtExt; @@ -94,32 +98,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } - let item_msg = - match self.describe_place_with_options(used_place, IncludingDowncast(true)) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - let mut err = self.cannot_act_on_uninitialized_variable( + let err = self.report_use_of_uninitialized( + mpi, + used_place, + moved_place, + desired_action, span, - desired_action.as_noun(), - &self - .describe_place_with_options(moved_place, IncludingDowncast(true)) - .unwrap_or_else(|| "_".to_owned()), + use_spans, ); - err.span_label(span, format!("use of possibly-uninitialized {}", item_msg)); - - use_spans.var_span_label_path_only( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); - self.buffer_error(err); } else { if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) { if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) { debug!( - "report_use_of_moved_or_uninitialized place: error suppressed \ - mois={:?}", + "report_use_of_moved_or_uninitialized place: error suppressed mois={:?}", move_out_indices ); return; @@ -326,6 +318,130 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + fn report_use_of_uninitialized( + &self, + mpi: MovePathIndex, + used_place: PlaceRef<'tcx>, + moved_place: PlaceRef<'tcx>, + desired_action: InitializationRequiringAction, + span: Span, + use_spans: UseSpans<'tcx>, + ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + // We need all statements in the body where the binding was assigned to to later find all + // the branching code paths where the binding *wasn't* assigned to. + let inits = &self.move_data.init_path_map[mpi]; + let move_path = &self.move_data.move_paths[mpi]; + let decl_span = self.body.local_decls[move_path.place.local].source_info.span; + let mut spans = vec![]; + for init_idx in inits { + let init = &self.move_data.inits[*init_idx]; + let span = init.span(&self.body); + if !span.is_dummy() { + spans.push(span); + } + } + + let (name, desc) = + match self.describe_place_with_options(moved_place, IncludingDowncast(true)) { + Some(name) => (format!("`{name}`"), format!("`{name}` ")), + None => ("the variable".to_string(), String::new()), + }; + let path = match self.describe_place_with_options(used_place, IncludingDowncast(true)) { + Some(name) => format!("`{name}`"), + None => "value".to_string(), + }; + + // We use the statements were the binding was initialized, and inspect the HIR to look + // for the branching codepaths that aren't covered, to point at them. + let hir_id = self.mir_hir_id(); + let map = self.infcx.tcx.hir(); + let body_id = map.body_owned_by(hir_id); + let body = map.body(body_id); + + let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] }; + visitor.visit_body(&body); + + let isnt_initialized = if let InitializationRequiringAction::PartialAssignment + | InitializationRequiringAction::Assignment = desired_action + { + // The same error is emitted for bindings that are *sometimes* initialized and the ones + // that are *partially* initialized by assigning to a field of an uninitialized + // binding. We differentiate between them for more accurate wording here. + "isn't fully initialized" + } else if spans + .iter() + .filter(|i| { + // We filter these to avoid misleading wording in cases like the following, + // where `x` has an `init`, but it is in the same place we're looking at: + // ``` + // let x; + // x += 1; + // ``` + !i.contains(span) + // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs` + && !visitor + .errors + .iter() + .map(|(sp, _)| *sp) + .any(|sp| span < sp && !sp.contains(span)) + }) + .count() + == 0 + { + "isn't initialized" + } else { + "is possibly-uninitialized" + }; + + let used = desired_action.as_general_verb_in_past_tense(); + let mut err = + struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}"); + use_spans.var_span_label_path_only( + &mut err, + format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), + ); + + if let InitializationRequiringAction::PartialAssignment + | InitializationRequiringAction::Assignment = desired_action + { + err.help( + "partial initialization isn't supported, fully initialize the binding with a \ + default value and mutate it, or use `std::mem::MaybeUninit`", + ); + } + err.span_label(span, format!("{path} {used} here but it {isnt_initialized}")); + + let mut shown = false; + for (sp, label) in visitor.errors { + if sp < span && !sp.overlaps(span) { + // When we have a case like `match-cfg-fake-edges.rs`, we don't want to mention + // match arms coming after the primary span because they aren't relevant: + // ``` + // let x; + // match y { + // _ if { x = 2; true } => {} + // _ if { + // x; //~ ERROR + // false + // } => {} + // _ => {} // We don't want to point to this. + // }; + // ``` + err.span_label(sp, &label); + shown = true; + } + } + if !shown { + for sp in &spans { + if *sp < span && !sp.overlaps(span) { + err.span_label(*sp, "binding initialized here in some conditions"); + } + } + } + err.span_label(decl_span, "binding declared here but left uninitialized"); + err + } + fn suggest_borrow_fn_like( &self, err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, @@ -1628,7 +1744,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, ) -> impl Iterator<Item = Location> + Captures<'tcx> + 'a { if location.statement_index == 0 { - let predecessors = body.predecessors()[location.block].to_vec(); + let predecessors = body.basic_blocks.predecessors()[location.block].to_vec(); Either::Left(predecessors.into_iter().map(move |bb| body.terminator_loc(bb))) } else { Either::Right(std::iter::once(Location { @@ -2448,3 +2564,142 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { } } } + +/// Detect whether one of the provided spans is a statement nested within the top-most visited expr +struct ReferencedStatementsVisitor<'a>(&'a [Span], bool); + +impl<'a, 'v> Visitor<'v> for ReferencedStatementsVisitor<'a> { + fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { + match s.kind { + hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => { + self.1 = true; + } + _ => {} + } + } +} + +/// Given a set of spans representing statements initializing the relevant binding, visit all the +/// function expressions looking for branching code paths that *do not* initialize the binding. +struct ConditionVisitor<'b> { + spans: &'b [Span], + name: &'b str, + errors: Vec<(Span, String)>, +} + +impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + match ex.kind { + hir::ExprKind::If(cond, body, None) => { + // `if` expressions with no `else` that initialize the binding might be missing an + // `else` arm. + let mut v = ReferencedStatementsVisitor(self.spans, false); + v.visit_expr(body); + if v.1 { + self.errors.push(( + cond.span, + format!( + "if this `if` condition is `false`, {} is not initialized", + self.name, + ), + )); + self.errors.push(( + ex.span.shrink_to_hi(), + format!("an `else` arm might be missing here, initializing {}", self.name), + )); + } + } + hir::ExprKind::If(cond, body, Some(other)) => { + // `if` expressions where the binding is only initialized in one of the two arms + // might be missing a binding initialization. + let mut a = ReferencedStatementsVisitor(self.spans, false); + a.visit_expr(body); + let mut b = ReferencedStatementsVisitor(self.spans, false); + b.visit_expr(other); + match (a.1, b.1) { + (true, true) | (false, false) => {} + (true, false) => { + if other.span.is_desugaring(DesugaringKind::WhileLoop) { + self.errors.push(( + cond.span, + format!( + "if this condition isn't met and the `while` loop runs 0 \ + times, {} is not initialized", + self.name + ), + )); + } else { + self.errors.push(( + body.span.shrink_to_hi().until(other.span), + format!( + "if the `if` condition is `false` and this `else` arm is \ + executed, {} is not initialized", + self.name + ), + )); + } + } + (false, true) => { + self.errors.push(( + cond.span, + format!( + "if this condition is `true`, {} is not initialized", + self.name + ), + )); + } + } + } + hir::ExprKind::Match(e, arms, loop_desugar) => { + // If the binding is initialized in one of the match arms, then the other match + // arms might be missing an initialization. + let results: Vec<bool> = arms + .iter() + .map(|arm| { + let mut v = ReferencedStatementsVisitor(self.spans, false); + v.visit_arm(arm); + v.1 + }) + .collect(); + if results.iter().any(|x| *x) && !results.iter().all(|x| *x) { + for (arm, seen) in arms.iter().zip(results) { + if !seen { + if loop_desugar == hir::MatchSource::ForLoopDesugar { + self.errors.push(( + e.span, + format!( + "if the `for` loop runs 0 times, {} is not initialized ", + self.name + ), + )); + } else if let Some(guard) = &arm.guard { + self.errors.push(( + arm.pat.span.to(guard.body().span), + format!( + "if this pattern and condition are matched, {} is not \ + initialized", + self.name + ), + )); + } else { + self.errors.push(( + arm.pat.span, + format!( + "if this pattern is matched, {} is not initialized", + self.name + ), + )); + } + } + } + } + } + // FIXME: should we also account for binops, particularly `&&` and `||`? `try` should + // also be accounted for. For now it is fine, as if we don't find *any* relevant + // branching code paths, we point at the places where the binding *is* initialized for + // *some* context. + _ => {} + } + walk_expr(self, ex); + } +} diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index fbc3a8cc088..6fea6941085 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -812,12 +812,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return FnSelfUse { var_span: stmt.source_info.span, fn_call_span: *fn_span, - fn_span: self - .infcx - .tcx - .sess - .source_map() - .guess_head_span(self.infcx.tcx.def_span(method_did)), + fn_span: self.infcx.tcx.def_span(method_did), kind, }; } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3c5dd32d281..8134e122662 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -861,7 +861,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let arg_pos = args .iter() .enumerate() - .filter(|(_, arg)| arg.span == self.body.span) + .filter(|(_, arg)| arg.hir_id == closure_id) .map(|(pos, _)| pos) .next(); let def_id = hir.local_def_id(item_id); @@ -903,9 +903,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(span) = arg { err.span_label(span, "change this to accept `FnMut` instead of `Fn`"); err.span_label(func.span, "expects `Fn` instead of `FnMut`"); - if self.infcx.tcx.sess.source_map().is_multiline(self.body.span) { - err.span_label(self.body.span, "in this closure"); - } + err.span_label(self.body.span, "in this closure"); look_at_return = false; } } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 0425c53d9dc..721fd3e1c0f 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -26,7 +26,7 @@ pub(super) fn generate_invalidates<'tcx>( if let Some(all_facts) = all_facts { let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - let dominators = body.dominators(); + let dominators = body.basic_blocks.dominators(); let mut ig = InvalidationGenerator { all_facts, borrow_set, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7d6f37340c2..2ed35062da1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -334,7 +334,7 @@ fn do_mir_borrowck<'a, 'tcx>( }; } - let dominators = body.dominators(); + let dominators = body.basic_blocks.dominators(); let mut mbcx = MirBorrowckCtxt { infcx, @@ -907,6 +907,16 @@ impl InitializationRequiringAction { InitializationRequiringAction::PartialAssignment => "partially assigned", } } + + fn as_general_verb_in_past_tense(self) -> &'static str { + match self { + InitializationRequiringAction::Borrow + | InitializationRequiringAction::MatchOn + | InitializationRequiringAction::Use => "used", + InitializationRequiringAction::Assignment => "assigned", + InitializationRequiringAction::PartialAssignment => "partially assigned", + } + } } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index d4e61ec213b..3795378b568 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -258,7 +258,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { let block = self.cx.elements.to_location(block_start).block; self.stack.extend( - self.cx.body.predecessors()[block] + self.cx.body.basic_blocks.predecessors()[block] .iter() .map(|&pred_bb| self.cx.body.terminator_loc(pred_bb)) .map(|pred_loc| self.cx.elements.point_from_location(pred_loc)), @@ -354,7 +354,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } let body = self.cx.body; - for &pred_block in body.predecessors()[block].iter() { + for &pred_block in body.basic_blocks.predecessors()[block].iter() { debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,); // Check whether the variable is (at least partially) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 05457ce15e9..50d8fc30d7d 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -66,7 +66,11 @@ fn emit_module( let work_product = if backend_config.disable_incr_cache { None } else { - rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(tcx.sess, &name, &tmp_file) + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + tcx.sess, + &name, + &[("o", &tmp_file)], + ) }; ModuleCodegenResult( @@ -82,7 +86,10 @@ fn reuse_workproduct_for_cgu( ) -> CompiledModule { let work_product = cgu.previous_work_product(tcx); let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); - let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &work_product.saved_file); + let source_file = rustc_incremental::in_incr_comp_dir_sess( + &tcx.sess, + &work_product.saved_files.get("o").expect("no saved object file in work product"), + ); if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { tcx.sess.err(&format!( "unable to copy {} to {}: {}", diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 87fbb737ea8..8fc8118849b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -93,8 +93,9 @@ impl<'tcx> UniqueTypeId<'tcx> { /// Right now this takes the form of a hex-encoded opaque hash value. pub fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { let mut hasher = StableHasher::new(); - let mut hcx = tcx.create_stable_hashing_context(); - hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)); + tcx.with_stable_hashing_context(|mut hcx| { + hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)) + }); hasher.finish::<Fingerprint>().to_hex() } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 72aa790c363..960e98243ac 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -151,11 +151,23 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( return; } - let remove_temps_from_module = |module: &CompiledModule| { - if let Some(ref obj) = module.object { - ensure_removed(sess.diagnostic(), obj); - } - }; + let maybe_remove_temps_from_module = + |preserve_objects: bool, preserve_dwarf_objects: bool, module: &CompiledModule| { + if !preserve_objects { + if let Some(ref obj) = module.object { + ensure_removed(sess.diagnostic(), obj); + } + } + + if !preserve_dwarf_objects { + if let Some(ref dwo_obj) = module.dwarf_object { + ensure_removed(sess.diagnostic(), dwo_obj); + } + } + }; + + let remove_temps_from_module = + |module: &CompiledModule| maybe_remove_temps_from_module(false, false, module); // Otherwise, always remove the metadata and allocator module temporaries. if let Some(ref metadata_module) = codegen_results.metadata_module { @@ -177,15 +189,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( debug!(?preserve_objects, ?preserve_dwarf_objects); for module in &codegen_results.modules { - if !preserve_objects { - remove_temps_from_module(module); - } - - if !preserve_dwarf_objects { - if let Some(ref obj) = module.dwarf_object { - ensure_removed(sess.diagnostic(), obj); - } - } + maybe_remove_temps_from_module(preserve_objects, preserve_dwarf_objects, module); } }); @@ -649,6 +653,7 @@ fn link_dwarf_object<'a>( sess.struct_err("linking dwarf objects with thorin failed") .note(&format!("{:?}", e)) .emit(); + sess.abort_if_errors(); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 632f07c5c2d..f4a5cac872e 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -494,12 +494,18 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir"); for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { - if let Some(path) = &module.object { - if let Some((id, product)) = - copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, path) - { - work_products.insert(id, product); - } + let mut files = Vec::new(); + if let Some(object_file_path) = &module.object { + files.push(("o", object_file_path.as_path())); + } + if let Some(dwarf_object_file_path) = &module.dwarf_object { + files.push(("dwo", dwarf_object_file_path.as_path())); + } + + if let Some((id, product)) = + copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, files.as_slice()) + { + work_products.insert(id, product); } } @@ -856,29 +862,50 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( assert!(module_config.emit_obj != EmitObj::None); let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)); - let source_file = in_incr_comp_dir(&incr_comp_session_dir, &module.source.saved_file); - debug!( - "copying pre-existing module `{}` from {:?} to {}", - module.name, - source_file, - obj_out.display() + + let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { + let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path); + debug!( + "copying pre-existing module `{}` from {:?} to {}", + module.name, + source_file, + output_path.display() + ); + match link_or_copy(&source_file, &output_path) { + Ok(_) => Some(output_path), + Err(err) => { + let diag_handler = cgcx.create_diag_handler(); + diag_handler.err(&format!( + "unable to copy {} to {}: {}", + source_file.display(), + output_path.display(), + err + )); + None + } + } + }; + + let object = load_from_incr_comp_dir( + cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)), + &module.source.saved_files.get("o").expect("no saved object file in work product"), ); - if let Err(err) = link_or_copy(&source_file, &obj_out) { - let diag_handler = cgcx.create_diag_handler(); - diag_handler.err(&format!( - "unable to copy {} to {}: {}", - source_file.display(), - obj_out.display(), - err - )); - } + let dwarf_object = + module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { + let dwarf_obj_out = cgcx + .output_filenames + .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, Some(&module.name)) + .expect( + "saved dwarf object in work product but `split_dwarf_path` returned `None`", + ); + load_from_incr_comp_dir(dwarf_obj_out, &saved_dwarf_object_file) + }); WorkItemResult::Compiled(CompiledModule { name: module.name, kind: ModuleKind::Regular, - object: Some(obj_out), - dwarf_object: None, + object, + dwarf_object, bytecode: None, }) } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 8755d91818d..8cd5a0fc247 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -701,16 +701,20 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // If we cannot evaluate the constant to a known type, we fall back // to emitting a stable hash value of the constant. This isn't very pretty // but we get a deterministic, virtually unique value for the constant. - let hcx = &mut tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - let ct = ct.eval(tcx, ty::ParamEnv::reveal_all()); - hcx.while_hashing_spans(false, |hcx| ct.to_valtree().hash_stable(hcx, &mut hasher)); + // // Let's only emit 64 bits of the hash value. That should be plenty for // avoiding collisions and will make the emitted type names shorter. - // Note: Don't use `StableHashResult` impl of `u64` here directly, since that - // would lead to endianness problems. - let hash: u128 = hasher.finish(); - let hash_short = (hash.to_le() as u64).to_le(); + let hash_short = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + let ct = ct.eval(tcx, ty::ParamEnv::reveal_all()); + hcx.while_hashing_spans(false, |hcx| { + ct.to_valtree().hash_stable(hcx, &mut hasher) + }); + // Note: Don't use `StableHashResult` impl of `u64` here directly, since that + // would lead to endianness problems. + let hash: u128 = hasher.finish(); + (hash.to_le() as u64).to_le() + }); if cpp_like_debuginfo(tcx) { write!(output, "CONST${:x}", hash_short) diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 5c26168b50d..24da48ead63 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -15,7 +15,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, ) -> BitSet<mir::Local> { let mir = fx.mir; - let dominators = mir.dominators(); + let dominators = mir.basic_blocks.dominators(); let locals = mir .local_decls .iter() diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 7f14b95317b..645afae30d8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -513,9 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let ty = substs.type_at(0); - if int_type_width_signed(ty, bx.tcx()).is_some() - || (ty.is_unsafe_ptr() && op == "xchg") - { + if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let mut ptr = args[0].immediate(); let mut val = args[1].immediate(); if ty.is_unsafe_ptr() { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 7ff12823bf7..55ab8b08d4a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -123,7 +123,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Do not generate stores and GEPis for zero-sized fields. if !op.layout.is_zst() { let field_index = active_field_index.unwrap_or(i); - let field = dest.project_field(&mut bx, field_index); + let field = if let mir::AggregateKind::Array(_) = **kind { + let llindex = bx.cx().const_usize(field_index as u64); + dest.project_index(&mut bx, llindex) + } else { + dest.project_field(&mut bx, field_index) + }; op.val.store(&mut bx, field); } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 0dac4f8978e..f84dd9521ee 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -189,6 +189,7 @@ pub(super) fn op_to_const<'tcx>( let len: usize = len.try_into().unwrap(); ConstValue::Slice { data, start, end: start + len } } + Immediate::Uninit => to_const_value(&op.assert_mem_place()), }, } } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index fc81b22b406..5d598b65c72 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -153,7 +153,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert_eq!(dest_layout.size, self.pointer_size()); assert!(src.layout.ty.is_unsafe_ptr()); return match **src { - Immediate::ScalarPair(data, _) => Ok(data.into()), + Immediate::ScalarPair(data, _) => Ok(data.check_init()?.into()), Immediate::Scalar(..) => span_bug!( self.cur_span(), "{:?} input to a fat-to-thin cast ({:?} -> {:?})", @@ -161,6 +161,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { src.layout.ty, cast_ty ), + Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), }; } } @@ -358,7 +359,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let src_field = self.operand_field(src, i)?; let dst_field = self.place_field(dest, i)?; if src_field.layout.ty == cast_ty_field.ty { - self.copy_op(&src_field, &dst_field)?; + self.copy_op(&src_field, &dst_field, /*allow_transmute*/ false)?; } else { self.unsize_into(&src_field, cast_ty_field, &dst_field)?; } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 031d508d70f..3892d1920ce 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -112,6 +112,8 @@ pub struct Frame<'mir, 'tcx, Tag: Provenance = AllocId, Extra = ()> { /// The locals are stored as `Option<Value>`s. /// `None` represents a local that is currently dead, while a live local /// can either directly contain `Scalar` or refer to some part of an `Allocation`. + /// + /// Do *not* access this directly; always go through the machine hook! pub locals: IndexVec<mir::Local, LocalState<'tcx, Tag>>, /// The span of the `tracing` crate is stored here. @@ -179,10 +181,6 @@ pub struct LocalState<'tcx, Tag: Provenance = AllocId> { pub enum LocalValue<Tag: Provenance = AllocId> { /// This local is not currently alive, and cannot be used at all. Dead, - /// This local is alive but not yet allocated. It cannot be read from or have its address taken, - /// and will be allocated on the first write. This is to support unsized locals, where we cannot - /// know their size in advance. - Unallocated, /// A normal, live local. /// Mostly for convenience, we re-use the `Operand` type here. /// This is an optimization over just always having a pointer here; @@ -196,12 +194,10 @@ impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> { /// /// Note: This may only be invoked from the `Machine::access_local` hook and not from /// anywhere else. You may be invalidating machine invariants if you do! - pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> { - match self.value { - LocalValue::Dead => throw_ub!(DeadLocal), - LocalValue::Unallocated => { - bug!("The type checker should prevent reading from a never-written local") - } + #[inline] + pub fn access(&self) -> InterpResult<'tcx, &Operand<Tag>> { + match &self.value { + LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"? LocalValue::Live(val) => Ok(val), } } @@ -211,15 +207,11 @@ impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> { /// /// Note: This may only be invoked from the `Machine::access_local_mut` hook and not from /// anywhere else. You may be invalidating machine invariants if you do! - pub fn access_mut( - &mut self, - ) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> { - match self.value { - LocalValue::Dead => throw_ub!(DeadLocal), - LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)), - ref mut local @ (LocalValue::Live(Operand::Immediate(_)) | LocalValue::Unallocated) => { - Ok(Ok(local)) - } + #[inline] + pub fn access_mut(&mut self) -> InterpResult<'tcx, &mut Operand<Tag>> { + match &mut self.value { + LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"? + LocalValue::Live(val) => Ok(val), } } } @@ -710,16 +702,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { })?; } - // Locals are initially unallocated. - let dummy = LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) }; + // Most locals are initially dead. + let dummy = LocalState { value: LocalValue::Dead, layout: Cell::new(None) }; let mut locals = IndexVec::from_elem(dummy, &body.local_decls); - // Now mark those locals as dead that we do not want to initialize - // Mark locals that use `Storage*` annotations as dead on function entry. + // Now mark those locals as live that have no `Storage*` annotations. let always_live = always_live_locals(self.body()); for local in locals.indices() { - if !always_live.contains(local) { - locals[local].value = LocalValue::Dead; + if always_live.contains(local) { + locals[local].value = LocalValue::Live(Operand::Immediate(Immediate::Uninit)); } } // done @@ -791,7 +782,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if unwinding { "during unwinding" } else { "returning from function" } ); - // Sanity check `unwinding`. + // Check `unwinding`. assert_eq!( unwinding, match self.frame().loc { @@ -799,51 +790,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Err(_) => true, } ); - if unwinding && self.frame_idx() == 0 { throw_ub_format!("unwinding past the topmost frame of the stack"); } - let frame = - self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); - - if !unwinding { - let op = self.local_to_op(&frame, mir::RETURN_PLACE, None)?; - self.copy_op_transmute(&op, &frame.return_place)?; - trace!("{:?}", self.dump_place(*frame.return_place)); - } - - let return_to_block = frame.return_to_block; - - // Now where do we jump next? + // Copy return value. Must of course happen *before* we deallocate the locals. + let copy_ret_result = if !unwinding { + let op = self + .local_to_op(self.frame(), mir::RETURN_PLACE, None) + .expect("return place should always be live"); + let dest = self.frame().return_place; + let err = self.copy_op(&op, &dest, /*allow_transmute*/ true); + trace!("return value: {:?}", self.dump_place(*dest)); + // We delay actually short-circuiting on this error until *after* the stack frame is + // popped, since we want this error to be attributed to the caller, whose type defines + // this transmute. + err + } else { + Ok(()) + }; + // Cleanup: deallocate locals. // Usually we want to clean up (deallocate locals), but in a few rare cases we don't. - // In that case, we return early. We also avoid validation in that case, - // because this is CTFE and the final value will be thoroughly validated anyway. + // We do this while the frame is still on the stack, so errors point to the callee. + let return_to_block = self.frame().return_to_block; let cleanup = match return_to_block { StackPopCleanup::Goto { .. } => true, StackPopCleanup::Root { cleanup, .. } => cleanup, }; + if cleanup { + // We need to take the locals out, since we need to mutate while iterating. + let locals = mem::take(&mut self.frame_mut().locals); + for local in &locals { + self.deallocate_local(local.value)?; + } + } + + // All right, now it is time to actually pop the frame. + // Note that its locals are gone already, but that's fine. + let frame = + self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); + // Report error from return value copy, if any. + copy_ret_result?; + // If we are not doing cleanup, also skip everything else. if !cleanup { assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked"); assert!(!unwinding, "tried to skip cleanup during unwinding"); - // Leak the locals, skip validation, skip machine hook. + // Skip machine hook. return Ok(()); } - - trace!("locals: {:#?}", frame.locals); - - // Cleanup: deallocate all locals that are backed by an allocation. - for local in &frame.locals { - self.deallocate_local(local.value)?; - } - if M::after_stack_pop(self, frame, unwinding)? == StackPopJump::NoJump { // The hook already did everything. - // We want to skip the `info!` below, hence early return. return Ok(()); } + // Normal return, figure out where to jump. if unwinding { // Follow the unwind edge. @@ -874,7 +875,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(local != mir::RETURN_PLACE, "Cannot make return place live"); trace!("{:?} is now live", local); - let local_val = LocalValue::Unallocated; + let local_val = LocalValue::Live(Operand::Immediate(Immediate::Uninit)); // StorageLive expects the local to be dead, and marks it live. let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val); if !matches!(old, LocalValue::Dead) { @@ -977,7 +978,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug match self.ecx.stack()[frame].locals[local].value { LocalValue::Dead => write!(fmt, " is dead")?, - LocalValue::Unallocated => write!(fmt, " is unallocated")?, + LocalValue::Live(Operand::Immediate(Immediate::Uninit)) => { + write!(fmt, " is uninitialized")? + } LocalValue::Live(Operand::Indirect(mplace)) => { write!( fmt, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 6744aace849..93b64d9d37a 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -174,7 +174,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?; - self.copy_op(&val, dest)?; + self.copy_op(&val, dest, /*allow_transmute*/ false)?; } sym::ctpop @@ -394,7 +394,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::transmute => { - self.copy_op_transmute(&args[0], dest)?; + self.copy_op(&args[0], dest, /*allow_transmute*/ true)?; } sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { let ty = instance.substs.type_at(0); @@ -461,7 +461,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let place = self.mplace_index(&dest, i)?; let value = if i == index { *elem } else { self.mplace_index(&input, i)?.into() }; - self.copy_op(&value, &place.into())?; + self.copy_op(&value, &place.into(), /*allow_transmute*/ false)?; } } sym::simd_extract => { @@ -473,11 +473,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { index, input_len ); - self.copy_op(&self.mplace_index(&input, index)?.into(), dest)?; + self.copy_op( + &self.mplace_index(&input, index)?.into(), + dest, + /*allow_transmute*/ false, + )?; } sym::likely | sym::unlikely | sym::black_box => { // These just return their argument - self.copy_op(&args[0], dest)?; + self.copy_op(&args[0], dest, /*allow_transmute*/ false)?; } sym::assume => { let cond = self.read_scalar(&args[0])?.check_init()?.to_bool()?; diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 54c9e99cf97..b3461b414b6 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -14,8 +14,7 @@ use rustc_target::spec::abi::Abi; use super::{ AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, - LocalValue, MemPlace, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, - StackPopUnwind, + MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; /// Data returned by Machine::stack_pop, @@ -145,7 +144,7 @@ pub trait Machine<'mir, 'tcx>: Sized { } /// Whether CheckedBinOp MIR statements should actually check for overflow. - fn check_binop_checks_overflow(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + fn checked_binop_checks_overflow(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Entry point for obtaining the MIR of anything that should get evaluated. /// So not just functions and shims, but also const/static initializers, anonymous @@ -226,11 +225,13 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Since reading a ZST is not actually accessing memory or locals, this is never invoked /// for ZST reads. #[inline] - fn access_local( - _ecx: &InterpCx<'mir, 'tcx, Self>, - frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, + fn access_local<'a>( + frame: &'a Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, local: mir::Local, - ) -> InterpResult<'tcx, Operand<Self::PointerTag>> { + ) -> InterpResult<'tcx, &'a Operand<Self::PointerTag>> + where + 'tcx: 'mir, + { frame.locals[local].access() } @@ -242,7 +243,7 @@ pub trait Machine<'mir, 'tcx>: Sized { ecx: &'a mut InterpCx<'mir, 'tcx, Self>, frame: usize, local: mir::Local, - ) -> InterpResult<'tcx, Result<&'a mut LocalValue<Self::PointerTag>, MemPlace<Self::PointerTag>>> + ) -> InterpResult<'tcx, &'a mut Operand<Self::PointerTag>> where 'tcx: 'mir, { @@ -418,12 +419,14 @@ pub trait Machine<'mir, 'tcx>: Sized { } /// Called immediately after a stack frame got popped, but before jumping back to the caller. + /// The `locals` have already been destroyed! fn after_stack_pop( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _frame: Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, - _unwinding: bool, + unwinding: bool, ) -> InterpResult<'tcx, StackPopJump> { // By default, we do not support unwinding from panics + assert!(!unwinding); Ok(StackPopJump::Normal) } } @@ -472,7 +475,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn check_binop_checks_overflow(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { + fn checked_binop_checks_overflow(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { true } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index d48f6521ba2..805dcb38895 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -14,7 +14,7 @@ use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ - alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, GlobalId, + alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, }; @@ -28,8 +28,15 @@ use super::{ /// defined on `Immediate`, and do not have to work with a `Place`. #[derive(Copy, Clone, PartialEq, Eq, HashStable, Hash, Debug)] pub enum Immediate<Tag: Provenance = AllocId> { + /// A single scalar value (must have *initialized* `Scalar` ABI). + /// FIXME: we also currently often use this for ZST. + /// `ScalarMaybeUninit` should reject ZST, and we should use `Uninit` for them instead. Scalar(ScalarMaybeUninit<Tag>), + /// A pair of two scalar value (must have `ScalarPair` ABI where both fields are + /// `Scalar::Initialized`). ScalarPair(ScalarMaybeUninit<Tag>, ScalarMaybeUninit<Tag>), + /// A value of fully uninitialized memory. Can have and size and layout. + Uninit, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -75,6 +82,7 @@ impl<'tcx, Tag: Provenance> Immediate<Tag> { match self { Immediate::Scalar(val) => val, Immediate::ScalarPair(..) => bug!("Got a scalar pair where a scalar was expected"), + Immediate::Uninit => ScalarMaybeUninit::Uninit, } } @@ -88,6 +96,7 @@ impl<'tcx, Tag: Provenance> Immediate<Tag> { match self { Immediate::ScalarPair(val1, val2) => (val1, val2), Immediate::Scalar(..) => bug!("Got a scalar where a scalar pair was expected"), + Immediate::Uninit => (ScalarMaybeUninit::Uninit, ScalarMaybeUninit::Uninit), } } @@ -149,7 +158,10 @@ impl<Tag: Provenance> std::fmt::Display for ImmTy<'_, Tag> { } Immediate::ScalarPair(a, b) => { // FIXME(oli-obk): at least print tuples and slices nicely - write!(f, "({:x}, {:x}): {}", a, b, self.layout.ty,) + write!(f, "({:x}, {:x}): {}", a, b, self.layout.ty) + } + Immediate::Uninit => { + write!(f, "uninit: {}", self.layout.ty) } } }) @@ -306,9 +318,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { s.is_ptr() || (number_may_have_provenance && size == self.pointer_size()) }; if let Some(s) = scalar_layout { - //FIXME(#96185): let size = s.size(self); - //FIXME(#96185): assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size"); - let size = mplace.layout.size; //FIXME(#96185): remove this line + let size = s.size(self); + assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size"); let scalar = alloc.read_scalar(alloc_range(Size::ZERO, size), read_provenance(s, size))?; return Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout })); @@ -398,7 +409,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.scalar_to_ptr(self.read_scalar(op)?.check_init()?) } - // Turn the wide MPlace into a string (must already be dereferenced!) + /// Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> { let len = mplace.len(self)?; let bytes = self.read_bytes_ptr(mplace.ptr, Size::from_bytes(len))?; @@ -529,10 +540,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Will not access memory, instead an indirect `Operand` is returned. /// /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an - /// OpTy from a local + /// OpTy from a local. pub fn local_to_op( &self, - frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, + frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, local: mir::Local, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { @@ -541,7 +552,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Do not read from ZST, they might not be initialized Operand::Immediate(Scalar::ZST.into()) } else { - M::access_local(&self, frame, local)? + *M::access_local(frame, local)? }; Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 942bdb36645..f0c113376ea 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -33,7 +33,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // As per https://github.com/rust-lang/rust/pull/98738, we always return `false` in the 2nd // component when overflow checking is disabled. let overflowed = - overflowed && (force_overflow_checks || M::check_binop_checks_overflow(self)); + overflowed && (force_overflow_checks || M::checked_binop_checks_overflow(self)); // Write the result to `dest`. if let Abi::ScalarPair(..) = dest.layout.abi { // We can use the optimized path and avoid `place_field` (which might do diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 926afe757ed..57ecad07b42 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -10,13 +10,14 @@ use rustc_macros::HashStable; use rustc_middle::mir; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding}; -use rustc_target::abi::{HasDataLayout, Size, VariantIdx, Variants}; +use rustc_target::abi::{ + Abi, Align, FieldsShape, HasDataLayout, Size, TagEncoding, VariantIdx, Variants, +}; use super::{ alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, - ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, - Operand, Pointer, Provenance, Scalar, ScalarMaybeUninit, + ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, OpTy, Operand, + Pointer, Provenance, Scalar, ScalarMaybeUninit, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] @@ -183,6 +184,18 @@ impl<Tag: Provenance> MemPlace<Tag> { } } +impl<Tag: Provenance> Place<Tag> { + /// Asserts that this points to some local variable. + /// Returns the frame idx and the variable idx. + #[inline] + pub fn assert_local(&self) -> (usize, mir::Local) { + match self { + Place::Local { frame, local } => (*frame, *local), + _ => bug!("assert_local: expected Place::Local, got {:?}", self), + } + } +} + impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { /// Produces a MemPlace that works for ZST but nothing else #[inline] @@ -286,7 +299,7 @@ impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> { } #[inline] - pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> { + pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Tag> { self.try_as_mplace().unwrap() } } @@ -314,6 +327,7 @@ where let (ptr, meta) = match **val { Immediate::Scalar(ptr) => (ptr, MemPlaceMeta::None), Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)), + Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), }; let mplace = MemPlace { ptr: self.scalar_to_ptr(ptr.check_init()?)?, meta }; @@ -746,32 +760,33 @@ where let mplace = match dest.place { Place::Local { frame, local } => { match M::access_local_mut(self, frame, local)? { - Ok(local) => { + Operand::Immediate(local) => { // Local can be updated in-place. - *local = LocalValue::Live(Operand::Immediate(src)); + *local = src; return Ok(()); } - Err(mplace) => { + Operand::Indirect(mplace) => { // The local is in memory, go on below. - mplace + *mplace } } } Place::Ptr(mplace) => mplace, // already referring to memory }; - let dest = MPlaceTy { mplace, layout: dest.layout, align: dest.align }; // This is already in memory, write there. - self.write_immediate_to_mplace_no_validate(src, &dest) + self.write_immediate_to_mplace_no_validate(src, dest.layout, dest.align, mplace) } /// Write an immediate to memory. /// If you use this you are responsible for validating that things got copied at the - /// right type. + /// right layout. fn write_immediate_to_mplace_no_validate( &mut self, value: Immediate<M::PointerTag>, - dest: &MPlaceTy<'tcx, M::PointerTag>, + layout: TyAndLayout<'tcx>, + align: Align, + dest: MemPlace<M::PointerTag>, ) -> InterpResult<'tcx> { // Note that it is really important that the type here is the right one, and matches the // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here @@ -779,31 +794,30 @@ where // wrong type. let tcx = *self.tcx; - let Some(mut alloc) = self.get_place_alloc_mut(dest)? else { + let Some(mut alloc) = self.get_place_alloc_mut(&MPlaceTy { mplace: dest, layout, align })? else { // zero-sized access return Ok(()); }; match value { Immediate::Scalar(scalar) => { - let Abi::Scalar(s) = dest.layout.abi else { span_bug!( + let Abi::Scalar(s) = layout.abi else { span_bug!( self.cur_span(), - "write_immediate_to_mplace: invalid Scalar layout: {:#?}", - dest.layout + "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}", ) }; let size = s.size(&tcx); - //FIXME(#96185): assert_eq!(dest.layout.size, size, "abi::Scalar size does not match layout size"); + assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); alloc.write_scalar(alloc_range(Size::ZERO, size), scalar) } Immediate::ScalarPair(a_val, b_val) => { // We checked `ptr_align` above, so all fields will have the alignment they need. // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. - let Abi::ScalarPair(a, b) = dest.layout.abi else { span_bug!( + let Abi::ScalarPair(a, b) = layout.abi else { span_bug!( self.cur_span(), "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}", - dest.layout + layout ) }; let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); @@ -817,6 +831,7 @@ where alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?; alloc.write_scalar(alloc_range(b_offset, b_size), b_val) } + Immediate::Uninit => alloc.write_uninit(), } } @@ -825,25 +840,13 @@ where Ok(mplace) => mplace, Err((frame, local)) => { match M::access_local_mut(self, frame, local)? { - Ok(local) => match dest.layout.abi { - Abi::Scalar(_) => { - *local = LocalValue::Live(Operand::Immediate(Immediate::Scalar( - ScalarMaybeUninit::Uninit, - ))); - return Ok(()); - } - Abi::ScalarPair(..) => { - *local = LocalValue::Live(Operand::Immediate(Immediate::ScalarPair( - ScalarMaybeUninit::Uninit, - ScalarMaybeUninit::Uninit, - ))); - return Ok(()); - } - _ => self.force_allocation(dest)?, - }, - Err(mplace) => { + Operand::Immediate(local) => { + *local = Immediate::Uninit; + return Ok(()); + } + Operand::Indirect(mplace) => { // The local is in memory, go on below. - MPlaceTy { mplace, layout: dest.layout, align: dest.align } + MPlaceTy { mplace: *mplace, layout: dest.layout, align: dest.align } } } } @@ -856,16 +859,17 @@ where Ok(()) } - /// Copies the data from an operand to a place. This does not support transmuting! - /// Use `copy_op_transmute` if the layouts could disagree. + /// Copies the data from an operand to a place. + /// `allow_transmute` indicates whether the layouts may disagree. #[inline(always)] #[instrument(skip(self), level = "debug")] pub fn copy_op( &mut self, src: &OpTy<'tcx, M::PointerTag>, dest: &PlaceTy<'tcx, M::PointerTag>, + allow_transmute: bool, ) -> InterpResult<'tcx> { - self.copy_op_no_validate(src, dest)?; + self.copy_op_no_validate(src, dest, allow_transmute)?; if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! @@ -875,8 +879,8 @@ where Ok(()) } - /// Copies the data from an operand to a place. This does not support transmuting! - /// Use `copy_op_transmute` if the layouts could disagree. + /// Copies the data from an operand to a place. + /// `allow_transmute` indicates whether the layouts may disagree. /// Also, if you use this you are responsible for validating that things get copied at the /// right type. #[instrument(skip(self), level = "debug")] @@ -884,10 +888,13 @@ where &mut self, src: &OpTy<'tcx, M::PointerTag>, dest: &PlaceTy<'tcx, M::PointerTag>, + allow_transmute: bool, ) -> InterpResult<'tcx> { // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. - if !mir_assign_valid_types(*self.tcx, self.param_env, src.layout, dest.layout) { + let layout_compat = + mir_assign_valid_types(*self.tcx, self.param_env, src.layout, dest.layout); + if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), "type mismatch when copying!\nsrc: {:?},\ndest: {:?}", @@ -896,100 +903,68 @@ where ); } - // Let us see if the layout is simple so we take a shortcut, avoid force_allocation. + // Let us see if the layout is simple so we take a shortcut, + // avoid force_allocation. let src = match self.read_immediate_raw(src, /*force*/ false)? { Ok(src_val) => { assert!(!src.layout.is_unsized(), "cannot have unsized immediates"); + assert!( + !dest.layout.is_unsized(), + "the src is sized, so the dest must also be sized" + ); + assert_eq!(src.layout.size, dest.layout.size); // Yay, we got a value that we can write directly. - return self.write_immediate_no_validate(*src_val, dest); + return if layout_compat { + self.write_immediate_no_validate(*src_val, dest) + } else { + // This is tricky. The problematic case is `ScalarPair`: the `src_val` was + // loaded using the offsets defined by `src.layout`. When we put this back into + // the destination, we have to use the same offsets! So (a) we make sure we + // write back to memory, and (b) we use `dest` *with the source layout*. + let dest_mem = self.force_allocation(dest)?; + self.write_immediate_to_mplace_no_validate( + *src_val, + src.layout, + dest_mem.align, + *dest_mem, + ) + }; } Err(mplace) => mplace, }; // Slow path, this does not fit into an immediate. Just memcpy. trace!("copy_op: {:?} <- {:?}: {}", *dest, src, dest.layout.ty); - // This interprets `src.meta` with the `dest` local's layout, if an unsized local - // is being initialized! - let (dest, size) = self.force_allocation_maybe_sized(dest, src.meta)?; - let size = size.unwrap_or_else(|| { - assert!( - !dest.layout.is_unsized(), - "Cannot copy into already initialized unsized place" - ); - dest.layout.size - }); - assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - - self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ false) - } - - /// Copies the data from an operand to a place. The layouts may disagree, but they must - /// have the same size. - pub fn copy_op_transmute( - &mut self, - src: &OpTy<'tcx, M::PointerTag>, - dest: &PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - if mir_assign_valid_types(*self.tcx, self.param_env, src.layout, dest.layout) { - // Fast path: Just use normal `copy_op` - return self.copy_op(src, dest); - } - // We still require the sizes to match. - if src.layout.size != dest.layout.size { - span_bug!( - self.cur_span(), - "size-changing transmute, should have been caught by transmute checking: {:#?}\ndest: {:#?}", - src, - dest - ); - } - // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want - // to avoid that here. - assert!( - !src.layout.is_unsized() && !dest.layout.is_unsized(), - "Cannot transmute unsized data" - ); - - // The hard case is `ScalarPair`. `src` is already read from memory in this case, - // using `src.layout` to figure out which bytes to use for the 1st and 2nd field. - // We have to write them to `dest` at the offsets they were *read at*, which is - // not necessarily the same as the offsets in `dest.layout`! - // Hence we do the copy with the source layout on both sides. We also make sure to write - // into memory, because if `dest` is a local we would not even have a way to write - // at the `src` offsets; the fact that we came from a different layout would - // just be lost. - let dest = self.force_allocation(dest)?; - self.copy_op_no_validate( - src, - &PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout, align: dest.align }), - )?; - - if M::enforce_validity(self) { - // Data got changed, better make sure it matches the type! - self.validate_operand(&dest.into())?; + let dest = self.force_allocation(&dest)?; + let Some((dest_size, _)) = self.size_and_align_of_mplace(&dest)? else { + span_bug!(self.cur_span(), "copy_op needs (dynamically) sized values") + }; + if cfg!(debug_assertions) { + let src_size = self.size_and_align_of_mplace(&src)?.unwrap().0; + assert_eq!(src_size, dest_size, "Cannot copy differently-sized data"); + } else { + // As a cheap approximation, we compare the fixed parts of the size. + assert_eq!(src.layout.size, dest.layout.size); } - Ok(()) + self.mem_copy( + src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ false, + ) } /// Ensures that a place is in memory, and returns where it is. /// If the place currently refers to a local that doesn't yet have a matching allocation, /// create such an allocation. /// This is essentially `force_to_memplace`. - /// - /// This supports unsized types and returns the computed size to avoid some - /// redundant computation when copying; use `force_allocation` for a simpler, sized-only - /// version. #[instrument(skip(self), level = "debug")] - pub fn force_allocation_maybe_sized( + pub fn force_allocation( &mut self, place: &PlaceTy<'tcx, M::PointerTag>, - meta: MemPlaceMeta<M::PointerTag>, - ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option<Size>)> { - let (mplace, size) = match place.place { + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let mplace = match place.place { Place::Local { frame, local } => { match M::access_local_mut(self, frame, local)? { - Ok(&mut local_val) => { + &mut Operand::Immediate(local_val) => { // We need to make an allocation. // We need the layout of the local. We can NOT use the layout we got, @@ -997,44 +972,34 @@ where // that has different alignment than the outer field. let local_layout = self.layout_of_local(&self.stack()[frame], local, None)?; - // We also need to support unsized types, and hence cannot use `allocate`. - let (size, align) = self - .size_and_align_of(&meta, &local_layout)? - .expect("Cannot allocate for non-dyn-sized type"); - let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; - let mplace = MemPlace { ptr: ptr.into(), meta }; - if let LocalValue::Live(Operand::Immediate(value)) = local_val { - // Preserve old value. + if local_layout.is_unsized() { + throw_unsup_format!("unsized locals are not supported"); + } + let mplace = *self.allocate(local_layout, MemoryKind::Stack)?; + if !matches!(local_val, Immediate::Uninit) { + // Preserve old value. (As an optimization, we can skip this if it was uninit.) // We don't have to validate as we can assume the local // was already valid for its type. - let mplace = MPlaceTy { + self.write_immediate_to_mplace_no_validate( + local_val, + local_layout, + local_layout.align.abi, mplace, - layout: local_layout, - align: local_layout.align.abi, - }; - self.write_immediate_to_mplace_no_validate(value, &mplace)?; + )?; } // Now we can call `access_mut` again, asserting it goes well, // and actually overwrite things. - *M::access_local_mut(self, frame, local).unwrap().unwrap() = - LocalValue::Live(Operand::Indirect(mplace)); - (mplace, Some(size)) + *M::access_local_mut(self, frame, local).unwrap() = + Operand::Indirect(mplace); + mplace } - Err(mplace) => (mplace, None), // this already was an indirect local + &mut Operand::Indirect(mplace) => mplace, // this already was an indirect local } } - Place::Ptr(mplace) => (mplace, None), + Place::Ptr(mplace) => mplace, }; // Return with the original layout, so that the caller can go on - Ok((MPlaceTy { mplace, layout: place.layout, align: place.align }, size)) - } - - #[inline(always)] - pub fn force_allocation( - &mut self, - place: &PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { - Ok(self.force_allocation_maybe_sized(place, MemPlaceMeta::None)?.0) + Ok(MPlaceTy { mplace, layout: place.layout, align: place.align }) } pub fn allocate( @@ -1042,6 +1007,7 @@ where layout: TyAndLayout<'tcx>, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + assert!(!layout.is_unsized()); let ptr = self.allocate_ptr(layout.size, layout.align.abi, kind)?; Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 2ee7ed57ab5..240910c08b2 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -169,7 +169,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Use(ref operand) => { // Avoid recomputing the layout let op = self.eval_operand(operand, Some(dest.layout))?; - self.copy_op(&op, &dest)?; + self.copy_op(&op, &dest, /*allow_transmute*/ false)?; } BinaryOp(bin_op, box (ref left, ref right)) => { @@ -204,7 +204,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (field_index, operand) in operands.iter().enumerate() { let op = self.eval_operand(operand, None)?; let field_dest = self.place_field(&dest, field_index)?; - self.copy_op(&op, &field_dest)?; + self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; } } @@ -220,7 +220,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { // Write the src to the first element. let first = self.mplace_field(&dest, 0)?; - self.copy_op(&src, &first.into())?; + self.copy_op(&src, &first.into(), /*allow_transmute*/ false)?; // This is performance-sensitive code for big static/const arrays! So we // avoid writing each operand individually and instead just make many copies diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 57d06b48ca4..515cc222dc6 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -12,8 +12,8 @@ use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMo use rustc_target::spec::abi::Abi; use super::{ - FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Scalar, - StackPopCleanup, StackPopUnwind, + FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand, + PlaceTy, Scalar, StackPopCleanup, StackPopUnwind, }; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { @@ -185,11 +185,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // No question return true; } + if caller_abi.layout.is_unsized() || callee_abi.layout.is_unsized() { + // No, no, no. We require the types to *exactly* match for unsized arguments. If + // these are somehow unsized "in a different way" (say, `dyn Trait` vs `[i32]`), + // then who knows what happens. + return false; + } if caller_abi.layout.size != callee_abi.layout.size || caller_abi.layout.align.abi != callee_abi.layout.align.abi { // This cannot go well... - // FIXME: What about unsized types? return false; } // The rest *should* be okay, but we are extra conservative. @@ -287,11 +292,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { caller_arg.layout.ty ) } + // Special handling for unsized parameters. + if caller_arg.layout.is_unsized() { + // `check_argument_compat` ensures that both have the same type, so we know they will use the metadata the same way. + assert_eq!(caller_arg.layout.ty, callee_arg.layout.ty); + // We have to properly pre-allocate the memory for the callee. + // So let's tear down some wrappers. + // This all has to be in memory, there are no immediate unsized values. + let src = caller_arg.assert_mem_place(); + // The destination cannot be one of these "spread args". + let (dest_frame, dest_local) = callee_arg.assert_local(); + // We are just initializing things, so there can't be anything here yet. + assert!(matches!( + *self.local_to_op(&self.stack()[dest_frame], dest_local, None)?, + Operand::Immediate(Immediate::Uninit) + )); + // Allocate enough memory to hold `src`. + let Some((size, align)) = self.size_and_align_of_mplace(&src)? else { + span_bug!(self.cur_span(), "unsized fn arg with `extern` type tail should not be allowed") + }; + let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; + let dest_place = + MPlaceTy::from_aligned_ptr_with_meta(ptr.into(), callee_arg.layout, src.meta); + // Update the local to be that new place. + *M::access_local_mut(self, dest_frame, dest_local)? = Operand::Indirect(*dest_place); + } // We allow some transmutes here. // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This // is true for all `copy_op`, but there are a lot of special cases for argument passing // specifically.) - self.copy_op_transmute(&caller_arg, callee_arg) + self.copy_op(&caller_arg, callee_arg, /*allow_transmute*/ true) } /// Call this function -- pushing the stack frame and initializing the arguments. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 0bf78446e37..08102585a7b 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -427,7 +427,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' err_ub!(DanglingIntPointer(0, _)) => { "a null {kind}" }, err_ub!(DanglingIntPointer(i, _)) => - { "a dangling {kind} (address 0x{i:x} is unallocated)" }, + { "a dangling {kind} (address {i:#x} is unallocated)" }, err_ub!(PointerOutOfBounds { .. }) => { "a dangling {kind} (going beyond the bounds of its allocation)" }, // This cannot happen during const-eval (because interning already detects @@ -941,7 +941,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // element that byte belongs to so we can // provide an index. let i = usize::try_from( - access.uninit_offset.bytes() / layout.size.bytes(), + access.uninit.start.bytes() / layout.size.bytes(), ) .unwrap(); self.path.push(PathElem::ArrayElem(i)); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 0c587220cb7..9574661282b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -155,8 +155,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }); if let Ok(Some(ImplSource::UserDefined(data))) = implsrc { - let span = - tcx.sess.source_map().guess_head_span(tcx.def_span(data.impl_def_id)); + let span = tcx.def_span(data.impl_def_id); err.span_note(span, "impl defined here, but it is not `const`"); } } @@ -205,7 +204,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { match self_ty.kind() { FnDef(def_id, ..) => { - let span = tcx.sess.source_map().guess_head_span(tcx.def_span(*def_id)); + let span = tcx.def_span(*def_id); if ccx.tcx.is_const_fn_raw(*def_id) { span_bug!(span, "calling const FnDef errored when it shouldn't"); } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 6298fa7f062..12527a9b2ae 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -856,7 +856,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { literal: ConstantKind::from_const(_const, tcx), })) }; - let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); + let blocks = self.source.basic_blocks.as_mut(); + let local_decls = &mut self.source.local_decls; let loc = candidate.location; let statement = &mut blocks[loc.block].statements[loc.statement_index]; match statement.kind { @@ -865,7 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Rvalue::Ref(ref mut region, borrow_kind, ref mut place), )) => { // Use the underlying local for this (necessarily interior) borrow. - let ty = local_decls.local_decls()[place.local].ty; + let ty = local_decls[place.local].ty; let span = statement.source_info.span; let ref_ty = tcx.mk_ref( diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 7b9c6329d32..56ecc553528 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::{ Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_live_locals; @@ -275,7 +276,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } }; - match parent_ty.ty.kind() { + let kind = match parent_ty.ty.kind() { + &ty::Opaque(def_id, substs) => { + self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind() + } + kind => kind, + }; + + match kind { ty::Tuple(fields) => { let Some(f_ty) = fields.get(f.as_usize()) else { fail_out_of_bounds(self, location); @@ -299,12 +307,39 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; check_equal(self, location, f_ty); } - ty::Generator(_, substs, _) => { - let substs = substs.as_generator(); - let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else { - fail_out_of_bounds(self, location); - return; + &ty::Generator(def_id, substs, _) => { + let f_ty = if let Some(var) = parent_ty.variant_index { + let gen_body = if def_id == self.body.source.def_id() { + self.body + } else { + self.tcx.optimized_mir(def_id) + }; + + let Some(layout) = gen_body.generator_layout() else { + self.fail(location, format!("No generator layout for {:?}", parent_ty)); + return; + }; + + let Some(&local) = layout.variant_fields[var].get(f) else { + fail_out_of_bounds(self, location); + return; + }; + + let Some(&f_ty) = layout.field_tys.get(local) else { + self.fail(location, format!("Out of bounds local {:?} for {:?}", local, parent_ty)); + return; + }; + + f_ty + } else { + let Some(f_ty) = substs.as_generator().prefix_tys().nth(f.index()) else { + fail_out_of_bounds(self, location); + return; + }; + + f_ty }; + check_equal(self, location, f_ty); } _ => { @@ -328,6 +363,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { { self.fail(location, format!("{:?}, has deref at the wrong place", place)); } + + self.super_place(place, cntxt, location); } fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 390a44d3f33..0a2d2b40709 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,6 +10,7 @@ #![feature(array_windows)] #![feature(associated_type_bounds)] #![feature(auto_traits)] +#![feature(cell_leak)] #![feature(control_flow_enum)] #![feature(extend_one)] #![feature(let_else)] diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 4437c0b1b69..cf0940df9e4 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -539,6 +539,33 @@ impl<T> RwLock<T> { pub fn borrow_mut(&self) -> WriteGuard<'_, T> { self.write() } + + #[cfg(not(parallel_compiler))] + #[inline(always)] + pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> { + ReadGuard::clone(rg) + } + + #[cfg(parallel_compiler)] + #[inline(always)] + pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> { + ReadGuard::rwlock(&rg).read() + } + + #[cfg(not(parallel_compiler))] + #[inline(always)] + pub fn leak(&self) -> &T { + ReadGuard::leak(self.read()) + } + + #[cfg(parallel_compiler)] + #[inline(always)] + pub fn leak(&self) -> &T { + let guard = self.read(); + let ret = unsafe { &*(&*guard as *const T) }; + std::mem::forget(guard); + ret + } } // FIXME: Probably a bad idea diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index c15dc024736..0d1d017d874 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,7 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DiagnosticMessage, Level, MultiSpan, SubdiagnosticMessage, Substitution, - SubstitutionPart, SuggestionStyle, + CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan, + SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::stable_map::FxHashMap; use rustc_error_messages::FluentValue; @@ -168,6 +168,14 @@ pub trait AddSubdiagnostic { fn add_to_diagnostic(self, diag: &mut Diagnostic); } +/// Trait implemented by lint types. This should not be implemented manually. Instead, use +/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. +#[rustc_diagnostic_item = "DecorateLint"] +pub trait DecorateLint<'a, G: EmissionGuarantee> { + /// Decorate and emit a lint. + fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>); +} + #[must_use] #[derive(Clone, Debug, Encodable, Decodable)] pub struct Diagnostic { diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 1ad33ef25b7..c3341fd68f4 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -589,3 +589,26 @@ macro_rules! struct_span_err { macro_rules! error_code { ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; } + +/// Wrapper around a `DiagnosticBuilder` for creating lints. +pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>); + +impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> { + /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`. + pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> { + self.0.set_primary_message(msg); + self.0.set_is_lint(); + self.0 + } + + /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`. + pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> { + LintDiagnosticBuilder(err) + } +} + +impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> { + pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> { + LintDiagnosticBuilder(self.0.forget_guarantee()) + } +} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b084e128483..ffe4ecebb2e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -370,10 +370,10 @@ impl fmt::Display for ExplicitBug { impl error::Error for ExplicitBug {} pub use diagnostic::{ - AddSubdiagnostic, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, + AddSubdiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee}; +pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder}; use std::backtrace::Backtrace; /// A handler deals with errors and other compiler output. diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 064ed0cde96..69ad623b7ea 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" doctest = false [dependencies] +rustc_arena = { path = "../rustc_arena" } rustc_target = { path = "../rustc_target" } rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 5d1314ebb48..a6d10f3adae 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -9,7 +9,7 @@ macro_rules! arena_types { // HIR types [] hir_krate: rustc_hir::Crate<'tcx>, [] arm: rustc_hir::Arm<'tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, Span), + [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, rustc_span::Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, [] block: rustc_hir::Block<'tcx>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 384a0f9c225..531d9f14040 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -19,7 +19,7 @@ //! - Example: Examine each expression to look for its type and do some check or other. //! - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to //! `nested_filter::OnlyBodies` (and implement `nested_visit_map`), and use -//! `tcx.hir().deep_visit_all_item_likes(&mut visitor)`. Within your +//! `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your //! `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke //! `intravisit::walk_expr()` to keep walking the subparts). //! - Pro: Visitor methods for any kind of HIR node, not just item-like things. @@ -190,7 +190,7 @@ use nested_filter::NestedFilter; /// (this is why the module is called `intravisit`, to distinguish it /// from the AST's `visit` module, which acts differently). If you /// simply want to visit all items in the crate in some order, you -/// should call `Crate::visit_all_items`. Otherwise, see the comment +/// should call `tcx.hir().visit_all_item_likes_in_crate`. Otherwise, see the comment /// on `visit_nested_item` for details on how to visit nested items. /// /// If you want to ensure that your code handles every variant diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 9f32a7da159..0f9e6fa7b98 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -18,6 +18,8 @@ extern crate rustc_macros; #[macro_use] extern crate rustc_data_structures; +extern crate self as rustc_hir; + mod arena; pub mod def; pub mod def_path_hash_map; @@ -41,3 +43,5 @@ pub use hir_id::*; pub use lang_items::{LangItem, LanguageItems}; pub use stable_hash_impls::HashStableContext; pub use target::{MethodKind, Target}; + +arena_types!(rustc_arena::declare_arena); diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index a89b9eafaa6..93528b4514b 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -75,7 +75,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; visitor.process_attrs(hir::CRATE_HIR_ID); - tcx.hir().deep_visit_all_item_likes(&mut visitor); + tcx.hir().visit_all_item_likes_in_crate(&mut visitor); (visitor.if_this_changed, visitor.then_this_would_need) }; diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 9c325faae80..f59d8d596b9 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -161,19 +161,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { Decodable::decode(&mut work_product_decoder); for swp in work_products { - let mut all_files_exist = true; - let path = in_incr_comp_dir_sess(sess, &swp.work_product.saved_file); - if !path.exists() { - all_files_exist = false; - - if sess.opts.debugging_opts.incremental_info { - eprintln!( - "incremental: could not find file for work \ - product: {}", - path.display() - ); + let all_files_exist = swp.work_product.saved_files.iter().all(|(_, path)| { + let exists = in_incr_comp_dir_sess(sess, path).exists(); + if !exists && sess.opts.debugging_opts.incremental_info { + eprintln!("incremental: could not find file for work product: {path}",); } - } + exists + }); if all_files_exist { debug!("reconcile_work_products: all files for {:?} exist", swp); diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 79836d66011..4059b7cfc8e 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -108,16 +108,17 @@ pub fn save_work_product_index( for (id, wp) in previous_work_products.iter() { if !new_work_products.contains_key(id) { work_product::delete_workproduct_files(sess, wp); - debug_assert!(!in_incr_comp_dir_sess(sess, &wp.saved_file).exists()); + debug_assert!( + !wp.saved_files.iter().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists()) + ); } } // Check that we did not delete one of the current work-products: debug_assert!({ - new_work_products - .iter() - .map(|(_, wp)| in_incr_comp_dir_sess(sess, &wp.saved_file)) - .all(|path| path.exists()) + new_work_products.iter().all(|(_, wp)| { + wp.saved_files.iter().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists()) + }) }); } diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 4789c0f581f..1b184eca964 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -3,6 +3,7 @@ //! [work products]: WorkProduct use crate::persist::fs::*; +use rustc_data_structures::stable_map::FxHashMap; use rustc_fs_util::link_or_copy; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; @@ -13,38 +14,41 @@ use std::path::Path; pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, - path: &Path, + files: &[(&'static str, &Path)], ) -> Option<(WorkProductId, WorkProduct)> { - debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path); + debug!(?cgu_name, ?files); sess.opts.incremental.as_ref()?; - let file_name = format!("{}.o", cgu_name); - let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); - let saved_file = match link_or_copy(path, &path_in_incr_dir) { - Ok(_) => file_name, - Err(err) => { - sess.warn(&format!( - "error copying object file `{}` to incremental directory as `{}`: {}", - path.display(), - path_in_incr_dir.display(), - err - )); - return None; + let mut saved_files = FxHashMap::default(); + for (ext, path) in files { + let file_name = format!("{cgu_name}.{ext}"); + let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); + match link_or_copy(path, &path_in_incr_dir) { + Ok(_) => { + let _ = saved_files.insert(ext.to_string(), file_name); + } + Err(err) => { + sess.warn(&format!( + "error copying object file `{}` to incremental directory as `{}`: {}", + path.display(), + path_in_incr_dir.display(), + err + )); + } } - }; - - let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file }; + } + let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files }; + debug!(?work_product); let work_product_id = WorkProductId::from_cgu_name(cgu_name); Some((work_product_id, work_product)) } /// Removes files for a given work product. pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { - let path = in_incr_comp_dir_sess(sess, &work_product.saved_file); - match std_fs::remove_file(&path) { - Ok(()) => {} - Err(err) => { + for (_, path) in &work_product.saved_files { + let path = in_incr_comp_dir_sess(sess, path); + if let Err(err) = std_fs::remove_file(&path) { sess.warn(&format!( "file-system error deleting outdated file `{}`: {}", path.display(), diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 976874c7cee..5b664e19c18 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1546,6 +1546,16 @@ impl<T: Idx> GrowableBitSet<T> { let (word_index, mask) = word_index_and_mask(elem); self.bit_set.words.get(word_index).map_or(false, |word| (word & mask) != 0) } + + #[inline] + pub fn iter(&self) -> BitIter<'_, T> { + self.bit_set.iter() + } + + #[inline] + pub fn len(&self) -> usize { + self.bit_set.count() + } } impl<T: Idx> From<BitSet<T>> for GrowableBitSet<T> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 665669be2dd..05556f7d0f9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -148,12 +148,10 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, ) -> (String, Span) { - let sm = tcx.sess.source_map(); - let scope = region.free_region_binding_scope(tcx).expect_local(); match *region { ty::ReEarlyBound(ref br) => { - let mut sp = sm.guess_head_span(tcx.def_span(scope)); + let mut sp = tcx.def_span(scope); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -174,7 +172,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( } else { match fr.bound_region { ty::BoundRegionKind::BrNamed(_, name) => { - let mut sp = sm.guess_head_span(tcx.def_span(scope)); + let mut sp = tcx.def_span(scope); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) { @@ -193,7 +191,7 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( ), _ => ( format!("the lifetime `{}` as defined here", region), - sm.guess_head_span(tcx.def_span(scope)), + tcx.def_span(scope), ), } } diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 4eafa3329c3..7e42458fda3 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -23,10 +23,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); - if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let span = self.tcx.sess.source_map().guess_head_span(trait_item_span); + if trait_item_def_id.is_local() { let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label(span, format!("definition of `{}` from trait", item_name)); + err.span_label( + self.tcx.def_span(trait_item_def_id), + format!("definition of `{}` from trait", item_name), + ); } err.span_label(sp, format!("impl has extra requirement {}", requirement)); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5b263aded9c..b7d1d6edfaa 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -14,7 +14,6 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; -use rustc_hir::Crate; use rustc_lint::{EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_metadata::{encode_metadata, EncodedMetadata}; @@ -482,37 +481,6 @@ pub fn configure_and_expand( Ok(krate) } -fn lower_to_hir<'tcx>( - sess: &Session, - definitions: &mut Definitions, - cstore: &CrateStoreDyn, - resolutions: &ty::ResolverOutputs, - resolver: ty::ResolverAstLowering, - krate: Rc<ast::Crate>, - arena: &'tcx rustc_ast_lowering::Arena<'tcx>, -) -> &'tcx Crate<'tcx> { - // Lower AST to HIR. - let hir_crate = rustc_ast_lowering::lower_crate( - sess, - &krate, - definitions, - cstore, - resolutions, - resolver, - arena, - ); - - // Drop AST to free memory - sess.time("drop_ast", || std::mem::drop(krate)); - - // Discard hygiene data, which isn't required after lowering to HIR. - if !sess.opts.debugging_opts.keep_hygiene_data { - rustc_span::hygiene::clear_syntax_context_map(); - } - - hir_crate -} - // Returns all the paths that correspond to generated files. fn generated_output_paths( sess: &Session, @@ -777,6 +745,7 @@ pub fn prepare_outputs( pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; + providers.hir_crate = rustc_ast_lowering::lower_to_hir; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -823,7 +792,7 @@ impl<'tcx> QueryContext<'tcx> { pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc<LintStore>, - krate: Rc<ast::Crate>, + krate: Lrc<ast::Crate>, dep_graph: DepGraph, resolver: Rc<RefCell<BoxedResolver>>, outputs: OutputFilenames, @@ -831,29 +800,17 @@ pub fn create_global_ctxt<'tcx>( queries: &'tcx OnceCell<TcxQueries<'tcx>>, global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>, - hir_arena: &'tcx WorkerLocal<rustc_ast_lowering::Arena<'tcx>>, + hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>, ) -> QueryContext<'tcx> { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to // incr. comp. yet. dep_graph.assert_ignored(); - let (mut definitions, cstore, resolver_outputs, resolver_for_lowering) = + let (definitions, cstore, resolver_outputs, resolver_for_lowering) = BoxedResolver::to_resolver_outputs(resolver); let sess = &compiler.session(); - - // Lower AST to HIR. - let krate = lower_to_hir( - sess, - &mut definitions, - &*cstore, - &resolver_outputs, - resolver_for_lowering, - krate, - hir_arena, - ); - let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); let codegen_backend = compiler.codegen_backend(); @@ -877,9 +834,11 @@ pub fn create_global_ctxt<'tcx>( sess, lint_store, arena, + hir_arena, definitions, cstore, resolver_outputs, + resolver_for_lowering, krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 136f0443fa0..8ffb1ad0539 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -72,13 +72,13 @@ pub struct Queries<'tcx> { queries: OnceCell<TcxQueries<'tcx>>, arena: WorkerLocal<Arena<'tcx>>, - hir_arena: WorkerLocal<rustc_ast_lowering::Arena<'tcx>>, + hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>, dep_graph_future: Query<Option<DepGraphFuture>>, parse: Query<ast::Crate>, crate_name: Query<String>, register_plugins: Query<(ast::Crate, Lrc<LintStore>)>, - expansion: Query<(Rc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>, + expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>, dep_graph: Query<DepGraph>, prepare_outputs: Query<OutputFilenames>, global_ctxt: Query<QueryContext<'tcx>>, @@ -92,7 +92,7 @@ impl<'tcx> Queries<'tcx> { gcx: OnceCell::new(), queries: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), - hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()), + hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -164,7 +164,7 @@ impl<'tcx> Queries<'tcx> { pub fn expansion( &self, - ) -> Result<&Query<(Rc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> { + ) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> { tracing::trace!("expansion"); self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); @@ -180,7 +180,7 @@ impl<'tcx> Queries<'tcx> { let krate = resolver.access(|resolver| { passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) })?; - Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) + Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) } diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index fab60b6f609..7c0f2c440d5 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -22,3 +22,4 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_parse_format = { path = "../rustc_parse_format" } rustc_infer = { path = "../rustc_infer" } rustc_type_ir = { path = "../rustc_type_ir" } +rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 53e3e1a198e..a0472f98d72 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -32,7 +32,8 @@ use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, MultiSpan, + fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, + LintDiagnosticBuilder, MultiSpan, }; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; @@ -40,7 +41,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind, PredicateOrigin}; use rustc_index::vec::Idx; -use rustc_middle::lint::{in_external_macro, LintDiagnosticBuilder}; +use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; @@ -551,7 +552,6 @@ impl MissingDoc { &self, cx: &LateContext<'_>, def_id: LocalDefId, - sp: Span, article: &'static str, desc: &'static str, ) { @@ -578,16 +578,12 @@ impl MissingDoc { let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id)); let has_doc = attrs.iter().any(has_doc); if !has_doc { - cx.struct_span_lint( - MISSING_DOCS, - cx.tcx.sess.source_map().guess_head_span(sp), - |lint| { - lint.build(fluent::lint::builtin_missing_doc) - .set_arg("article", article) - .set_arg("desc", desc) - .emit(); - }, - ); + cx.struct_span_lint(MISSING_DOCS, cx.tcx.def_span(def_id), |lint| { + lint.build(fluent::lint::builtin_missing_doc) + .set_arg("article", article) + .set_arg("desc", desc) + .emit(); + }); } } } @@ -610,13 +606,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'_>) { - self.check_missing_docs_attrs( - cx, - CRATE_DEF_ID, - cx.tcx.def_span(CRATE_DEF_ID), - "the", - "crate", - ); + self.check_missing_docs_attrs(cx, CRATE_DEF_ID, "the", "crate"); } fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { @@ -646,13 +636,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, it.def_id, it.span, article, desc); + self.check_missing_docs_attrs(cx, it.def_id, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, trait_item.def_id, trait_item.span, article, desc); + self.check_missing_docs_attrs(cx, trait_item.def_id, article, desc); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { @@ -680,23 +670,23 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, impl_item.def_id, impl_item.span, article, desc); + self.check_missing_docs_attrs(cx, impl_item.def_id, article, desc); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, foreign_item.def_id, foreign_item.span, article, desc); + self.check_missing_docs_attrs(cx, foreign_item.def_id, article, desc); } fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) { if !sf.is_positional() { let def_id = cx.tcx.hir().local_def_id(sf.hir_id); - self.check_missing_docs_attrs(cx, def_id, sf.span, "a", "struct field") + self.check_missing_docs_attrs(cx, def_id, "a", "struct field") } } fn check_variant(&mut self, cx: &LateContext<'_>, v: &hir::Variant<'_>) { - self.check_missing_docs_attrs(cx, cx.tcx.hir().local_def_id(v.id), v.span, "a", "variant"); + self.check_missing_docs_attrs(cx, cx.tcx.hir().local_def_id(v.id), "a", "variant"); } } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index eeb66f2d738..5725c240320 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -22,18 +22,19 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err}; -use rustc_errors::{Applicability, MultiSpan, SuggestionStyle}; +use rustc_errors::{ + Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle, +}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt}; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::Session; use rustc_span::lev_distance::find_best_match_for_name; @@ -871,6 +872,17 @@ pub trait LintContext: Sized { decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>), ); + /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, + /// typically generated by `#[derive(LintDiagnostic)]`). + fn emit_spanned_lint<S: Into<MultiSpan>>( + &self, + lint: &'static Lint, + span: S, + decorator: impl for<'a> DecorateLint<'a, ()>, + ) { + self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag)); + } + fn struct_span_lint<S: Into<MultiSpan>>( &self, lint: &'static Lint, @@ -879,6 +891,13 @@ pub trait LintContext: Sized { ) { self.lookup(lint, Some(span), decorate); } + + /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically + /// generated by `#[derive(LintDiagnostic)]`). + fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) { + self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag)); + } + /// Emit a lint at the appropriate level, with no associated span. fn lint( &self, @@ -887,6 +906,29 @@ pub trait LintContext: Sized { ) { self.lookup(lint, None as Option<Span>, decorate); } + + /// This returns the lint level for the given lint at the current location. + fn get_lint_level(&self, lint: &'static Lint) -> Level; + + /// This function can be used to manually fulfill an expectation. This can + /// be used for lints which contain several spans, and should be suppressed, + /// if either location was marked with an expectation. + /// + /// Note that this function should only be called for [`LintExpectationId`]s + /// retrieved from the current lint pass. Buffered or manually created ids can + /// cause ICEs. + fn fulfill_expectation(&self, expectation: LintExpectationId) { + // We need to make sure that submitted expectation ids are correctly fulfilled suppressed + // and stored between compilation sessions. To not manually do these steps, we simply create + // a dummy diagnostic and emit is as usual, which will be suppressed and stored like a normal + // expected lint diagnostic. + self.sess() + .struct_expect( + "this is a dummy diagnostic, to submit and store an expectation", + expectation, + ) + .emit(); + } } impl<'a> EarlyContext<'a> { @@ -934,6 +976,10 @@ impl LintContext for LateContext<'_> { None => self.tcx.struct_lint_node(lint, hir_id, decorate), } } + + fn get_lint_level(&self, lint: &'static Lint) -> Level { + self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).0 + } } impl LintContext for EarlyContext<'_> { @@ -956,6 +1002,10 @@ impl LintContext for EarlyContext<'_> { ) { self.builder.struct_lint(lint, span.map(|s| s.into()), decorate) } + + fn get_lint_level(&self, lint: &'static Lint) -> Level { + self.builder.lint_level(lint).0 + } } impl<'tcx> LateContext<'tcx> { diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 5bcf9390c07..738f475983e 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -414,7 +414,7 @@ impl LateLintPass<'_> for Diagnostics { let Impl { of_trait: Some(of_trait), .. } = impl_ && let Some(def_id) = of_trait.trait_def_id() && let Some(name) = cx.tcx.get_diagnostic_name(def_id) && - matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic) + matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic | sym::DecorateLint) { found_impl = true; break; diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index c1d8d76c975..27f67207209 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -34,7 +34,7 @@ use tracing::debug; /// Extract the `LintStore` from the query context. /// This function exists because we've erased `LintStore` as `dyn Any` in the context. -pub(crate) fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { +pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { let store: &dyn Any = &*tcx.lint_store; store.downcast_ref().unwrap() } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index bf4a726b061..00e96f20d1a 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -3,13 +3,13 @@ use crate::late::unerased_lint_store; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ - struct_lint_level, LevelAndSource, LintDiagnosticBuilder, LintExpectation, LintLevelMap, - LintLevelSets, LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE, + struct_lint_level, LevelAndSource, LintExpectation, LintLevelMap, LintLevelSets, + LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c1255ae5056..aaee0caa070 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -99,7 +99,7 @@ pub use builtin::SoftLints; pub use context::{CheckLintNameResult, FindLintError, LintStore}; pub use context::{EarlyContext, LateContext, LintContext}; pub use early::{check_ast_node, EarlyCheckNode}; -pub use late::check_crate; +pub use late::{check_crate, unerased_lint_store}; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId}; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7f6ef910453..be4843c7ff1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{fluent, Applicability, DiagnosticMessage}; use rustc_hir as hir; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; +use rustc_macros::LintDiagnostic; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; @@ -1553,13 +1554,20 @@ impl InvalidAtomicOrdering { let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return }; if matches!(fail_ordering, sym::Release | sym::AcqRel) { - cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg.span, |diag| { - diag.build(fluent::lint::atomic_ordering_invalid) - .set_arg("method", method) - .span_label(fail_order_arg.span, fluent::lint::label) - .help(fluent::lint::help) - .emit(); - }); + #[derive(LintDiagnostic)] + #[lint(lint::atomic_ordering_invalid)] + #[help] + struct InvalidAtomicOrderingDiag { + method: Symbol, + #[label] + fail_order_arg_span: Span, + } + + cx.emit_spanned_lint( + INVALID_ATOMIC_ORDERING, + fail_order_arg.span, + InvalidAtomicOrderingDiag { method, fail_order_arg_span: fail_order_arg.span }, + ); } let Some(success_ordering) = Self::match_ordering(cx, success_order_arg) else { return }; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 40601bb5aad..9fc2249b290 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -520,6 +520,11 @@ declare_lint! { /// The `expect` attribute can be removed if this is intended behavior otherwise /// it should be investigated why the expected lint is no longer issued. /// + /// In rare cases, the expectation might be emitted at a different location than + /// shown in the shown code snippet. In most cases, the `#[expect]` attribute + /// works when added to the outer scope. A few lints can only be expected + /// on a crate level. + /// /// Part of RFC 2383. The progress is being tracked in [#54503] /// /// [#54503]: https://github.com/rust-lang/rust/issues/54503 diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 1cd19c7eaab..48f441e69d6 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -232,6 +232,13 @@ impl Level { Level::Deny | Level::Forbid => true, } } + + pub fn get_expectation_id(&self) -> Option<LintExpectationId> { + match self { + Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id), + _ => None, + } + } } /// Specification of a single lint. diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index d0c86527189..027f377b0ac 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -1,125 +1,54 @@ #![deny(unused_must_use)] -use crate::diagnostics::error::{ - invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - SessionDiagnosticDeriveError, -}; -use crate::diagnostics::utils::{ - report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, - Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, -}; -use proc_macro2::{Ident, TokenStream}; -use quote::{format_ident, quote}; -use std::collections::HashMap; -use std::str::FromStr; -use syn::{ - parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, -}; -use synstructure::{BindingInfo, Structure}; +use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; +use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; +use crate::diagnostics::utils::{build_field_mapping, SetOnce}; +use proc_macro2::TokenStream; +use quote::quote; +use syn::spanned::Spanned; +use synstructure::Structure; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. pub(crate) struct SessionDiagnosticDerive<'a> { structure: Structure<'a>, - builder: SessionDiagnosticDeriveBuilder, + sess: syn::Ident, + builder: DiagnosticDeriveBuilder, } impl<'a> SessionDiagnosticDerive<'a> { pub(crate) fn new(diag: syn::Ident, sess: syn::Ident, structure: Structure<'a>) -> Self { - // Build the mapping of field names to fields. This allows attributes to peek values from - // other fields. - let mut fields_map = HashMap::new(); - - // Convenience bindings. - let ast = structure.ast(); - - if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data { - for field in fields.iter() { - if let Some(ident) = &field.ident { - fields_map.insert(ident.to_string(), quote! { &self.#ident }); - } - } - } - Self { - builder: SessionDiagnosticDeriveBuilder { + builder: DiagnosticDeriveBuilder { diag, - sess, - fields: fields_map, + fields: build_field_mapping(&structure), kind: None, code: None, slug: None, }, + sess, structure, } } pub(crate) fn into_tokens(self) -> TokenStream { - let SessionDiagnosticDerive { mut structure, mut builder } = self; + let SessionDiagnosticDerive { mut structure, sess, mut builder } = self; let ast = structure.ast(); - let attrs = &ast.attrs; - let (implementation, param_ty) = { if let syn::Data::Struct(..) = ast.data { - let preamble = { - let preamble = attrs.iter().map(|attr| { - builder - .generate_structure_code(attr) - .unwrap_or_else(|v| v.to_compile_error()) - }); - - quote! { - #(#preamble)*; - } - }; - - // Keep track of which fields are subdiagnostics or have no attributes. - let mut subdiagnostics_or_empty = std::collections::HashSet::new(); - - // Generates calls to `span_label` and similar functions based on the attributes - // on fields. Code for suggestions uses formatting machinery and the value of - // other fields - because any given field can be referenced multiple times, it - // should be accessed through a borrow. When passing fields to `add_subdiagnostic` - // or `set_arg` (which happens below) for Fluent, we want to move the data, so that - // has to happen in a separate pass over the fields. - let attrs = structure - .clone() - .filter(|field_binding| { - let attrs = &field_binding.ast().attrs; - - (!attrs.is_empty() - && attrs.iter().all(|attr| { - "subdiagnostic" - != attr.path.segments.last().unwrap().ident.to_string() - })) - || { - subdiagnostics_or_empty.insert(field_binding.binding.clone()); - false - } - }) - .each(|field_binding| builder.generate_field_attrs_code(field_binding)); - - structure.bind_with(|_| synstructure::BindStyle::Move); - // When a field has attributes like `#[label]` or `#[note]` then it doesn't - // need to be passed as an argument to the diagnostic. But when a field has no - // attributes or a `#[subdiagnostic]` attribute then it must be passed as an - // argument to the diagnostic so that it can be referred to by Fluent messages. - let args = structure - .filter(|field_binding| { - subdiagnostics_or_empty.contains(&field_binding.binding) - }) - .each(|field_binding| builder.generate_field_attrs_code(field_binding)); + let preamble = builder.preamble(&structure); + let (attrs, args) = builder.body(&mut structure); let span = ast.span().unwrap(); - let (diag, sess) = (&builder.diag, &builder.sess); - let init = match (builder.kind, builder.slug) { + let diag = &builder.diag; + let init = match (builder.kind.value(), builder.slug.value()) { (None, _) => { span_err(span, "diagnostic kind not specified") .help("use the `#[error(...)]` attribute to create an error") .emit(); - return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } - (Some((kind, _)), None) => { + (Some(kind), None) => { span_err(span, "diagnostic slug not specified") .help(&format!( "specify the slug as the first argument to the attribute, such as \ @@ -127,14 +56,20 @@ impl<'a> SessionDiagnosticDerive<'a> { kind.descr() )) .emit(); - return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } - (Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => { + (Some(DiagnosticDeriveKind::Lint), _) => { + span_err(span, "only `#[error(..)]` and `#[warn(..)]` are supported") + .help("use the `#[error(...)]` attribute to create a error") + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some(DiagnosticDeriveKind::Error), Some(slug)) => { quote! { let mut #diag = #sess.struct_err(rustc_errors::fluent::#slug); } } - (Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => { + (Some(DiagnosticDeriveKind::Warn), Some(slug)) => { quote! { let mut #diag = #sess.struct_warn(rustc_errors::fluent::#slug); } @@ -153,10 +88,12 @@ impl<'a> SessionDiagnosticDerive<'a> { #diag }; let param_ty = match builder.kind { - Some((SessionDiagnosticKind::Error, _)) => { + Some((DiagnosticDeriveKind::Error, _)) => { quote! { rustc_errors::ErrorGuaranteed } } - Some((SessionDiagnosticKind::Warn, _)) => quote! { () }, + Some((DiagnosticDeriveKind::Lint | DiagnosticDeriveKind::Warn, _)) => { + quote! { () } + } _ => unreachable!(), }; @@ -168,13 +105,12 @@ impl<'a> SessionDiagnosticDerive<'a> { ) .emit(); - let implementation = SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + let implementation = DiagnosticDeriveError::ErrorHandled.to_compile_error(); let param_ty = quote! { rustc_errors::ErrorGuaranteed }; (implementation, param_ty) } }; - let sess = &builder.sess; structure.gen_impl(quote! { gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess, #param_ty> for @Self @@ -191,525 +127,99 @@ impl<'a> SessionDiagnosticDerive<'a> { } } -/// What kind of session diagnostic is being derived - an error or a warning? -#[derive(Copy, Clone)] -enum SessionDiagnosticKind { - /// `#[error(..)]` - Error, - /// `#[warn(..)]` - Warn, +/// The central struct for constructing the `decorate_lint` method from an annotated struct. +pub(crate) struct LintDiagnosticDerive<'a> { + structure: Structure<'a>, + builder: DiagnosticDeriveBuilder, } -impl SessionDiagnosticKind { - /// Returns human-readable string corresponding to the kind. - fn descr(&self) -> &'static str { - match self { - SessionDiagnosticKind::Error => "error", - SessionDiagnosticKind::Warn => "warning", +impl<'a> LintDiagnosticDerive<'a> { + pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self { + Self { + builder: DiagnosticDeriveBuilder { + diag, + fields: build_field_mapping(&structure), + kind: None, + code: None, + slug: None, + }, + structure, } } -} - -/// Tracks persistent information required for building up the individual calls to diagnostic -/// methods for the final generated method. This is a separate struct to `SessionDiagnosticDerive` -/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a -/// double mut borrow later on. -struct SessionDiagnosticDeriveBuilder { - /// Name of the session parameter that's passed in to the `as_error` method. - sess: syn::Ident, - /// The identifier to use for the generated `DiagnosticBuilder` instance. - diag: syn::Ident, - - /// Store a map of field name to its corresponding field. This is built on construction of the - /// derive builder. - fields: HashMap<String, TokenStream>, - - /// Kind of diagnostic requested via the struct attribute. - kind: Option<(SessionDiagnosticKind, proc_macro::Span)>, - /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that - /// has the actual diagnostic message. - slug: Option<(Path, proc_macro::Span)>, - /// Error codes are a optional part of the struct attribute - this is only set to detect - /// multiple specifications. - code: Option<(String, proc_macro::Span)>, -} - -impl HasFieldMap for SessionDiagnosticDeriveBuilder { - fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.fields.get(field) - } -} - -impl SessionDiagnosticDeriveBuilder { - /// Establishes state in the `SessionDiagnosticDeriveBuilder` resulting from the struct - /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates - /// diagnostic builder calls for setting error code and creating note/help messages. - fn generate_structure_code( - &mut self, - attr: &Attribute, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let diag = &self.diag; - let span = attr.span().unwrap(); - - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - let meta = attr.parse_meta()?; - - let is_help_or_note = matches!(name, "help" | "note"); - - let nested = match meta { - // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or - // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. - Meta::List(MetaList { ref nested, .. }) => nested, - // Subdiagnostics without spans can be applied to the type too, and these are just - // paths: `#[help]` and `#[note]` - Meta::Path(_) if is_help_or_note => { - let fn_name = proc_macro2::Ident::new(name, attr.span()); - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); - } - _ => throw_invalid_attr!(attr, &meta), - }; - - // Check the kind before doing any further processing so that there aren't misleading - // "no kind specified" errors if there are failures later. - match name { - "error" => self.kind.set_once((SessionDiagnosticKind::Error, span)), - "warning" => self.kind.set_once((SessionDiagnosticKind::Warn, span)), - "help" | "note" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `error`, `warning`, `help` and `note` are valid attributes") - }), - } - // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or - // `#[help(typeck::another_help)]`. - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - // Report an error if there are any other list items after the path. - if is_help_or_note && nested_iter.next().is_some() { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("`help` and `note` struct attributes can only have one argument") - }); - } - - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) if is_help_or_note => { - let fn_name = proc_macro2::Ident::new(name, attr.span()); - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); - } - NestedMeta::Meta(Meta::Path(path)) => { - self.slug.set_once((path.clone(), span)); - } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if !is_help_or_note - && meta.path().segments.last().unwrap().ident.to_string() == "code" => - { - // don't error for valid follow-up attributes - } - nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("first argument of the attribute should be the diagnostic slug") - }), - }; - } + pub(crate) fn into_tokens(self) -> TokenStream { + let LintDiagnosticDerive { mut structure, mut builder } = self; - // Remaining attributes are optional, only `code = ".."` at the moment. - let mut tokens = Vec::new(); - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(meta) => meta, - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; + let ast = structure.ast(); + let implementation = { + if let syn::Data::Struct(..) = ast.data { + let preamble = builder.preamble(&structure); + let (attrs, args) = builder.body(&mut structure); - let path = meta.path(); - let nested_name = path.segments.last().unwrap().ident.to_string(); - // Struct attributes are only allowed to be applied once, and the diagnostic - // changes will be set in the initialisation code. - if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { - let span = s.span().unwrap(); - match nested_name.as_str() { - "code" => { - self.code.set_once((s.value(), span)); - let code = &self.code.as_ref().map(|(v, _)| v); - tokens.push(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); - }); + let diag = &builder.diag; + let span = ast.span().unwrap(); + let init = match (builder.kind.value(), builder.slug.value()) { + (None, _) => { + span_err(span, "diagnostic kind not specified") + .help("use the `#[error(...)]` attribute to create an error") + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } - _ => invalid_nested_attr(attr, &nested_attr) - .help("only `code` is a valid nested attributes following the slug") - .emit(), - } - } else { - invalid_nested_attr(attr, &nested_attr).emit() - } - } - - Ok(tokens.drain(..).collect()) - } - - fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { - let field = binding_info.ast(); - let field_binding = &binding_info.binding; - - let inner_ty = FieldInnerTy::from_type(&field.ty); - - // When generating `set_arg` or `add_subdiagnostic` calls, move data rather than - // borrow it to avoid requiring clones - this must therefore be the last use of - // each field (for example, any formatting machinery that might refer to a field - // should be generated already). - if field.attrs.is_empty() { - let diag = &self.diag; - let ident = field.ident.as_ref().unwrap(); - quote! { - #diag.set_arg( - stringify!(#ident), - #field_binding - ); - } - } else { - field - .attrs - .iter() - .map(move |attr| { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let (binding, needs_destructure) = match (name.as_str(), &inner_ty) { - // `primary_span` can accept a `Vec<Span>` so don't destructure that. - ("primary_span", FieldInnerTy::Vec(_)) => { - (quote! { #field_binding.clone() }, false) + (Some(kind), None) => { + span_err(span, "diagnostic slug not specified") + .help(&format!( + "specify the slug as the first argument to the attribute, such as \ + `#[{}(typeck::example_error)]`", + kind.descr() + )) + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some(DiagnosticDeriveKind::Error | DiagnosticDeriveKind::Warn), _) => { + span_err(span, "only `#[lint(..)]` is supported") + .help("use the `#[lint(...)]` attribute to create a lint") + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some(DiagnosticDeriveKind::Lint), Some(slug)) => { + quote! { + let mut #diag = #diag.build(rustc_errors::fluent::#slug); } - // `subdiagnostics` are not derefed because they are bound by value. - ("subdiagnostic", _) => (quote! { #field_binding }, true), - _ => (quote! { *#field_binding }, true), - }; - - let generated_code = self - .generate_inner_field_code( - attr, - FieldInfo { - binding: binding_info, - ty: inner_ty.inner_type().unwrap_or(&field.ty), - span: &field.span(), - }, - binding, - ) - .unwrap_or_else(|v| v.to_compile_error()); - - if needs_destructure { - inner_ty.with(field_binding, generated_code) - } else { - generated_code } - }) - .collect() - } - } - - fn generate_inner_field_code( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let meta = attr.parse_meta()?; - match meta { - Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), - Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), - _ => throw_invalid_attr!(attr, &meta), - } - } - - fn generate_inner_field_code_path( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - assert!(matches!(attr.parse_meta()?, Meta::Path(_))); - let diag = &self.diag; - - let meta = attr.parse_meta()?; - - let ident = &attr.path.segments.last().unwrap().ident; - let name = ident.to_string(); - let name = name.as_str(); - match name { - "skip_arg" => { - // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. - Ok(quote! {}) - } - "primary_span" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(quote! { - #diag.set_span(#binding); - }) - } - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) - } - "note" | "help" => { - let path = match name { - "note" => parse_quote! { _subdiag::note }, - "help" => parse_quote! { _subdiag::help }, - _ => unreachable!(), }; - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - Ok(self.add_spanned_subdiagnostic(binding, ident, path)) - } else if type_is_unit(&info.ty) { - Ok(self.add_subdiagnostic(ident, path)) - } else { - report_type_error(attr, "`Span` or `()`")?; - } - } - "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ - are valid field attributes", - ) - }), - } - } - - fn generate_inner_field_code_list( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; - - let ident = &attr.path.segments.last().unwrap().ident; - let name = path.segments.last().unwrap().ident.to_string(); - let name = name.as_ref(); - match name { - "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { - return self.generate_inner_field_code_suggestion(attr, info); - } - "label" | "help" | "note" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `label`, `note`, `help` or `suggestion{,_short,_hidden,_verbose}` are \ - valid field attributes", - ) - }), - } - // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a - // path, e.g. `#[label(typeck::label)]`. - let mut nested_iter = nested.into_iter(); - let msg = match nested_iter.next() { - Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), - Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), - None => throw_invalid_attr!(attr, &meta), - }; - - // None of these attributes should have anything following the slug. - if nested_iter.next().is_some() { - throw_invalid_attr!(attr, &meta); - } - - match name { - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), - "note" | "help" => { - report_type_error(attr, "`Span` or `()`")?; - } - _ => unreachable!(), - } - } - - fn generate_inner_field_code_suggestion( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let diag = &self.diag; - - let mut meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; - - let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; - - let mut msg = None; - let mut code = None; - - let mut nested_iter = nested.into_iter().peekable(); - if let Some(nested_attr) = nested_iter.peek() { - if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { - msg = Some(path.clone()); - } - }; - // Move the iterator forward if a path was found (don't otherwise so that - // code/applicability can be found or an error emitted). - if msg.is_some() { - let _ = nested_iter.next(); - } - - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, - syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let span = meta.span().unwrap(); - match nested_name { - "code" => { - let formatted_str = self.build_format(&s.value(), s.span()); - code = Some(formatted_str); - } - "applicability" => { - applicability = match applicability { - Some(v) => { - span_err( - span, - "applicability cannot be set in both the field and \ - attribute", - ) - .emit(); - Some(v) - } - None => match Applicability::from_str(&s.value()) { - Ok(v) => Some(quote! { #v }), - Err(()) => { - span_err(span, "invalid applicability").emit(); - None - } - }, - } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "only `message`, `code` and `applicability` are valid field \ - attributes", - ) - }), + let implementation = quote! { + #init + #preamble + match self { + #attrs } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - if matches!(meta, Meta::Path(_)) { - diag.help("a diagnostic slug must be the first argument to the attribute") - } else { - diag + match self { + #args } - }), - } - } - - let applicability = - applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - - let name = path.segments.last().unwrap().ident.to_string(); - let method = format_ident!("span_{}", name); - - let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); - let msg = quote! { rustc_errors::fluent::#msg }; - let code = code.unwrap_or_else(|| quote! { String::new() }); - - Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) - } - - /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug - /// and `fluent_attr_identifier`. - fn add_spanned_subdiagnostic( - &self, - field_binding: TokenStream, - kind: &Ident, - fluent_attr_identifier: Path, - ) -> TokenStream { - let diag = &self.diag; - let fn_name = format_ident!("span_{}", kind); - quote! { - #diag.#fn_name( - #field_binding, - rustc_errors::fluent::#fluent_attr_identifier - ); - } - } + #diag.emit(); + }; - /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug - /// and `fluent_attr_identifier`. - fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { - let diag = &self.diag; - quote! { - #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier); - } - } + implementation + } else { + span_err( + ast.span().unwrap(), + "`#[derive(LintDiagnostic)]` can only be used on structs", + ) + .emit(); - fn span_and_applicability_of_ty( - &self, - info: FieldInfo<'_>, - ) -> Result<(TokenStream, Option<TokenStream>), SessionDiagnosticDeriveError> { - match &info.ty { - // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. - ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { - let binding = &info.binding.binding; - Ok((quote!(*#binding), None)) + DiagnosticDeriveError::ErrorHandled.to_compile_error() } - // If `ty` is `(Span, Applicability)` then return tokens accessing those. - Type::Tuple(tup) => { - let mut span_idx = None; - let mut applicability_idx = None; - - for (idx, elem) in tup.elems.iter().enumerate() { - if type_matches_path(elem, &["rustc_span", "Span"]) { - if span_idx.is_none() { - span_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one `Span`" - ); - } - } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { - if applicability_idx.is_none() { - applicability_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one Applicability" - ); - } - } - } - - if let Some(span_idx) = span_idx { - let binding = &info.binding.binding; - let span = quote!(#binding.#span_idx); - let applicability = applicability_idx - .map(|applicability_idx| quote!(#binding.#applicability_idx)) - .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + }; - return Ok((span, Some(applicability))); + let diag = &builder.diag; + structure.gen_impl(quote! { + gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self { + fn decorate_lint(self, #diag: rustc_errors::LintDiagnosticBuilder<'__a, ()>) { + use rustc_errors::IntoDiagnosticArg; + #implementation } - - throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { - diag.help( - "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ - `(Span, Applicability)`", - ) - }); } - // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. - _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { - diag.help( - "`#[suggestion(...)]` should be applied to fields of type `Span` or \ - `(Span, Applicability)`", - ) - }), - } + }) } } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs new file mode 100644 index 00000000000..74ce1ab08c2 --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -0,0 +1,590 @@ +#![deny(unused_must_use)] + +use crate::diagnostics::error::{ + invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, + DiagnosticDeriveError, +}; +use crate::diagnostics::utils::{ + report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, + Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, +}; +use proc_macro2::{Ident, TokenStream}; +use quote::{format_ident, quote}; +use std::collections::HashMap; +use std::str::FromStr; +use syn::{ + parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, +}; +use synstructure::{BindingInfo, Structure}; + +/// What kind of diagnostic is being derived - an error, a warning or a lint? +#[derive(Copy, Clone)] +pub(crate) enum DiagnosticDeriveKind { + /// `#[error(..)]` + Error, + /// `#[warn(..)]` + Warn, + /// `#[lint(..)]` + Lint, +} + +impl DiagnosticDeriveKind { + /// Returns human-readable string corresponding to the kind. + pub fn descr(&self) -> &'static str { + match self { + DiagnosticDeriveKind::Error => "error", + DiagnosticDeriveKind::Warn => "warning", + DiagnosticDeriveKind::Lint => "lint", + } + } +} + +/// Tracks persistent information required for building up individual calls to diagnostic methods +/// for generated diagnostic derives - both `SessionDiagnostic` for errors/warnings and +/// `LintDiagnostic` for lints. +pub(crate) struct DiagnosticDeriveBuilder { + /// The identifier to use for the generated `DiagnosticBuilder` instance. + pub diag: syn::Ident, + + /// Store a map of field name to its corresponding field. This is built on construction of the + /// derive builder. + pub fields: HashMap<String, TokenStream>, + + /// Kind of diagnostic requested via the struct attribute. + pub kind: Option<(DiagnosticDeriveKind, proc_macro::Span)>, + /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that + /// has the actual diagnostic message. + pub slug: Option<(Path, proc_macro::Span)>, + /// Error codes are a optional part of the struct attribute - this is only set to detect + /// multiple specifications. + pub code: Option<(String, proc_macro::Span)>, +} + +impl HasFieldMap for DiagnosticDeriveBuilder { + fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { + self.fields.get(field) + } +} + +impl DiagnosticDeriveBuilder { + pub fn preamble<'s>(&mut self, structure: &Structure<'s>) -> TokenStream { + let ast = structure.ast(); + let attrs = &ast.attrs; + let preamble = attrs.iter().map(|attr| { + self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error()) + }); + + quote! { + #(#preamble)*; + } + } + + pub fn body<'s>(&mut self, structure: &mut Structure<'s>) -> (TokenStream, TokenStream) { + // Keep track of which fields are subdiagnostics or have no attributes. + let mut subdiagnostics_or_empty = std::collections::HashSet::new(); + + // Generates calls to `span_label` and similar functions based on the attributes + // on fields. Code for suggestions uses formatting machinery and the value of + // other fields - because any given field can be referenced multiple times, it + // should be accessed through a borrow. When passing fields to `add_subdiagnostic` + // or `set_arg` (which happens below) for Fluent, we want to move the data, so that + // has to happen in a separate pass over the fields. + let attrs = structure + .clone() + .filter(|field_binding| { + let attrs = &field_binding.ast().attrs; + + (!attrs.is_empty() + && attrs.iter().all(|attr| { + "subdiagnostic" != attr.path.segments.last().unwrap().ident.to_string() + })) + || { + subdiagnostics_or_empty.insert(field_binding.binding.clone()); + false + } + }) + .each(|field_binding| self.generate_field_attrs_code(field_binding)); + + structure.bind_with(|_| synstructure::BindStyle::Move); + // When a field has attributes like `#[label]` or `#[note]` then it doesn't + // need to be passed as an argument to the diagnostic. But when a field has no + // attributes or a `#[subdiagnostic]` attribute then it must be passed as an + // argument to the diagnostic so that it can be referred to by Fluent messages. + let args = structure + .filter(|field_binding| subdiagnostics_or_empty.contains(&field_binding.binding)) + .each(|field_binding| self.generate_field_attrs_code(field_binding)); + + (attrs, args) + } + + /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct + /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates + /// diagnostic builder calls for setting error code and creating note/help messages. + fn generate_structure_code_for_attr( + &mut self, + attr: &Attribute, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let diag = &self.diag; + let span = attr.span().unwrap(); + + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); + let meta = attr.parse_meta()?; + + let is_help_or_note = matches!(name, "help" | "note"); + + let nested = match meta { + // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or + // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. + Meta::List(MetaList { ref nested, .. }) => nested, + // Subdiagnostics without spans can be applied to the type too, and these are just + // paths: `#[help]` and `#[note]` + Meta::Path(_) if is_help_or_note => { + let fn_name = proc_macro2::Ident::new(name, attr.span()); + return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); + } + _ => throw_invalid_attr!(attr, &meta), + }; + + // Check the kind before doing any further processing so that there aren't misleading + // "no kind specified" errors if there are failures later. + match name { + "error" => self.kind.set_once((DiagnosticDeriveKind::Error, span)), + "warning" => self.kind.set_once((DiagnosticDeriveKind::Warn, span)), + "lint" => self.kind.set_once((DiagnosticDeriveKind::Lint, span)), + "help" | "note" => (), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help("only `error`, `warning`, `help` and `note` are valid attributes") + }), + } + + // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or + // `#[help(typeck::another_help)]`. + let mut nested_iter = nested.into_iter(); + if let Some(nested_attr) = nested_iter.next() { + // Report an error if there are any other list items after the path. + if is_help_or_note && nested_iter.next().is_some() { + throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("`help` and `note` struct attributes can only have one argument") + }); + } + + match nested_attr { + NestedMeta::Meta(Meta::Path(path)) if is_help_or_note => { + let fn_name = proc_macro2::Ident::new(name, attr.span()); + return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); + } + NestedMeta::Meta(Meta::Path(path)) => { + self.slug.set_once((path.clone(), span)); + } + NestedMeta::Meta(meta @ Meta::NameValue(_)) + if !is_help_or_note + && meta.path().segments.last().unwrap().ident.to_string() == "code" => + { + // don't error for valid follow-up attributes + } + nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("first argument of the attribute should be the diagnostic slug") + }), + }; + } + + // Remaining attributes are optional, only `code = ".."` at the moment. + let mut tokens = Vec::new(); + for nested_attr in nested_iter { + let meta = match nested_attr { + syn::NestedMeta::Meta(meta) => meta, + _ => throw_invalid_nested_attr!(attr, &nested_attr), + }; + + let path = meta.path(); + let nested_name = path.segments.last().unwrap().ident.to_string(); + // Struct attributes are only allowed to be applied once, and the diagnostic + // changes will be set in the initialisation code. + if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { + let span = s.span().unwrap(); + match nested_name.as_str() { + "code" => { + self.code.set_once((s.value(), span)); + let code = &self.code.as_ref().map(|(v, _)| v); + tokens.push(quote! { + #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + }); + } + _ => invalid_nested_attr(attr, &nested_attr) + .help("only `code` is a valid nested attributes following the slug") + .emit(), + } + } else { + invalid_nested_attr(attr, &nested_attr).emit() + } + } + + Ok(tokens.drain(..).collect()) + } + + fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { + let field = binding_info.ast(); + let field_binding = &binding_info.binding; + + let inner_ty = FieldInnerTy::from_type(&field.ty); + + // When generating `set_arg` or `add_subdiagnostic` calls, move data rather than + // borrow it to avoid requiring clones - this must therefore be the last use of + // each field (for example, any formatting machinery that might refer to a field + // should be generated already). + if field.attrs.is_empty() { + let diag = &self.diag; + let ident = field.ident.as_ref().unwrap(); + quote! { + #diag.set_arg( + stringify!(#ident), + #field_binding + ); + } + } else { + field + .attrs + .iter() + .map(move |attr| { + let name = attr.path.segments.last().unwrap().ident.to_string(); + let (binding, needs_destructure) = match (name.as_str(), &inner_ty) { + // `primary_span` can accept a `Vec<Span>` so don't destructure that. + ("primary_span", FieldInnerTy::Vec(_)) => { + (quote! { #field_binding.clone() }, false) + } + // `subdiagnostics` are not derefed because they are bound by value. + ("subdiagnostic", _) => (quote! { #field_binding }, true), + _ => (quote! { *#field_binding }, true), + }; + + let generated_code = self + .generate_inner_field_code( + attr, + FieldInfo { + binding: binding_info, + ty: inner_ty.inner_type().unwrap_or(&field.ty), + span: &field.span(), + }, + binding, + ) + .unwrap_or_else(|v| v.to_compile_error()); + + if needs_destructure { + inner_ty.with(field_binding, generated_code) + } else { + generated_code + } + }) + .collect() + } + } + + fn generate_inner_field_code( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let meta = attr.parse_meta()?; + match meta { + Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), + Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), + _ => throw_invalid_attr!(attr, &meta), + } + } + + fn generate_inner_field_code_path( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result<TokenStream, DiagnosticDeriveError> { + assert!(matches!(attr.parse_meta()?, Meta::Path(_))); + let diag = &self.diag; + + let meta = attr.parse_meta()?; + + let ident = &attr.path.segments.last().unwrap().ident; + let name = ident.to_string(); + let name = name.as_str(); + match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + Ok(quote! {}) + } + "primary_span" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(quote! { + #diag.set_span(#binding); + }) + } + "label" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) + } + "note" | "help" => { + let path = match name { + "note" => parse_quote! { _subdiag::note }, + "help" => parse_quote! { _subdiag::help }, + _ => unreachable!(), + }; + if type_matches_path(&info.ty, &["rustc_span", "Span"]) { + Ok(self.add_spanned_subdiagnostic(binding, ident, path)) + } else if type_is_unit(&info.ty) { + Ok(self.add_subdiagnostic(ident, path)) + } else { + report_type_error(attr, "`Span` or `()`")? + } + } + "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help( + "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ + are valid field attributes", + ) + }), + } + } + + fn generate_inner_field_code_list( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let meta = attr.parse_meta()?; + let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; + + let ident = &attr.path.segments.last().unwrap().ident; + let name = path.segments.last().unwrap().ident.to_string(); + let name = name.as_ref(); + match name { + "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { + return self.generate_inner_field_code_suggestion(attr, info); + } + "label" | "help" | "note" => (), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help( + "only `label`, `note`, `help` or `suggestion{,_short,_hidden,_verbose}` are \ + valid field attributes", + ) + }), + } + + // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a + // path, e.g. `#[label(typeck::label)]`. + let mut nested_iter = nested.into_iter(); + let msg = match nested_iter.next() { + Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), + Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), + None => throw_invalid_attr!(attr, &meta), + }; + + // None of these attributes should have anything following the slug. + if nested_iter.next().is_some() { + throw_invalid_attr!(attr, &meta); + } + + match name { + "label" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) + } + "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { + Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) + } + "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), + "note" | "help" => report_type_error(attr, "`Span` or `()`")?, + _ => unreachable!(), + } + } + + fn generate_inner_field_code_suggestion( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let diag = &self.diag; + + let mut meta = attr.parse_meta()?; + let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; + + let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; + + let mut msg = None; + let mut code = None; + + let mut nested_iter = nested.into_iter().peekable(); + if let Some(nested_attr) = nested_iter.peek() { + if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { + msg = Some(path.clone()); + } + }; + // Move the iterator forward if a path was found (don't otherwise so that + // code/applicability can be found or an error emitted). + if msg.is_some() { + let _ = nested_iter.next(); + } + + for nested_attr in nested_iter { + let meta = match nested_attr { + syn::NestedMeta::Meta(ref meta) => meta, + syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), + }; + + let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + let nested_name = nested_name.as_str(); + match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { + let span = meta.span().unwrap(); + match nested_name { + "code" => { + let formatted_str = self.build_format(&s.value(), s.span()); + code = Some(formatted_str); + } + "applicability" => { + applicability = match applicability { + Some(v) => { + span_err( + span, + "applicability cannot be set in both the field and \ + attribute", + ) + .emit(); + Some(v) + } + None => match Applicability::from_str(&s.value()) { + Ok(v) => Some(quote! { #v }), + Err(()) => { + span_err(span, "invalid applicability").emit(); + None + } + }, + } + } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help( + "only `message`, `code` and `applicability` are valid field \ + attributes", + ) + }), + } + } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + if matches!(meta, Meta::Path(_)) { + diag.help("a diagnostic slug must be the first argument to the attribute") + } else { + diag + } + }), + } + } + + let applicability = + applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + + let name = path.segments.last().unwrap().ident.to_string(); + let method = format_ident!("span_{}", name); + + let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); + let msg = quote! { rustc_errors::fluent::#msg }; + let code = code.unwrap_or_else(|| quote! { String::new() }); + + Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) + } + + /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// and `fluent_attr_identifier`. + fn add_spanned_subdiagnostic( + &self, + field_binding: TokenStream, + kind: &Ident, + fluent_attr_identifier: Path, + ) -> TokenStream { + let diag = &self.diag; + let fn_name = format_ident!("span_{}", kind); + quote! { + #diag.#fn_name( + #field_binding, + rustc_errors::fluent::#fluent_attr_identifier + ); + } + } + + /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// and `fluent_attr_identifier`. + fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { + let diag = &self.diag; + quote! { + #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier); + } + } + + fn span_and_applicability_of_ty( + &self, + info: FieldInfo<'_>, + ) -> Result<(TokenStream, Option<TokenStream>), DiagnosticDeriveError> { + match &info.ty { + // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. + ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { + let binding = &info.binding.binding; + Ok((quote!(*#binding), None)) + } + // If `ty` is `(Span, Applicability)` then return tokens accessing those. + Type::Tuple(tup) => { + let mut span_idx = None; + let mut applicability_idx = None; + + for (idx, elem) in tup.elems.iter().enumerate() { + if type_matches_path(elem, &["rustc_span", "Span"]) { + if span_idx.is_none() { + span_idx = Some(syn::Index::from(idx)); + } else { + throw_span_err!( + info.span.unwrap(), + "type of field annotated with `#[suggestion(...)]` contains more \ + than one `Span`" + ); + } + } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { + if applicability_idx.is_none() { + applicability_idx = Some(syn::Index::from(idx)); + } else { + throw_span_err!( + info.span.unwrap(), + "type of field annotated with `#[suggestion(...)]` contains more \ + than one Applicability" + ); + } + } + } + + if let Some(span_idx) = span_idx { + let binding = &info.binding.binding; + let span = quote!(#binding.#span_idx); + let applicability = applicability_idx + .map(|applicability_idx| quote!(#binding.#applicability_idx)) + .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + + return Ok((span, Some(applicability))); + } + + throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { + diag.help( + "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ + `(Span, Applicability)`", + ) + }); + } + // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. + _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { + diag.help( + "`#[suggestion(...)]` should be applied to fields of type `Span` or \ + `(Span, Applicability)`", + ) + }), + } + } +} diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index d088402abc6..0b1ededa775 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -4,16 +4,16 @@ use quote::quote; use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta}; #[derive(Debug)] -pub(crate) enum SessionDiagnosticDeriveError { +pub(crate) enum DiagnosticDeriveError { SynError(SynError), ErrorHandled, } -impl SessionDiagnosticDeriveError { +impl DiagnosticDeriveError { pub(crate) fn to_compile_error(self) -> TokenStream { match self { - SessionDiagnosticDeriveError::SynError(e) => e.to_compile_error(), - SessionDiagnosticDeriveError::ErrorHandled => { + DiagnosticDeriveError::SynError(e) => e.to_compile_error(), + DiagnosticDeriveError::ErrorHandled => { // Return ! to avoid having to create a blank DiagnosticBuilder to return when an // error has already been emitted to the compiler. quote! { @@ -24,9 +24,9 @@ impl SessionDiagnosticDeriveError { } } -impl From<SynError> for SessionDiagnosticDeriveError { +impl From<SynError> for DiagnosticDeriveError { fn from(e: SynError) -> Self { - SessionDiagnosticDeriveError::SynError(e) + DiagnosticDeriveError::SynError(e) } } @@ -34,9 +34,9 @@ impl From<SynError> for SessionDiagnosticDeriveError { pub(crate) fn _throw_err( diag: Diagnostic, f: impl FnOnce(Diagnostic) -> Diagnostic, -) -> SessionDiagnosticDeriveError { +) -> DiagnosticDeriveError { f(diag).emit(); - SessionDiagnosticDeriveError::ErrorHandled + DiagnosticDeriveError::ErrorHandled } /// Helper function for printing `syn::Path` - doesn't handle arguments in paths and these are @@ -60,7 +60,7 @@ pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { /// Emit a diagnostic on span `$span` with msg `$msg` (optionally performing additional decoration /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// -/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_span_err { ($span:expr, $msg:expr) => {{ throw_span_err!($span, $msg, |diag| diag) }}; ($span:expr, $msg:expr, $f:expr) => {{ @@ -87,7 +87,7 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { /// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// -/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_invalid_attr { ($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }}; ($attr:expr, $meta:expr, $f:expr) => {{ @@ -129,7 +129,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag /// Emit a error diagnostic for an invalid nested attribute (optionally performing additional /// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// -/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_invalid_nested_attr { ($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }}; ($attr:expr, $nested_attr:expr, $f:expr) => {{ diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 2eee4bfb5dd..39979002666 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,10 +1,11 @@ mod diagnostic; +mod diagnostic_builder; mod error; mod fluent; mod subdiagnostic; mod utils; -use diagnostic::SessionDiagnosticDerive; +use diagnostic::{LintDiagnosticDerive, SessionDiagnosticDerive}; pub(crate) use fluent::fluent_messages; use proc_macro2::TokenStream; use quote::format_ident; @@ -56,13 +57,55 @@ use synstructure::Structure; /// ``` /// /// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`: -/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html> +/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html> pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { - // Names for the diagnostic we build and the session we build it from. - let diag = format_ident!("diag"); - let sess = format_ident!("sess"); + SessionDiagnosticDerive::new(format_ident!("diag"), format_ident!("sess"), s).into_tokens() +} - SessionDiagnosticDerive::new(diag, sess, s).into_tokens() +/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, +/// independent from the actual lint emitting code. +/// +/// ```ignore (rust) +/// #[derive(LintDiagnostic)] +/// #[lint(lint::atomic_ordering_invalid_fail_success)] +/// pub struct AtomicOrderingInvalidLint { +/// method: Symbol, +/// success_ordering: Symbol, +/// fail_ordering: Symbol, +/// #[label(lint::fail_label)] +/// fail_order_arg_span: Span, +/// #[label(lint::success_label)] +/// #[suggestion( +/// code = "std::sync::atomic::Ordering::{success_suggestion}", +/// applicability = "maybe-incorrect" +/// )] +/// success_order_arg_span: Span, +/// } +/// ``` +/// +/// ```fluent +/// lint-atomic-ordering-invalid-fail-success = `{$method}`'s success ordering must be at least as strong as its failure ordering +/// .fail-label = `{$fail_ordering}` failure ordering +/// .success-label = `{$success_ordering}` success ordering +/// .suggestion = consider using `{$success_suggestion}` success ordering instead +/// ``` +/// +/// Then, later, to emit the error: +/// +/// ```ignore (rust) +/// cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint { +/// method, +/// success_ordering, +/// fail_ordering, +/// fail_order_arg_span, +/// success_order_arg_span, +/// }); +/// ``` +/// +/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: +/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html> +pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { + LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens() } /// Implements `#[derive(SessionSubdiagnostic)]`, which allows for labels, notes, helps and diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index eab954a9c1b..2a5b6beba94 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,8 +1,7 @@ #![deny(unused_must_use)] use crate::diagnostics::error::{ - span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - SessionDiagnosticDeriveError, + span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, @@ -214,7 +213,7 @@ impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> { } impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { - fn identify_kind(&mut self) -> Result<(), SessionDiagnosticDeriveError> { + fn identify_kind(&mut self) -> Result<(), DiagnosticDeriveError> { for attr in self.variant.ast().attrs { let span = attr.span().unwrap(); @@ -351,7 +350,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { &mut self, binding: &BindingInfo<'_>, is_suggestion: bool, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { + ) -> Result<TokenStream, DiagnosticDeriveError> { let ast = binding.ast(); let inner_ty = FieldInnerTy::from_type(&ast.ty); @@ -411,7 +410,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { Ok(inner_ty.with(binding, generated)) } - fn into_tokens(&mut self) -> Result<TokenStream, SessionDiagnosticDeriveError> { + fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> { self.identify_kind()?; let Some(kind) = self.kind.map(|(kind, _)| kind) else { throw_span_err!( diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 636bcf1f7b1..8977db4606c 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,11 +1,11 @@ -use crate::diagnostics::error::{span_err, throw_span_err, SessionDiagnosticDeriveError}; +use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError}; use proc_macro::Span; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; -use std::collections::BTreeSet; +use std::collections::{BTreeSet, HashMap}; use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple}; -use synstructure::BindingInfo; +use synstructure::{BindingInfo, Structure}; /// Checks whether the type name of `ty` matches `name`. /// @@ -34,7 +34,7 @@ pub(crate) fn type_is_unit(ty: &Type) -> bool { pub(crate) fn report_type_error( attr: &Attribute, ty_name: &str, -) -> Result<!, SessionDiagnosticDeriveError> { +) -> Result<!, DiagnosticDeriveError> { let name = attr.path.segments.last().unwrap().ident.to_string(); let meta = attr.parse_meta()?; @@ -59,7 +59,7 @@ fn report_error_if_not_applied_to_ty( info: &FieldInfo<'_>, path: &[&str], ty_name: &str, -) -> Result<(), SessionDiagnosticDeriveError> { +) -> Result<(), DiagnosticDeriveError> { if !type_matches_path(&info.ty, path) { report_type_error(attr, ty_name)?; } @@ -71,7 +71,7 @@ fn report_error_if_not_applied_to_ty( pub(crate) fn report_error_if_not_applied_to_applicability( attr: &Attribute, info: &FieldInfo<'_>, -) -> Result<(), SessionDiagnosticDeriveError> { +) -> Result<(), DiagnosticDeriveError> { report_error_if_not_applied_to_ty( attr, info, @@ -84,7 +84,7 @@ pub(crate) fn report_error_if_not_applied_to_applicability( pub(crate) fn report_error_if_not_applied_to_span( attr: &Attribute, info: &FieldInfo<'_>, -) -> Result<(), SessionDiagnosticDeriveError> { +) -> Result<(), DiagnosticDeriveError> { report_error_if_not_applied_to_ty(attr, info, &["rustc_span", "Span"], "`Span`") } @@ -166,10 +166,12 @@ pub(crate) struct FieldInfo<'a> { /// Small helper trait for abstracting over `Option` fields that contain a value and a `Span` /// for error reporting if they are set more than once. pub(crate) trait SetOnce<T> { - fn set_once(&mut self, value: T); + fn set_once(&mut self, _: (T, Span)); + + fn value(self) -> Option<T>; } -impl<T> SetOnce<(T, Span)> for Option<(T, Span)> { +impl<T> SetOnce<T> for Option<(T, Span)> { fn set_once(&mut self, (value, span): (T, Span)) { match self { None => { @@ -182,6 +184,10 @@ impl<T> SetOnce<(T, Span)> for Option<(T, Span)> { } } } + + fn value(self) -> Option<T> { + self.map(|(v, _)| v) + } } pub(crate) trait HasFieldMap { @@ -325,3 +331,20 @@ impl quote::ToTokens for Applicability { }); } } + +/// Build the mapping of field names to fields. This allows attributes to peek values from +/// other fields. +pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap<String, TokenStream> { + let mut fields_map = HashMap::new(); + + let ast = structure.ast(); + if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data { + for field in fields.iter() { + if let Some(ident) = &field.ident { + fields_map.insert(ident.to_string(), quote! { &self.#ident }); + } + } + } + + fields_map +} diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index ab1d6a439cd..168530c54b9 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -129,6 +129,7 @@ decl_derive!( // struct attributes warning, error, + lint, note, help, // field attributes @@ -142,6 +143,24 @@ decl_derive!( suggestion_verbose)] => diagnostics::session_diagnostic_derive ); decl_derive!( + [LintDiagnostic, attributes( + // struct attributes + warning, + error, + lint, + note, + help, + // field attributes + skip_arg, + primary_span, + label, + subdiagnostic, + suggestion, + suggestion_short, + suggestion_hidden, + suggestion_verbose)] => diagnostics::lint_diagnostic_derive +); +decl_derive!( [SessionSubdiagnostic, attributes( // struct/variant attributes label, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index bb4b502bded..caf5965c3a4 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -419,11 +419,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return; } - self.tcx.hir().deep_visit_all_item_likes(self); + self.tcx.hir().visit_all_item_likes_in_crate(self); } fn encode_def_path_table(&mut self) { - let table = self.tcx.definitions_untracked().def_path_table(); + let table = self.tcx.def_path_table(); if self.is_proc_macro { for def_index in std::iter::once(CRATE_DEF_INDEX) .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)) @@ -443,9 +443,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'static>> { - self.lazy(DefPathHashMapRef::BorrowedFromTcx( - self.tcx.definitions_untracked().def_path_hash_to_def_index_map(), - )) + self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } fn encode_source_map(&mut self) -> LazyArray<rustc_span::SourceFile> { @@ -614,7 +612,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let interpret_alloc_index_bytes = self.position() - i; // Encode the proc macro data. This affects 'tables', - // so we need to do this before we encode the tables + // so we need to do this before we encode the tables. + // This overwrites def_keys, so it must happen after encode_def_path_table. i = self.position(); let proc_macro_data = self.encode_proc_macros(); let proc_macro_data_bytes = self.position() - i; @@ -992,8 +991,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return; } let tcx = self.tcx; - let hir = tcx.hir(); - for local_id in hir.iter_local_def_id() { + for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.opt_def_kind(local_id); let Some(def_kind) = def_kind else { continue }; @@ -1854,12 +1852,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_traits_and_impls()"); empty_proc_macro!(self); let tcx = self.tcx; - let mut ctx = tcx.create_stable_hashing_context(); let mut all_impls: Vec<_> = tcx.crate_inherent_impls(()).incoherent_impls.iter().collect(); - all_impls.sort_by_cached_key(|&(&simp, _)| { - let mut hasher = StableHasher::new(); - simp.hash_stable(&mut ctx, &mut hasher); - hasher.finish::<Fingerprint>(); + tcx.with_stable_hashing_context(|mut ctx| { + all_impls.sort_by_cached_key(|&(&simp, _)| { + let mut hasher = StableHasher::new(); + simp.hash_stable(&mut ctx, &mut hasher); + hasher.finish::<Fingerprint>() + }) }); let all_impls: Vec<_> = all_impls .into_iter() diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 984c95b314b..661a9b1944c 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -96,6 +96,7 @@ macro_rules! arena_types { // (during lowering) and the `librustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, + [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>, [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, [] dep_kind: rustc_middle::dep_graph::DepKindStruct, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 555baae35f5..2d095438fc4 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -183,6 +183,9 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, + // We use this to create a forever-red node. + [] Red, + [anon] TraitSelect, // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below. diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index e335cb395f8..c8b3b52b0fb 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -23,6 +23,7 @@ pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; + const RED: Self = DepKind::Red; fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}(", node.kind)?; @@ -71,8 +72,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { type DepKind = DepKind; #[inline] - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - TyCtxt::create_stable_hashing_context(*self) + fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { + TyCtxt::with_stable_hashing_context(*self, f) } #[inline] diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 26b43488408..3e99ba5742a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -218,14 +218,8 @@ impl<'hir> Map<'hir> { self.tcx.local_def_id_to_hir_id(def_id) } - pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'hir { - // Create a dependency to the crate to be sure we re-execute this when the amount of - // definitions change. - self.tcx.ensure().hir_crate(()); - self.tcx.definitions_untracked().iter_local_def_id() - } - - pub fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> { + /// Do not call this function directly. The query should be called. + pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> { let hir_id = self.local_def_id_to_hir_id(local_def_id); let def_kind = match self.find(hir_id)? { Node::Item(item) => match item.kind { @@ -567,7 +561,7 @@ impl<'hir> Map<'hir> { } } - /// Walks the contents of a crate. See also `Crate::visit_all_items`. + /// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`. pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) { let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID); visitor.visit_mod(top_mod, span, hir_id); @@ -587,53 +581,61 @@ impl<'hir> Map<'hir> { } } - /// Visits all items in the crate in some deterministic (but - /// unspecified) order. If you need to process every item, - /// and care about nesting -- usually because your algorithm - /// follows lexical scoping rules -- then this method is the best choice. - /// If you don't care about nesting, you should use the `tcx.hir_crate_items()` query - /// or `items()` instead. + /// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you + /// need to process every item-like, and don't care about visiting nested items in a particular + /// order then this method is the best choice. If you do care about this nesting, you should + /// use the `tcx.hir().walk_toplevel_module`. + /// + /// Note that this function will access HIR for all the item-likes in the crate. If you only + /// need to access some of them, it is usually better to manually loop on the iterators + /// provided by `tcx.hir_crate_items(())`. /// /// Please see the notes in `intravisit.rs` for more information. - pub fn deep_visit_all_item_likes<V>(self, visitor: &mut V) + pub fn visit_all_item_likes_in_crate<V>(self, visitor: &mut V) where V: Visitor<'hir>, { - let krate = self.krate(); - for owner in krate.owners.iter().filter_map(|i| i.as_owner()) { - match owner.node() { - OwnerNode::Item(item) => visitor.visit_item(item), - OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), - OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), - OwnerNode::TraitItem(item) => visitor.visit_trait_item(item), - OwnerNode::Crate(_) => {} - } + let krate = self.tcx.hir_crate_items(()); + + for id in krate.items() { + visitor.visit_item(self.item(id)); + } + + for id in krate.trait_items() { + visitor.visit_trait_item(self.trait_item(id)); + } + + for id in krate.impl_items() { + visitor.visit_impl_item(self.impl_item(id)); + } + + for id in krate.foreign_items() { + visitor.visit_foreign_item(self.foreign_item(id)); } } - /// If you don't care about nesting, you should use the - /// `tcx.hir_module_items()` query or `module_items()` instead. - /// Please see notes in `deep_visit_all_item_likes`. - pub fn deep_visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V) + /// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to + /// item-likes in a single module. + pub fn visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V) where V: Visitor<'hir>, { let module = self.tcx.hir_module_items(module); - for id in module.items.iter() { - visitor.visit_item(self.item(*id)); + for id in module.items() { + visitor.visit_item(self.item(id)); } - for id in module.trait_items.iter() { - visitor.visit_trait_item(self.trait_item(*id)); + for id in module.trait_items() { + visitor.visit_trait_item(self.trait_item(id)); } - for id in module.impl_items.iter() { - visitor.visit_impl_item(self.impl_item(*id)); + for id in module.impl_items() { + visitor.visit_impl_item(self.impl_item(id)); } - for id in module.foreign_items.iter() { - visitor.visit_foreign_item(self.foreign_item(*id)); + for id in module.foreign_items() { + visitor.visit_foreign_item(self.foreign_item(id)); } } @@ -1012,12 +1014,14 @@ impl<'hir> Map<'hir> { ItemKind::Use(path, _) => path.span, _ => named_span(item.span, item.ident, item.kind.generics()), }, + Node::Variant(variant) => named_span(variant.span, variant.ident, None), Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)), Node::ForeignItem(item) => match item.kind { ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), _ => named_span(item.span, item.ident, None), }, - Node::Ctor(..) => return self.opt_span(self.get_parent_node(hir_id)), + Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)), + Node::Expr(Expr { kind: ExprKind::Closure { fn_decl_span, .. }, .. }) => *fn_decl_span, _ => self.span_with_body(hir_id), }; Some(span) @@ -1140,34 +1144,35 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { source_file_names.sort_unstable(); - let mut hcx = tcx.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); - upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); - source_file_names.hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.debugging_opts.incremental_relative_spans { - let definitions = &tcx.definitions_untracked(); - let mut owner_spans: Vec<_> = krate - .owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let _ = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); - let span = resolutions.source_span[def_id]; - debug_assert_eq!(span.parent(), None); - Some((def_path_hash, span)) - }) - .collect(); - owner_spans.sort_unstable_by_key(|bn| bn.0); - owner_spans.hash_stable(&mut hcx, &mut stable_hasher); - } - tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); - // Hash visibility information since it does not appear in HIR. - resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); - resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); + upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); + source_file_names.hash_stable(&mut hcx, &mut stable_hasher); + if tcx.sess.opts.debugging_opts.incremental_relative_spans { + let definitions = tcx.definitions_untracked(); + let mut owner_spans: Vec<_> = krate + .owners + .iter_enumerated() + .filter_map(|(def_id, info)| { + let _ = info.as_owner()?; + let def_path_hash = definitions.def_path_hash(def_id); + let span = resolutions.source_span[def_id]; + debug_assert_eq!(span.parent(), None); + Some((def_path_hash, span)) + }) + .collect(); + owner_spans.sort_unstable_by_key(|bn| bn.0); + owner_spans.hash_stable(&mut hcx, &mut stable_hasher); + } + tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); + // Hash visibility information since it does not appear in HIR. + resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); + resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); - let crate_hash: Fingerprint = stable_hasher.finish(); Svh::new(crate_hash.to_smaller_hash()) } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 8622a620721..070a063c881 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -63,6 +63,15 @@ impl ModuleItems { self.foreign_items.iter().copied() } + pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ { + self.items + .iter() + .map(|id| id.def_id) + .chain(self.trait_items.iter().map(|id| id.def_id)) + .chain(self.impl_items.iter().map(|id| id.def_id)) + .chain(self.foreign_items.iter().map(|id| id.def_id)) + } + pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { par_for_each_in(&self.items[..], |&id| f(id)) } @@ -102,7 +111,6 @@ pub fn provide(providers: &mut Providers) { let hir = tcx.hir(); hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) }; - providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; diff --git a/compiler/rustc_middle/src/hir/nested_filter.rs b/compiler/rustc_middle/src/hir/nested_filter.rs index d56e87bbb47..6896837aa91 100644 --- a/compiler/rustc_middle/src/hir/nested_filter.rs +++ b/compiler/rustc_middle/src/hir/nested_filter.rs @@ -8,7 +8,7 @@ use rustc_hir::intravisit::nested_filter::NestedFilter; /// constant arguments of types, e.g. in `let _: [(); /* HERE */];`. /// /// **This is the most common choice.** A very common pattern is -/// to use `deep_visit_all_item_likes()` as an outer loop, +/// to use `visit_all_item_likes_in_crate()` as an outer loop, /// and to have the visitor that visits the contents of each item /// using this setting. pub struct OnlyBodies(()); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 32c0a7e2605..4b156de410d 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,10 +2,7 @@ use std::cmp; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::{ - Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee, - ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan}; use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_query_system::ich::StableHashingContext; @@ -228,28 +225,6 @@ impl LintExpectation { } } -pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>); - -impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> { - /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`. - pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> { - self.0.set_primary_message(msg); - self.0.set_is_lint(); - self.0 - } - - /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`. - pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> { - LintDiagnosticBuilder(err) - } -} - -impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> { - pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> { - LintDiagnosticBuilder(self.0.forget_guarantee()) - } -} - pub fn explain_lint_level_source( lint: &'static Lint, level: Level, diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs new file mode 100644 index 00000000000..78080fcd581 --- /dev/null +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -0,0 +1,147 @@ +use crate::mir::graph_cyclic_cache::GraphIsCyclicCache; +use crate::mir::predecessors::{PredecessorCache, Predecessors}; +use crate::mir::switch_sources::{SwitchSourceCache, SwitchSources}; +use crate::mir::traversal::PostorderCache; +use crate::mir::{BasicBlock, BasicBlockData, Successors, START_BLOCK}; + +use rustc_data_structures::graph; +use rustc_data_structures::graph::dominators::{dominators, Dominators}; +use rustc_index::vec::IndexVec; + +#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] +pub struct BasicBlocks<'tcx> { + basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, + predecessor_cache: PredecessorCache, + switch_source_cache: SwitchSourceCache, + is_cyclic: GraphIsCyclicCache, + postorder_cache: PostorderCache, +} + +impl<'tcx> BasicBlocks<'tcx> { + #[inline] + pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { + BasicBlocks { + basic_blocks, + predecessor_cache: PredecessorCache::new(), + switch_source_cache: SwitchSourceCache::new(), + is_cyclic: GraphIsCyclicCache::new(), + postorder_cache: PostorderCache::new(), + } + } + + /// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`. + #[inline] + pub fn is_cfg_cyclic(&self) -> bool { + self.is_cyclic.is_cyclic(self) + } + + #[inline] + pub fn dominators(&self) -> Dominators<BasicBlock> { + dominators(&self) + } + + /// Returns predecessors for each basic block. + #[inline] + pub fn predecessors(&self) -> &Predecessors { + self.predecessor_cache.compute(&self.basic_blocks) + } + + /// Returns basic blocks in a postorder. + #[inline] + pub fn postorder(&self) -> &[BasicBlock] { + self.postorder_cache.compute(&self.basic_blocks) + } + + /// `switch_sources()[&(target, switch)]` returns a list of switch + /// values that lead to a `target` block from a `switch` block. + #[inline] + pub fn switch_sources(&self) -> &SwitchSources { + self.switch_source_cache.compute(&self.basic_blocks) + } + + /// Returns mutable reference to basic blocks. Invalidates CFG cache. + #[inline] + pub fn as_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> { + self.invalidate_cfg_cache(); + &mut self.basic_blocks + } + + /// Get mutable access to basic blocks without invalidating the CFG cache. + /// + /// By calling this method instead of e.g. [`BasicBlocks::as_mut`] you promise not to change + /// the CFG. This means that + /// + /// 1) The number of basic blocks remains unchanged + /// 2) The set of successors of each terminator remains unchanged. + /// 3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator + /// kind is not changed. + /// + /// If any of these conditions cannot be upheld, you should call [`BasicBlocks::invalidate_cfg_cache`]. + #[inline] + pub fn as_mut_preserves_cfg(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> { + &mut self.basic_blocks + } + + /// Invalidates cached information about the CFG. + /// + /// You will only ever need this if you have also called [`BasicBlocks::as_mut_preserves_cfg`]. + /// All other methods that allow you to mutate the basic blocks also call this method + /// themselves, thereby avoiding any risk of accidentaly cache invalidation. + pub fn invalidate_cfg_cache(&mut self) { + self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); + self.is_cyclic.invalidate(); + self.postorder_cache.invalidate(); + } +} + +impl<'tcx> std::ops::Deref for BasicBlocks<'tcx> { + type Target = IndexVec<BasicBlock, BasicBlockData<'tcx>>; + + #[inline] + fn deref(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> { + &self.basic_blocks + } +} + +impl<'tcx> graph::DirectedGraph for BasicBlocks<'tcx> { + type Node = BasicBlock; +} + +impl<'tcx> graph::WithNumNodes for BasicBlocks<'tcx> { + #[inline] + fn num_nodes(&self) -> usize { + self.basic_blocks.len() + } +} + +impl<'tcx> graph::WithStartNode for BasicBlocks<'tcx> { + #[inline] + fn start_node(&self) -> Self::Node { + START_BLOCK + } +} + +impl<'tcx> graph::WithSuccessors for BasicBlocks<'tcx> { + #[inline] + fn successors(&self, node: Self::Node) -> <Self as graph::GraphSuccessors<'_>>::Iter { + self.basic_blocks[node].terminator().successors() + } +} + +impl<'a, 'b> graph::GraphSuccessors<'b> for BasicBlocks<'a> { + type Item = BasicBlock; + type Iter = Successors<'b>; +} + +impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for BasicBlocks<'tcx> { + type Item = BasicBlock; + type Iter = std::iter::Copied<std::slice::Iter<'graph, BasicBlock>>; +} + +impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> { + #[inline] + fn predecessors(&self, node: Self::Node) -> <Self as graph::GraphPredecessors<'_>>::Iter { + self.predecessors()[node].iter().copied() + } +} diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 1bbd71c3f1f..ae333846f06 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -179,6 +179,11 @@ pub fn alloc_range(start: Size, size: Size) -> AllocRange { } impl AllocRange { + #[inline] + pub fn from(r: Range<Size>) -> Self { + alloc_range(r.start, r.end - r.start) // `Size` subtraction (overflow-checked) + } + #[inline(always)] pub fn end(self) -> Size { self.start + self.size // This does overflow checking. @@ -1095,9 +1100,9 @@ impl InitMask { /// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte /// indexes for the first contiguous span of the uninitialized access. #[inline] - pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range<Size>> { + pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), AllocRange> { if end > self.len { - return Err(self.len..end); + return Err(AllocRange::from(self.len..end)); } let uninit_start = self.find_bit(start, end, false); @@ -1105,7 +1110,7 @@ impl InitMask { match uninit_start { Some(uninit_start) => { let uninit_end = self.find_bit(uninit_start, end, true).unwrap_or(end); - Err(uninit_start..uninit_end) + Err(AllocRange::from(uninit_start..uninit_end)) } None => Ok(()), } @@ -1176,19 +1181,17 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { /// /// Returns `Ok(())` if it's initialized. Otherwise returns the range of byte /// indexes of the first contiguous uninitialized access. - fn is_init(&self, range: AllocRange) -> Result<(), Range<Size>> { + fn is_init(&self, range: AllocRange) -> Result<(), AllocRange> { self.init_mask.is_range_initialized(range.start, range.end()) // `Size` addition } /// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes` /// error which will report the first range of bytes which is uninitialized. fn check_init(&self, range: AllocRange) -> AllocResult { - self.is_init(range).map_err(|idx_range| { + self.is_init(range).map_err(|uninit_range| { AllocError::InvalidUninitBytes(Some(UninitBytesAccess { - access_offset: range.start, - access_size: range.size, - uninit_offset: idx_range.start, - uninit_size: idx_range.end - idx_range.start, // `Size` subtraction + access: range, + uninit: uninit_range, })) }) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 2a1fd6f736e..795f23edb31 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -1,4 +1,4 @@ -use super::{AllocId, ConstAlloc, Pointer, Scalar}; +use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar}; use crate::mir::interpret::ConstValue; use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty, ValTree}; @@ -162,9 +162,9 @@ impl fmt::Display for InvalidProgramInfo<'_> { AlreadyReported(ErrorGuaranteed { .. }) => { write!(f, "encountered constants with type errors, stopping evaluation") } - Layout(ref err) => write!(f, "{}", err), - FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err), - SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{}`", ty), + Layout(ref err) => write!(f, "{err}"), + FnAbiAdjustForForeignAbi(ref err) => write!(f, "{err}"), + SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{ty}`"), } } } @@ -205,14 +205,10 @@ impl fmt::Display for CheckInAllocMsg { /// Details of an access to uninitialized bytes where it is not allowed. #[derive(Debug)] pub struct UninitBytesAccess { - /// Location of the original memory access. - pub access_offset: Size, - /// Size of the original memory access. - pub access_size: Size, - /// Location of the first uninitialized byte that was accessed. - pub uninit_offset: Size, - /// Number of consecutive uninitialized bytes that were accessed. - pub uninit_size: Size, + /// Range of the original memory access. + pub access: AllocRange, + /// Range of the uninit memory that was encountered. (Might not be maximal.) + pub uninit: AllocRange, } /// Information about a size mismatch. @@ -308,30 +304,28 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UndefinedBehaviorInfo::*; match self { - Ub(msg) => write!(f, "{}", msg), + Ub(msg) => write!(f, "{msg}"), Unreachable => write!(f, "entering unreachable code"), BoundsCheckFailed { ref len, ref index } => { - write!(f, "indexing out of bounds: the len is {} but the index is {}", len, index) + write!(f, "indexing out of bounds: the len is {len} but the index is {index}") } DivisionByZero => write!(f, "dividing by zero"), RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), DivisionOverflow => write!(f, "overflow in signed division (dividing MIN by -1)"), RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"), PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"), - InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg), + InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {msg}"), InvalidVtableDropFn(sig) => write!( f, - "invalid drop function signature: got {}, expected exactly one argument which must be a pointer type", - sig + "invalid drop function signature: got {sig}, expected exactly one argument which must be a pointer type", ), InvalidVtableSize => { write!(f, "invalid vtable: size is bigger than largest supported object") } - InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg), + InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {msg}"), UnterminatedCString(p) => write!( f, - "reading a null-terminated string starting at {:?} with no null found before end of allocation", - p, + "reading a null-terminated string starting at {p:?} with no null found before end of allocation", ), PointerUseAfterFree(a) => { write!(f, "pointer to {a:?} was dereferenced after this allocation got freed") @@ -359,41 +353,36 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { } AlignmentCheckFailed { required, has } => write!( f, - "accessing memory with alignment {}, but alignment {} is required", - has.bytes(), - required.bytes() + "accessing memory with alignment {has}, but alignment {required} is required", + has = has.bytes(), + required = required.bytes() ), WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"), DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"), ValidationFailure { path: None, msg } => { - write!(f, "constructing invalid value: {}", msg) + write!(f, "constructing invalid value: {msg}") } ValidationFailure { path: Some(path), msg } => { - write!(f, "constructing invalid value at {}: {}", path, msg) + write!(f, "constructing invalid value at {path}: {msg}") } InvalidBool(b) => { - write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:02x}", b) + write!(f, "interpreting an invalid 8-bit value as a bool: 0x{b:02x}") } InvalidChar(c) => { - write!(f, "interpreting an invalid 32-bit value as a char: 0x{:08x}", c) + write!(f, "interpreting an invalid 32-bit value as a char: 0x{c:08x}") } - InvalidTag(val) => write!(f, "enum value has invalid tag: {:x}", val), + InvalidTag(val) => write!(f, "enum value has invalid tag: {val:x}"), InvalidFunctionPointer(p) => { - write!(f, "using {:?} as function pointer but it does not point to a function", p) + write!(f, "using {p:?} as function pointer but it does not point to a function") } - InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err), - InvalidUninitBytes(Some((alloc, access))) => write!( + InvalidStr(err) => write!(f, "this string is not valid UTF-8: {err}"), + InvalidUninitBytes(Some((alloc, info))) => write!( f, - "reading {} byte{} of memory starting at {:?}, \ - but {} byte{} {} uninitialized starting at {:?}, \ + "reading memory at {alloc:?}{access:?}, \ + but memory is uninitialized at {uninit:?}, \ and this operation requires initialized memory", - access.access_size.bytes(), - pluralize!(access.access_size.bytes()), - Pointer::new(*alloc, access.access_offset), - access.uninit_size.bytes(), - pluralize!(access.uninit_size.bytes()), - pluralize!("is", access.uninit_size.bytes()), - Pointer::new(*alloc, access.uninit_offset), + access = info.access, + uninit = info.uninit, ), InvalidUninitBytes(None) => write!( f, @@ -402,8 +391,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { DeadLocal => write!(f, "accessing a dead local variable"), ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!( f, - "scalar size mismatch: expected {} bytes but got {} bytes instead", - target_size, data_size + "scalar size mismatch: expected {target_size} bytes but got {data_size} bytes instead", ), UninhabitedEnumVariantWritten => { write!(f, "writing discriminant of an uninhabited enum") @@ -437,13 +425,13 @@ impl fmt::Display for UnsupportedOpInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UnsupportedOpInfo::*; match self { - Unsupported(ref msg) => write!(f, "{}", msg), + Unsupported(ref msg) => write!(f, "{msg}"), ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes"), PartialPointerOverwrite(ptr) => { - write!(f, "unable to overwrite parts of a pointer in memory at {:?}", ptr) + write!(f, "unable to overwrite parts of a pointer in memory at {ptr:?}") } - ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({:?})", did), - ReadExternStatic(did) => write!(f, "cannot read from extern static ({:?})", did), + ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({did:?})"), + ReadExternStatic(did) => write!(f, "cannot read from extern static ({did:?})"), } } } @@ -526,11 +514,11 @@ impl fmt::Display for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use InterpError::*; match *self { - Unsupported(ref msg) => write!(f, "{}", msg), - InvalidProgram(ref msg) => write!(f, "{}", msg), - UndefinedBehavior(ref msg) => write!(f, "{}", msg), - ResourceExhaustion(ref msg) => write!(f, "{}", msg), - MachineStop(ref msg) => write!(f, "{}", msg), + Unsupported(ref msg) => write!(f, "{msg}"), + InvalidProgram(ref msg) => write!(f, "{msg}"), + UndefinedBehavior(ref msg) => write!(f, "{msg}"), + ResourceExhaustion(ref msg) => write!(f, "{msg}"), + MachineStop(ref msg) => write!(f, "{msg}"), } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e7d7317456c..93686128101 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -5,7 +5,6 @@ use crate::mir::interpret::{ AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar, }; -use crate::mir::traversal::PostorderCache; use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; @@ -27,8 +26,7 @@ use rustc_target::abi::{Size, VariantIdx}; use polonius_engine::Atom; pub use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::graph::dominators::{dominators, Dominators}; -use rustc_data_structures::graph::{self, GraphSuccessors}; +use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitMatrix; use rustc_index::vec::{Idx, IndexVec}; use rustc_serialize::{Decodable, Encodable}; @@ -43,11 +41,10 @@ use std::fmt::{self, Debug, Display, Formatter, Write}; use std::ops::{ControlFlow, Index, IndexMut}; use std::{iter, mem}; -use self::graph_cyclic_cache::GraphIsCyclicCache; -use self::predecessors::{PredecessorCache, Predecessors}; pub use self::query::*; -use self::switch_sources::{SwitchSourceCache, SwitchSources}; +pub use basic_blocks::BasicBlocks; +mod basic_blocks; pub mod coverage; mod generic_graph; pub mod generic_graphviz; @@ -189,7 +186,7 @@ pub struct GeneratorInfo<'tcx> { pub struct Body<'tcx> { /// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`] /// that indexes into this vector. - basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, + pub basic_blocks: BasicBlocks<'tcx>, /// Records how far through the "desugaring and optimization" process this particular /// MIR has traversed. This is particularly useful when inlining, since in that context @@ -257,11 +254,6 @@ pub struct Body<'tcx> { /// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this. pub is_polymorphic: bool, - predecessor_cache: PredecessorCache, - switch_source_cache: SwitchSourceCache, - is_cyclic: GraphIsCyclicCache, - postorder_cache: PostorderCache, - pub tainted_by_errors: Option<ErrorGuaranteed>, } @@ -289,7 +281,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, source, - basic_blocks, + basic_blocks: BasicBlocks::new(basic_blocks), source_scopes, generator: generator_kind.map(|generator_kind| { Box::new(GeneratorInfo { @@ -307,10 +299,6 @@ impl<'tcx> Body<'tcx> { span, required_consts: Vec::new(), is_polymorphic: false, - predecessor_cache: PredecessorCache::new(), - switch_source_cache: SwitchSourceCache::new(), - is_cyclic: GraphIsCyclicCache::new(), - postorder_cache: PostorderCache::new(), tainted_by_errors, }; body.is_polymorphic = body.has_param_types_or_consts(); @@ -326,7 +314,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, source: MirSource::item(CRATE_DEF_ID.to_def_id()), - basic_blocks, + basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), generator: None, local_decls: IndexVec::new(), @@ -337,10 +325,6 @@ impl<'tcx> Body<'tcx> { required_consts: Vec::new(), var_debug_info: Vec::new(), is_polymorphic: false, - predecessor_cache: PredecessorCache::new(), - switch_source_cache: SwitchSourceCache::new(), - is_cyclic: GraphIsCyclicCache::new(), - postorder_cache: PostorderCache::new(), tainted_by_errors: None, }; body.is_polymorphic = body.has_param_types_or_consts(); @@ -354,74 +338,7 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> { - // Because the user could mutate basic block terminators via this reference, we need to - // invalidate the caches. - // - // FIXME: Use a finer-grained API for this, so only transformations that alter terminators - // invalidate the caches. - self.invalidate_cfg_cache(); - &mut self.basic_blocks - } - - #[inline] - pub fn basic_blocks_and_local_decls_mut( - &mut self, - ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) { - self.invalidate_cfg_cache(); - (&mut self.basic_blocks, &mut self.local_decls) - } - - #[inline] - pub fn basic_blocks_local_decls_mut_and_var_debug_info( - &mut self, - ) -> ( - &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, - &mut LocalDecls<'tcx>, - &mut Vec<VarDebugInfo<'tcx>>, - ) { - self.invalidate_cfg_cache(); - (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) - } - - /// Get mutable access to parts of the Body without invalidating the CFG cache. - /// - /// By calling this method instead of eg [`Body::basic_blocks_mut`], you promise not to change - /// the CFG. This means that - /// - /// 1) The number of basic blocks remains unchanged - /// 2) The set of successors of each terminator remains unchanged. - /// 3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator - /// kind is not changed. - /// - /// If any of these conditions cannot be upheld, you should call [`Body::invalidate_cfg_cache`]. - #[inline] - pub fn basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate( - &mut self, - ) -> ( - &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, - &mut LocalDecls<'tcx>, - &mut Vec<VarDebugInfo<'tcx>>, - ) { - (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) - } - - /// Invalidates cached information about the CFG. - /// - /// You will only ever need this if you have also called - /// [`Body::basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate`]. All other methods - /// that allow you to mutate the body also call this method themselves, thereby avoiding any - /// risk of accidentaly cache invalidation. - pub fn invalidate_cfg_cache(&mut self) { - self.predecessor_cache.invalidate(); - self.switch_source_cache.invalidate(); - self.is_cyclic.invalidate(); - self.postorder_cache.invalidate(); - } - - /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the - /// `START_BLOCK`. - pub fn is_cfg_cyclic(&self) -> bool { - self.is_cyclic.is_cyclic(self) + self.basic_blocks.as_mut() } #[inline] @@ -495,14 +412,6 @@ impl<'tcx> Body<'tcx> { self.local_decls.drain(self.arg_count + 1..) } - /// Changes a statement to a nop. This is both faster than deleting instructions and avoids - /// invalidating statement indices in `Location`s. - pub fn make_statement_nop(&mut self, location: Location) { - let block = &mut self.basic_blocks[location.block]; - debug_assert!(location.statement_index < block.statements.len()); - block.statements[location.statement_index].make_nop() - } - /// Returns the source info associated with `location`. pub fn source_info(&self, location: Location) -> &SourceInfo { let block = &self[location.block]; @@ -539,23 +448,6 @@ impl<'tcx> Body<'tcx> { } #[inline] - pub fn predecessors(&self) -> &Predecessors { - self.predecessor_cache.compute(&self.basic_blocks) - } - - /// `body.switch_sources()[&(target, switch)]` returns a list of switch - /// values that lead to a `target` block from a `switch` block. - #[inline] - pub fn switch_sources(&self) -> &SwitchSources { - self.switch_source_cache.compute(&self.basic_blocks) - } - - #[inline] - pub fn dominators(&self) -> Dominators<BasicBlock> { - dominators(self) - } - - #[inline] pub fn yield_ty(&self) -> Option<Ty<'tcx>> { self.generator.as_ref().and_then(|generator| generator.yield_ty) } @@ -599,7 +491,7 @@ impl<'tcx> Index<BasicBlock> for Body<'tcx> { impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> { #[inline] fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> { - &mut self.basic_blocks_mut()[index] + &mut self.basic_blocks.as_mut()[index] } } @@ -2890,48 +2782,6 @@ fn pretty_print_const_value<'tcx>( }) } -impl<'tcx> graph::DirectedGraph for Body<'tcx> { - type Node = BasicBlock; -} - -impl<'tcx> graph::WithNumNodes for Body<'tcx> { - #[inline] - fn num_nodes(&self) -> usize { - self.basic_blocks.len() - } -} - -impl<'tcx> graph::WithStartNode for Body<'tcx> { - #[inline] - fn start_node(&self) -> Self::Node { - START_BLOCK - } -} - -impl<'tcx> graph::WithSuccessors for Body<'tcx> { - #[inline] - fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter { - self.basic_blocks[node].terminator().successors() - } -} - -impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { - type Item = BasicBlock; - type Iter = Successors<'b>; -} - -impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> { - type Item = BasicBlock; - type Iter = std::iter::Copied<std::slice::Iter<'graph, BasicBlock>>; -} - -impl<'tcx> graph::WithPredecessors for Body<'tcx> { - #[inline] - fn predecessors(&self, node: Self::Node) -> <Self as graph::GraphPredecessors<'_>>::Iter { - self.predecessors()[node].iter().copied() - } -} - /// `Location` represents the position of the start of the statement; or, if /// `statement_index` equals the number of statements, then the start of the /// terminator. @@ -2968,7 +2818,7 @@ impl Location { return true; } - let predecessors = body.predecessors(); + let predecessors = body.basic_blocks.predecessors(); // If we're in another block, then we want to check that block is a predecessor of `other`. let mut queue: Vec<BasicBlock> = predecessors[other.block].to_vec(); diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 5d4f3ea9e4c..dcc37c565c9 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -396,6 +396,8 @@ pub struct CopyNonOverlapping<'tcx> { /////////////////////////////////////////////////////////////////////////// // Terminators +/// The various kinds of terminators, representing ways of exiting from a basic block. +/// /// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the /// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such /// terminators have a `cleanup: Option<BasicBlock>` field on them. If stack unwinding occurs, then @@ -911,7 +913,7 @@ pub enum Operand<'tcx> { static_assert_size!(Operand<'_>, 24); /////////////////////////////////////////////////////////////////////////// -/// Rvalues +// Rvalues /// The various kinds of rvalues that can appear in MIR. /// diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 30648679dae..627dc32f37e 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -104,22 +104,25 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { /// /// A Postorder traversal of this graph is `D B C A` or `D C B A` pub struct Postorder<'a, 'tcx> { - body: &'a Body<'tcx>, + basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>, visited: BitSet<BasicBlock>, visit_stack: Vec<(BasicBlock, Successors<'a>)>, root_is_start_block: bool, } impl<'a, 'tcx> Postorder<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> { + pub fn new( + basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>, + root: BasicBlock, + ) -> Postorder<'a, 'tcx> { let mut po = Postorder { - body, - visited: BitSet::new_empty(body.basic_blocks().len()), + basic_blocks, + visited: BitSet::new_empty(basic_blocks.len()), visit_stack: Vec::new(), root_is_start_block: root == START_BLOCK, }; - let data = &po.body[root]; + let data = &po.basic_blocks[root]; if let Some(ref term) = data.terminator { po.visited.insert(root); @@ -190,7 +193,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { }; if self.visited.insert(bb) { - if let Some(term) = &self.body[bb].terminator { + if let Some(term) = &self.basic_blocks[bb].terminator { self.visit_stack.push((bb, term.successors())); } } @@ -199,7 +202,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { } pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Postorder<'a, 'tcx> { - Postorder::new(body, START_BLOCK) + Postorder::new(&body.basic_blocks, START_BLOCK) } impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { @@ -211,12 +214,12 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { self.traverse_successor(); } - next.map(|(bb, _)| (bb, &self.body[bb])) + next.map(|(bb, _)| (bb, &self.basic_blocks[bb])) } fn size_hint(&self) -> (usize, Option<usize>) { // All the blocks, minus the number of blocks we've visited. - let upper = self.body.basic_blocks().len() - self.visited.count(); + let upper = self.basic_blocks.len() - self.visited.count(); let lower = if self.root_is_start_block { // We will visit all remaining blocks exactly once. @@ -263,10 +266,8 @@ pub struct ReversePostorder<'a, 'tcx> { impl<'a, 'tcx> ReversePostorder<'a, 'tcx> { pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> { - let blocks: Vec<_> = Postorder::new(body, root).map(|(bb, _)| bb).collect(); - + let blocks: Vec<_> = Postorder::new(&body.basic_blocks, root).map(|(bb, _)| bb).collect(); let len = blocks.len(); - ReversePostorder { body, blocks, idx: len } } } @@ -334,10 +335,8 @@ impl<'a, 'tcx> Iterator for ReversePostorderIter<'a, 'tcx> { impl<'a, 'tcx> ExactSizeIterator for ReversePostorderIter<'a, 'tcx> {} pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter<'a, 'tcx> { - let blocks = body.postorder_cache.compute(body); - + let blocks = body.basic_blocks.postorder(); let len = blocks.len(); - ReversePostorderIter { body, blocks, idx: len } } @@ -360,7 +359,7 @@ impl PostorderCache { /// Returns the `&[BasicBlocks]` represents the postorder graph for this MIR. #[inline] - pub(super) fn compute(&self, body: &Body<'_>) -> &[BasicBlock] { + pub(super) fn compute(&self, body: &IndexVec<BasicBlock, BasicBlockData<'_>>) -> &[BasicBlock] { self.cache.get_or_init(|| Postorder::new(body, START_BLOCK).map(|(bb, _)| bb).collect()) } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b8bb93891c2..cbc45526e89 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -26,6 +26,12 @@ rustc_queries! { desc { "get the resolver outputs" } } + query resolver_for_lowering(_: ()) -> &'tcx Steal<ty::ResolverAstLowering> { + eval_always + no_hash + desc { "get the resolver for lowering" } + } + /// Return the span for a definition. /// Contrary to `def_span` below, this query returns the full absolute span of the definition. /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside @@ -40,7 +46,8 @@ rustc_queries! { /// This is because the `hir_crate` query gives you access to all other items. /// To avoid this fate, do not call `tcx.hir().krate()`; instead, /// prefer wrappers like `tcx.visit_all_items_in_krate()`. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { + query hir_crate(key: ()) -> Crate<'tcx> { + storage(ArenaCacheSelector<'tcx>) eval_always desc { "get the crate HIR" } } @@ -1573,7 +1580,7 @@ rustc_queries! { Option<&'tcx FxHashMap<ItemLocalId, Region>> { desc { "looking up a named region" } } - query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxHashSet<LocalDefId>> { + query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> { desc { "testing if a region is late bound" } } /// For a given item (like a struct), gets the default lifetimes to be used diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1468e1407ff..a594dab2e20 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -4,7 +4,7 @@ use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; -use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; +use crate::lint::{struct_lint_level, LintLevelSource}; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::resolve_lifetime; use crate::middle::stability; @@ -32,12 +32,13 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal}; use rustc_data_structures::vec_map::VecMap; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -1045,6 +1046,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> { pub struct GlobalCtxt<'tcx> { pub arena: &'tcx WorkerLocal<Arena<'tcx>>, + pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, interners: CtxtInterners<'tcx>, @@ -1069,13 +1071,15 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, - definitions: rustc_hir::definitions::Definitions, + definitions: RwLock<Definitions>, cstore: Box<CrateStoreDyn>, /// Output of the resolver. pub(crate) untracked_resolutions: ty::ResolverOutputs, - - pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, + untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>, + /// The entire crate as AST. This field serves as the input for the hir_crate query, + /// which lowers it from AST to HIR. It must not be read or used by anything else. + pub untracked_crate: Steal<Lrc<ast::Crate>>, /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by @@ -1233,10 +1237,12 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, lint_store: Lrc<dyn Any + sync::Send + sync::Sync>, arena: &'tcx WorkerLocal<Arena<'tcx>>, - definitions: rustc_hir::definitions::Definitions, + hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, + definitions: Definitions, cstore: Box<CrateStoreDyn>, untracked_resolutions: ty::ResolverOutputs, - krate: &'tcx hir::Crate<'tcx>, + untracked_resolver_for_lowering: ty::ResolverAstLowering, + krate: Lrc<ast::Crate>, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, @@ -1263,16 +1269,18 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, arena, + hir_arena, interners, dep_graph, - definitions, + definitions: RwLock::new(definitions), cstore, - untracked_resolutions, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, consts: common_consts, - untracked_crate: krate, + untracked_resolutions, + untracked_resolver_for_lowering: Steal::new(untracked_resolver_for_lowering), + untracked_crate: Steal::new(krate), on_disk_cache, queries, query_caches: query::QueryCaches::default(), @@ -1368,7 +1376,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey { // Accessing the DefKey is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.definitions.def_key(id) + self.definitions_untracked().def_key(id) } else { self.cstore.def_key(id) } @@ -1382,7 +1390,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath { // Accessing the DefPath is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.definitions.def_path(id) + self.definitions_untracked().def_path(id) } else { self.cstore.def_path(id) } @@ -1392,7 +1400,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash { // Accessing the DefPathHash is ok, it is incr. comp. stable. if let Some(def_id) = def_id.as_local() { - self.definitions.def_path_hash(def_id) + self.definitions_untracked().def_path_hash(def_id) } else { self.cstore.def_path_hash(def_id) } @@ -1429,7 +1437,7 @@ impl<'tcx> TyCtxt<'tcx> { // If this is a DefPathHash from the local crate, we can look up the // DefId in the tcx's `Definitions`. if stable_crate_id == self.sess.local_stable_crate_id() { - self.definitions.local_def_path_hash_to_def_id(hash, err).to_def_id() + self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id() } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. @@ -1460,6 +1468,64 @@ impl<'tcx> TyCtxt<'tcx> { ) } + /// Create a new definition within the incr. comp. engine. + pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) -> LocalDefId { + // This function modifies `self.definitions` using a side-effect. + // We need to ensure that these side effects are re-run by the incr. comp. engine. + // Depending on the forever-red node will tell the graph that the calling query + // needs to be re-evaluated. + use rustc_query_system::dep_graph::DepNodeIndex; + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + + // The following call has the side effect of modifying the tables inside `definitions`. + // These very tables are relied on by the incr. comp. engine to decode DepNodes and to + // decode the on-disk cache. + // + // Any LocalDefId which is used within queries, either as key or result, either: + // - has been created before the construction of the TyCtxt; + // - has been created by this call to `create_def`. + // As a consequence, this LocalDefId is always re-created before it is needed by the incr. + // comp. engine itself. + // + // This call also writes to the value of `source_span` and `expn_that_defined` queries. + // This is fine because: + // - those queries are `eval_always` so we won't miss their result changing; + // - this write will have happened before these queries are called. + self.definitions.write().create_def(parent, data) + } + + pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx { + // Create a dependency to the crate to be sure we re-execute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.iter_local_def_id() + } + + pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.def_path_table() + } + + pub fn def_path_hash_to_def_index_map( + self, + ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap { + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.def_path_hash_to_def_index_map() + } + /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn { @@ -1468,8 +1534,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries - pub fn definitions_untracked(self) -> &'tcx hir::definitions::Definitions { - &self.definitions + #[inline] + pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> { + self.definitions.read() } /// Note that this is *untracked* and should only be used within the query @@ -1480,23 +1547,18 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline(always)] - pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - StableHashingContext::new( - self.sess, - &self.definitions, - &*self.cstore, - &self.untracked_resolutions.source_span, - ) - } - - #[inline(always)] - pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> { - StableHashingContext::ignore_spans( + pub fn with_stable_hashing_context<R>( + self, + f: impl FnOnce(StableHashingContext<'_>) -> R, + ) -> R { + let definitions = self.definitions_untracked(); + let hcx = StableHashingContext::new( self.sess, - &self.definitions, + &*definitions, &*self.cstore, &self.untracked_resolutions.source_span, - ) + ); + f(hcx) } pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult { @@ -2304,7 +2366,7 @@ impl<'tcx> TyCtxt<'tcx> { self.interners.intern_ty( st, self.sess, - &self.definitions, + &self.definitions.read(), &*self.cstore, // This is only used to create a stable hashing context. &self.untracked_resolutions.source_span, @@ -2787,6 +2849,18 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, + /// typically generated by `#[derive(LintDiagnostic)]`). + pub fn emit_spanned_lint( + self, + lint: &'static Lint, + hir_id: HirId, + span: impl Into<MultiSpan>, + decorator: impl for<'a> DecorateLint<'a, ()>, + ) { + self.struct_span_lint_hir(lint, hir_id, span, |diag| decorator.decorate_lint(diag)) + } + pub fn struct_span_lint_hir( self, lint: &'static Lint, @@ -2798,6 +2872,17 @@ impl<'tcx> TyCtxt<'tcx> { struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate); } + /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically + /// generated by `#[derive(LintDiagnostic)]`). + pub fn emit_lint( + self, + lint: &'static Lint, + id: HirId, + decorator: impl for<'a> DecorateLint<'a, ()>, + ) { + self.struct_lint_node(lint, id, |diag| decorator.decorate_lint(diag)) + } + pub fn struct_lint_node( self, lint: &'static Lint, @@ -2899,6 +2984,7 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool { pub fn provide(providers: &mut ty::query::Providers) { providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; + providers.resolver_for_lowering = |tcx, ()| &tcx.untracked_resolver_for_lowering; providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 9796b152911..49a518b101d 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -795,7 +795,7 @@ fn foo(&self) -> Self::T { String::new() } if item_def_id == proj_ty_item_def_id => { Some(( - self.sess.source_map().guess_head_span(self.def_span(item.def_id)), + self.def_span(item.def_id), format!("consider calling `{}`", self.def_path_str(item.def_id)), )) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index eb675444362..f87b6e4212d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -235,9 +235,8 @@ fn sanity_check_layout<'tcx>( if cfg!(debug_assertions) { fn check_layout_abi<'tcx>(tcx: TyCtxt<'tcx>, layout: Layout<'tcx>) { match layout.abi() { - Abi::Scalar(_scalar) => { + Abi::Scalar(scalar) => { // No padding in scalars. - /* FIXME(#96185): assert_eq!( layout.align().abi, scalar.align(&tcx).abi, @@ -247,7 +246,7 @@ fn sanity_check_layout<'tcx>( layout.size(), scalar.size(&tcx), "size mismatch between ABI and layout in {layout:#?}" - );*/ + ); } Abi::Vector { count, element } => { // No padding in vectors. Alignment can be strengthened, though. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3a876df84c2..0e581d7f1f7 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -142,16 +142,16 @@ impl<'tcx> TyCtxt<'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { - let mut hasher = StableHasher::new(); - let mut hcx = self.create_stable_hashing_context(); - // We want the type_id be independent of the types free regions, so we // erase them. The erase_regions() call will also anonymize bound // regions, which is desirable too. let ty = self.erase_regions(ty); - hcx.while_hashing_spans(false, |hcx| ty.hash_stable(hcx, &mut hasher)); - hasher.finish() + self.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| ty.hash_stable(hcx, &mut hasher)); + hasher.finish() + }) } pub fn res_generics_def_id(self, res: Res) -> Option<DefId> { diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 5470cc1262e..d21a8c4f9b9 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -2,7 +2,7 @@ use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; use rustc_hir::intravisit::FnKind; -use rustc_middle::mir::{BasicBlock, Body, Operand, TerminatorKind}; +use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind}; use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; @@ -30,7 +30,9 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { }; let mut vis = Search { tcx, body, reachable_recursive_calls: vec![], trait_substs }; - if let Some(NonRecursive) = TriColorDepthFirstSearch::new(&body).run_from_start(&mut vis) { + if let Some(NonRecursive) = + TriColorDepthFirstSearch::new(&body.basic_blocks).run_from_start(&mut vis) + { return; } if vis.reachable_recursive_calls.is_empty() { @@ -101,7 +103,7 @@ impl<'mir, 'tcx> Search<'mir, 'tcx> { } } -impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> { +impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> { type BreakVal = NonRecursive; fn node_examined( diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 05a4d7bbf3e..5c77f3ea395 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -228,7 +228,7 @@ impl Direction for Backward { ) where A: Analysis<'tcx>, { - for pred in body.predecessors()[bb].iter().copied() { + for pred in body.basic_blocks.predecessors()[bb].iter().copied() { match body[pred].terminator().kind { // Apply terminator-specific edge effects. // @@ -316,7 +316,7 @@ where fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { assert!(!self.effects_applied); - let values = &self.body.switch_sources()[&(self.bb, self.pred)]; + let values = &self.body.basic_blocks.switch_sources()[&(self.bb, self.pred)]; let targets = values.iter().map(|&value| SwitchIntTarget { value, target: self.bb }); let mut tmp = None; diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 20e14a77c1e..180376d648a 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -101,7 +101,7 @@ where // transfer function for each block exactly once (assuming that we process blocks in RPO). // // In this case, there's no need to compute the block transfer functions ahead of time. - if !body.is_cfg_cyclic() { + if !body.basic_blocks.is_cfg_cyclic() { return Self::new(tcx, body, analysis, None); } diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 67c16e6c084..f9fd6c9c56b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -1,7 +1,7 @@ //! A framework that can express both [gen-kill] and generic dataflow problems. //! -//! To actually use this framework, you must implement either the `Analysis` or the -//! `GenKillAnalysis` trait. If your transfer function can be expressed with only gen/kill +//! To use this framework, implement either the [`Analysis`] or the +//! [`GenKillAnalysis`] trait. If your transfer function can be expressed with only gen/kill //! operations, prefer `GenKillAnalysis` since it will run faster while iterating to fixpoint. The //! `impls` module contains several examples of gen/kill dataflow analyses. //! @@ -96,7 +96,7 @@ impl<T: Idx> BitSetExt<T> for ChunkedBitSet<T> { } } -/// Define the domain of a dataflow problem. +/// Defines the domain of a dataflow problem. /// /// This trait specifies the lattice on which this analysis operates (the domain) as well as its /// initial value at the entry point of each basic block. @@ -113,12 +113,12 @@ pub trait AnalysisDomain<'tcx> { /// suitable as part of a filename. const NAME: &'static str; - /// The initial value of the dataflow state upon entry to each basic block. + /// Returns the initial value of the dataflow state upon entry to each basic block. fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain; /// Mutates the initial value of the dataflow state upon entry to the `START_BLOCK`. /// - /// For backward analyses, initial state besides the bottom value is not yet supported. Trying + /// For backward analyses, initial state (besides the bottom value) is not yet supported. Trying /// to mutate the initial state will result in a panic. // // FIXME: For backward dataflow analyses, the initial state should be applied to every basic @@ -155,9 +155,9 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// Updates the current dataflow state with an effect that occurs immediately *before* the /// given statement. /// - /// This method is useful if the consumer of the results of this analysis needs only to observe + /// This method is useful if the consumer of the results of this analysis only needs to observe /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule, - /// analyses should not implement this without implementing `apply_statement_effect`. + /// analyses should not implement this without also implementing `apply_statement_effect`. fn apply_before_statement_effect( &self, _state: &mut Self::Domain, @@ -184,7 +184,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// /// This method is useful if the consumer of the results of this analysis needs only to observe /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule, - /// analyses should not implement this without implementing `apply_terminator_effect`. + /// analyses should not implement this without also implementing `apply_terminator_effect`. fn apply_before_terminator_effect( &self, _state: &mut Self::Domain, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index eae9313b771..f6b5af90a85 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -153,7 +153,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc _: &mir::Statement<'tcx>, loc: Location, ) { - // If we move from a place then only stops needing storage *after* + // If we move from a place then it only stops needing storage *after* // that statement. self.check_for_move(trans, loc); } diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 10d52271734..f12c8560c0e 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -39,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { impl AddCallGuards { pub fn add_call_guards(&self, body: &mut Body<'_>) { let mut pred_count: IndexVec<_, _> = - body.predecessors().iter().map(|ps| ps.len()).collect(); + body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect(); pred_count[START_BLOCK] += 1; // We need a place to store the new blocks generated diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 0f87e638d26..5d15f03491d 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -91,7 +91,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag { super::add_call_guards::AllCallEdges.run_pass(tcx, body); let (span, arg_count) = (body.span, body.arg_count); - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + let basic_blocks = body.basic_blocks.as_mut(); + let local_decls = &body.local_decls; let needs_retag = |place: &Place<'tcx>| { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 097a6186cd5..8838b14c53a 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -1,5 +1,4 @@ -use rustc_errors::DiagnosticBuilder; -use rustc_middle::lint::LintDiagnosticBuilder; +use rustc_errors::{DiagnosticBuilder, LintDiagnosticBuilder}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 070e563f396..01eda979f9e 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -29,9 +29,8 @@ use rustc_trait_selection::traits; use crate::MirPass; use rustc_const_eval::interpret::{ self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame, - ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy, - Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup, - StackPopUnwind, + ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemoryKind, OpTy, PlaceTy, + Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind, }; /// The maximum number of bytes that we'll allocate space for a local or the return value. @@ -237,15 +236,19 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } - fn access_local( - _ecx: &InterpCx<'mir, 'tcx, Self>, - frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, + fn access_local<'a>( + frame: &'a Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, local: Local, - ) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> { + ) -> InterpResult<'tcx, &'a interpret::Operand<Self::PointerTag>> { let l = &frame.locals[local]; - if l.value == LocalValue::Unallocated { - throw_machine_stop_str!("tried to access an unallocated local") + if matches!( + l.value, + LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit)) + ) { + // For us "uninit" means "we don't know its value, might be initiailized or not". + // So stop here. + throw_machine_stop_str!("tried to access alocal with unknown value ") } l.access() @@ -255,8 +258,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> ecx: &'a mut InterpCx<'mir, 'tcx, Self>, frame: usize, local: Local, - ) -> InterpResult<'tcx, Result<&'a mut LocalValue<Self::PointerTag>, MemPlace<Self::PointerTag>>> - { + ) -> InterpResult<'tcx, &'a mut interpret::Operand<Self::PointerTag>> { if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation { throw_machine_stop_str!("tried to write to a local that is marked as not propagatable") } @@ -391,7 +393,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { .layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs)) .ok() // Don't bother allocating memory for large values. - .filter(|ret_layout| ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)) + // I don't know how return types can seem to be unsized but this happens in the + // `type/type-unsatisfiable.rs` test. + .filter(|ret_layout| { + !ret_layout.is_unsized() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) + }) .unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap()); let ret = ecx @@ -436,8 +442,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Remove `local` from the pool of `Locals`. Allows writing to them, /// but not reading from them anymore. fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) { - ecx.frame_mut().locals[local] = - LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) }; + ecx.frame_mut().locals[local] = LocalState { + value: LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit)), + layout: Cell::new(None), + }; } fn use_ecx<F, T>(&mut self, f: F) -> Option<T> @@ -1042,7 +1050,9 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { let frame = self.ecx.frame_mut(); frame.locals[local].value = if let StatementKind::StorageLive(_) = statement.kind { - LocalValue::Unallocated + LocalValue::Live(interpret::Operand::Immediate( + interpret::Immediate::Uninit, + )) } else { LocalValue::Dead }; diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index e3ab42d09ef..280ed17f03c 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -31,8 +31,8 @@ use crate::MirLint; use rustc_const_eval::const_eval::ConstEvalErr; use rustc_const_eval::interpret::{ self, compile_time_machine, AllocId, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, - LocalState, LocalValue, MemPlace, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, - Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind, + LocalState, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, + StackPopCleanup, StackPopUnwind, }; /// The maximum number of bytes that we'll allocate space for a local or the return value. @@ -229,15 +229,19 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } - fn access_local( - _ecx: &InterpCx<'mir, 'tcx, Self>, - frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, + fn access_local<'a>( + frame: &'a Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, local: Local, - ) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> { + ) -> InterpResult<'tcx, &'a interpret::Operand<Self::PointerTag>> { let l = &frame.locals[local]; - if l.value == LocalValue::Unallocated { - throw_machine_stop_str!("tried to access an uninitialized local") + if matches!( + l.value, + LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit)) + ) { + // For us "uninit" means "we don't know its value, might be initiailized or not". + // So stop here. + throw_machine_stop_str!("tried to access a local with unknown value") } l.access() @@ -247,8 +251,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> ecx: &'a mut InterpCx<'mir, 'tcx, Self>, frame: usize, local: Local, - ) -> InterpResult<'tcx, Result<&'a mut LocalValue<Self::PointerTag>, MemPlace<Self::PointerTag>>> - { + ) -> InterpResult<'tcx, &'a mut interpret::Operand<Self::PointerTag>> { if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation { throw_machine_stop_str!("tried to write to a local that is marked as not propagatable") } @@ -384,7 +387,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { .layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs)) .ok() // Don't bother allocating memory for large values. - .filter(|ret_layout| ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)) + // I don't know how return types can seem to be unsized but this happens in the + // `type/type-unsatisfiable.rs` test. + .filter(|ret_layout| { + !ret_layout.is_unsized() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) + }) .unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap()); let ret = ecx @@ -430,8 +437,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Remove `local` from the pool of `Locals`. Allows writing to them, /// but not reading from them anymore. fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) { - ecx.frame_mut().locals[local] = - LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) }; + ecx.frame_mut().locals[local] = LocalState { + value: LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit)), + layout: Cell::new(None), + }; } fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> { @@ -915,7 +924,9 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { let frame = self.ecx.frame_mut(); frame.locals[local].value = if let StatementKind::StorageLive(_) = statement.kind { - LocalValue::Unallocated + LocalValue::Live(interpret::Operand::Immediate( + interpret::Immediate::Uninit, + )) } else { LocalValue::Dead }; diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 510f1e64ed1..759ea7cd328 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -80,7 +80,7 @@ impl CoverageGraph { IndexVec<BasicCoverageBlock, BasicCoverageBlockData>, IndexVec<BasicBlock, Option<BasicCoverageBlock>>, ) { - let num_basic_blocks = mir_body.num_nodes(); + let num_basic_blocks = mir_body.basic_blocks.len(); let mut bcbs = IndexVec::with_capacity(num_basic_blocks); let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks); @@ -95,7 +95,7 @@ impl CoverageGraph { let mut basic_blocks = Vec::new(); for (bb, data) in mir_cfg_without_unwind { if let Some(last) = basic_blocks.last() { - let predecessors = &mir_body.predecessors()[bb]; + let predecessors = &mir_body.basic_blocks.predecessors()[bb]; if predecessors.len() > 1 || !predecessors.contains(last) { // The `bb` has more than one _incoming_ edge, and should start its own // `BasicCoverageBlockData`. (Note, the `basic_blocks` vector does not yet diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 782b620e28f..88ad5b7ef14 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -15,7 +15,6 @@ use spans::{CoverageSpan, CoverageSpans}; use crate::MirPass; use rustc_data_structures::graph::WithNumNodes; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; use rustc_middle::hir; @@ -576,12 +575,6 @@ fn get_body_span<'tcx>( fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. - let mut hcx = tcx.create_no_span_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); let owner = hir_body.id().hir_id.owner; - let bodies = &tcx.hir_owner_nodes(owner).unwrap().bodies; - hcx.with_hir_bodies(false, owner, bodies, |hcx| { - hir_body.value.hash_stable(hcx, &mut stable_hasher) - }); - stable_hasher.finish() + tcx.hir_owner_nodes(owner).unwrap().hash_including_bodies.to_smaller_hash() } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 82070b90325..423e78317aa 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -321,7 +321,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { } fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> { - let mut initial_spans = Vec::<CoverageSpan>::with_capacity(self.mir_body.num_nodes() * 2); + let mut initial_spans = + Vec::<CoverageSpan>::with_capacity(self.mir_body.basic_blocks.len() * 2); for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() { initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data)); } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 213bb6608e1..6380f03528a 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -222,6 +222,7 @@ fn print_mir_graphviz(name: &str, mir_body: &Body<'_>) { bb, debug::term_type(&data.terminator().kind), mir_body + .basic_blocks .successors(bb) .map(|successor| { format!(" {:?} -> {:?};", bb, successor) }) .join("\n") diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index c96497abf8f..9163672f570 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -66,7 +66,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS return; } - let bbs = body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate().0; + let bbs = body.basic_blocks.as_mut_preserves_cfg(); for Location { block, statement_index } in patch { bbs[block].statements[statement_index].make_nop(); } diff --git a/compiler/rustc_mir_transform/src/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs index 01f490e23bf..b93fe5879f4 100644 --- a/compiler/rustc_mir_transform/src/deaggregator.rs +++ b/compiler/rustc_mir_transform/src/deaggregator.rs @@ -11,9 +11,7 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let (basic_blocks, local_decls, _) = - body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); - let local_decls = &*local_decls; + let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); for bb in basic_blocks { bb.expand_statements(|stmt| { // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL). @@ -38,7 +36,7 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { Some(expand_aggregate( lhs, operands.into_iter().map(|op| { - let ty = op.ty(local_decls, tcx); + let ty = op.ty(&body.local_decls, tcx); (op, ty) }), *kind, diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index a80d2fbd644..44e3945d6fc 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -110,13 +110,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { let patch = MirPatch::new(body); - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + let local_decls = &mut body.local_decls; let mut visitor = ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch }; for (block, BasicBlockData { statements, terminator, .. }) in - basic_blocks.iter_enumerated_mut() + body.basic_blocks.as_mut().iter_enumerated_mut() { let mut index = 0; for statement in statements { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 12f5764152e..8f049a182ee 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -588,7 +588,7 @@ impl<'tcx> Inliner<'tcx> { ); expn_data.def_site = callee_body.span; let expn_data = - LocalExpnId::fresh(expn_data, self.tcx.create_stable_hashing_context()); + self.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); let mut integrator = Integrator { args: &args, new_locals: Local::new(caller_body.local_decls.len()).., diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs index ea10ec5f25c..2f3c65869ef 100644 --- a/compiler/rustc_mir_transform/src/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -16,9 +16,8 @@ impl<'tcx> MirPass<'tcx> for InstCombine { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); - let ctx = InstCombineContext { tcx, local_decls }; - for block in basic_blocks.iter_mut() { + let ctx = InstCombineContext { tcx, local_decls: &body.local_decls }; + for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { match statement.kind { StatementKind::Assign(box (_place, ref mut rvalue)) => { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9776cd0ab8b..0887775aae5 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -173,7 +173,7 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> { intravisit::walk_struct_def(self, v) } } - tcx.hir().deep_visit_all_item_likes(&mut GatherCtors { tcx, set: &mut set }); + tcx.hir().visit_all_item_likes_in_crate(&mut GatherCtors { tcx, set: &mut set }); set } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 989b94b68c1..b7ba616510c 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -11,8 +11,8 @@ pub struct LowerIntrinsics; impl<'tcx> MirPass<'tcx> for LowerIntrinsics { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); - for block in basic_blocks { + let local_decls = &body.local_decls; + for block in body.basic_blocks.as_mut() { let terminator = block.terminator.as_mut().unwrap(); if let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 813ab4001a7..47848cfa497 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -27,12 +27,10 @@ pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { }; // The one successor remains unchanged, so no need to invalidate - let (basic_blocks, local_decls, _) = - body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); - + let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); for block in basic_blocks { // lower `<[_]>::len` calls - lower_slice_len_call(tcx, block, &*local_decls, slice_len_fn_item_def_id); + lower_slice_len_call(tcx, block, &body.local_decls, slice_len_fn_item_def_id); } } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 7cd7d26328a..a0ba69c89b0 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { let def_id = body.source.def_id(); let param_env = tcx.param_env(def_id); - let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut(); + let bbs = body.basic_blocks.as_mut(); let mut should_cleanup = false; 'outer: for bb_idx in bbs.indices() { if !tcx.consider_optimizing(|| format!("MatchBranchSimplification {:?} ", def_id)) { @@ -108,7 +108,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { // Introduce a temporary for the discriminant value. let source_info = bbs[bb_idx].terminator().source_info; - let discr_local = local_decls.push(LocalDecl::new(switch_ty, source_info.span)); + let discr_local = body.local_decls.push(LocalDecl::new(switch_ty, source_info.span)); // We already checked that first and second are different blocks, // and bb_idx has a different terminator from both of them. diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 3396a446df2..c0217a10541 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -33,8 +33,8 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // We don't ever touch terminators, so no need to invalidate the CFG cache - let (basic_blocks, local_decls, _) = - body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); + let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); + let local_decls = &mut body.local_decls; // do a preliminary analysis to see if we ever have locals of type `[T;N]` or `&[T;N]` let mut interesting_locals = BitSet::new_empty(local_decls.len()); diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index d29d17399af..bb063915f55 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -133,7 +133,7 @@ fn find_local_assigned_to_return_place( return local; } - match body.predecessors()[block].as_slice() { + match body.basic_blocks.predecessors()[block].as_slice() { &[pred] => block = pred, _ => return None, } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index 5bb4f8bb9b3..dbe082e9093 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -17,7 +17,7 @@ impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers { } trace!("Running RemoveStorageMarkers on {:?}", body.source); - for data in body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate().0 { + for data in body.basic_blocks.as_mut_preserves_cfg() { data.statements.retain(|statement| match statement.kind { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 921a11a3a06..84ccf6e1f61 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -20,11 +20,10 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { let param_env = tcx.param_env_reveal_all_normalized(did); let mut should_simplify = false; - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); - for block in basic_blocks { + for block in body.basic_blocks.as_mut() { let terminator = block.terminator_mut(); if let TerminatorKind::Drop { place, target, .. } = terminator.kind { - let ty = place.ty(local_decls, tcx); + let ty = place.ty(&body.local_decls, tcx); if ty.ty.needs_drop(tcx, param_env) { continue; } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 34941c1907d..40be4f146db 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -18,9 +18,9 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { return; } let param_env = tcx.param_env(body.source.def_id()); - let (basic_blocks, local_decls, _) = - body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); - for block in basic_blocks.iter_mut() { + let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); + let local_decls = &body.local_decls; + for block in basic_blocks { for statement in block.statements.iter_mut() { if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) = statement.kind diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 33ea1c4ba2f..194c2794aac 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -61,7 +61,7 @@ impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { /// Returns the amount of blocks that were duplicated pub fn separate_const_switch(body: &mut Body<'_>) -> usize { let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new(); - let predecessors = body.predecessors(); + let predecessors = body.basic_blocks.predecessors(); 'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() { if let TerminatorKind::SwitchInt { discr: Operand::Copy(switch_place) | Operand::Move(switch_place), diff --git a/compiler/rustc_mir_transform/src/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs index 6902213ddad..fca9f7eeb24 100644 --- a/compiler/rustc_mir_transform/src/simplify_try.rs +++ b/compiler/rustc_mir_transform/src/simplify_try.rs @@ -386,14 +386,17 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { trace!("running SimplifyArmIdentity on {:?}", source); let local_uses = LocalUseCounter::get_local_uses(body); - let (basic_blocks, local_decls, debug_info) = - body.basic_blocks_local_decls_mut_and_var_debug_info(); - for bb in basic_blocks { + for bb in body.basic_blocks.as_mut() { if let Some(opt_info) = - get_arm_identity_info(&bb.statements, local_decls.len(), debug_info) + get_arm_identity_info(&bb.statements, body.local_decls.len(), &body.var_debug_info) { trace!("got opt_info = {:#?}", opt_info); - if !optimization_applies(&opt_info, local_decls, &local_uses, &debug_info) { + if !optimization_applies( + &opt_info, + &body.local_decls, + &local_uses, + &body.var_debug_info, + ) { debug!("optimization skipped for {:?}", source); continue; } @@ -431,7 +434,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { // Fix the debug info to point to the right local for dbg_index in opt_info.dbg_info_to_adjust { - let dbg_info = &mut debug_info[dbg_index]; + let dbg_info = &mut body.var_debug_info[dbg_index]; assert!( matches!(dbg_info.value, VarDebugInfoContents::Place(_)), "value was not a Place" diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 00002f6f59b..67e6402c0ae 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1353,7 +1353,16 @@ impl<'a> Parser<'a> { /// Parses `extern string_literal?`. fn parse_extern(&mut self) -> Extern { - if self.eat_keyword(kw::Extern) { Extern::from_abi(self.parse_abi()) } else { Extern::None } + if self.eat_keyword(kw::Extern) { + let mut extern_span = self.prev_token.span; + let abi = self.parse_abi(); + if let Some(abi) = abi { + extern_span = extern_span.to(abi.span); + } + Extern::from_abi(abi, extern_span) + } else { + Extern::None + } } /// Parses a string literal as an ABI spec. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8c123c052e5..d0723c68a77 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2428,7 +2428,7 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let check_attr_visitor = &mut CheckAttrVisitor { tcx }; - tcx.hir().deep_visit_item_likes_in_module(module_def_id, check_attr_visitor); + tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor); if module_def_id.is_top_level_module() { check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None); check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs()); diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 996ca66de0e..31c159c1f75 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -56,7 +56,7 @@ impl NonConstExpr { fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let mut vis = CheckConstVisitor::new(tcx); - tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut vis); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis); } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 23ff0a91159..9deb0042ff3 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,9 +1,9 @@ -use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit; use rustc_hir::{HirId, ItemLocalId}; +use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; @@ -15,32 +15,35 @@ pub fn check_crate(tcx: TyCtxt<'_>) { crate::hir_stats::print_hir_stats(tcx); } - let errors = Lock::new(Vec::new()); - let hir_map = tcx.hir(); + #[cfg(debug_assertions)] + { + let errors = Lock::new(Vec::new()); + let hir_map = tcx.hir(); - hir_map.par_for_each_module(|module_id| { - let mut v = HirIdValidator { - hir_map, - owner: None, - hir_ids_seen: Default::default(), - errors: &errors, - }; + hir_map.par_for_each_module(|module_id| { + let mut v = HirIdValidator { + hir_map, + owner: None, + hir_ids_seen: Default::default(), + errors: &errors, + }; - tcx.hir().deep_visit_item_likes_in_module(module_id, &mut v); - }); + tcx.hir().visit_item_likes_in_module(module_id, &mut v); + }); - let errors = errors.into_inner(); + let errors = errors.into_inner(); - if !errors.is_empty() { - let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message); + if !errors.is_empty() { + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); + tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message); + } } } struct HirIdValidator<'a, 'hir> { hir_map: Map<'hir>, owner: Option<LocalDefId>, - hir_ids_seen: FxHashSet<ItemLocalId>, + hir_ids_seen: GrowableBitSet<ItemLocalId>, errors: &'a Lock<Vec<String>>, } @@ -80,7 +83,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { if max != self.hir_ids_seen.len() - 1 { // Collect the missing ItemLocalIds let missing: Vec<_> = (0..=max as u32) - .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) + .filter(|&i| !self.hir_ids_seen.contains(ItemLocalId::from_u32(i))) .collect(); // Try to map those to something more useful @@ -106,7 +109,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { missing_items, self.hir_ids_seen .iter() - .map(|&local_id| HirId { owner, local_id }) + .map(|local_id| HirId { owner, local_id }) .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) .collect::<Vec<_>>() ) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 80a263f4cb2..0070c0699a4 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -140,7 +140,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { } fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx)); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx)); } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 9cfef26fd03..68b2a052391 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -31,7 +31,7 @@ struct CheckLoopVisitor<'a, 'hir> { } fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - tcx.hir().deep_visit_item_likes_in_module( + tcx.hir().visit_item_likes_in_module( module_def_id, &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }, ); diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 40844b84af0..20765abf392 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -14,7 +14,7 @@ use rustc_span::Span; use rustc_target::spec::abi::Abi; fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut CheckNakedFunctions { tcx }); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckNakedFunctions { tcx }); } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9eaefc8b8aa..12050dceb60 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -660,7 +660,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { /// Cross-references the feature names of unstable APIs with enabled /// features and possibly prints errors. fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut Checker { tcx }); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }); } pub(crate) fn provide(providers: &mut Providers) { @@ -890,7 +890,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let mut missing = MissingStabilityAnnotations { tcx, access_levels }; missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID)); tcx.hir().walk_toplevel_module(&mut missing); - tcx.hir().deep_visit_all_item_likes(&mut missing); + tcx.hir().visit_all_item_likes_in_crate(&mut missing); } let declared_lang_features = &tcx.features().declared_lang_features; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index cd91e402cac..5560d44aa0d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -467,7 +467,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { } let macro_module_def_id = self.tcx.local_parent(local_def_id); - if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) { + if self.tcx.opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) { // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252). return; } diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index b01c512a3b4..4c25075327f 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -653,12 +653,11 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId { #[cfg(debug_assertions)] { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - let mut hcx = decoder.tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - hcx.while_hashing_spans(true, |hcx| { - expn_id.expn_data().hash_stable(hcx, &mut hasher) + let local_hash: u64 = decoder.tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + expn_id.expn_data().hash_stable(&mut hcx, &mut hasher); + hasher.finish() }); - let local_hash: u64 = hasher.finish(); debug_assert_eq!(hash.local_hash(), local_hash); } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 307ad4e844b..333dc5aa668 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -282,17 +282,21 @@ macro_rules! define_queries { } else { Some(key.default_span(*tcx)) }; - // Use `tcx.hir().opt_def_kind()` to reduce the chance of - // accidentally triggering an infinite query loop. - let def_kind = key.key_as_def_id() - .and_then(|def_id| def_id.as_local()) - .and_then(|def_id| tcx.hir().opt_def_kind(def_id)); + let def_kind = if kind == dep_graph::DepKind::opt_def_kind { + // Try to avoid infinite recursion. + None + } else { + key.key_as_def_id() + .and_then(|def_id| def_id.as_local()) + .and_then(|def_id| tcx.opt_def_kind(def_id)) + }; let hash = || { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::<u64>() + tcx.with_stable_hashing_context(|mut hcx|{ + let mut hasher = StableHasher::new(); + std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); + key.hash_stable(&mut hcx, &mut hasher); + hasher.finish::<u64>() + }) }; QueryStackFrame::new(name, description, span, def_kind, hash) @@ -373,6 +377,17 @@ macro_rules! define_queries { } } + // We use this for the forever-red node. + pub fn Red() -> DepKindStruct { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + try_load_from_on_disk_cache: None, + } + } + pub fn TraitSelect() -> DepKindStruct { DepKindStruct { is_anon: true, diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index bb2179a2495..c6210095b60 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -131,12 +131,11 @@ where #[inline(always)] default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - - self.hash_stable(&mut hcx, &mut hasher); - - hasher.finish() + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }) } #[inline(always)] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 341cf8f827b..0da42fddd4c 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -43,6 +43,7 @@ rustc_index::newtype_index! { impl DepNodeIndex { pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0); + pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1); } impl std::convert::From<DepNodeIndex> for QueryInvocationId { @@ -124,6 +125,8 @@ impl<K: DepKind> DepGraph<K> { record_stats, ); + let colors = DepNodeColorMap::new(prev_graph_node_count); + // Instantiate a dependy-less node only once for anonymous queries. let _green_node_index = current.intern_new_node( profiler, @@ -131,7 +134,19 @@ impl<K: DepKind> DepGraph<K> { smallvec![], Fingerprint::ZERO, ); - debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); + assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); + + // Instantiate a dependy-less red node only once for anonymous queries. + let (_red_node_index, _prev_and_index) = current.intern_node( + profiler, + &prev_graph, + DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() }, + smallvec![], + None, + false, + ); + assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE); + assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red)))); DepGraph { data: Some(Lrc::new(DepGraphData { @@ -140,7 +155,7 @@ impl<K: DepKind> DepGraph<K> { current, processed_side_effects: Default::default(), previous: prev_graph, - colors: DepNodeColorMap::new(prev_graph_node_count), + colors, debug_loaded_from_disk: Default::default(), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), @@ -328,10 +343,8 @@ impl<K: DepKind> DepGraph<K> { let dcx = cx.dep_context(); let hashing_timer = dcx.profiler().incr_result_hashing(); - let current_fingerprint = hash_result.map(|f| { - let mut hcx = dcx.create_stable_hashing_context(); - f(&mut hcx, &result) - }); + let current_fingerprint = + hash_result.map(|f| dcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, &result))); let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; @@ -886,8 +899,12 @@ impl<K: DepKind> DepGraph<K> { #[derive(Clone, Debug, Encodable, Decodable)] pub struct WorkProduct { pub cgu_name: String, - /// Saved file associated with this CGU. - pub saved_file: String, + /// Saved files associated with this CGU. In each key/value pair, the value is the path to the + /// saved file and the key is some identifier for the type of file being saved. + /// + /// By convention, file extensions are currently used as identifiers, i.e. the key "o" maps to + /// the object file's path, and "dwo" to the dwarf object file's path. + pub saved_files: FxHashMap<String, String>, } // Index type for `DepNodeData`'s edges. @@ -967,6 +984,7 @@ impl<K: DepKind> CurrentDepGraph<K> { let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64; let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); + let anon_id_seed = stable_hasher.finish(); #[cfg(debug_assertions)] let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { @@ -1002,7 +1020,7 @@ impl<K: DepKind> CurrentDepGraph<K> { ) }), prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)), - anon_id_seed: stable_hasher.finish(), + anon_id_seed, #[cfg(debug_assertions)] forbidden_edge, total_read_count: AtomicU64::new(0), diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 5907ae309ca..342d95ca490 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -23,7 +23,7 @@ pub trait DepContext: Copy { type DepKind: self::DepKind; /// Create a hashing context for hashing new results. - fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; + fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; /// Access the DepGraph. fn dep_graph(&self) -> &DepGraph<Self::DepKind>; @@ -85,8 +85,12 @@ impl FingerprintStyle { /// Describe the different families of dependency nodes. pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable<FileEncoder> + 'static { + /// DepKind to use when incr. comp. is turned off. const NULL: Self; + /// DepKind to use to create the initial forever-red node. + const RED: Self; + /// Implementation of `std::fmt::Debug` for `DepNode`. fn debug_node(node: &DepNode<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result; diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 62a1f776fb3..843f6f9d703 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,4 +1,5 @@ use crate::ich; + use rustc_ast as ast; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; @@ -118,13 +119,13 @@ impl<'a> StableHashingContext<'a> { &mut self, hash_bodies: bool, owner: LocalDefId, - bodies: &'a SortedMap<hir::ItemLocalId, &'a hir::Body<'a>>, - f: impl FnOnce(&mut Self), + bodies: &SortedMap<hir::ItemLocalId, &hir::Body<'_>>, + f: impl FnOnce(&mut StableHashingContext<'_>), ) { - let prev = self.body_resolver; - self.body_resolver = BodyResolver::Traverse { hash_bodies, owner, bodies }; - f(self); - self.body_resolver = prev; + f(&mut StableHashingContext { + body_resolver: BodyResolver::Traverse { hash_bodies, owner, bodies }, + ..self.clone() + }); } #[inline] diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3e4c7ad9f8f..bbcd00be943 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -542,8 +542,7 @@ fn incremental_verify_ich<CTX, K, V: Debug>( debug!("BEGIN verify_ich({:?})", dep_node); let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { - let mut hcx = tcx.create_stable_hashing_context(); - f(&mut hcx, result) + tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) }); let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); debug!("END verify_ich({:?})", dep_node); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4fbbd9deaeb..ec9ae63ca36 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1499,10 +1499,16 @@ impl<'a> Resolver<'a> { && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind && let Some(span) = self.opt_span(def_id) { - err.span_help( - self.session.source_map().guess_head_span(span), - "consider adding `#[derive(Default)]` to this enum", - ); + let source_map = self.session.source_map(); + let head_span = source_map.guess_head_span(span); + if let Ok(head) = source_map.span_to_snippet(head_span) { + err.span_suggestion(head_span, "consider adding a derive", format!("#[derive(Default)]\n{head}"), Applicability::MaybeIncorrect); + } else { + err.span_help( + head_span, + "consider adding `#[derive(Default)]` to this enum", + ); + } } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( @@ -2589,8 +2595,10 @@ fn show_candidates( } else { "item".to_string() }; + let plural_descr = + if descr.ends_with("s") { format!("{}es", descr) } else { format!("{}s", descr) }; - let mut msg = format!("{}these {}s exist but are inaccessible", prefix, descr); + let mut msg = format!("{}these {} exist but are inaccessible", prefix, plural_descr); let mut has_colon = false; let mut spans = Vec::new(); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index ed5d1165c7d..557dbecfabe 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2539,12 +2539,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// "Constrained" basically means that it appears in any type but /// not amongst the inputs to a projection. In other words, `<&'a /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`. -fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxHashSet<LocalDefId>> { +fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<LocalDefId>> { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?; let generics = tcx.hir().get_generics(def_id)?; - let mut late_bound = FxHashSet::default(); + let mut late_bound = FxIndexSet::default(); let mut constrained_by_input = ConstrainedCollector::default(); for arg_ty in decl.inputs { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4e28d2b6001..65a2a18e02f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -173,6 +173,7 @@ symbols! { DebugTuple, Decodable, Decoder, + DecorateLint, Default, Deref, DiagnosticMessage, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 470438471cb..e3045c9321d 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -96,47 +96,48 @@ fn get_symbol_hash<'tcx>( let substs = instance.substs; debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs); - let mut hasher = StableHasher::new(); - let mut hcx = tcx.create_stable_hashing_context(); - - record_time(&tcx.sess.perf_stats.symbol_hash_time, || { - // the main symbol name is not necessarily unique; hash in the - // compiler's internal def-path, guaranteeing each symbol has a - // truly unique path - tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); - - // Include the main item-type. Note that, in this case, the - // assertions about `needs_subst` may not hold, but this item-type - // ought to be the same for every reference anyway. - assert!(!item_type.has_erasable_regions()); - hcx.while_hashing_spans(false, |hcx| { - item_type.hash_stable(hcx, &mut hasher); - - // If this is a function, we hash the signature as well. - // This is not *strictly* needed, but it may help in some - // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::FnDef(..) = item_type.kind() { - item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); - } + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + + record_time(&tcx.sess.perf_stats.symbol_hash_time, || { + // the main symbol name is not necessarily unique; hash in the + // compiler's internal def-path, guaranteeing each symbol has a + // truly unique path + tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); + + // Include the main item-type. Note that, in this case, the + // assertions about `needs_subst` may not hold, but this item-type + // ought to be the same for every reference anyway. + assert!(!item_type.has_erasable_regions()); + hcx.while_hashing_spans(false, |hcx| { + item_type.hash_stable(hcx, &mut hasher); + + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::FnDef(..) = item_type.kind() { + item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); + } - // also include any type parameters (for generic items) - substs.hash_stable(hcx, &mut hasher); + // also include any type parameters (for generic items) + substs.hash_stable(hcx, &mut hasher); - if let Some(instantiating_crate) = instantiating_crate { - tcx.def_path_hash(instantiating_crate.as_def_id()) - .stable_crate_id() - .hash_stable(hcx, &mut hasher); - } + if let Some(instantiating_crate) = instantiating_crate { + tcx.def_path_hash(instantiating_crate.as_def_id()) + .stable_crate_id() + .hash_stable(hcx, &mut hasher); + } - // We want to avoid accidental collision between different types of instances. - // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original - // instances without this. - discriminant(&instance.def).hash_stable(hcx, &mut hasher); + // We want to avoid accidental collision between different types of instances. + // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original + // instances without this. + discriminant(&instance.def).hash_stable(hcx, &mut hasher); + }); }); - }); - // 64 bits should be enough to avoid collisions. - hasher.finish::<u64>() + // 64 bits should be enough to avoid collisions. + hasher.finish::<u64>() + }) } // Follow C++ namespace-mangling style, see diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 8fd58f3ce1a..8efefd476ab 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1112,18 +1112,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }) .collect::<Option<Vec<ArgKind>>>()?, ), - Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) - | Node::ImplItem(&hir::ImplItem { - span, - kind: hir::ImplItemKind::Fn(ref sig, _), - .. - }) + Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. }) + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) | Node::TraitItem(&hir::TraitItem { - span, - kind: hir::TraitItemKind::Fn(ref sig, _), - .. + kind: hir::TraitItemKind::Fn(ref sig, _), .. }) => ( - sm.guess_head_span(span), + sig.span, sig.decl .inputs .iter() @@ -1138,7 +1132,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ), Node::Ctor(ref variant_data) => { let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id)); - let span = sm.guess_head_span(span); (span, vec![ArgKind::empty(); variant_data.fields().len()]) } _ => panic!("non-FnLike node found: {:?}", node), @@ -2185,7 +2178,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let mut post = vec![]; for def_id in impls { match self.tcx.span_of_impl(*def_id) { - Ok(span) => spans.push(self.tcx.sess.source_map().guess_head_span(span)), + Ok(span) => spans.push(span), Err(name) => { crates.push(name); if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) { @@ -2532,8 +2525,7 @@ pub fn recursive_type_with_infinite_size_error<'tcx>( spans: Vec<(Span, Option<hir::HirId>)>, ) { assert!(type_def_id.is_local()); - let span = tcx.hir().span_if_local(type_def_id).unwrap(); - let span = tcx.sess.source_map().guess_head_span(span); + let span = tcx.def_span(type_def_id); let path = tcx.def_path_str(type_def_id); let mut err = struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a1861529b59..a80354897d6 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -16,9 +16,8 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, EmissionGuarantee}; +use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, ImplSubject, TyCtxt}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; @@ -341,10 +340,7 @@ fn report_negative_positive_conflict( positive_impl_def_id: DefId, sg: &mut specialization_graph::Graph, ) { - let impl_span = tcx - .sess - .source_map() - .guess_head_span(tcx.span_of_impl(local_impl_def_id.to_def_id()).unwrap()); + let impl_span = tcx.def_span(local_impl_def_id); let mut err = struct_span_err!( tcx.sess, @@ -357,10 +353,7 @@ fn report_negative_positive_conflict( match tcx.span_of_impl(negative_impl_def_id) { Ok(span) => { - err.span_label( - tcx.sess.source_map().guess_head_span(span), - "negative implementation here".to_string(), - ); + err.span_label(span, "negative implementation here"); } Err(cname) => { err.note(&format!("negative implementation in crate `{}`", cname)); @@ -369,10 +362,7 @@ fn report_negative_positive_conflict( match tcx.span_of_impl(positive_impl_def_id) { Ok(span) => { - err.span_label( - tcx.sess.source_map().guess_head_span(span), - "positive implementation here".to_string(), - ); + err.span_label(span, "positive implementation here"); } Err(cname) => { err.note(&format!("positive implementation in crate `{}`", cname)); @@ -389,8 +379,7 @@ fn report_conflicting_impls( used_to_be_allowed: Option<FutureCompatOverlapErrorKind>, sg: &mut specialization_graph::Graph, ) { - let impl_span = - tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id.to_def_id()).unwrap()); + let impl_span = tcx.def_span(impl_def_id); // Work to be done after we've built the DiagnosticBuilder. We have to define it // now because the struct_lint methods don't return back the DiagnosticBuilder @@ -417,10 +406,7 @@ fn report_conflicting_impls( let mut err = err.build(&msg); match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { - err.span_label( - tcx.sess.source_map().guess_head_span(span), - "first implementation here".to_string(), - ); + err.span_label(span, "first implementation here".to_string()); err.span_label( impl_span, diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 703277ec66a..0a2b54eec47 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1958,9 +1958,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } - if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) { - let sp = tcx.sess.source_map().guess_head_span(sp); - err.span_label(sp, format!("variant `{}` not found here", assoc_ident)); + if adt_def.did().is_local() { + err.span_label( + tcx.def_span(adt_def.did()), + format!("variant `{assoc_ident}` not found for this enum"), + ); } err.emit() @@ -2450,7 +2452,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let msg = format!("`Self` is of type `{ty}`"); if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) { - let i_sp = tcx.sess.source_map().guess_head_span(i_sp); let mut span: MultiSpan = vec![t_sp].into(); span.push_span_label( i_sp, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 6ed2ce155d9..e9709b64d93 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -288,11 +288,9 @@ fn check_panic_info_fn( tcx.sess.span_err(decl.output.span(), "return type should be `!`"); } - let span = tcx.def_span(fn_id); let inputs = fn_sig.inputs(); if inputs.len() != 1 { - let span = tcx.sess.source_map().guess_head_span(span); - tcx.sess.span_err(span, "function should have one argument"); + tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); return; } @@ -345,9 +343,7 @@ fn check_alloc_error_fn( let inputs = fn_sig.inputs(); if inputs.len() != 1 { - let span = tcx.def_span(fn_id); - let span = tcx.sess.source_map().guess_head_span(span); - tcx.sess.span_err(span, "function should have one argument"); + tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); return; } @@ -1034,7 +1030,6 @@ fn check_impl_items_against_trait<'tcx>( compare_impl_method( tcx, &ty_impl_item, - impl_item.span, &ty_trait_item, impl_trait_ref, opt_trait_span, @@ -1094,17 +1089,20 @@ fn check_impl_items_against_trait<'tcx>( } if !missing_items.is_empty() { - let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); - missing_items_err(tcx, impl_span, &missing_items, full_impl_span); + missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span); } if let Some(missing_items) = must_implement_one_of { - let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); let attr_span = tcx .get_attr(impl_trait_ref.def_id, sym::rustc_must_implement_one_of) .map(|attr| attr.span); - missing_items_must_implement_one_of_err(tcx, impl_span, missing_items, attr_span); + missing_items_must_implement_one_of_err( + tcx, + tcx.def_span(impl_id), + missing_items, + attr_span, + ); } } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 0a9b6863ef5..2bfb9343877 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -33,14 +33,13 @@ use super::{potentially_plural_count, FnCtxt, Inherited}; pub(crate) fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, - impl_m_span: Span, trait_m: &ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, trait_item_span: Option<Span>, ) { debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); - let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span); + let impl_m_span = tcx.def_span(impl_m.def_id); if let Err(_) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) { return; @@ -444,13 +443,9 @@ fn check_region_bounds_on_impl_item<'tcx>( .as_local() .and_then(|did| tcx.hir().get_generics(did)) .map_or(def_span, |g| g.span); - let generics_span = tcx.hir().span_if_local(trait_m.def_id).map(|sp| { - let def_sp = tcx.sess.source_map().guess_head_span(sp); - trait_m - .def_id - .as_local() - .and_then(|did| tcx.hir().get_generics(did)) - .map_or(def_sp, |g| g.span) + let generics_span = trait_m.def_id.as_local().map(|did| { + let def_sp = tcx.def_span(did); + tcx.hir().get_generics(did).map_or(def_sp, |g| g.span) }); let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait { @@ -1044,8 +1039,7 @@ fn compare_generic_param_kinds<'tcx>( err.span_label(trait_header_span, ""); err.span_label(param_trait_span, make_param_message("expected", param_trait)); - let impl_header_span = - tcx.sess.source_map().guess_head_span(tcx.def_span(tcx.parent(impl_item.def_id))); + let impl_header_span = tcx.def_span(tcx.parent(impl_item.def_id)); err.span_label(impl_header_span, ""); err.span_label(param_impl_span, make_param_message("found", param_impl)); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 7195da863db..edb0ec027a0 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -184,9 +184,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if let (ty::FnDef(def_id, ..), true) = (&found.kind(), self.suggest_fn_call(err, expr, expected, found)) { - if let Some(sp) = self.tcx.hir().span_if_local(*def_id) { - let sp = self.sess().source_map().guess_head_span(sp); - err.span_label(sp, &format!("{} defined here", found)); + if def_id.is_local() { + err.span_label(self.tcx.def_span(def_id), &format!("{} defined here", found)); } } else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) { let is_struct_pat_shorthand_field = diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index e7a2b32571c..4e1a105fc71 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -121,11 +121,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) else { continue; }; - let note_span = self - .tcx - .hir() - .span_if_local(item.def_id) - .or_else(|| self.tcx.hir().span_if_local(impl_did)); + + let note_span = if item.def_id.is_local() { + Some(self.tcx.def_span(item.def_id)) + } else if impl_did.is_local() { + Some(self.tcx.def_span(impl_did)) + } else { + None + }; let impl_ty = self.tcx.at(span).type_of(impl_did); @@ -158,10 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Some(note_span) = note_span { // We have a span pointing to the method. Show note with snippet. - err.span_note( - self.tcx.sess.source_map().guess_head_span(note_span), - ¬e_str, - ); + err.span_note(note_span, ¬e_str); } else { err.note(¬e_str); } @@ -197,11 +197,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } CandidateSource::Trait(trait_did) => { let Some(item) = self.associated_value(trait_did, item_name) else { continue }; - let item_span = self - .tcx - .sess - .source_map() - .guess_head_span(self.tcx.def_span(item.def_id)); + let item_span = self.tcx.def_span(item.def_id); let idx = if sources.len() > 1 { let msg = &format!( "candidate #{} is defined in the trait `{}`", @@ -471,9 +467,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement")); } } else if !unsatisfied_predicates.is_empty() { - let def_span = |def_id| { - self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) - }; let mut type_params = FxHashMap::default(); // Pick out the list of unimplemented traits on the receiver. @@ -564,22 +557,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); match &self_ty.kind() { // Point at the type that couldn't satisfy the bound. - ty::Adt(def, _) => bound_spans.push((def_span(def.did()), msg)), + ty::Adt(def, _) => { + bound_spans.push((self.tcx.def_span(def.did()), msg)) + } // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { for pred in preds.iter() { match pred.skip_binder() { - ty::ExistentialPredicate::Trait(tr) => { - bound_spans.push((def_span(tr.def_id), msg.clone())) - } + ty::ExistentialPredicate::Trait(tr) => bound_spans + .push((self.tcx.def_span(tr.def_id), msg.clone())), ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => {} } } } // Point at the closure that couldn't satisfy the bound. - ty::Closure(def_id, _) => bound_spans - .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))), + ty::Closure(def_id, _) => bound_spans.push(( + tcx.def_span(*def_id), + format!("doesn't satisfy `{}`", quiet), + )), _ => {} } }; @@ -1469,21 +1465,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }) .collect::<FxHashSet<_>>(); - let sm = self.tcx.sess.source_map(); let mut spans: MultiSpan = def_ids .iter() .filter_map(|def_id| { let span = self.tcx.def_span(*def_id); - if span.is_dummy() { None } else { Some(sm.guess_head_span(span)) } + if span.is_dummy() { None } else { Some(span) } }) .collect::<Vec<_>>() .into(); for pred in &preds { match pred.self_ty().kind() { - ty::Adt(def, _) => { + ty::Adt(def, _) if def.did().is_local() => { spans.push_span_label( - sm.guess_head_span(self.tcx.def_span(def.did())), + self.tcx.def_span(def.did()), format!("must implement `{}`", pred.trait_ref.print_only_trait_path()), ); } @@ -2090,9 +2085,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &potential_candidates[..] { [] => {} [trait_info] if trait_info.def_id.is_local() => { - let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap(); err.span_note( - self.tcx.sess.source_map().guess_head_span(span), + self.tcx.def_span(trait_info.def_id), &format!( "`{}` defines an item `{}`, perhaps you need to {} it", self.tcx.def_path_str(trait_info.def_id), diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 87f85a9842f..74546ed9080 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -747,14 +747,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (migration_string, migrated_variables_concat) = migration_suggestion_for_2229(self.tcx, &need_migrations); - let local_def_id = closure_def_id.expect_local(); - let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); - let closure_span = self.tcx.hir().span(closure_hir_id); - let closure_head_span = self.tcx.sess.source_map().guess_head_span(closure_span); + let closure_hir_id = + self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_head_span = self.tcx.def_span(closure_def_id); self.tcx.struct_span_lint_hir( lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_hir_id, - closure_head_span, + closure_head_span, |lint| { let mut diagnostics_builder = lint.build( &reasons.migration_message(), @@ -827,12 +826,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { migrated_variables_concat ); + let closure_span = self.tcx.hir().span_with_body(closure_hir_id); let mut closure_body_span = { // If the body was entirely expanded from a macro // invocation, i.e. the body is not contained inside the // closure span, then we walk up the expansion until we // find the span before the expansion. - let s = self.tcx.hir().span(body_id.hir_id); + let s = self.tcx.hir().span_with_body(body_id.hir_id); s.find_ancestor_inside(closure_span).unwrap_or(s) }; diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 623c2a15232..ae9ebe59091 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -9,7 +9,6 @@ use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; -use rustc_span::Span; use rustc_trait_selection::traits; mod builtin; @@ -18,11 +17,6 @@ mod inherent_impls_overlap; mod orphan; mod unsafety; -/// Obtains the span of just the impl header of `impl_def_id`. -fn impl_header_span(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Span { - tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id.to_def_id()).unwrap()) -} - fn check_impl(tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_ref: ty::TraitRef<'_>) { debug!( "(checking implementation) adding impl for trait '{:?}', item '{}'", @@ -47,56 +41,53 @@ fn enforce_trait_manually_implementable( ) { let did = Some(trait_def_id); let li = tcx.lang_items(); + let impl_header_span = tcx.def_span(impl_def_id); // Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now. if did == li.pointee_trait() { - let span = impl_header_span(tcx, impl_def_id); struct_span_err!( tcx.sess, - span, + impl_header_span, E0322, "explicit impls for the `Pointee` trait are not permitted" ) - .span_label(span, "impl of `Pointee` not allowed") + .span_label(impl_header_span, "impl of `Pointee` not allowed") .emit(); return; } if did == li.discriminant_kind_trait() { - let span = impl_header_span(tcx, impl_def_id); struct_span_err!( tcx.sess, - span, + impl_header_span, E0322, "explicit impls for the `DiscriminantKind` trait are not permitted" ) - .span_label(span, "impl of `DiscriminantKind` not allowed") + .span_label(impl_header_span, "impl of `DiscriminantKind` not allowed") .emit(); return; } if did == li.sized_trait() { - let span = impl_header_span(tcx, impl_def_id); struct_span_err!( tcx.sess, - span, + impl_header_span, E0322, "explicit impls for the `Sized` trait are not permitted" ) - .span_label(span, "impl of `Sized` not allowed") + .span_label(impl_header_span, "impl of `Sized` not allowed") .emit(); return; } if did == li.unsize_trait() { - let span = impl_header_span(tcx, impl_def_id); struct_span_err!( tcx.sess, - span, + impl_header_span, E0328, "explicit impls for the `Unsize` trait are not permitted" ) - .span_label(span, "impl of `Unsize` not allowed") + .span_label(impl_header_span, "impl of `Unsize` not allowed") .emit(); return; } @@ -110,10 +101,9 @@ fn enforce_trait_manually_implementable( tcx.trait_def(trait_def_id).specialization_kind { if !tcx.features().specialization && !tcx.features().min_specialization { - let span = impl_header_span(tcx, impl_def_id); tcx.sess .struct_span_err( - span, + impl_header_span, "implementing `rustc_specialization_trait` traits is unstable", ) .help("add `#![feature(min_specialization)]` to the crate attributes to enable") @@ -138,8 +128,13 @@ fn enforce_empty_impls_for_marker_traits( return; } - let span = impl_header_span(tcx, impl_def_id); - struct_span_err!(tcx.sess, span, E0715, "impls for marker traits cannot contain items").emit(); + struct_span_err!( + tcx.sess, + tcx.def_span(impl_def_id), + E0715, + "impls for marker traits cannot contain items" + ) + .emit(); } pub fn provide(providers: &mut Providers) { @@ -217,7 +212,7 @@ fn check_object_overlap<'tcx>( } else { let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id); if supertrait_def_ids.any(|d| d == trait_def_id) { - let span = impl_header_span(tcx, impl_def_id); + let span = tcx.def_span(impl_def_id); struct_span_err!( tcx.sess, span, diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index ef0a9a27a01..697ef7bc022 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -47,7 +47,7 @@ fn do_orphan_check_impl<'tcx>( let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!("{:?} is not an impl: {:?}", def_id, item); }; - let sp = tcx.sess.source_map().guess_head_span(item.span); + let sp = tcx.def_span(def_id); let tr = impl_.of_trait.as_ref().unwrap(); // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index a0cbb7c2c5a..44b9c8392f8 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -59,7 +59,7 @@ struct OnlySelfBounds(bool); // Main entry point fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx }); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx }); } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index b6d4f5fcda6..08c194ec0b6 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -223,15 +223,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().find(hir_id) { - Some(Node::Item(hir::Item { span: item_span, .. })) => { - Some(tcx.sess.source_map().guess_head_span(*item_span)) - } - _ => { - span_bug!(tcx.def_span(def_id), "main has a non-function type"); - } - } + Some(tcx.def_span(def_id)) } fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { @@ -416,7 +408,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { error = true; } if let hir::IsAsync::Async = sig.header.asyncness { - let span = tcx.sess.source_map().guess_head_span(it.span); + let span = tcx.def_span(it.def_id); struct_span_err!( tcx.sess, span, diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index a7dcbfff207..d79450e1ae7 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -64,74 +64,28 @@ pub fn add_constraints_from_crate<'a, 'tcx>( let crate_items = tcx.hir_crate_items(()); - for id in crate_items.items() { - constraint_cx.check_item(id); - } - - for id in crate_items.trait_items() { - if let DefKind::AssocFn = tcx.def_kind(id.def_id) { - constraint_cx.check_node_helper(id.hir_id()); - } - } - - for id in crate_items.impl_items() { - if let DefKind::AssocFn = tcx.def_kind(id.def_id) { - constraint_cx.check_node_helper(id.hir_id()); - } - } - - for id in crate_items.foreign_items() { - if let DefKind::Fn = tcx.def_kind(id.def_id) { - constraint_cx.check_node_helper(id.hir_id()); - } - } - - constraint_cx -} - -impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { - fn check_item(&mut self, id: hir::ItemId) { - let def_kind = self.tcx().def_kind(id.def_id); + for def_id in crate_items.definitions() { + let def_kind = tcx.def_kind(def_id); match def_kind { - DefKind::Struct | DefKind::Union => { - let item = self.tcx().hir().item(id); - - if let hir::ItemKind::Struct(ref struct_def, _) - | hir::ItemKind::Union(ref struct_def, _) = item.kind - { - self.check_node_helper(item.hir_id()); + DefKind::Struct | DefKind::Union | DefKind::Enum => { + constraint_cx.build_constraints_for_item(def_id); - if let hir::VariantData::Tuple(..) = *struct_def { - self.check_node_helper(struct_def.ctor_hir_id().unwrap()); + let adt = tcx.adt_def(def_id); + for variant in adt.variants() { + if let Some(ctor) = variant.ctor_def_id { + constraint_cx.build_constraints_for_item(ctor.expect_local()); } } } - DefKind::Enum => { - let item = self.tcx().hir().item(id); - - if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { - self.check_node_helper(item.hir_id()); - - for variant in enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.data { - self.check_node_helper(variant.data.ctor_hir_id().unwrap()); - } - } - } - } - DefKind::Fn => { - self.check_node_helper(id.hir_id()); - } + DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id), _ => {} } } - fn check_node_helper(&mut self, id: hir::HirId) { - let tcx = self.terms_cx.tcx; - let def_id = tcx.hir().local_def_id(id); - self.build_constraints_for_item(def_id); - } + constraint_cx +} +impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.terms_cx.tcx } @@ -145,8 +99,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { return; } - let id = tcx.hir().local_def_id_to_hir_id(def_id); - let inferred_start = self.terms_cx.inferred_starts[&id]; + let inferred_start = self.terms_cx.inferred_starts[&def_id]; let current_item = &CurrentItem { inferred_start }; match tcx.type_of(def_id).kind() { ty::Adt(def, _) => { @@ -372,8 +325,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } let (local, remote) = if let Some(def_id) = def_id.as_local() { - let id = self.tcx().hir().local_def_id_to_hir_id(def_id); - (Some(self.terms_cx.inferred_starts[&id]), None) + (Some(self.terms_cx.inferred_starts[&def_id]), None) } else { (None, Some(self.tcx().variances_of(def_id))) }; diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_typeck/src/variance/solve.rs index 1a4d88ced0e..97aca621aa2 100644 --- a/compiler/rustc_typeck/src/variance/solve.rs +++ b/compiler/rustc_typeck/src/variance/solve.rs @@ -96,8 +96,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { self.terms_cx .inferred_starts .iter() - .map(|(&id, &InferredIndex(start))| { - let def_id = tcx.hir().local_def_id(id); + .map(|(&def_id, &InferredIndex(start))| { let generics = tcx.generics_of(def_id); let count = generics.count(); diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_typeck/src/variance/terms.rs index ab64befe5dc..1f763011e06 100644 --- a/compiler/rustc_typeck/src/variance/terms.rs +++ b/compiler/rustc_typeck/src/variance/terms.rs @@ -10,9 +10,8 @@ // a variable. use rustc_arena::DroplessArena; -use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::HirIdMap; +use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; use rustc_middle::ty::{self, TyCtxt}; use std::fmt; @@ -52,11 +51,11 @@ pub struct TermsContext<'a, 'tcx> { // For marker types, UnsafeCell, and other lang items where // variance is hardcoded, records the item-id and the hardcoded // variance. - pub lang_items: Vec<(hir::HirId, Vec<ty::Variance>)>, + pub lang_items: Vec<(LocalDefId, Vec<ty::Variance>)>, // Maps from the node id of an item to the first inferred index // used for its type & region parameters. - pub inferred_starts: HirIdMap<InferredIndex>, + pub inferred_starts: LocalDefIdMap<InferredIndex>, // Maps from an InferredIndex to the term for that variable. pub inferred_terms: Vec<VarianceTermPtr<'a>>, @@ -81,32 +80,31 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>( // - https://rustc-dev-guide.rust-lang.org/variance.html let crate_items = tcx.hir_crate_items(()); - for id in crate_items.items() { - terms_cx.check_item(id); - } + for def_id in crate_items.definitions() { + debug!("add_inferreds for item {:?}", def_id); - for id in crate_items.trait_items() { - if let DefKind::AssocFn = tcx.def_kind(id.def_id) { - terms_cx.add_inferreds_for_item(id.hir_id()); - } - } + let def_kind = tcx.def_kind(def_id); - for id in crate_items.impl_items() { - if let DefKind::AssocFn = tcx.def_kind(id.def_id) { - terms_cx.add_inferreds_for_item(id.hir_id()); - } - } + match def_kind { + DefKind::Struct | DefKind::Union | DefKind::Enum => { + terms_cx.add_inferreds_for_item(def_id); - for id in crate_items.foreign_items() { - if let DefKind::Fn = tcx.def_kind(id.def_id) { - terms_cx.add_inferreds_for_item(id.hir_id()); + let adt = tcx.adt_def(def_id); + for variant in adt.variants() { + if let Some(ctor) = variant.ctor_def_id { + terms_cx.add_inferreds_for_item(ctor.expect_local()); + } + } + } + DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id), + _ => {} } } terms_cx } -fn lang_items(tcx: TyCtxt<'_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> { +fn lang_items(tcx: TyCtxt<'_>) -> Vec<(LocalDefId, Vec<ty::Variance>)> { let lang_items = tcx.lang_items(); let all = [ (lang_items.phantom_data(), vec![ty::Covariant]), @@ -114,18 +112,16 @@ fn lang_items(tcx: TyCtxt<'_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> { ]; all.into_iter() // iterating over (Option<DefId>, Variance) - .filter(|&(ref d, _)| d.is_some()) - .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance) .filter_map(|(d, v)| { - d.as_local().map(|d| tcx.hir().local_def_id_to_hir_id(d)).map(|n| (n, v)) - }) // (HirId, Variance) + let def_id = d?.as_local()?; // LocalDefId + Some((def_id, v)) + }) .collect() } impl<'a, 'tcx> TermsContext<'a, 'tcx> { - fn add_inferreds_for_item(&mut self, id: hir::HirId) { + fn add_inferreds_for_item(&mut self, def_id: LocalDefId) { let tcx = self.tcx; - let def_id = tcx.hir().local_def_id(id); let count = tcx.generics_of(def_id).count(); if count == 0 { @@ -134,7 +130,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { // Record the start of this item's inferreds. let start = self.inferred_terms.len(); - let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none(); + let newly_added = self.inferred_starts.insert(def_id, InferredIndex(start)).is_none(); assert!(newly_added); // N.B., in the code below for writing the results back into the @@ -146,42 +142,4 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { (start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))), ); } - - fn check_item(&mut self, id: hir::ItemId) { - debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(id.hir_id())); - - let def_kind = self.tcx.def_kind(id.def_id); - match def_kind { - DefKind::Struct | DefKind::Union => { - let item = self.tcx.hir().item(id); - - if let hir::ItemKind::Struct(ref struct_def, _) - | hir::ItemKind::Union(ref struct_def, _) = item.kind - { - self.add_inferreds_for_item(item.hir_id()); - - if let hir::VariantData::Tuple(..) = *struct_def { - self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap()); - } - } - } - DefKind::Enum => { - let item = self.tcx.hir().item(id); - - if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { - self.add_inferreds_for_item(item.hir_id()); - - for variant in enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.data { - self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap()); - } - } - } - } - DefKind::Fn => { - self.add_inferreds_for_item(id.hir_id()); - } - _ => {} - } - } } diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 778f06aeb63..7c5f82f5ea4 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -93,7 +93,7 @@ impl const From<char> for u128 { /// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing /// if the code point is greater than U+00FF. /// -/// See [`impl From<u8> for char`](char#impl-From<u8>) for details on the encoding. +/// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding. #[stable(feature = "u8_from_char", since = "1.59.0")] impl TryFrom<char> for u8 { type Error = TryFromCharError; @@ -229,7 +229,7 @@ impl TryFrom<u32> for char { /// The error type returned when a conversion from [`prim@u32`] to [`prim@char`] fails. /// -/// This `struct` is created by the [`char::try_from<u32>`](char#impl-TryFrom<u32>) method. +/// This `struct` is created by the [`char::try_from<u32>`](char#impl-TryFrom<u32>-for-char) method. /// See its documentation for more. #[stable(feature = "try_from", since = "1.34.0")] #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 1e4c22aea10..cf428e0b1cf 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -180,7 +180,7 @@ mod sip; /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html /// [`hash`]: Hash::hash -/// [impl]: ../../std/primitive.str.html#impl-Hash +/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Hash"] pub trait Hash { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 28ea45ed235..bca73cb770f 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -389,7 +389,7 @@ //! [`Option`] of a collection of each contained value of the original //! [`Option`] values, or [`None`] if any of the elements was [`None`]. //! -//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E +//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E-for-Option%3CV%3E //! //! ``` //! let v = [Some(2), Some(4), None, Some(8)]; @@ -405,8 +405,8 @@ //! to provide the [`product`][Iterator::product] and //! [`sum`][Iterator::sum] methods. //! -//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E -//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E +//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E-for-Option%3CT%3E +//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E-for-Option%3CT%3E //! //! ``` //! let v = [None, Some(1), Some(2), Some(3)]; diff --git a/library/core/src/result.rs b/library/core/src/result.rs index c4dc34fff97..8a68cdf7d65 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -459,7 +459,7 @@ //! [`Result`] of a collection of each contained value of the original //! [`Result`] values, or [`Err`] if any of the elements was [`Err`]. //! -//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E +//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E-for-Result%3CV%2C%20E%3E //! //! ``` //! let v = [Ok(2), Ok(4), Err("err!"), Ok(8)]; @@ -475,8 +475,8 @@ //! to provide the [`product`][Iterator::product] and //! [`sum`][Iterator::sum] methods. //! -//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E -//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E +//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E-for-Result%3CT%2C%20E%3E +//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E-for-Result%3CT%2C%20E%3E //! //! ``` //! let v = [Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")]; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 90e2dfd5d3d..bf8ce6971b8 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1451,6 +1451,347 @@ impl<T> AtomicPtr<T> { } Err(prev) } + + /// Offsets the pointer's address by adding `val` (in units of `T`), + /// returning the previous pointer. + /// + /// This is equivalent to using [`wrapping_add`] to atomically perform the + /// equivalent of `ptr = ptr.wrapping_add(val);`. + /// + /// This method operates in units of `T`, which means that it cannot be used + /// to offset the pointer by an amount which is not a multiple of + /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to + /// work with a deliberately misaligned pointer. In such cases, you may use + /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead. + /// + /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the + /// memory ordering of this operation. All ordering modes are possible. Note + /// that using [`Acquire`] makes the store part of this operation + /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_add`]: pointer::wrapping_add + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); + /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0); + /// // Note: units of `size_of::<i64>()`. + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { + self.fetch_byte_add(val.wrapping_mul(core::mem::size_of::<T>()), order) + } + + /// Offsets the pointer's address by subtracting `val` (in units of `T`), + /// returning the previous pointer. + /// + /// This is equivalent to using [`wrapping_sub`] to atomically perform the + /// equivalent of `ptr = ptr.wrapping_sub(val);`. + /// + /// This method operates in units of `T`, which means that it cannot be used + /// to offset the pointer by an amount which is not a multiple of + /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to + /// work with a deliberately misaligned pointer. In such cases, you may use + /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead. + /// + /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_sub`]: pointer::wrapping_sub + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let array = [1i32, 2i32]; + /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _); + /// + /// assert!(core::ptr::eq( + /// atom.fetch_ptr_sub(1, Ordering::Relaxed), + /// &array[1], + /// )); + /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0])); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { + self.fetch_byte_sub(val.wrapping_mul(core::mem::size_of::<T>()), order) + } + + /// Offsets the pointer's address by adding `val` *bytes*, returning the + /// previous pointer. + /// + /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically + /// perform `ptr = ptr.cast::<u8>().wrapping_add(val).cast::<T>()`. + /// + /// `fetch_byte_add` takes an [`Ordering`] argument which describes the + /// memory ordering of this operation. All ordering modes are possible. Note + /// that using [`Acquire`] makes the store part of this operation + /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_add`]: pointer::wrapping_add + /// [`cast`]: pointer::cast + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); + /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0); + /// // Note: in units of bytes, not `size_of::<i64>()`. + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { + #[cfg(not(bootstrap))] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_add(self.p.get(), core::ptr::invalid_mut(val), order).cast() + } + #[cfg(bootstrap)] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_add(self.p.get().cast::<usize>(), val, order) as *mut T + } + } + + /// Offsets the pointer's address by subtracting `val` *bytes*, returning the + /// previous pointer. + /// + /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically + /// perform `ptr = ptr.cast::<u8>().wrapping_sub(val).cast::<T>()`. + /// + /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the + /// memory ordering of this operation. All ordering modes are possible. Note + /// that using [`Acquire`] makes the store part of this operation + /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_sub`]: pointer::wrapping_sub + /// [`cast`]: pointer::cast + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let atom = AtomicPtr::<i64>::new(core::ptr::invalid_mut(1)); + /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1); + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { + #[cfg(not(bootstrap))] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_sub(self.p.get(), core::ptr::invalid_mut(val), order).cast() + } + #[cfg(bootstrap)] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_sub(self.p.get().cast::<usize>(), val, order) as *mut T + } + } + + /// Performs a bitwise "or" operation on the address of the current pointer, + /// and the argument `val`, and stores a pointer with provenance of the + /// current pointer and the resulting address. + /// + /// This is equivalent equivalent to using [`map_addr`] to atomically + /// perform `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged + /// pointer schemes to atomically set tag bits. + /// + /// **Caveat**: This operation returns the previous value. To compute the + /// stored value without losing provenance, you may use [`map_addr`]. For + /// example: `a.fetch_or(val).map_addr(|a| a | val)`. + /// + /// `fetch_or` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// This API and its claimed semantics are part of the Strict Provenance + /// experiment, see the [module documentation for `ptr`][crate::ptr] for + /// details. + /// + /// [`map_addr`]: pointer::map_addr + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let pointer = &mut 3i64 as *mut i64; + /// + /// let atom = AtomicPtr::<i64>::new(pointer); + /// // Tag the bottom bit of the pointer. + /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0); + /// // Extract and untag. + /// let tagged = atom.load(Ordering::Relaxed); + /// assert_eq!(tagged.addr() & 1, 1); + /// assert_eq!(tagged.map_addr(|p| p & !1), pointer); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { + #[cfg(not(bootstrap))] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_or(self.p.get(), core::ptr::invalid_mut(val), order).cast() + } + #[cfg(bootstrap)] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_or(self.p.get().cast::<usize>(), val, order) as *mut T + } + } + + /// Performs a bitwise "and" operation on the address of the current + /// pointer, and the argument `val`, and stores a pointer with provenance of + /// the current pointer and the resulting address. + /// + /// This is equivalent equivalent to using [`map_addr`] to atomically + /// perform `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged + /// pointer schemes to atomically unset tag bits. + /// + /// **Caveat**: This operation returns the previous value. To compute the + /// stored value without losing provenance, you may use [`map_addr`]. For + /// example: `a.fetch_and(val).map_addr(|a| a & val)`. + /// + /// `fetch_and` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// This API and its claimed semantics are part of the Strict Provenance + /// experiment, see the [module documentation for `ptr`][crate::ptr] for + /// details. + /// + /// [`map_addr`]: pointer::map_addr + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let pointer = &mut 3i64 as *mut i64; + /// // A tagged pointer + /// let atom = AtomicPtr::<i64>::new(pointer.map_addr(|a| a | 1)); + /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1); + /// // Untag, and extract the previously tagged pointer. + /// let untagged = atom.fetch_and(!1, Ordering::Relaxed) + /// .map_addr(|a| a & !1); + /// assert_eq!(untagged, pointer); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { + #[cfg(not(bootstrap))] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_and(self.p.get(), core::ptr::invalid_mut(val), order).cast() + } + #[cfg(bootstrap)] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_and(self.p.get().cast::<usize>(), val, order) as *mut T + } + } + + /// Performs a bitwise "xor" operation on the address of the current + /// pointer, and the argument `val`, and stores a pointer with provenance of + /// the current pointer and the resulting address. + /// + /// This is equivalent equivalent to using [`map_addr`] to atomically + /// perform `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged + /// pointer schemes to atomically toggle tag bits. + /// + /// **Caveat**: This operation returns the previous value. To compute the + /// stored value without losing provenance, you may use [`map_addr`]. For + /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`. + /// + /// `fetch_xor` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// This API and its claimed semantics are part of the Strict Provenance + /// experiment, see the [module documentation for `ptr`][crate::ptr] for + /// details. + /// + /// [`map_addr`]: pointer::map_addr + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let pointer = &mut 3i64 as *mut i64; + /// let atom = AtomicPtr::<i64>::new(pointer); + /// + /// // Toggle a tag bit on the pointer. + /// atom.fetch_xor(1, Ordering::Relaxed); + /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "95228")] + pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { + #[cfg(not(bootstrap))] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_xor(self.p.get(), core::ptr::invalid_mut(val), order).cast() + } + #[cfg(bootstrap)] + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_xor(self.p.get().cast::<usize>(), val, order) as *mut T + } + } } #[cfg(target_has_atomic_load_store = "8")] diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 7f8672f0354..13b12db209a 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -127,6 +127,91 @@ fn int_max() { assert_eq!(x.load(SeqCst), 0xf731); } +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn ptr_add_null() { + let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); + assert_eq!(atom.fetch_ptr_add(1, SeqCst).addr(), 0); + assert_eq!(atom.load(SeqCst).addr(), 8); + + assert_eq!(atom.fetch_byte_add(1, SeqCst).addr(), 8); + assert_eq!(atom.load(SeqCst).addr(), 9); + + assert_eq!(atom.fetch_ptr_sub(1, SeqCst).addr(), 9); + assert_eq!(atom.load(SeqCst).addr(), 1); + + assert_eq!(atom.fetch_byte_sub(1, SeqCst).addr(), 1); + assert_eq!(atom.load(SeqCst).addr(), 0); +} + +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn ptr_add_data() { + let num = 0i64; + let n = &num as *const i64 as *mut _; + let atom = AtomicPtr::<i64>::new(n); + assert_eq!(atom.fetch_ptr_add(1, SeqCst), n); + assert_eq!(atom.load(SeqCst), n.wrapping_add(1)); + + assert_eq!(atom.fetch_ptr_sub(1, SeqCst), n.wrapping_add(1)); + assert_eq!(atom.load(SeqCst), n); + let bytes_from_n = |b| n.cast::<u8>().wrapping_add(b).cast::<i64>(); + + assert_eq!(atom.fetch_byte_add(1, SeqCst), n); + assert_eq!(atom.load(SeqCst), bytes_from_n(1)); + + assert_eq!(atom.fetch_byte_add(5, SeqCst), bytes_from_n(1)); + assert_eq!(atom.load(SeqCst), bytes_from_n(6)); + + assert_eq!(atom.fetch_byte_sub(1, SeqCst), bytes_from_n(6)); + assert_eq!(atom.load(SeqCst), bytes_from_n(5)); + + assert_eq!(atom.fetch_byte_sub(5, SeqCst), bytes_from_n(5)); + assert_eq!(atom.load(SeqCst), n); +} + +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn ptr_bitops() { + let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); + assert_eq!(atom.fetch_or(0b0111, SeqCst).addr(), 0); + assert_eq!(atom.load(SeqCst).addr(), 0b0111); + + assert_eq!(atom.fetch_and(0b1101, SeqCst).addr(), 0b0111); + assert_eq!(atom.load(SeqCst).addr(), 0b0101); + + assert_eq!(atom.fetch_xor(0b1111, SeqCst).addr(), 0b0101); + assert_eq!(atom.load(SeqCst).addr(), 0b1010); +} + +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn ptr_bitops_tagging() { + #[repr(align(16))] + struct Tagme(u128); + + let tagme = Tagme(1000); + let ptr = &tagme as *const Tagme as *mut Tagme; + let atom: AtomicPtr<Tagme> = AtomicPtr::new(ptr); + + const MASK_TAG: usize = 0b1111; + const MASK_PTR: usize = !MASK_TAG; + + assert_eq!(ptr.addr() & MASK_TAG, 0); + + assert_eq!(atom.fetch_or(0b0111, SeqCst), ptr); + assert_eq!(atom.load(SeqCst), ptr.map_addr(|a| a | 0b111)); + + assert_eq!(atom.fetch_and(MASK_PTR | 0b0010, SeqCst), ptr.map_addr(|a| a | 0b111)); + assert_eq!(atom.load(SeqCst), ptr.map_addr(|a| a | 0b0010)); + + assert_eq!(atom.fetch_xor(0b1011, SeqCst), ptr.map_addr(|a| a | 0b0010)); + assert_eq!(atom.load(SeqCst), ptr.map_addr(|a| a | 0b1001)); + + assert_eq!(atom.fetch_and(MASK_PTR, SeqCst), ptr.map_addr(|a| a | 0b1001)); + assert_eq!(atom.load(SeqCst), ptr); +} + static S_FALSE: AtomicBool = AtomicBool::new(false); static S_TRUE: AtomicBool = AtomicBool::new(true); static S_INT: AtomicIsize = AtomicIsize::new(0); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9611e197a41..fe89dd8c88d 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -90,6 +90,7 @@ #![feature(slice_group_by)] #![feature(split_array)] #![feature(strict_provenance)] +#![feature(strict_provenance_atomic_ptr)] #![feature(trusted_random_access)] #![feature(unsize)] #![feature(unzip_option)] diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 345beb1824d..ff4e25b792a 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -73,7 +73,7 @@ pub trait FromRawFd { /// /// # Safety /// - /// The `fd` passed in must be a valid an open file descriptor. + /// The `fd` passed in must be a valid and open file descriptor. /// /// # Example /// diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index a6b75493e6e..073168cf2d2 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -234,3 +234,26 @@ impl ChildExt for process::Child { self.handle.main_thread_handle() } } + +/// Windows-specific extensions to [`process::ExitCode`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[unstable(feature = "windows_process_exit_code_from", issue = "none")] +pub trait ExitCodeExt: Sealed { + /// Creates a new `ExitCode` from the raw underlying `u32` return value of + /// a process. + /// + /// The exit code should not be 259, as this conflicts with the `STILL_ACTIVE` + /// macro returned from the `GetExitCodeProcess` function to signal that the + /// process has yet to run to completion. + #[unstable(feature = "windows_process_exit_code_from", issue = "none")] + fn from_raw(raw: u32) -> Self; +} + +#[unstable(feature = "windows_process_exit_code_from", issue = "none")] +impl ExitCodeExt for process::ExitCode { + fn from_raw(raw: u32) -> Self { + process::ExitCode::from_inner(From::from(raw)) + } +} diff --git a/library/std/src/process.rs b/library/std/src/process.rs index ab1a1e6c76f..d6cba7e7598 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1724,6 +1724,10 @@ impl crate::error::Error for ExitStatusError {} #[stable(feature = "process_exitcode", since = "1.61.0")] pub struct ExitCode(imp::ExitCode); +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl crate::sealed::Sealed for ExitCode {} + #[stable(feature = "process_exitcode", since = "1.61.0")] impl ExitCode { /// The canonical `ExitCode` for successful termination on this platform. @@ -1814,6 +1818,18 @@ impl From<u8> for ExitCode { } } +impl AsInner<imp::ExitCode> for ExitCode { + fn as_inner(&self) -> &imp::ExitCode { + &self.0 + } +} + +impl FromInner<imp::ExitCode> for ExitCode { + fn from_inner(s: imp::ExitCode) -> ExitCode { + ExitCode(s) + } +} + impl Child { /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] /// error is returned. diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 9fd399f4ba1..02d5af4719a 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -707,6 +707,12 @@ impl From<u8> for ExitCode { } } +impl From<u32> for ExitCode { + fn from(code: u32) -> Self { + ExitCode(c::DWORD::from(code)) + } +} + fn zeroed_startupinfo() -> c::STARTUPINFO { c::STARTUPINFO { cb: 0, diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index dc6a0f6f241..2e89abe202c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -346,11 +346,7 @@ impl StepDescription { eprintln!( "note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" ); - #[cfg(not(test))] - std::process::exit(1); - #[cfg(test)] - // so we can use #[should_panic] - panic!() + crate::detail_exit(1); } } } @@ -1008,7 +1004,7 @@ impl<'a> Builder<'a> { if !help_on_error.is_empty() { eprintln!("{}", help_on_error); } - std::process::exit(1); + crate::detail_exit(1); } } @@ -1437,7 +1433,7 @@ impl<'a> Builder<'a> { "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" ); eprintln!("help: try `rustup component add clippy`"); - std::process::exit(1); + crate::detail_exit(1); }); if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") { rustflags.arg("--cfg=bootstrap"); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 399be26d5ac..ed5023ac61b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -13,7 +13,7 @@ use std::fs; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; -use std::process::{exit, Command, Stdio}; +use std::process::{Command, Stdio}; use std::str; use serde::Deserialize; @@ -1377,7 +1377,7 @@ pub fn run_cargo( }); if !ok { - exit(1); + crate::detail_exit(1); } // Ok now we need to actually find all the files listed in `toplevel`. We've diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 2fc18c9e79e..e71fbff14dd 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -11,7 +11,7 @@ use std::ffi::OsStr; use std::fmt; use std::fs; use std::path::{Path, PathBuf}; -use std::process::{exit, Command}; +use std::process::Command; use std::str::FromStr; use crate::builder::{Builder, TaskPath}; @@ -805,8 +805,6 @@ impl Config { let get_toml = |_| TomlConfig::default(); #[cfg(not(test))] let get_toml = |file: &Path| { - use std::process; - let contents = t!(fs::read_to_string(file), format!("config file {} not found", file.display())); // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of @@ -817,7 +815,7 @@ impl Config { Ok(table) => table, Err(err) => { eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err); - process::exit(2); + crate::detail_exit(2); } } }; @@ -1487,7 +1485,7 @@ fn download_ci_rustc_commit( println!("help: maybe your repository history is too shallow?"); println!("help: consider disabling `download-rustc`"); println!("help: or fetch enough history to include one upstream commit"); - exit(1); + crate::detail_exit(1); } // Warn if there were changes to the compiler or standard library since the ancestor commit. diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 7ebae55efc1..eec19ab4fc9 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -4,7 +4,6 @@ //! has various flags to configure how it's run. use std::path::PathBuf; -use std::process; use getopts::Options; @@ -261,7 +260,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", // subcommand. println!("{}\n", subcommand_help); let exit_code = if args.is_empty() { 0 } else { 1 }; - process::exit(exit_code); + crate::detail_exit(exit_code); } }; @@ -347,7 +346,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", } else if verbose { panic!("No paths available for subcommand `{}`", subcommand.as_str()); } - process::exit(exit_code); + crate::detail_exit(exit_code); }; // Done specifying what options are possible, so do the getopts parsing @@ -379,7 +378,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", "Sorry, I couldn't figure out which subcommand you were trying to specify.\n\ You may need to move some options to after the subcommand.\n" ); - process::exit(1); + crate::detail_exit(1); } // Extra help text for some commands match subcommand { @@ -600,7 +599,7 @@ Arguments: eprintln!("error: {}", err); eprintln!("help: the available profiles are:"); eprint!("{}", Profile::all_for_help("- ")); - std::process::exit(1); + crate::detail_exit(1); }) } else { t!(crate::setup::interactive_path()) @@ -614,7 +613,7 @@ Arguments: || matches.opt_str("keep-stage-std").is_some() { eprintln!("--keep-stage not yet supported for x.py check"); - process::exit(1); + crate::detail_exit(1); } } @@ -805,7 +804,7 @@ fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> { Some("warn") => Some(false), Some(value) => { eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,); - process::exit(1); + crate::detail_exit(1); } None => None, } diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 60a53c28686..f25977c1d46 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -32,7 +32,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F code, run `./x.py fmt` instead.", cmd_debug, ); - std::process::exit(1); + crate::detail_exit(1); } } } @@ -114,7 +114,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { eprintln!("./x.py fmt is not supported on this channel"); - std::process::exit(1); + crate::detail_exit(1); }); assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); let src = build.src.clone(); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 73bd588472d..82025efcbe0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -109,7 +109,7 @@ use std::env; use std::fs::{self, File}; use std::io; use std::path::{Path, PathBuf}; -use std::process::{self, Command}; +use std::process::Command; use std::str; use filetime::FileTime; @@ -711,7 +711,7 @@ impl Build { for failure in failures.iter() { eprintln!(" - {}\n", failure); } - process::exit(1); + detail_exit(1); } #[cfg(feature = "build-metrics")] @@ -1617,7 +1617,7 @@ Alternatively, set `download-ci-llvm = true` in that `[llvm]` section to download LLVM rather than building it. " ); - std::process::exit(1); + detail_exit(1); } } @@ -1646,6 +1646,20 @@ fn chmod(path: &Path, perms: u32) { #[cfg(windows)] fn chmod(_path: &Path, _perms: u32) {} +/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.) +/// If the test is running and code is an error code, it will cause a panic. +fn detail_exit(code: i32) -> ! { + // Successful exit + if code == 0 { + std::process::exit(0); + } + if cfg!(test) { + panic!("status code: {}", code); + } else { + std::panic::resume_unwind(Box::new(code)); + } +} + impl Compiler { pub fn with_stage(mut self, stage: u32) -> Compiler { self.stage = stage; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 64c5dd7aea7..cae41286f08 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -104,7 +104,7 @@ You should install cmake, or set `download-ci-llvm = true` in the than building it. " ); - std::process::exit(1); + crate::detail_exit(1); } } diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 82f55440ce5..740c12ed725 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -94,7 +94,7 @@ pub fn setup(config: &Config, profile: Profile) { "note: this will use the configuration in {}", profile.include_path(&config.src).display() ); - std::process::exit(1); + crate::detail_exit(1); } let settings = format!( @@ -287,7 +287,7 @@ pub fn interactive_path() -> io::Result<Profile> { io::stdin().read_line(&mut input)?; if input.is_empty() { eprintln!("EOF on stdin, when expecting answer to question. Giving up."); - std::process::exit(1); + crate::detail_exit(1); } break match parse_with_abbrev(&input) { Ok(profile) => profile, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 6be3da55291..4c6b5ba0afc 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -673,7 +673,7 @@ impl Step for Clippy { } if !builder.config.cmd.bless() { - std::process::exit(1); + crate::detail_exit(1); } let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run"); @@ -1021,7 +1021,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, ); - std::process::exit(1); + crate::detail_exit(1); } crate::format::format(&builder, !builder.config.cmd.bless(), &[]); } @@ -1251,7 +1251,7 @@ help: to test the compiler, use `--stage 1` instead help: to test the standard library, use `--stage 0 library/std` instead note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." ); - std::process::exit(1); + crate::detail_exit(1); } let compiler = self.compiler; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 74a793d257e..23832b6c43e 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::env; use std::fs; use std::path::{Path, PathBuf}; -use std::process::{exit, Command}; +use std::process::Command; use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; use crate::channel::GitInfo; @@ -204,7 +204,7 @@ impl Step for ToolBuild { if !is_expected { if !is_optional_tool { - exit(1); + crate::detail_exit(1); } else { None } diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 3ee6a42d987..2cfeae7dc78 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -93,7 +93,7 @@ fn print_error(tool: &str, submodule: &str) { eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool); eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule); eprintln!("proper steps."); - std::process::exit(3); + crate::detail_exit(3); } fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) { @@ -108,7 +108,7 @@ fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) { Ok(o) => o, Err(e) => { eprintln!("Failed to get changed files: {:?}", e); - std::process::exit(1); + crate::detail_exit(1); } }; @@ -179,7 +179,7 @@ impl Step for ToolStateCheck { } if did_error { - std::process::exit(1); + crate::detail_exit(1); } check_changed_files(&toolstates); @@ -225,7 +225,7 @@ impl Step for ToolStateCheck { } if did_error { - std::process::exit(1); + crate::detail_exit(1); } if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6f4266a7f29..b627e503789 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -336,7 +336,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>( pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { if !try_run(cmd, print_cmd_on_fail) { - std::process::exit(1); + crate::detail_exit(1); } } @@ -375,7 +375,7 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { pub fn run_suppressed(cmd: &mut Command) { if !try_run_suppressed(cmd) { - std::process::exit(1); + crate::detail_exit(1); } } @@ -465,7 +465,7 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { fn fail(s: &str) -> ! { eprintln!("\n\n{}\n\n", s); - std::process::exit(1); + crate::detail_exit(1); } /// Copied from `std::path::absolute` until it stabilizes. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6ee725edcfc..efa73a79e99 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -629,6 +629,7 @@ fn clean_ty_generics<'tcx>( .params .iter() .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime if param.name == kw::UnderscoreLifetime => None, ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), ty::GenericParamDefKind::Type { synthetic, .. } => { if param.name == kw::SelfUpper { @@ -1704,8 +1705,8 @@ fn clean_ty<'tcx>(this: Ty<'tcx>, cx: &mut DocContext<'tcx>, def_id: Option<DefI ImplTrait(bounds) } - ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) - + ty::Closure(..) => panic!("Closure"), + ty::Generator(..) => panic!("Generator"), ty::Bound(..) => panic!("Bound"), ty::Placeholder(..) => panic!("Placeholder"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), @@ -1759,7 +1760,6 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool { match tcx.def_kind(parent) { DefKind::Struct | DefKind::Union => false, DefKind::Variant => true, - // FIXME: what about DefKind::Ctor? parent_kind => panic!("unexpected parent kind: {:?}", parent_kind), } } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index f0b54cb444d..272188f8299 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -239,9 +239,6 @@ pub(crate) struct RenderOptions { pub(crate) resource_suffix: String, /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by /// default. - // - // FIXME(misdreavus): the flag name is `--disable-minification` but the meaning is inverted - // once read. pub(crate) enable_minification: bool, /// Whether to create an index page in the root of the output directory. If this is true but /// `enable_index_page` is None, generate a static listing of crates instead. diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0982c4b3ace..84ab8d988bd 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -268,6 +268,12 @@ impl clean::Generics { } } +#[derive(Clone, Copy, PartialEq, Eq)] +pub(crate) enum Ending { + Newline, + NoNewline, +} + /// * The Generics from which to emit a where-clause. /// * The number of spaces to indent each line with. /// * Whether the where-clause needs to add a comma and newline after the last bound. @@ -275,7 +281,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( gens: &'a clean::Generics, cx: &'a Context<'tcx>, indent: usize, - end_newline: bool, + ending: Ending, ) -> impl fmt::Display + 'a + Captures<'tcx> { use fmt::Write; @@ -342,7 +348,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( let where_preds = comma_sep(where_predicates, false); let clause = if f.alternate() { - if end_newline { + if ending == Ending::Newline { // add a space so stripping <br> tags and breaking spaces still renders properly format!(" where{where_preds}, ") } else { @@ -356,7 +362,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( } let where_preds = where_preds.to_string().replace("<br>", &br_with_padding); - if end_newline { + if ending == Ending::Newline { let mut clause = " ".repeat(indent.saturating_sub(1)); // add a space so stripping <br> tags and breaking spaces still renders properly write!( @@ -1167,7 +1173,7 @@ impl clean::Impl { fmt_type(&self.for_, f, use_absolute, cx)?; } - fmt::Display::fmt(&print_where_clause(&self.generics, cx, 0, true), f)?; + fmt::Display::fmt(&print_where_clause(&self.generics, cx, 0, Ending::Newline), f)?; Ok(()) }) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 548f6c3a987..459b0fed6e8 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -70,7 +70,7 @@ use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ href, join_with_double_colon, print_abi_with_space, print_constness_with_space, - print_default_space, print_generic_bounds, print_where_clause, Buffer, HrefError, + print_default_space, print_generic_bounds, print_where_clause, Buffer, Ending, HrefError, PrintWithSpace, }; use crate::html::highlight; @@ -634,7 +634,6 @@ fn render_impls( &[], ImplRenderingParameters { show_def_docs: true, - is_on_foreign_type: false, show_default_items: true, show_non_assoc_items: true, toggle_open_by_default, @@ -748,7 +747,7 @@ fn assoc_type( if !bounds.is_empty() { write!(w, ": {}", print_generic_bounds(bounds, cx)) } - write!(w, "{}", print_where_clause(generics, cx, indent, false)); + write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); if let Some(default) = default { write!(w, " = {}", default.print(cx)) } @@ -797,10 +796,10 @@ fn assoc_method( header_len += 4; let indent_str = " "; render_attributes_in_pre(w, meth, indent_str); - (4, indent_str, false) + (4, indent_str, Ending::NoNewline) } else { render_attributes_in_code(w, meth); - (0, "", true) + (0, "", Ending::Newline) }; w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len()); write!( @@ -1071,7 +1070,6 @@ fn render_assoc_items_inner( &[], ImplRenderingParameters { show_def_docs: true, - is_on_foreign_type: false, show_default_items: true, show_non_assoc_items: true, toggle_open_by_default: true, @@ -1287,7 +1285,6 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { #[derive(Clone, Copy, Debug)] struct ImplRenderingParameters { show_def_docs: bool, - is_on_foreign_type: bool, show_default_items: bool, /// Whether or not to show methods. show_non_assoc_items: bool, @@ -1415,7 +1412,10 @@ fn render_impl( id, item_type, in_trait_class, ); render_rightside(w, cx, item, containing_item, render_mode); - write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + } w.write_str("<h4 class=\"code-header\">"); render_assoc_item( w, @@ -1438,7 +1438,10 @@ fn render_impl( id, item_type, in_trait_class ); render_rightside(w, cx, item, containing_item, render_mode); - write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + } w.write_str("<h4 class=\"code-header\">"); assoc_const( w, @@ -1460,7 +1463,10 @@ fn render_impl( let source_id = format!("{}.{}", item_type, name); let id = cx.derive_id(source_id.clone()); write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class); - write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + } w.write_str("<h4 class=\"code-header\">"); assoc_type( w, @@ -1483,7 +1489,10 @@ fn render_impl( "<section id=\"{}\" class=\"{}{} has-srclink\">", id, item_type, in_trait_class ); - write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); + } w.write_str("<h4 class=\"code-header\">"); assoc_type( w, @@ -1603,7 +1612,6 @@ fn render_impl( parent, rendering_params.show_def_docs, use_absolute, - rendering_params.is_on_foreign_type, aliases, ); if toggled { @@ -1688,21 +1696,12 @@ pub(crate) fn render_impl_summary( containing_item: &clean::Item, show_def_docs: bool, use_absolute: Option<bool>, - is_on_foreign_type: bool, // This argument is used to reference same type with different paths to avoid duplication // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], ) { - let id = cx.derive_id(match i.inner_impl().trait_ { - Some(ref t) => { - if is_on_foreign_type { - get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx) - } else { - format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx)))) - } - } - None => "impl".to_string(), - }); + let id = + cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx)); let aliases = if aliases.is_empty() { String::new() } else { @@ -1986,21 +1985,18 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let mut ret = impls .iter() .filter_map(|it| { - if let Some(ref i) = it.inner_impl().trait_ { - let i_display = format!("{:#}", i.print(cx)); - let out = Escape(&i_display); - let encoded = - id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx)))); - let prefix = match it.inner_impl().polarity { - ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", - ty::ImplPolarity::Negative => "!", - }; - let generated = - format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out); - if links.insert(generated.clone()) { Some(generated) } else { None } - } else { - None - } + let trait_ = it.inner_impl().trait_.as_ref()?; + let encoded = + id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx)); + + let i_display = format!("{:#}", trait_.print(cx)); + let out = Escape(&i_display); + let prefix = match it.inner_impl().polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", + ty::ImplPolarity::Negative => "!", + }; + let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out); + if links.insert(generated.clone()) { Some(generated) } else { None } }) .collect::<Vec<String>>(); ret.sort(); @@ -2147,12 +2143,11 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea } } -fn get_id_for_impl_on_foreign_type( - for_: &clean::Type, - trait_: &clean::Path, - cx: &Context<'_>, -) -> String { - small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx))) +fn get_id_for_impl(for_: &clean::Type, trait_: Option<&clean::Path>, cx: &Context<'_>) -> String { + match trait_ { + Some(t) => small_url_encode(format!("impl-{:#}-for-{:#}", t.print(cx), for_.print(cx))), + None => small_url_encode(format!("impl-{:#}", for_.print(cx))), + } } fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> { @@ -2161,10 +2156,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String i.trait_.as_ref().map(|trait_| { // Alternative format produces no URLs, // so this parameter does nothing. - ( - format!("{:#}", i.for_.print(cx)), - get_id_for_impl_on_foreign_type(&i.for_, trait_, cx), - ) + (format!("{:#}", i.for_.print(cx)), get_id_for_impl(&i.for_, Some(trait_), cx)) }) } _ => None, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3525007baf3..daacc57a55a 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -29,7 +29,7 @@ use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause, - Buffer, PrintWithSpace, + Buffer, Ending, PrintWithSpace, }; use crate::html::highlight; use crate::html::layout::Page; @@ -69,7 +69,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>( cx: &'a Context<'tcx>, ) -> bool { let len_before = buffer.len(); - write!(buffer, "{}", print_where_clause(gens, cx, 0, true)); + write!(buffer, "{}", print_where_clause(gens, cx, 0, Ending::Newline)); len_before != buffer.len() } @@ -519,7 +519,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle abi = abi, name = name, generics = f.generics.print(cx), - where_clause = print_where_clause(&f.generics, cx, 0, true), + where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline), decl = f.decl.full_print(header_len, 0, header.asyncness, cx), notable_traits = notable_traits_decl(&f.decl, cx), ); @@ -556,7 +556,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: ); if !t.generics.where_predicates.is_empty() { - write!(w, "{}", print_where_clause(&t.generics, cx, 0, true)); + write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline)); } else { w.write_str(" "); } @@ -864,7 +864,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: &[], ImplRenderingParameters { show_def_docs: false, - is_on_foreign_type: true, show_default_items: false, show_non_assoc_items: true, toggle_open_by_default: false, @@ -1026,7 +1025,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: & "trait {}{}{} = {};", it.name.unwrap(), t.generics.print(cx), - print_where_clause(&t.generics, cx, 0, true), + print_where_clause(&t.generics, cx, 0, Ending::Newline), bounds(&t.bounds, true, cx) ); }); @@ -1050,7 +1049,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl "type {}{}{where_clause} = impl {bounds};", it.name.unwrap(), t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, true), + where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), bounds = bounds(&t.bounds, false, cx), ); }); @@ -1075,7 +1074,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea "type {}{}{where_clause} = {type_};", it.name.unwrap(), t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, true), + where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), type_ = t.type_.print(cx), ); }); @@ -1642,7 +1641,6 @@ fn render_implementor( aliases, ImplRenderingParameters { show_def_docs: false, - is_on_foreign_type: false, show_default_items: false, show_non_assoc_items: false, toggle_open_by_default: false, @@ -1786,7 +1784,7 @@ fn render_struct( } w.write_str(")"); if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, false)); + write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline)); } // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. if structhead { @@ -1796,7 +1794,7 @@ fn render_struct( CtorKind::Const => { // Needed for PhantomData. if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, false)); + write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline)); } w.write_str(";"); } diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index e3b349af661..0172ef5700b 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -1,7 +1,8 @@ //! Validates syntax inside Rust code blocks (\`\`\`rust). use rustc_data_structures::sync::{Lock, Lrc}; -use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle}; -use rustc_middle::lint::LintDiagnosticBuilder; +use rustc_errors::{ + emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle, LintDiagnosticBuilder, +}; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; @@ -52,7 +53,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { None, None, ); - let expn_id = LocalExpnId::fresh(expn_data, self.cx.tcx.create_stable_hashing_context()); + let expn_id = + self.cx.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); let span = DUMMY_SP.fresh_expansion(expn_id); let is_empty = rustc_driver::catch_fatal_errors(|| { diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index f6c599297fc..c0fe8b49cfd 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -303,7 +303,7 @@ pub(crate) fn run( // Run call-finder on all items let mut calls = FxHashMap::default(); let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates }; - tcx.hir().deep_visit_all_item_likes(&mut finder); + tcx.hir().visit_all_item_likes_in_crate(&mut finder); // Sort call locations within a given file in document order for fn_calls in calls.values_mut() { diff --git a/src/llvm-project b/src/llvm-project -Subproject d1ddc34c4b23468f6d2bf553084834b104e16dd +Subproject 8b6b5014fdad3a750f7242a6bfdcad83619498d diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 74b1eb948b0..033da80be16 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -27,11 +27,11 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 14, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 14, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]], diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 3ec860f2cbc..9c9f5518b66 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -33,11 +33,11 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 14, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 14, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], diff --git a/src/test/incremental/async-lifetimes.rs b/src/test/incremental/async-lifetimes.rs new file mode 100644 index 00000000000..90a0b93b99a --- /dev/null +++ b/src/test/incremental/async-lifetimes.rs @@ -0,0 +1,19 @@ +// revisions: rpass1 rpass2 +// edition:2021 + +// See https://github.com/rust-lang/rust/issues/98890 + +#![allow(unused)] + +struct Foo; + +impl Foo { + async fn f(&self, _: &&()) -> &() { + &() + } +} + +#[cfg(rpass2)] +enum Bar {} + +fn main() {} diff --git a/src/test/incremental/split_debuginfo_cached.rs b/src/test/incremental/split_debuginfo_cached.rs new file mode 100644 index 00000000000..25c802d5a1d --- /dev/null +++ b/src/test/incremental/split_debuginfo_cached.rs @@ -0,0 +1,25 @@ +// Check that compiling with packed Split DWARF twice succeeds. This should confirm that DWARF +// objects are cached as work products and available to the incremental compilation for `thorin` to +// pack into a DWARF package. + +// ignore-tidy-linelength +// only-x86_64-unknown-linux-gnu +// revisions:rpass1 rpass2 + +// [rpass1]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split +// [rpass2]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split + +#![feature(rustc_attrs)] +// For `rpass2`, nothing has changed so everything should re-used. +#![rustc_partition_reused(module = "split_debuginfo_cached", cfg = "rpass2")] +#![rustc_partition_reused(module = "split_debuginfo_cached-another_module", cfg = "rpass2")] + +mod another_module { + pub fn foo() -> &'static str { + "hello world" + } +} + +pub fn main() { + println!("{}", another_module::foo()); +} diff --git a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir index 84ccf25ef75..c78c345dec2 100644 --- a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir +++ b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir @@ -14,22 +14,22 @@ }, } */ -fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6]) -> () { - let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 - let mut _2: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 +fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 10:17]) -> () { + let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 + let mut _2: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 let _3: std::string::String; // in scope 0 at $DIR/generator-drop-cleanup.rs:11:13: 11:15 let _4: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:12:9: 12:14 let mut _5: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:12:9: 12:14 let mut _6: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:18: 10:18 - let mut _7: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 - let mut _8: u32; // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + let mut _7: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 + let mut _8: u32; // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 scope 1 { debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:11:13: 11:15 } bb0: { - _8 = discriminant((*_1)); // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 - switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + _8 = discriminant((*_1)); // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 + switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb1: { @@ -44,11 +44,11 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1 } bb3: { - return; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + return; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb4 (cleanup): { - resume; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + resume; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb5 (cleanup): { @@ -57,11 +57,11 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1 } bb6: { - return; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + return; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb7: { - goto -> bb9; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + goto -> bb9; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb8: { @@ -69,16 +69,16 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1 } bb9: { - goto -> bb6; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + goto -> bb6; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb10: { - StorageLive(_4); // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 - StorageLive(_5); // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 - goto -> bb1; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + StorageLive(_4); // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 + StorageLive(_5); // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 + goto -> bb1; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } bb11: { - return; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 + return; // scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 10:17 } } diff --git a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir index 739492d7d24..9abb0cf2046 100644 --- a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir +++ b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 28:6], _2: ()) -> () +fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 22:18], _2: ()) -> () yields () { let mut _0: (); // return place in scope 0 at $DIR/generator-storage-dead-unwind.rs:22:19: 22:19 @@ -66,7 +66,7 @@ yields () } bb4: { - return; // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:6: 28:6 + return; // scope 0 at $DIR/generator-storage-dead-unwind.rs:22:18: 22:18 } bb5: { @@ -82,7 +82,7 @@ yields () } bb7: { - generator_drop; // scope 0 at $DIR/generator-storage-dead-unwind.rs:22:16: 28:6 + generator_drop; // scope 0 at $DIR/generator-storage-dead-unwind.rs:22:16: 22:18 } bb8 (cleanup): { @@ -104,7 +104,7 @@ yields () } bb11 (cleanup): { - resume; // scope 0 at $DIR/generator-storage-dead-unwind.rs:22:16: 28:6 + resume; // scope 0 at $DIR/generator-storage-dead-unwind.rs:22:16: 22:18 } bb12 (cleanup): { diff --git a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir index 7f5ebe2a59b..ce587433617 100644 --- a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir +++ b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir @@ -14,31 +14,31 @@ }, } */ -fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]>, _2: u8) -> GeneratorState<(), ()> { +fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]>, _2: u8) -> GeneratorState<(), ()> { debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 - let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 let _3: HasDrop; // in scope 0 at $DIR/generator-tiny.rs:20:13: 20:15 let mut _4: !; // in scope 0 at $DIR/generator-tiny.rs:21:9: 24:10 - let mut _5: (); // in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + let mut _5: (); // in scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 let _6: u8; // in scope 0 at $DIR/generator-tiny.rs:22:13: 22:18 let mut _7: (); // in scope 0 at $DIR/generator-tiny.rs:22:13: 22:18 let _8: (); // in scope 0 at $DIR/generator-tiny.rs:23:13: 23:21 let mut _9: (); // in scope 0 at $DIR/generator-tiny.rs:19:25: 19:25 let _10: u8; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 - let mut _11: u32; // in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + let mut _11: u32; // in scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 scope 1 { - debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:20:13: 20:15 + debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:20:13: 20:15 } bb0: { - _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 - switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]))); // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 + switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 } bb1: { - _10 = move _2; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + _10 = move _2; // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 nop; // scope 0 at $DIR/generator-tiny.rs:20:13: 20:15 - Deinit((((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6])) as variant#3).0: HasDrop)); // scope 0 at $DIR/generator-tiny.rs:20:18: 20:25 + Deinit((((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop)); // scope 0 at $DIR/generator-tiny.rs:20:18: 20:25 StorageLive(_4); // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10 goto -> bb2; // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10 } @@ -50,7 +50,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6] Deinit(_0); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 discriminant(_0) = 0; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 - discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 + discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 return; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 } @@ -71,14 +71,14 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6] } bb5: { - StorageLive(_4); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 - StorageLive(_6); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 - StorageLive(_7); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 - _6 = move _2; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 - goto -> bb3; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + StorageLive(_4); // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 + StorageLive(_6); // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 + StorageLive(_7); // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 + _6 = move _2; // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 + goto -> bb3; // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 } bb6: { - unreachable; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + unreachable; // scope 0 at $DIR/generator-tiny.rs:19:16: 19:24 } } diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index c6b49b66dc5..fc8118d475a 100644 --- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -19,8 +19,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) { debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:10:17: 10:18 let mut _10: i32; // in scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 let mut _11: T; // in scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 - let mut _12: &i32; // in scope 2 at $DIR/inline-closure-captures.rs:11:13: 11:24 - let mut _13: &T; // in scope 2 at $DIR/inline-closure-captures.rs:11:13: 11:24 + let mut _12: &i32; // in scope 2 at $DIR/inline-closure-captures.rs:11:13: 11:17 + let mut _13: &T; // in scope 2 at $DIR/inline-closure-captures.rs:11:13: 11:17 } } @@ -33,8 +33,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) { Deinit(_3); // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 (_3.0: &i32) = move _4; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 (_3.1: &T) = move _5; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 - StorageDead(_5); // scope 0 at $DIR/inline-closure-captures.rs:11:23: 11:24 - StorageDead(_4); // scope 0 at $DIR/inline-closure-captures.rs:11:23: 11:24 + StorageDead(_5); // scope 0 at $DIR/inline-closure-captures.rs:11:16: 11:17 + StorageDead(_4); // scope 0 at $DIR/inline-closure-captures.rs:11:16: 11:17 StorageLive(_6); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:6 _6 = &_3; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:6 StorageLive(_7); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 3e1c4a46701..51994323c45 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -4,22 +4,22 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline-generator.rs:8:11: 8:11 let _1: std::ops::GeneratorState<i32, bool>; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11 - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32 - let mut _3: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31 - let mut _4: [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31 + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32 + let mut _3: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31 + let mut _4: [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31 + let mut _7: bool; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:46 scope 1 { debug _r => _1; // in scope 1 at $DIR/inline-generator.rs:9:9: 9:11 } + scope 2 (inlined g) { // at $DIR/inline-generator.rs:9:28: 9:31 + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32 ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32 + debug pointer => _3; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL -+ let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL ++ let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new_unchecked) { // at $SRC_DIR/core/src/pin.rs:LL:COL ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new_unchecked) { // at $SRC_DIR/core/src/pin.rs:LL:COL + debug pointer => _5; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL -+ let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + } + } + } @@ -29,10 +29,10 @@ + let mut _9: bool; // in scope 6 at $DIR/inline-generator.rs:15:20: 15:21 + let mut _10: bool; // in scope 6 at $DIR/inline-generator.rs:15:9: 15:9 + let _11: bool; // in scope 6 at $DIR/inline-generator.rs:15:6: 15:7 -+ let mut _12: u32; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ let mut _13: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ let mut _14: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ let mut _15: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ let mut _12: u32; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ let mut _13: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ let mut _14: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ let mut _15: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8 + } bb0: { @@ -50,11 +50,11 @@ + Deinit(_4); // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 + discriminant(_4) = 0; // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 _3 = &mut _4; // scope 0 at $DIR/inline-generator.rs:9:23: 9:31 -- _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:32 +- _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:32 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:14: 9:22 - // + user_ty: UserType(0) -- // + literal: Const { ty: fn(&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]) -> Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]> {Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new}, val: Value(Scalar(<ZST>)) } +- // + literal: Const { ty: fn(&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]) -> Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]> {Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new}, val: Value(Scalar(<ZST>)) } - } - - bb2: { @@ -63,24 +63,24 @@ + StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL -+ (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL StorageDead(_3); // scope 0 at $DIR/inline-generator.rs:9:31: 9:32 -- _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 +- _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:33: 9:39 -- // + literal: Const { ty: for<'r> fn(Pin<&'r mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator<bool>>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator<bool>>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator<bool>>::resume}, val: Value(Scalar(<ZST>)) } +- // + literal: Const { ty: for<'r> fn(Pin<&'r mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(Scalar(<ZST>)) } + StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_12); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 -+ StorageLive(_13); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ _13 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ _12 = discriminant((*_13)); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ StorageDead(_13); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ StorageLive(_13); // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ _13 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ _12 = discriminant((*_13)); // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ StorageDead(_13); // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 } - bb3: { @@ -102,7 +102,7 @@ + } + + bb3: { -+ _11 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ _11 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 + StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:17: 15:39 + StorageLive(_9); // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 + _9 = _11; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21 @@ -125,32 +125,32 @@ + ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + discriminant(_1) = 0; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + StorageLive(_14); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ _14 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 ++ _14 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + discriminant((*_14)) = 3; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + StorageDead(_14); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39 + } + + bb7: { -+ StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ _10 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 ++ _10 = move _7; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 + StorageDead(_8); // scope 6 at $DIR/inline-generator.rs:15:38: 15:39 -+ Deinit(_1); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ StorageLive(_15); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ _15 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ discriminant((*_15)) = 1; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ StorageDead(_15); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41 ++ Deinit(_1); // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ StorageLive(_15); // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ _15 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ discriminant((*_15)) = 1; // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ StorageDead(_15); // scope 6 at $DIR/inline-generator.rs:15:8: 15:8 ++ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:8: 15:8 + } + + bb8: { -+ assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 + } + + bb9: { -+ unreachable; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ unreachable; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8 } } diff --git a/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index 7c3048a69af..242073574f2 100644 --- a/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -2,8 +2,8 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:4:11: 4:11 - let _1: [closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:33]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:5:9: 5:10 - let mut _2: &[closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:33]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:6 + let _1: [closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:5:9: 5:10 + let mut _2: &[closure@$DIR/issue-76997-inline-scopes-parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:6 let mut _3: ((),); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 let mut _4: (); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:7: 6:9 let mut _5: (); // in scope 0 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir index 0b8c4d25d2d..5808c607752 100644 --- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir @@ -9,14 +9,14 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { } bb0: { - Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:40:31: 43:6 - Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:40:31: 43:6 + Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:40:31: 40:48 + Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:40:31: 40:48 StorageLive(_3); // scope 0 at $DIR/retag.rs:41:13: 41:15 _3 = _2; // scope 0 at $DIR/retag.rs:41:18: 41:19 Retag(_3); // scope 0 at $DIR/retag.rs:41:18: 41:19 _0 = _2; // scope 1 at $DIR/retag.rs:42:9: 42:10 Retag(_0); // scope 1 at $DIR/retag.rs:42:9: 42:10 StorageDead(_3); // scope 0 at $DIR/retag.rs:43:5: 43:6 - return; // scope 0 at $DIR/retag.rs:43:6: 43:6 + return; // scope 0 at $DIR/retag.rs:40:48: 40:48 } } diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 2fda8c949b0..89b1ded7f93 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -121,7 +121,7 @@ fn main() -> () { // ] Retag(_14); // scope 1 at $DIR/retag.rs:40:31: 43:6 _13 = move _14 as for<'r> fn(&'r i32) -> &'r i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:40:31: 43:6 - StorageDead(_14); // scope 1 at $DIR/retag.rs:43:5: 43:6 + StorageDead(_14); // scope 1 at $DIR/retag.rs:40:47: 40:48 StorageLive(_15); // scope 6 at $DIR/retag.rs:44:9: 44:11 StorageLive(_16); // scope 6 at $DIR/retag.rs:44:14: 44:15 _16 = _13; // scope 6 at $DIR/retag.rs:44:14: 44:15 diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.32bit.mir index d106da84fc7..028281ba450 100644 --- a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.32bit.mir @@ -1,12 +1,12 @@ // MIR for `Test::X` 0 mir_map fn Test::X(_1: usize) -> Test { - let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 bb0: { - Deinit(_0); // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + Deinit(_0); // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 + ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 + discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 + return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 } } diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir index d106da84fc7..028281ba450 100644 --- a/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir +++ b/src/test/mir-opt/unusual_item_types.Test-X-{constructor#0}.mir_map.0.64bit.mir @@ -1,12 +1,12 @@ // MIR for `Test::X` 0 mir_map fn Test::X(_1: usize) -> Test { - let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 bb0: { - Deinit(_0); // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + Deinit(_0); // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 + ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 + discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 + return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:6 } } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt index e463099a5ee..09ad276aa45 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt @@ -37,7 +37,7 @@ 37| 0| countdown = 10; 38| 0| } 39| 0| "alt string 2".to_owned() - 40| 0| }; + 40| | }; 41| 1| println!( 42| 1| "The string or alt: {}" 43| 1| , @@ -79,7 +79,7 @@ 79| 0| countdown = 10; 80| 1| } 81| 1| "alt string 4".to_owned() - 82| 1| }; + 82| | }; 83| 1| println!( 84| 1| "The string or alt: {}" 85| 1| , @@ -101,7 +101,7 @@ 101| 0| countdown = 10; 102| 5| } 103| 5| format!("'{}'", val) - 104| 5| }; + 104| | }; 105| 1| println!( 106| 1| "Repeated, quoted string: {:?}" 107| 1| , @@ -125,7 +125,7 @@ 125| 0| countdown = 10; 126| 0| } 127| 0| "closure should be unused".to_owned() - 128| 0| }; + 128| | }; 129| | 130| 1| let mut countdown = 10; 131| 1| let _short_unused_closure = | _unused_arg: u8 | countdown += 1; @@ -177,7 +177,7 @@ 173| 0| println!( 174| 0| "not called: {}", 175| 0| if is_true { "check" } else { "me" } - 176| 0| ) + 176| | ) 177| | ; 178| | 179| 1| let short_used_not_covered_closure_line_break_block_embedded_branch = @@ -187,7 +187,7 @@ 183| 0| "not called: {}", 184| 0| if is_true { "check" } else { "me" } 185| | ) - 186| 0| } + 186| | } 187| | ; 188| | 189| 1| let short_used_covered_closure_line_break_no_block_embedded_branch = @@ -196,7 +196,7 @@ 192| 1| "not called: {}", 193| 1| if is_true { "check" } else { "me" } ^0 - 194| 1| ) + 194| | ) 195| | ; 196| | 197| 1| let short_used_covered_closure_line_break_block_embedded_branch = @@ -207,7 +207,7 @@ 202| 1| if is_true { "check" } else { "me" } ^0 203| | ) - 204| 1| } + 204| | } 205| | ; 206| | 207| 1| if is_false { diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt index 0fb3808ff2e..d70e12e4128 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt @@ -18,7 +18,7 @@ 17| 1| let mut generator = || { 18| 1| yield get_u32(is_true); 19| 1| return "foo"; - 20| 1| }; + 20| | }; 21| | 22| 1| match Pin::new(&mut generator).resume(()) { 23| 1| GeneratorState::Yielded(Ok(1)) => {} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.yield.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.yield.txt index 6e2f23ee77b..60a8d943f1f 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.yield.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.yield.txt @@ -8,7 +8,7 @@ 8| 1| let mut generator = || { 9| 1| yield 1; 10| 1| return "foo" - 11| 1| }; + 11| | }; 12| | 13| 1| match Pin::new(&mut generator).resume(()) { 14| 1| GeneratorState::Yielded(1) => {} @@ -24,7 +24,7 @@ 24| 1| yield 2; 25| 0| yield 3; 26| 0| return "foo" - 27| 0| }; + 27| | }; 28| | 29| 1| match Pin::new(&mut generator).resume(()) { 30| 1| GeneratorState::Yielded(1) => {} diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml index ddfb23a4f86..84b8bbd1b32 100644 --- a/src/test/rustdoc-gui/anchors.goml +++ b/src/test/rustdoc-gui/anchors.goml @@ -28,7 +28,7 @@ move-cursor-to: "h2#implementations" assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"}) // Same thing with the impl block title. -move-cursor-to: "#impl" -assert-css: ("#impl a.anchor", {"color": "rgb(0, 0, 0)"}) +move-cursor-to: "#impl-HeavilyDocumentedStruct" +assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(0, 0, 0)"}) assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"}) diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index cf9caa2d586..a47a9c8a14c 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -23,9 +23,9 @@ assert-css: ( ALL, ) -goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl +goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo assert-css: ( - "#impl", + "#impl-Foo", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"}, ) @@ -62,9 +62,9 @@ assert-css: ( ALL, ) -goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl +goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo assert-css: ( - "#impl", + "#impl-Foo", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"}, ) @@ -99,8 +99,8 @@ assert-css: ( ALL, ) -goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl -assert-css: ("#impl", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}) +goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo +assert-css: ("#impl-Foo", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}) goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use assert-css: ( diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml index 67e97eb686e..cc3dd61e99a 100644 --- a/src/test/rustdoc-gui/headings.goml +++ b/src/test/rustdoc-gui/headings.goml @@ -32,8 +32,8 @@ assert-css: ("h4#sub-heading-for-field", {"border-bottom-width": "0px"}) assert-css: ("h2#implementations", {"font-size": "22px"}) assert-css: ("h2#implementations", {"border-bottom-width": "1px"}) -assert-css: ("#impl > h3.code-header", {"font-size": "18px"}) -assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"}) +assert-css: ("#impl-HeavilyDocumentedStruct > h3.code-header", {"font-size": "18px"}) +assert-css: ("#impl-HeavilyDocumentedStruct > h3.code-header", {"border-bottom-width": "0px"}) assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"}) assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"}) @@ -87,8 +87,8 @@ assert-css: ("h6#structy-prose-sub-heading", {"border-bottom-width": "0px"}) assert-css: ("h2#implementations", {"font-size": "22px"}) assert-css: ("h2#implementations", {"border-bottom-width": "1px"}) -assert-css: ("#impl > h3.code-header", {"font-size": "18px"}) -assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"}) +assert-css: ("#impl-HeavilyDocumentedEnum > h3.code-header", {"font-size": "18px"}) +assert-css: ("#impl-HeavilyDocumentedEnum > h3.code-header", {"border-bottom-width": "0px"}) assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"}) assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"}) @@ -129,8 +129,8 @@ assert-css: ("h4#sub-heading-for-union-variant", {"border-bottom-width": "0px"}) assert-css: ("h2#implementations", {"font-size": "22px"}) assert-css: ("h2#implementations", {"border-bottom-width": "1px"}) -assert-css: ("#impl > h3.code-header", {"font-size": "18px"}) -assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"}) +assert-css: ("#impl-HeavilyDocumentedUnion > h3.code-header", {"font-size": "18px"}) +assert-css: ("#impl-HeavilyDocumentedUnion > h3.code-header", {"border-bottom-width": "0px"}) assert-css: ("h4#title-for-union-impl-doc", {"font-size": "16px"}) assert-css: ("h4#title-for-union-impl-doc", {"border-bottom-width": "0px"}) assert-css: ("h5#sub-heading-for-union-impl-doc", {"font-size": "16px"}) diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index f29613f78b1..666a6e1253d 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -6,8 +6,8 @@ assert: "#implementors-list" assert-count: ("#implementors-list .impl", 2) // Now we check that both implementors have an anchor, an ID and a similar DOM. assert: ("#implementors-list .impl:nth-child(1) > a.anchor") -assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever"}) -assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"}) +assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever-for-Struct"}) +assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever-for-Struct"}) assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band" assert: ("#implementors-list .impl:nth-child(2) > a.anchor") @@ -16,8 +16,16 @@ assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band" goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html -compare-elements-position-near-false: ("#impl-EmptyTrait1", "#impl-EmptyTrait2", {"y": 30}) -compare-elements-position-near: ("#impl-EmptyTrait3 h3", "#impl-EmptyTrait3 .item-info", {"y": 30}) +compare-elements-position-near-false: ( + "#impl-EmptyTrait1-for-HasEmptyTraits", + "#impl-EmptyTrait2-for-HasEmptyTraits", + {"y": 30}, +) +compare-elements-position-near: ( + "#impl-EmptyTrait3-for-HasEmptyTraits h3", + "#impl-EmptyTrait3-for-HasEmptyTraits .item-info", + {"y": 30}, +) // Now check that re-exports work correctly. // There should be exactly one impl shown on both of these pages. diff --git a/src/test/rustdoc-gui/item-info-overflow.goml b/src/test/rustdoc-gui/item-info-overflow.goml index d6385e2acb8..b7095a3c532 100644 --- a/src/test/rustdoc-gui/item-info-overflow.goml +++ b/src/test/rustdoc-gui/item-info-overflow.goml @@ -15,14 +15,17 @@ assert-text: ( // Checking the "item-info" on an impl block as well: goto: file://|DOC_PATH|/lib2/struct.LongItemInfo2.html compare-elements-property: ( - "#impl-SimpleTrait .item-info", - "#impl-SimpleTrait + .docblock", + "#impl-SimpleTrait-for-LongItemInfo2 .item-info", + "#impl-SimpleTrait-for-LongItemInfo2 + .docblock", ["scrollWidth"], ) -assert-property: ("#impl-SimpleTrait .item-info", {"scrollWidth": "866"}) +assert-property: ( + "#impl-SimpleTrait-for-LongItemInfo2 .item-info", + {"scrollWidth": "866"}, +) // Just to be sure we're comparing the correct "item-info": assert-text: ( - "#impl-SimpleTrait .item-info", + "#impl-SimpleTrait-for-LongItemInfo2 .item-info", "Available on Android or Linux or Emscripten or DragonFly BSD", STARTS_WITH, ) diff --git a/src/test/rustdoc-gui/toggle-click-deadspace.goml b/src/test/rustdoc-gui/toggle-click-deadspace.goml index 7bc3c563157..4a328c9f9e0 100644 --- a/src/test/rustdoc-gui/toggle-click-deadspace.goml +++ b/src/test/rustdoc-gui/toggle-click-deadspace.goml @@ -8,5 +8,5 @@ click: ".impl-items .rustdoc-toggle summary::before" // This is the position of assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""}) // Click the "Trait" part of "impl Trait" and verify it navigates. -click: "#impl-Trait h3 a:first-of-type" +click: "#impl-Trait-for-Foo h3 a:first-of-type" assert-text: (".fqn .in-band", "Trait lib2::Trait") diff --git a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr index 821e6b99f7b..5025b0b0ca8 100644 --- a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr +++ b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr @@ -16,7 +16,7 @@ error: missing documentation for a struct --> $DIR/deny-missing-docs-crate.rs:3:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/rustdoc/anchors.no_const_anchor.html b/src/test/rustdoc/anchors.no_const_anchor.html new file mode 100644 index 00000000000..98f47e53038 --- /dev/null +++ b/src/test/rustdoc/anchors.no_const_anchor.html @@ -0,0 +1 @@ +<div id="associatedconstant.YOLO" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#16">source</a></div><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></div> diff --git a/src/test/rustdoc/anchors.no_const_anchor2.html b/src/test/rustdoc/anchors.no_const_anchor2.html new file mode 100644 index 00000000000..6d37e8e5eee --- /dev/null +++ b/src/test/rustdoc/anchors.no_const_anchor2.html @@ -0,0 +1 @@ +<section id="associatedconstant.X" class="associatedconstant has-srclink"><span class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#42">source</a></span><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section> diff --git a/src/test/rustdoc/anchors.no_method_anchor.html b/src/test/rustdoc/anchors.no_method_anchor.html new file mode 100644 index 00000000000..f46d3090ed3 --- /dev/null +++ b/src/test/rustdoc/anchors.no_method_anchor.html @@ -0,0 +1 @@ +<section id="method.new" class="method has-srclink"><span class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#48">source</a></span><h4 class="code-header">pub fn <a href="#method.new" class="fnname">new</a>() -> Self</h4></section> \ No newline at end of file diff --git a/src/test/rustdoc/anchors.no_trait_method_anchor.html b/src/test/rustdoc/anchors.no_trait_method_anchor.html new file mode 100644 index 00000000000..445a7bb560a --- /dev/null +++ b/src/test/rustdoc/anchors.no_trait_method_anchor.html @@ -0,0 +1 @@ +<div id="method.bar" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#23">source</a></div><h4 class="code-header">fn <a href="#method.bar" class="fnname">bar</a>()</h4></div> \ No newline at end of file diff --git a/src/test/rustdoc/anchors.no_tymethod_anchor.html b/src/test/rustdoc/anchors.no_tymethod_anchor.html new file mode 100644 index 00000000000..bb0771b1003 --- /dev/null +++ b/src/test/rustdoc/anchors.no_tymethod_anchor.html @@ -0,0 +1 @@ +<div id="tymethod.foo" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#20">source</a></div><h4 class="code-header">fn <a href="#tymethod.foo" class="fnname">foo</a>()</h4></div> \ No newline at end of file diff --git a/src/test/rustdoc/anchors.no_type_anchor.html b/src/test/rustdoc/anchors.no_type_anchor.html new file mode 100644 index 00000000000..d317eb50050 --- /dev/null +++ b/src/test/rustdoc/anchors.no_type_anchor.html @@ -0,0 +1 @@ +<div id="associatedtype.T" class="method has-srclink"><div class="rightside"><a class="srclink" href="../src/foo/anchors.rs.html#13">source</a></div><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></div> \ No newline at end of file diff --git a/src/test/rustdoc/anchors.no_type_anchor2.html b/src/test/rustdoc/anchors.no_type_anchor2.html new file mode 100644 index 00000000000..72a1186bf7e --- /dev/null +++ b/src/test/rustdoc/anchors.no_type_anchor2.html @@ -0,0 +1 @@ +<section id="associatedtype.Y" class="associatedtype has-srclink"><h4 class="code-header">type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> diff --git a/src/test/rustdoc/anchors.rs b/src/test/rustdoc/anchors.rs new file mode 100644 index 00000000000..034cf8eaf4f --- /dev/null +++ b/src/test/rustdoc/anchors.rs @@ -0,0 +1,49 @@ +// This test ensures that anchors are generated in the right places. + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] +#![crate_name = "foo"] + +pub struct Foo; + +// @has 'foo/trait.Bar.html' +pub trait Bar { + // There should be no anchors here. + // @snapshot no_type_anchor - '//*[@id="associatedtype.T"]' + type T; + // There should be no anchors here. + // @snapshot no_const_anchor - '//*[@id="associatedconstant.YOLO"]' + const YOLO: u32; + + // There should be no anchors here. + // @snapshot no_tymethod_anchor - '//*[@id="tymethod.foo"]' + fn foo(); + // There should be no anchors here. + // @snapshot no_trait_method_anchor - '//*[@id="method.bar"]' + fn bar() {} +} + +// @has 'foo/struct.Foo.html' +impl Bar for Foo { + // @has - '//*[@id="associatedtype.T"]/a[@class="anchor"]' '' + type T = u32; + // @has - '//*[@id="associatedconstant.YOLO"]/a[@class="anchor"]' '' + const YOLO: u32 = 0; + + // @has - '//*[@id="method.foo"]/a[@class="anchor"]' '' + fn foo() {} + // Same check for provided "bar" method. + // @has - '//*[@id="method.bar"]/a[@class="anchor"]' '' +} + +impl Foo { + // @snapshot no_const_anchor2 - '//*[@id="associatedconstant.X"]' + // There should be no anchors here. + pub const X: i32 = 0; + // @snapshot no_type_anchor2 - '//*[@id="associatedtype.Y"]' + // There should be no anchors here. + pub type Y = u32; + // @snapshot no_method_anchor - '//*[@id="method.new"]' + // There should be no anchors here. + pub fn new() -> Self { Self } +} diff --git a/src/test/rustdoc/auto-trait-not-send.rs b/src/test/rustdoc/auto-trait-not-send.rs index 7bd4f6dbd8c..661d905ab63 100644 --- a/src/test/rustdoc/auto-trait-not-send.rs +++ b/src/test/rustdoc/auto-trait-not-send.rs @@ -1,8 +1,8 @@ #![crate_name = "foo"] // @has 'foo/struct.Foo.html' -// @has - '//*[@id="impl-Send"]' 'impl !Send for Foo' -// @has - '//*[@id="impl-Sync"]' 'impl !Sync for Foo' +// @has - '//*[@id="impl-Send-for-Foo"]' 'impl !Send for Foo' +// @has - '//*[@id="impl-Sync-for-Foo"]' 'impl !Sync for Foo' pub struct Foo(*const i8); pub trait Whatever: Send {} impl<T: Send + ?Sized> Whatever for T {} diff --git a/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs b/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs index 22cbeae7266..4e55e7ed576 100644 --- a/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs +++ b/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs @@ -7,3 +7,11 @@ where { unimplemented!() } + +pub struct Extra; + +pub trait MyTrait<T> { + fn run() {} +} + +impl MyTrait<&Extra> for Extra {} diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs index 4c686730b11..676d656dabf 100644 --- a/src/test/rustdoc/blanket-reexport-item.rs +++ b/src/test/rustdoc/blanket-reexport-item.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T' +// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T' pub struct S2 {} mod m { pub struct S {} diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index fc3a2731089..61af7de4794 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -36,7 +36,7 @@ pub struct Foo<const N: usize> where u8: Trait<N>; // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)' pub struct Bar<T, const N: usize>([T; N]); -// @has foo/struct.Foo.html '//*[@id="impl"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>' +// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>' impl<const M: usize> Foo<M> where u8: Trait<M> { // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' pub const FOO_ASSOC: usize = M + 13; @@ -47,7 +47,7 @@ impl<const M: usize> Foo<M> where u8: Trait<M> { } } -// @has foo/struct.Bar.html '//*[@id="impl"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>' +// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>' impl<const M: usize> Bar<u8, M> { // @has - '//*[@id="method.hey"]' \ // 'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>' diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index a3ef084165a..f1181d54ac8 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -9,20 +9,20 @@ pub enum Order { } // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>' -// @has foo/struct.VSet.html '//*[@id="impl-Send"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>' -// @has foo/struct.VSet.html '//*[@id="impl-Sync"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>' +// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>' +// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>' pub struct VSet<T, const ORDER: Order> { inner: Vec<T>, } -// @has foo/struct.VSet.html '//*[@id="impl"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Sorted }>' +// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Sorted }>' impl<T> VSet<T, { Order::Sorted }> { pub fn new() -> Self { Self { inner: Vec::new() } } } -// @has foo/struct.VSet.html '//*[@id="impl-1"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Unsorted }>' +// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Unsorted }>' impl<T> VSet<T, { Order::Unsorted }> { pub fn new() -> Self { Self { inner: Vec::new() } @@ -31,7 +31,7 @@ impl<T> VSet<T, { Order::Unsorted }> { pub struct Escape<const S: &'static str>; -// @has foo/struct.Escape.html '//*[@id="impl"]/h3[@class="code-header in-band"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>' +// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header in-band"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>' impl Escape<r#"<script>alert("Escape");</script>"#> { pub fn f() {} } diff --git a/src/test/rustdoc/double-quote-escape.rs b/src/test/rustdoc/double-quote-escape.rs index b7bbf140cfd..350c897417d 100644 --- a/src/test/rustdoc/double-quote-escape.rs +++ b/src/test/rustdoc/double-quote-escape.rs @@ -1,6 +1,5 @@ #![crate_name = "foo"] - pub trait Foo<T> { fn foo() {} } @@ -8,5 +7,5 @@ pub trait Foo<T> { pub struct Bar; // @has foo/struct.Bar.html -// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E"]' 'Foo<unsafe extern "C" fn()>' +// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E-for-Bar"]' 'Foo<unsafe extern "C" fn()>' impl Foo<unsafe extern "C" fn()> for Bar {} diff --git a/src/test/rustdoc/empty-impls.rs b/src/test/rustdoc/empty-impls.rs index d18f404212f..83902d6f7ab 100644 --- a/src/test/rustdoc/empty-impls.rs +++ b/src/test/rustdoc/empty-impls.rs @@ -1,19 +1,19 @@ #![crate_name = "foo"] // @has foo/struct.Foo.html -// @has - '//div[@id="synthetic-implementations-list"]/*[@id="impl-Send"]' 'impl Send for Foo' +// @has - '//div[@id="synthetic-implementations-list"]/*[@id="impl-Send-for-Foo"]' 'impl Send for Foo' pub struct Foo; pub trait EmptyTrait {} -// @has - '//div[@id="trait-implementations-list"]/*[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo' +// @has - '//div[@id="trait-implementations-list"]/*[@id="impl-EmptyTrait-for-Foo"]' 'impl EmptyTrait for Foo' impl EmptyTrait for Foo {} pub trait NotEmpty { fn foo(&self); } -// @has - '//div[@id="trait-implementations-list"]/details/summary/*[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo' +// @has - '//div[@id="trait-implementations-list"]/details/summary/*[@id="impl-NotEmpty-for-Foo"]' 'impl NotEmpty for Foo' impl NotEmpty for Foo { fn foo(&self) {} } diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs index 1268c9587f8..c6beed70abe 100644 --- a/src/test/rustdoc/generic-impl.rs +++ b/src/test/rustdoc/generic-impl.rs @@ -2,12 +2,12 @@ use std::fmt; -// @!has foo/struct.Bar.html '//*[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' +// @!has foo/struct.Bar.html '//*[@id="impl-ToString-for-Bar"]' '' pub struct Bar; -// @has foo/struct.Foo.html '//*[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' +// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' pub struct Foo; -// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString"]' 'ToString' +// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-Foo"]' 'ToString' impl fmt::Display for Foo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/test/rustdoc/hidden-trait-struct-impls.rs b/src/test/rustdoc/hidden-trait-struct-impls.rs index 1be956ef393..cc3f6337719 100644 --- a/src/test/rustdoc/hidden-trait-struct-impls.rs +++ b/src/test/rustdoc/hidden-trait-struct-impls.rs @@ -11,11 +11,11 @@ pub struct Bar; struct Hidden; -// @!has foo/struct.Bar.html '//*[@id="impl-Foo"]' 'impl Foo for Bar' +// @!has foo/struct.Bar.html '//*[@id="impl-Foo-for-Bar"]' 'impl Foo for Bar' impl Foo for Bar {} -// @!has foo/struct.Bar.html '//*[@id="impl-Dark"]' 'impl Dark for Bar' +// @!has foo/struct.Bar.html '//*[@id="impl-Dark-for-Bar"]' 'impl Dark for Bar' impl Dark for Bar {} -// @has foo/struct.Bar.html '//*[@id="impl-Bam"]' 'impl Bam for Bar' +// @has foo/struct.Bar.html '//*[@id="impl-Bam-for-Bar"]' 'impl Bam for Bar' // @has foo/trait.Bam.html '//*[@id="implementors-list"]' 'impl Bam for Bar' impl Bam for Bar {} // @!has foo/trait.Bam.html '//*[@id="implementors-list"]' 'impl Bam for Hidden' diff --git a/src/test/rustdoc/impl-box.rs b/src/test/rustdoc/impl-box.rs index a371db135cf..592b6c98587 100644 --- a/src/test/rustdoc/impl-box.rs +++ b/src/test/rustdoc/impl-box.rs @@ -5,7 +5,7 @@ pub struct MyType; // @has 'impl_box/struct.MyType.html' -// @has '-' '//*[@id="impl-Iterator"]' 'impl Iterator for Box<MyType>' +// @has '-' '//*[@id="impl-Iterator-for-Box%3CMyType%3E"]' 'impl Iterator for Box<MyType>' impl Iterator for Box<MyType> { type Item = (); diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index 490d7e51e32..635c3175f81 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -5,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait']//h3[@class='code-header in-band']" "impl<T> MyTrait for T where T: Debug" +// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for T where T: Debug" impl<T> MyTrait for T where T: fmt::Debug, diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs index a8cb16ec34c..ac97b94fb35 100644 --- a/src/test/rustdoc/issue-75588.rs +++ b/src/test/rustdoc/issue-75588.rs @@ -13,5 +13,5 @@ extern crate real_gimli; // @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice' pub use realcore::Deref; -// @has foo/trait.Join.html '//*[@id="impl-Join"]//h3[@class="code-header in-band"]' 'impl Join for Foo' +// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo' pub use realcore::Join; diff --git a/src/test/rustdoc/issue-78701.rs b/src/test/rustdoc/issue-78701.rs index 796d553fac4..e3e46468f38 100644 --- a/src/test/rustdoc/issue-78701.rs +++ b/src/test/rustdoc/issue-78701.rs @@ -5,8 +5,8 @@ // the ID is correctly derived. // @has 'foo/struct.AnotherStruct.html' -// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait"]' 1 -// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-1"]' 1 +// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-AnotherStruct%3C()%3E"]' 1 +// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-for-AnotherStruct%3CT%3E"]' 1 pub trait Something {} diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs index 25ab55acd77..83e08094c09 100644 --- a/src/test/rustdoc/issue-98697.rs +++ b/src/test/rustdoc/issue-98697.rs @@ -11,3 +11,7 @@ extern crate issue_98697_reexport_with_anonymous_lifetime; // @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro<F>() where F: Fn(&str)' // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' pub use issue_98697_reexport_with_anonymous_lifetime::repro; + +// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl MyTrait<&Extra> for Extra' +// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl<' +pub use issue_98697_reexport_with_anonymous_lifetime::Extra; diff --git a/src/test/rustdoc/primitive/primitive-generic-impl.rs b/src/test/rustdoc/primitive/primitive-generic-impl.rs index 28adff84c70..eebb2cf5a35 100644 --- a/src/test/rustdoc/primitive/primitive-generic-impl.rs +++ b/src/test/rustdoc/primitive/primitive-generic-impl.rs @@ -1,7 +1,7 @@ #![feature(rustdoc_internals)] #![crate_name = "foo"] -// @has foo/primitive.i32.html '//*[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' +// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' #[doc(primitive = "i32")] /// Some useless docs, wouhou! diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs index ec70a69ff10..f3e211e3017 100644 --- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs +++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs @@ -29,10 +29,11 @@ pub trait Tr<T> { } } -// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone' -// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]' '' +// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]' '~const' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone' +// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone' impl<T: ~const Clone + ~const Destruct> const Tr<T> for T where Option<T>: ~const Clone + ~const Destruct, diff --git a/src/test/rustdoc/sized_trait.rs b/src/test/rustdoc/sized_trait.rs index 252a8126036..9d2c1967757 100644 --- a/src/test/rustdoc/sized_trait.rs +++ b/src/test/rustdoc/sized_trait.rs @@ -11,7 +11,7 @@ pub struct Bar { pub struct Foo<T: ?Sized>(T); // @has foo/struct.Unsized.html -// @has - '//*[@id="impl-Sized"]//h3[@class="code-header in-band"]' 'impl !Sized for Unsized' +// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header in-band"]' 'impl !Sized for Unsized' pub struct Unsized { data: [u8], } diff --git a/src/test/rustdoc/src-links-auto-impls.rs b/src/test/rustdoc/src-links-auto-impls.rs index 0f461a1185b..69be9aa8d5f 100644 --- a/src/test/rustdoc/src-links-auto-impls.rs +++ b/src/test/rustdoc/src-links-auto-impls.rs @@ -1,12 +1,12 @@ #![crate_name = "foo"] // @has foo/struct.Unsized.html -// @has - '//*[@id="impl-Sized"]/h3[@class="code-header in-band"]' 'impl !Sized for Unsized' -// @!has - '//*[@id="impl-Sized"]//a[@class="srclink"]' 'source' -// @has - '//*[@id="impl-Sync"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized' -// @!has - '//*[@id="impl-Sync"]//a[@class="srclink"]' 'source' -// @has - '//*[@id="impl-Any"]/h3[@class="code-header in-band"]' 'impl<T> Any for T' -// @has - '//*[@id="impl-Any"]//a[@class="srclink"]' 'source' +// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header in-band"]' 'impl !Sized for Unsized' +// @!has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="srclink"]' 'source' +// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized' +// @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="srclink"]' 'source' +// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header in-band"]' 'impl<T> Any for T' +// @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink"]' 'source' pub struct Unsized { data: [u8], } diff --git a/src/test/rustdoc/trait-impl.rs b/src/test/rustdoc/trait-impl.rs index 05ccc074bf1..4f7e2dfe3b9 100644 --- a/src/test/rustdoc/trait-impl.rs +++ b/src/test/rustdoc/trait-impl.rs @@ -43,5 +43,5 @@ impl Trait for Struct { // @!has - '//*[@id="method.d"]/../../div[@class="docblock"]/p/em' fn d() {} - // @has - '//*[@id="impl-Trait"]/h3//a/@href' 'trait.Trait.html' + // @has - '//*[@id="impl-Trait-for-Struct"]/h3//a/@href' 'trait.Trait.html' } diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 18283c19cb4..56e95d70fd5 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -17,7 +17,7 @@ use rustc_span::symbol::Ident; use rustc_span::Span; extern crate rustc_macros; -use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_macros::{SessionDiagnostic, LintDiagnostic, SessionSubdiagnostic}; extern crate rustc_middle; use rustc_middle::ty::Ty; @@ -535,3 +535,20 @@ struct LabelWithTrailingList { //~^ ERROR `#[label(...)]` is not a valid attribute span: Span, } + +#[derive(SessionDiagnostic)] +#[lint(typeck::ambiguous_lifetime_bound)] +//~^ ERROR only `#[error(..)]` and `#[warn(..)]` are supported +struct LintsBad { +} + +#[derive(LintDiagnostic)] +#[lint(typeck::ambiguous_lifetime_bound)] +struct LintsGood { +} + +#[derive(LintDiagnostic)] +#[error(typeck::ambiguous_lifetime_bound)] +//~^ ERROR only `#[lint(..)]` is supported +struct ErrorsBad { +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 9e2e34e4bec..98c22af387e 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -363,6 +363,28 @@ error: `#[label(...)]` is not a valid attribute LL | #[label(typeck::label, foo("..."))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: only `#[error(..)]` and `#[warn(..)]` are supported + --> $DIR/diagnostic-derive.rs:540:1 + | +LL | / #[lint(typeck::ambiguous_lifetime_bound)] +LL | | +LL | | struct LintsBad { +LL | | } + | |_^ + | + = help: use the `#[error(...)]` attribute to create a error + +error: only `#[lint(..)]` is supported + --> $DIR/diagnostic-derive.rs:551:1 + | +LL | / #[error(typeck::ambiguous_lifetime_bound)] +LL | | +LL | | struct ErrorsBad { +LL | | } + | |_^ + | + = help: use the `#[lint(...)]` attribute to create a lint + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:53:3 | @@ -395,7 +417,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 46 previous errors +error: aborting due to 48 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs index e4d29754556..aa12d4aa4b4 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.rs +++ b/src/test/ui/asm/aarch64/type-check-2-2.rs @@ -17,10 +17,10 @@ fn main() { let x: u64; asm!("{}", in(reg) x); - //~^ ERROR use of possibly-uninitialized variable: `x` + //~^ ERROR used binding `x` isn't initialized let mut y: u64; asm!("{}", inout(reg) y); - //~^ ERROR use of possibly-uninitialized variable: `y` + //~^ ERROR used binding `y` isn't initialized let _ = y; // Outputs require mutable places diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr index 37bbe394994..b2a695529f9 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.stderr +++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr @@ -1,14 +1,18 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-2-2.rs:19:28 | +LL | let x: u64; + | - binding declared here but left uninitialized LL | asm!("{}", in(reg) x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `y` +error[E0381]: used binding `y` isn't initialized --> $DIR/type-check-2-2.rs:22:9 | +LL | let mut y: u64; + | ----- binding declared here but left uninitialized LL | asm!("{}", inout(reg) y); - | ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y` + | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-2-2.rs:30:29 diff --git a/src/test/ui/asm/aarch64/type-check-2.stderr b/src/test/ui/asm/aarch64/type-check-2.stderr index 4b99652cd20..875df44ffab 100644 --- a/src/test/ui/asm/aarch64/type-check-2.stderr +++ b/src/test/ui/asm/aarch64/type-check-2.stderr @@ -22,7 +22,7 @@ LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:38]` for inline assembly +error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:36]` for inline assembly --> $DIR/type-check-2.rs:41:28 | LL | asm!("{}", in(reg) |x: i32| x); diff --git a/src/test/ui/asm/x86_64/type-check-2.stderr b/src/test/ui/asm/x86_64/type-check-2.stderr index 46baeb511ca..d9ca25519dc 100644 --- a/src/test/ui/asm/x86_64/type-check-2.stderr +++ b/src/test/ui/asm/x86_64/type-check-2.stderr @@ -30,7 +30,7 @@ LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `[closure@$DIR/type-check-2.rs:52:28: 52:38]` for inline assembly +error: cannot use value of type `[closure@$DIR/type-check-2.rs:52:28: 52:36]` for inline assembly --> $DIR/type-check-2.rs:52:28 | LL | asm!("{}", in(reg) |x: i32| x); diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs index 474478f6a88..6190e0b52f4 100644 --- a/src/test/ui/asm/x86_64/type-check-5.rs +++ b/src/test/ui/asm/x86_64/type-check-5.rs @@ -13,10 +13,10 @@ fn main() { let x: u64; asm!("{}", in(reg) x); - //~^ ERROR use of possibly-uninitialized variable: `x` + //~^ ERROR E0381 let mut y: u64; asm!("{}", inout(reg) y); - //~^ ERROR use of possibly-uninitialized variable: `y` + //~^ ERROR E0381 let _ = y; // Outputs require mutable places diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr index 181ecaf5855..e9c93fea561 100644 --- a/src/test/ui/asm/x86_64/type-check-5.stderr +++ b/src/test/ui/asm/x86_64/type-check-5.stderr @@ -1,14 +1,18 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-5.rs:15:28 | +LL | let x: u64; + | - binding declared here but left uninitialized LL | asm!("{}", in(reg) x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `y` +error[E0381]: used binding `y` isn't initialized --> $DIR/type-check-5.rs:18:9 | +LL | let mut y: u64; + | ----- binding declared here but left uninitialized LL | asm!("{}", inout(reg) y); - | ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y` + | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-5.rs:26:29 diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index e9b76b19dc4..9b6917df45d 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -9,11 +9,8 @@ LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { note: required because it's used within this closure --> $DIR/issue-70935-complex-spans.rs:25:13 | -LL | baz(|| async{ - | _____________^ -LL | | foo(tx.clone()); -LL | | }).await; - | |_________^ +LL | baz(|| async{ + | ^^ note: required because it's used within this `async fn` body --> $DIR/issue-70935-complex-spans.rs:9:67 | diff --git a/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr b/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr index 2174f260a71..88b646d2792 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr @@ -14,7 +14,7 @@ LL | | foo(tx.clone()); LL | | }).await; | | - ^^^^^^ await occurs here, with the value maybe used later | |_________| - | has type `[closure@$DIR/issue-70935-complex-spans.rs:25:13: 27:10]` which is not `Send` + | has type `[closure@$DIR/issue-70935-complex-spans.rs:25:13: 25:15]` which is not `Send` note: the value is later dropped here --> $DIR/issue-70935-complex-spans.rs:27:17 | diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index ccdd9c57a0f..5cbbf89a222 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -24,15 +24,15 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^^ only allowed inside `async` functions and blocks -error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future +error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future --> $DIR/issue-62009-1.rs:12:15 | LL | (|_| 2333).await; - | ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future + | ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future | - = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` - = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited - = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` + = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` + = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` help: remove the `.await` | LL - (|_| 2333).await; diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.rs b/src/test/ui/async-await/no-non-guaranteed-initialization.rs index 24070fe3308..c4d81bf83a3 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.rs +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.rs @@ -6,8 +6,7 @@ async fn no_non_guaranteed_initialization(x: usize) -> usize { if x > 5 { y = echo(10).await; } - y - //~^ use of possibly-uninitialized variable: `y` + y //~ ERROR E0381 } async fn echo(x: usize) -> usize { x + 1 } diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr index f5991f4bcca..12c15bf56ce 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr @@ -1,8 +1,15 @@ -error[E0381]: use of possibly-uninitialized variable: `y` +error[E0381]: used binding `y` is possibly-uninitialized --> $DIR/no-non-guaranteed-initialization.rs:9:5 | +LL | let y; + | - binding declared here but left uninitialized +LL | if x > 5 { + | ----- if this `if` condition is `false`, `y` is not initialized +LL | y = echo(10).await; +LL | } + | - an `else` arm might be missing here, initializing `y` LL | y - | ^ use of possibly-uninitialized `y` + | ^ `y` used here but it is possibly-uninitialized error: aborting due to previous error diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs index 8a98a4b0f6b..7577aee3fb7 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.rs +++ b/src/test/ui/async-await/partial-initialization-across-await.rs @@ -10,8 +10,7 @@ async fn noop() {} async fn test_tuple() { let mut t: (i32, i32); - t.0 = 42; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 42; //~ ERROR E0381 noop().await; t.1 = 88; let _ = t; @@ -19,8 +18,7 @@ async fn test_tuple() { async fn test_tuple_struct() { let mut t: T; - t.0 = 42; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 42; //~ ERROR E0381 noop().await; t.1 = 88; let _ = t; @@ -28,8 +26,7 @@ async fn test_tuple_struct() { async fn test_struct() { let mut t: S; - t.x = 42; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.x = 42; //~ ERROR E0381 noop().await; t.y = 88; let _ = t; diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr index 9a510c22c4b..6a0eeffb946 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.stderr +++ b/src/test/ui/async-await/partial-initialization-across-await.stderr @@ -1,20 +1,32 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/partial-initialization-across-await.rs:13:5 | +LL | let mut t: (i32, i32); + | ----- binding declared here but left uninitialized LL | t.0 = 42; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:22:5 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-await.rs:21:5 | +LL | let mut t: T; + | ----- binding declared here but left uninitialized LL | t.0 = 42; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:31:5 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-await.rs:29:5 | +LL | let mut t: S; + | ----- binding declared here but left uninitialized LL | t.x = 42; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 3 previous errors diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index e9ca0ad9029..37bad64c5bf 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -7,7 +7,7 @@ LL | |y| x + y | ^^^^^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14]` + found closure `[closure@$DIR/issue-20862.rs:2:5: 2:8]` error[E0618]: expected function, found `()` --> $DIR/issue-20862.rs:7:13 diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr index 40f1aae092d..1ed92865da5 100644 --- a/src/test/ui/borrowck/assign_mutable_fields.stderr +++ b/src/test/ui/borrowck/assign_mutable_fields.stderr @@ -1,14 +1,22 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/assign_mutable_fields.rs:9:5 | +LL | let mut x: (u32, u32); + | ----- binding declared here but left uninitialized LL | x.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/assign_mutable_fields.rs:17:5 | +LL | let mut x: (u32, u32); + | ----- binding declared here but left uninitialized LL | x.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr index 003c40d2773..6235e0db0da 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr @@ -1,15 +1,13 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation-impl-trait.rs:11:9 | -LL | fn bar() -> impl Fn() -> usize { - | --- ------------------ change this to return `FnMut` instead of `Fn` -LL | let mut x = 0; -LL | / move || { -LL | | x += 1; - | | ^^^^^^ cannot assign -LL | | x -LL | | } - | |_____- in this closure +LL | fn bar() -> impl Fn() -> usize { + | --- ------------------ change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | move || { + | ------- in this closure +LL | x += 1; + | ^^^^^^ cannot assign error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr index a28cb7431e6..093589ed092 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -5,8 +5,9 @@ LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(|| x = 42); - | ----- ^^^^^^ cannot assign - | | + | ----- -- ^^^^^^ cannot assign + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure @@ -16,8 +17,9 @@ LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(|| set(&mut y)); - | ----- ^^^^^^ cannot borrow as mutable - | | + | ----- -- ^^^^^^ cannot borrow as mutable + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure @@ -27,8 +29,9 @@ LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(|| z = 42); - | ----- ^^^^^^ cannot assign - | | + | ----- -- ^^^^^^ cannot assign + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure @@ -38,8 +41,9 @@ LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(move || x = 42); - | ----- ^^^^^^ cannot assign - | | + | ----- ------- ^^^^^^ cannot assign + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure @@ -49,8 +53,9 @@ LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(move || set(&mut y)); - | ----- ^^^^^^ cannot borrow as mutable - | | + | ----- ------- ^^^^^^ cannot borrow as mutable + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure @@ -60,23 +65,21 @@ LL | fn to_fn<A, F: Fn<A>>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(move || z = 42); - | ----- ^^^^^^ cannot assign - | | + | ----- ------- ^^^^^^ cannot assign + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:53:9 | -LL | fn foo() -> Box<dyn Fn() -> usize> { - | --- ---------------------- change this to return `FnMut` instead of `Fn` -LL | let mut x = 0; -LL | Box::new(move || { - | ______________- -LL | | x += 1; - | | ^^^^^^ cannot assign -LL | | x -LL | | }) - | |_____- in this closure +LL | fn foo() -> Box<dyn Fn() -> usize> { + | --- ---------------------- change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | Box::new(move || { + | ------- in this closure +LL | x += 1; + | ^^^^^^ cannot assign error: aborting due to 7 previous errors 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 ea74fb96684..869375cb2c6 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -29,32 +29,28 @@ LL | f(); error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:29:17 | -LL | fn make_fn<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn make_fn<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | let f = make_fn(|| { - | _____________-------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | let y = &raw mut x; - | | ^^^^^^^^^^ cannot borrow as mutable -LL | | }); - | |_____- in this closure +LL | let f = make_fn(|| { + | ------- -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:37:17 | -LL | fn make_fn<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn make_fn<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | let f = make_fn(move || { - | _____________-------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | let y = &raw mut x; - | | ^^^^^^^^^^ cannot borrow as mutable -LL | | }); - | |_____- in this closure +LL | let f = make_fn(move || { + | ------- ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable error: aborting due to 5 previous errors diff --git a/src/test/ui/borrowck/borrowck-and-init.rs b/src/test/ui/borrowck/borrowck-and-init.rs index f11d44e2217..eeb4f05d60c 100644 --- a/src/test/ui/borrowck/borrowck-and-init.rs +++ b/src/test/ui/borrowck/borrowck-and-init.rs @@ -2,5 +2,5 @@ fn main() { let i: isize; println!("{}", false && { i = 5; true }); - println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i` + println!("{}", i); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr index d2c7473c036..7f3d27d6091 100644 --- a/src/test/ui/borrowck/borrowck-and-init.stderr +++ b/src/test/ui/borrowck/borrowck-and-init.stderr @@ -1,8 +1,13 @@ -error[E0381]: borrow of possibly-uninitialized variable: `i` +error[E0381]: used binding `i` is possibly-uninitialized --> $DIR/borrowck-and-init.rs:5:20 | +LL | let i: isize; + | - binding declared here but left uninitialized +LL | +LL | println!("{}", false && { i = 5; true }); + | ----- binding initialized here in some conditions LL | println!("{}", i); - | ^ use of possibly-uninitialized `i` + | ^ `i` used here but it is possibly-uninitialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/borrowck-block-unint.rs b/src/test/ui/borrowck/borrowck-block-unint.rs index 1e7306acaee..8d13b25a357 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.rs +++ b/src/test/ui/borrowck/borrowck-block-unint.rs @@ -1,7 +1,7 @@ fn force<F>(f: F) where F: FnOnce() { f(); } fn main() { let x: isize; - force(|| { //~ ERROR borrow of possibly-uninitialized variable: `x` + force(|| { //~ ERROR E0381 println!("{}", x); }); } diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr index 578f89df46c..e720db1c696 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.stderr +++ b/src/test/ui/borrowck/borrowck-block-unint.stderr @@ -1,8 +1,10 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-block-unint.rs:4:11 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | force(|| { - | ^^ use of possibly-uninitialized `x` + | ^^ `x` used here but it isn't initialized LL | println!("{}", x); | - borrow occurs due to use in closure diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.rs b/src/test/ui/borrowck/borrowck-break-uninit-2.rs index 126d991a51c..3abca33a84a 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.rs +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.rs @@ -6,7 +6,7 @@ fn foo() -> isize { x = 0; } - println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` + println!("{}", x); //~ ERROR E0381 return 17; } diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr index b134f5cc2d8..23ea1a2de7f 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr @@ -1,8 +1,11 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-break-uninit-2.rs:9:20 | +LL | let x: isize; + | - binding declared here but left uninitialized +... LL | println!("{}", x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/borrowck-break-uninit.rs b/src/test/ui/borrowck/borrowck-break-uninit.rs index 8ccb21ae8ee..824f91dbc62 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.rs +++ b/src/test/ui/borrowck/borrowck-break-uninit.rs @@ -6,7 +6,7 @@ fn foo() -> isize { x = 0; } - println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` + println!("{}", x); //~ ERROR E0381 return 17; } diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr index 652d7d3076f..2b9b0a190f6 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr @@ -1,8 +1,11 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-break-uninit.rs:9:20 | +LL | let x: isize; + | - binding declared here but left uninitialized +... LL | println!("{}", x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs index 50edfb6ba2d..03edf445ee9 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.rs +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs @@ -78,20 +78,20 @@ fn fu_move_after_fu_move() { fn copy_after_field_assign_after_uninit() { let mut x: A; - x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` + x.a = 1; //~ ERROR E0381 drop(x.a); } fn borrow_after_field_assign_after_uninit() { let mut x: A; - x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` + x.a = 1; //~ ERROR E0381 let p = &x.a; drop(*p); } fn move_after_field_assign_after_uninit() { let mut x: A; - x.b = Box::new(1); //~ ERROR assign to part of possibly-uninitialized variable: `x` + x.b = Box::new(1); //~ ERROR E0381 drop(x.b); } diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr index bb4d2f06016..e009f5913ed 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr @@ -108,23 +108,35 @@ LL | let _z = A { a: 4, .. x }; | = note: move occurs because `x.b` has type `Box<isize>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/borrowck-field-sensitivity.rs:81:5 | +LL | let mut x: A; + | ----- binding declared here but left uninitialized LL | x.a = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/borrowck-field-sensitivity.rs:87:5 | +LL | let mut x: A; + | ----- binding declared here but left uninitialized LL | x.a = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/borrowck-field-sensitivity.rs:94:5 | +LL | let mut x: A; + | ----- binding declared here but left uninitialized LL | x.b = Box::new(1); - | ^^^ use of possibly-uninitialized `x` + | ^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 14 previous errors diff --git a/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs new file mode 100644 index 00000000000..f619c045b25 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs @@ -0,0 +1,7 @@ +fn f() -> isize { + let mut x: isize; + for _ in 0..0 { x = 10; } + return x; //~ ERROR E0381 +} + +fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr new file mode 100644 index 00000000000..c08c93f3617 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr @@ -0,0 +1,13 @@ +error[E0381]: used binding `x` is possibly-uninitialized + --> $DIR/borrowck-for-loop-uninitialized-binding.rs:4:12 + | +LL | let mut x: isize; + | ----- binding declared here but left uninitialized +LL | for _ in 0..0 { x = 10; } + | ---- if the `for` loop runs 0 times, `x` is not initialized +LL | return x; + | ^ `x` used here but it is possibly-uninitialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/borrowck-if-no-else.rs b/src/test/ui/borrowck/borrowck-if-no-else.rs index f59bcad6f61..534d771be1d 100644 --- a/src/test/ui/borrowck/borrowck-if-no-else.rs +++ b/src/test/ui/borrowck/borrowck-if-no-else.rs @@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); } fn main() { let x: isize; if 1 > 2 { x = 10; } - foo(x); //~ ERROR use of possibly-uninitialized variable: `x` + foo(x); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr index 3e9d3d4f6d5..9eafc2c2a86 100644 --- a/src/test/ui/borrowck/borrowck-if-no-else.stderr +++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr @@ -1,8 +1,13 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` is possibly-uninitialized --> $DIR/borrowck-if-no-else.rs:5:9 | +LL | let x: isize; if 1 > 2 { x = 10; } + | - ----- - an `else` arm might be missing here, initializing `x` + | | | + | | if this `if` condition is `false`, `x` is not initialized + | binding declared here but left uninitialized LL | foo(x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it is possibly-uninitialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-if-with-else.rs b/src/test/ui/borrowck/borrowck-if-with-else.rs index c13318b16c2..69d450c5989 100644 --- a/src/test/ui/borrowck/borrowck-if-with-else.rs +++ b/src/test/ui/borrowck/borrowck-if-with-else.rs @@ -7,5 +7,5 @@ fn main() { } else { x = 10; } - foo(x); //~ ERROR use of possibly-uninitialized variable: `x` + foo(x); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr index 53b8a6bba2c..3f0fe291ca2 100644 --- a/src/test/ui/borrowck/borrowck-if-with-else.stderr +++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr @@ -1,8 +1,13 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` is possibly-uninitialized --> $DIR/borrowck-if-with-else.rs:10:9 | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | if 1 > 2 { + | ----- if this condition is `true`, `x` is not initialized +... LL | foo(x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it is possibly-uninitialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index 30e74c5ec95..2033e4a5730 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -4,9 +4,8 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | Box::new(|| x) - | ---^ - | | | - | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | -- ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | | | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs index 9905e420f94..e6476b9c1be 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs @@ -1,7 +1,7 @@ fn main() { let j = || -> isize { let i: isize; - i //~ ERROR use of possibly-uninitialized variable: `i` + i //~ ERROR E0381 }; j(); } diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr index 2d1d9bc8fa4..e8a2fbc91ea 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `i` +error[E0381]: used binding `i` isn't initialized --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9 | +LL | let i: isize; + | - binding declared here but left uninitialized LL | i - | ^ use of possibly-uninitialized `i` + | ^ `i` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs index 7dd3396c8c2..7eb204a0d16 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs @@ -1,7 +1,7 @@ fn main() { let f = || -> isize { let i: isize; - i //~ ERROR use of possibly-uninitialized variable: `i` + i //~ ERROR E0381 }; println!("{}", f()); } diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr index fd8b90eda60..1e950d6a20d 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `i` +error[E0381]: used binding `i` isn't initialized --> $DIR/borrowck-init-in-fn-expr.rs:4:9 | +LL | let i: isize; + | - binding declared here but left uninitialized LL | i - | ^ use of possibly-uninitialized `i` + | ^ `i` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.rs b/src/test/ui/borrowck/borrowck-init-in-fru.rs index d7ec2ed75c8..c07957ab139 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.rs +++ b/src/test/ui/borrowck/borrowck-init-in-fru.rs @@ -7,6 +7,6 @@ struct Point { fn main() { let mut origin: Point; origin = Point { x: 10, ..origin }; - //~^ ERROR use of possibly-uninitialized variable: `origin` [E0381] + //~^ ERROR E0381 origin.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr index f01afe1466a..83a3e3e0e3a 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `origin` +error[E0381]: used binding `origin` isn't initialized --> $DIR/borrowck-init-in-fru.rs:9:14 | +LL | let mut origin: Point; + | ---------- binding declared here but left uninitialized LL | origin = Point { x: 10, ..origin }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `origin.y` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.rs b/src/test/ui/borrowck/borrowck-init-op-equal.rs index 784eb8cf85b..3d08c1b81a7 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.rs +++ b/src/test/ui/borrowck/borrowck-init-op-equal.rs @@ -1,6 +1,6 @@ fn test() { let v: isize; - v += 1; //~ ERROR use of possibly-uninitialized variable: `v` + v += 1; //~ ERROR E0381 v.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr index 6c88778ae0e..74704b2abfe 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `v` +error[E0381]: used binding `v` isn't initialized --> $DIR/borrowck-init-op-equal.rs:3:5 | +LL | let v: isize; + | - binding declared here but left uninitialized LL | v += 1; - | ^^^^^^ use of possibly-uninitialized `v` + | ^^^^^^ `v` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.rs b/src/test/ui/borrowck/borrowck-init-plus-equal.rs index d9d20a2a9c1..2a52a3f4e5e 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.rs +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.rs @@ -1,6 +1,6 @@ fn test() { let mut v: isize; - v = v + 1; //~ ERROR use of possibly-uninitialized variable: `v` + v = v + 1; //~ ERROR E0381 v.clone(); } diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr index fe09c8581df..7542576d636 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `v` +error[E0381]: used binding `v` isn't initialized --> $DIR/borrowck-init-plus-equal.rs:3:9 | +LL | let mut v: isize; + | ----- binding declared here but left uninitialized LL | v = v + 1; - | ^ use of possibly-uninitialized `v` + | ^ `v` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.stderr b/src/test/ui/borrowck/borrowck-move-by-capture.stderr index f81b34a641b..8ddc48b2a99 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.stderr +++ b/src/test/ui/borrowck/borrowck-move-by-capture.stderr @@ -1,18 +1,16 @@ error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure --> $DIR/borrowck-move-by-capture.rs:9:29 | -LL | let bar: Box<_> = Box::new(3); - | --- captured outer variable -LL | let _g = to_fn_mut(|| { - | ________________________- -LL | | let _h = to_fn_once(move || -> isize { *bar }); - | | ^^^^^^^^^^^^^^^^ ---- - | | | | - | | | variable moved due to use in closure - | | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait - | | move out of `bar` occurs here -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let bar: Box<_> = Box::new(3); + | --- captured outer variable +LL | let _g = to_fn_mut(|| { + | -- captured by this `FnMut` closure +LL | let _h = to_fn_once(move || -> isize { *bar }); + | ^^^^^^^^^^^^^^^^ ---- + | | | + | | variable moved due to use in closure + | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait + | move out of `bar` occurs here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-or-init.rs b/src/test/ui/borrowck/borrowck-or-init.rs index 81b0b80bf11..079cf899e6d 100644 --- a/src/test/ui/borrowck/borrowck-or-init.rs +++ b/src/test/ui/borrowck/borrowck-or-init.rs @@ -2,5 +2,5 @@ fn main() { let i: isize; println!("{}", false || { i = 5; true }); - println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i` + println!("{}", i); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr index 6c757759f71..0bc24f1b693 100644 --- a/src/test/ui/borrowck/borrowck-or-init.stderr +++ b/src/test/ui/borrowck/borrowck-or-init.stderr @@ -1,8 +1,13 @@ -error[E0381]: borrow of possibly-uninitialized variable: `i` +error[E0381]: used binding `i` is possibly-uninitialized --> $DIR/borrowck-or-init.rs:5:20 | +LL | let i: isize; + | - binding declared here but left uninitialized +LL | +LL | println!("{}", false || { i = 5; true }); + | ----- binding initialized here in some conditions LL | println!("{}", i); - | ^ use of possibly-uninitialized `i` + | ^ `i` used here but it is possibly-uninitialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs index 5e5a8cdf423..a43a1936678 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs +++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs @@ -14,8 +14,7 @@ impl Drop for Test2 { fn stuff() { let mut x : (Test2, Test2); - (x.0).0 = Some(Test); - //~^ ERROR assign of possibly-uninitialized variable: `x.0` + (x.0).0 = Some(Test); //~ ERROR E0381 } fn main() { diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr index 218c4f2de5b..d12a482cb69 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr +++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr @@ -1,8 +1,12 @@ -error[E0381]: assign of possibly-uninitialized variable: `x.0` +error[E0381]: assigned binding `x.0` isn't fully initialized --> $DIR/borrowck-partial-reinit-4.rs:17:5 | +LL | let mut x : (Test2, Test2); + | ----- binding declared here but left uninitialized LL | (x.0).0 = Some(Test); - | ^^^^^^^ use of possibly-uninitialized `x.0` + | ^^^^^^^ `x.0` assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-return.rs b/src/test/ui/borrowck/borrowck-return.rs index 8c623356f6c..a63ffcff732 100644 --- a/src/test/ui/borrowck/borrowck-return.rs +++ b/src/test/ui/borrowck/borrowck-return.rs @@ -1,6 +1,6 @@ fn f() -> isize { let x: isize; - return x; //~ ERROR use of possibly-uninitialized variable: `x` + return x; //~ ERROR E0381 } fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr index bc74e8e3438..1c916e22317 100644 --- a/src/test/ui/borrowck/borrowck-return.stderr +++ b/src/test/ui/borrowck/borrowck-return.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-return.rs:3:12 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | return x; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr index 8e4932142f0..2cea4392d6a 100644 --- a/src/test/ui/borrowck/borrowck-storage-dead.stderr +++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-storage-dead.rs:16:17 | +LL | let x: i32; + | - binding declared here but left uninitialized LL | let _ = x + 1; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.rs b/src/test/ui/borrowck/borrowck-uninit-after-item.rs index e9a389657c8..e97ce6aa407 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.rs +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.rs @@ -1,5 +1,5 @@ fn main() { let bar; fn baz(_x: isize) { } - baz(bar); //~ ERROR use of possibly-uninitialized variable: `bar` + baz(bar); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr index f7f069b81be..588b1b0c972 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr @@ -1,8 +1,11 @@ -error[E0381]: use of possibly-uninitialized variable: `bar` +error[E0381]: used binding `bar` isn't initialized --> $DIR/borrowck-uninit-after-item.rs:4:9 | +LL | let bar; + | --- binding declared here but left uninitialized +LL | fn baz(_x: isize) { } LL | baz(bar); - | ^^^ use of possibly-uninitialized `bar` + | ^^^ `bar` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr index 7951a5b1b5d..6a38a798919 100644 --- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `a` +error[E0381]: used binding `a` isn't initialized --> $DIR/borrowck-uninit-field-access.rs:21:13 | +LL | let mut a: Point; + | ----- binding declared here but left uninitialized LL | let _ = a.x + 1; - | ^^^ use of possibly-uninitialized `a.x` + | ^^^ `a.x` used here but it isn't initialized error[E0382]: use of moved value: `line1.origin` --> $DIR/borrowck-uninit-field-access.rs:25:13 diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs index 20350d61d5b..92c3692bd2f 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs @@ -3,32 +3,32 @@ pub fn main() { let x: isize; - x += 1; //~ ERROR use of possibly-uninitialized variable: `x` + x += 1; //~ ERROR E0381 let x: isize; - x -= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x -= 1; //~ ERROR E0381 let x: isize; - x *= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x *= 1; //~ ERROR E0381 let x: isize; - x /= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x /= 1; //~ ERROR E0381 let x: isize; - x %= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x %= 1; //~ ERROR E0381 let x: isize; - x ^= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x ^= 1; //~ ERROR E0381 let x: isize; - x &= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x &= 1; //~ ERROR E0381 let x: isize; - x |= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x |= 1; //~ ERROR E0381 let x: isize; - x <<= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x <<= 1; //~ ERROR E0381 let x: isize; - x >>= 1; //~ ERROR use of possibly-uninitialized variable: `x` + x >>= 1; //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr index f2036df3ce9..744cb14e662 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr @@ -1,62 +1,82 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:6:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x += 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:9:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x -= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:12:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x *= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:15:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x /= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:18:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x %= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:21:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x ^= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:24:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x &= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:27:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x |= 1; - | ^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:30:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x <<= 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:33:5 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | x >>= 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` used here but it isn't initialized error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs index 0ccea49f329..c36b9707d22 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs @@ -5,29 +5,29 @@ struct S<X, Y> { fn main() { let x: &&Box<i32>; - let _y = &**x; //~ [E0381] + let _y = &**x; //~ ERROR [E0381] let x: &&S<i32, i32>; - let _y = &**x; //~ [E0381] + let _y = &**x; //~ ERROR [E0381] let x: &&i32; - let _y = &**x; //~ [E0381] + let _y = &**x; //~ ERROR [E0381] let mut a: S<i32, i32>; - a.x = 0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] + a.x = 0; //~ ERROR [E0381] let _b = &a.x; let mut a: S<&&i32, &&i32>; - a.x = &&0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] + a.x = &&0; //~ ERROR [E0381] let _b = &**a.x; let mut a: S<i32, i32>; - a.x = 0; //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381] + a.x = 0; //~ ERROR [E0381] let _b = &a.y; let mut a: S<&&i32, &&i32>; - a.x = &&0; //~ assign to part of possibly-uninitialized variable: `a` [E0381] + a.x = &&0; //~ ERROR [E0381] let _b = &**a.y; } diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr index d99a50df75b..c486cb6dd0c 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr @@ -1,44 +1,66 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-ref-chain.rs:8:14 | +LL | let x: &&Box<i32>; + | - binding declared here but left uninitialized LL | let _y = &**x; - | ^^^^ use of possibly-uninitialized `**x` + | ^^^^ `**x` used here but it isn't initialized -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-ref-chain.rs:11:14 | +LL | let x: &&S<i32, i32>; + | - binding declared here but left uninitialized LL | let _y = &**x; - | ^^^^ use of possibly-uninitialized `**x` + | ^^^^ `**x` used here but it isn't initialized -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-ref-chain.rs:14:14 | +LL | let x: &&i32; + | - binding declared here but left uninitialized LL | let _y = &**x; - | ^^^^ use of possibly-uninitialized `**x` + | ^^^^ `**x` used here but it isn't initialized -error[E0381]: assign to part of possibly-uninitialized variable: `a` +error[E0381]: partially assigned binding `a` isn't fully initialized --> $DIR/borrowck-uninit-ref-chain.rs:18:5 | +LL | let mut a: S<i32, i32>; + | ----- binding declared here but left uninitialized LL | a.x = 0; - | ^^^^^^^ use of possibly-uninitialized `a` + | ^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `a` +error[E0381]: partially assigned binding `a` isn't fully initialized --> $DIR/borrowck-uninit-ref-chain.rs:22:5 | +LL | let mut a: S<&&i32, &&i32>; + | ----- binding declared here but left uninitialized LL | a.x = &&0; - | ^^^^^^^^^ use of possibly-uninitialized `a` + | ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `a` +error[E0381]: partially assigned binding `a` isn't fully initialized --> $DIR/borrowck-uninit-ref-chain.rs:27:5 | +LL | let mut a: S<i32, i32>; + | ----- binding declared here but left uninitialized LL | a.x = 0; - | ^^^^^^^ use of possibly-uninitialized `a` + | ^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `a` +error[E0381]: partially assigned binding `a` isn't fully initialized --> $DIR/borrowck-uninit-ref-chain.rs:31:5 | +LL | let mut a: S<&&i32, &&i32>; + | ----- binding declared here but left uninitialized LL | a.x = &&0; - | ^^^^^^^^^ use of possibly-uninitialized `a` + | ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 7 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit.rs b/src/test/ui/borrowck/borrowck-uninit.rs index 017b955a395..5d0ebabb008 100644 --- a/src/test/ui/borrowck/borrowck-uninit.rs +++ b/src/test/ui/borrowck/borrowck-uninit.rs @@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); } fn main() { let x: isize; - foo(x); //~ ERROR use of possibly-uninitialized variable: `x` + foo(x); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr index effc209e816..d5566691a82 100644 --- a/src/test/ui/borrowck/borrowck-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-uninit.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit.rs:5:9 | +LL | let x: isize; + | - binding declared here but left uninitialized LL | foo(x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.rs b/src/test/ui/borrowck/borrowck-union-uninitialized.rs index 3cc71e7cece..bbe9f22aac3 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.rs +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.rs @@ -10,8 +10,8 @@ fn main() { unsafe { let mut s: S; let mut u: U; - s.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `s` - u.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `u` + s.a = 0; //~ ERROR E0381 + u.a = 0; //~ ERROR E0381 let sa = s.a; let ua = u.a; } diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr index bd9ec5e579c..b7ff5f3955e 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr @@ -1,14 +1,24 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `s` +error[E0381]: partially assigned binding `s` isn't fully initialized --> $DIR/borrowck-union-uninitialized.rs:13:9 | +LL | let mut s: S; + | ----- binding declared here but left uninitialized +LL | let mut u: U; LL | s.a = 0; - | ^^^^^^^ use of possibly-uninitialized `s` + | ^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `u` +error[E0381]: partially assigned binding `u` isn't fully initialized --> $DIR/borrowck-union-uninitialized.rs:14:9 | +LL | let mut u: U; + | ----- binding declared here but left uninitialized +LL | s.a = 0; LL | u.a = 0; - | ^^^^^^^ use of possibly-uninitialized `u` + | ^^^^^^^ `u` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr index d1b396aba82..459cf1398b7 100644 --- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr @@ -1,14 +1,18 @@ -error[E0381]: use of possibly-uninitialized variable: `w` +error[E0381]: used binding `w` isn't initialized --> $DIR/borrowck-use-in-index-lvalue.rs:3:5 | +LL | let w: &mut [isize]; + | - binding declared here but left uninitialized LL | w[5] = 0; - | ^^^^ use of possibly-uninitialized `*w` + | ^^^^ `*w` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `w` +error[E0381]: used binding `w` isn't initialized --> $DIR/borrowck-use-in-index-lvalue.rs:6:5 | +LL | let mut w: &mut [isize]; + | ----- binding declared here but left uninitialized LL | w[5] = 0; - | ^^^^ use of possibly-uninitialized `*w` + | ^^^^ `*w` used here but it isn't initialized error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr index ca5227c98c8..942ed4fc6ca 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -1,8 +1,10 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13 | +LL | let x: &i32; + | - binding declared here but left uninitialized LL | let y = x as *const dyn Foo; - | ^ use of possibly-uninitialized `*x` + | ^ `*x` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr index 24897a0f2dc..f3289e23981 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -1,8 +1,10 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13 | +LL | let x: &i32; + | - binding declared here but left uninitialized LL | let y = x as *const i32; - | ^ use of possibly-uninitialized `*x` + | ^ `*x` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while-break.rs b/src/test/ui/borrowck/borrowck-while-break.rs index 48e42214702..7100b713031 100644 --- a/src/test/ui/borrowck/borrowck-while-break.rs +++ b/src/test/ui/borrowck/borrowck-while-break.rs @@ -4,7 +4,7 @@ fn test(cond: bool) { v = 3; break; } - println!("{}", v); //~ ERROR borrow of possibly-uninitialized variable: `v` + println!("{}", v); //~ ERROR E0381 } fn main() { diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr index fc144a066bb..44674febf49 100644 --- a/src/test/ui/borrowck/borrowck-while-break.stderr +++ b/src/test/ui/borrowck/borrowck-while-break.stderr @@ -1,8 +1,13 @@ -error[E0381]: borrow of possibly-uninitialized variable: `v` +error[E0381]: used binding `v` is possibly-uninitialized --> $DIR/borrowck-while-break.rs:7:20 | +LL | let v; + | - binding declared here but left uninitialized +LL | while cond { + | ---- if this condition isn't met and the `while` loop runs 0 times, `v` is not initialized +... LL | println!("{}", v); - | ^ use of possibly-uninitialized `v` + | ^ `v` used here but it is possibly-uninitialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/borrowck-while-cond.rs b/src/test/ui/borrowck/borrowck-while-cond.rs index b3ec20711c1..62a9bdd2020 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.rs +++ b/src/test/ui/borrowck/borrowck-while-cond.rs @@ -1,4 +1,4 @@ fn main() { let x: bool; - while x { } //~ ERROR use of possibly-uninitialized variable: `x` + while x { } //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr index 92937a9c573..e41c1c55e60 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.stderr +++ b/src/test/ui/borrowck/borrowck-while-cond.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-while-cond.rs:3:11 | +LL | let x: bool; + | - binding declared here but left uninitialized LL | while x { } - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while.rs b/src/test/ui/borrowck/borrowck-while.rs index 6b3220c7d85..f49a778eb6b 100644 --- a/src/test/ui/borrowck/borrowck-while.rs +++ b/src/test/ui/borrowck/borrowck-while.rs @@ -1,7 +1,7 @@ fn f() -> isize { let mut x: isize; while 1 == 1 { x = 10; } - return x; //~ ERROR use of possibly-uninitialized variable: `x` + return x; //~ ERROR E0381 } fn main() { f(); } diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr index a1f8f64725d..c45235990c3 100644 --- a/src/test/ui/borrowck/borrowck-while.stderr +++ b/src/test/ui/borrowck/borrowck-while.stderr @@ -1,8 +1,12 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` is possibly-uninitialized --> $DIR/borrowck-while.rs:4:12 | +LL | let mut x: isize; + | ----- binding declared here but left uninitialized +LL | while 1 == 1 { x = 10; } + | ------ if this condition isn't met and the `while` loop runs 0 times, `x` is not initialized LL | return x; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it is possibly-uninitialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs index 7043cb3a164..17de40d5ba9 100644 --- a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs @@ -4,19 +4,19 @@ fn main() { let mut t: (u64, u64); t.0 = 1; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + //~^ ERROR E0381 t.1 = 1; let mut t: (u64, u64); t.1 = 1; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + //~^ ERROR E0381 t.0 = 1; let mut t: (u64, u64); t.0 = 1; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + //~^ ERROR E0381 let mut t: (u64,); t.0 = 1; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + //~^ ERROR E0381 } diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr index 8d5b39341c1..9a84c6fefae 100644 --- a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr @@ -1,26 +1,42 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/disallow-possibly-uninitialized.rs:6:5 | +LL | let mut t: (u64, u64); + | ----- binding declared here but left uninitialized LL | t.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/disallow-possibly-uninitialized.rs:11:5 | +LL | let mut t: (u64, u64); + | ----- binding declared here but left uninitialized LL | t.1 = 1; - | ^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/disallow-possibly-uninitialized.rs:16:5 | +LL | let mut t: (u64, u64); + | ----- binding declared here but left uninitialized LL | t.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/disallow-possibly-uninitialized.rs:20:5 | +LL | let mut t: (u64,); + | ----- binding declared here but left uninitialized LL | t.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 4 previous errors diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.rs b/src/test/ui/borrowck/issue-24267-flow-exit.rs index d6809ee4143..c419c5840d9 100644 --- a/src/test/ui/borrowck/issue-24267-flow-exit.rs +++ b/src/test/ui/borrowck/issue-24267-flow-exit.rs @@ -9,11 +9,11 @@ pub fn main() { pub fn foo1() { let x: i32; loop { x = break; } - println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` + println!("{}", x); //~ ERROR E0381 } pub fn foo2() { let x: i32; for _ in 0..10 { x = continue; } - println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x` + println!("{}", x); //~ ERROR E0381 } diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr index e29cf7a1a75..d436e8ff909 100644 --- a/src/test/ui/borrowck/issue-24267-flow-exit.stderr +++ b/src/test/ui/borrowck/issue-24267-flow-exit.stderr @@ -1,16 +1,22 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/issue-24267-flow-exit.rs:12:20 | +LL | let x: i32; + | - binding declared here but left uninitialized +LL | loop { x = break; } LL | println!("{}", x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/issue-24267-flow-exit.rs:18:20 | +LL | let x: i32; + | - binding declared here but left uninitialized +LL | for _ in 0..10 { x = continue; } LL | println!("{}", x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr b/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr index a7c3b9eec73..d98b3bae4e0 100644 --- a/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr +++ b/src/test/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | let _action = move || { | ------- | | | - | | return type of closure `[closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:15]` contains a lifetime `'2` + | | return type of closure `[closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:11]` contains a lifetime `'2` | lifetime `'1` represents this closure's body LL | || f() // The `nested` closure | ^^^^^^ returning this value requires that `'1` must outlive `'2` diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs index f031a144443..205ea10c90b 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs @@ -10,7 +10,7 @@ fn main() { { let mut t: Tuple; t.0 = S(1); - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + //~^ ERROR E0381 t.1 = 2; println!("{:?} {:?}", t.0, t.1); } @@ -18,7 +18,7 @@ fn main() { { let mut u: Tpair; u.0 = S(1); - //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381] + //~^ ERROR E0381 u.1 = 2; println!("{:?} {:?}", u.0, u.1); } @@ -26,7 +26,7 @@ fn main() { { let mut v: Spair; v.x = S(1); - //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381] + //~^ ERROR E0381 v.y = 2; println!("{:?} {:?}", v.x, v.y); } diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr index 22c6c3964ed..2a0eba396f1 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr @@ -1,20 +1,32 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9 | +LL | let mut t: Tuple; + | ----- binding declared here but left uninitialized LL | t.0 = S(1); - | ^^^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `u` +error[E0381]: partially assigned binding `u` isn't fully initialized --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9 | +LL | let mut u: Tpair; + | ----- binding declared here but left uninitialized LL | u.0 = S(1); - | ^^^^^^^^^^ use of possibly-uninitialized `u` + | ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `v` +error[E0381]: partially assigned binding `v` isn't fully initialized --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9 | +LL | let mut v: Spair; + | ----- binding declared here but left uninitialized LL | v.x = S(1); - | ^^^^^^^^^^ use of possibly-uninitialized `v` + | ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs index 660d9e85ef5..50d0c40fdf6 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs @@ -10,7 +10,7 @@ fn main() { { let t: Tuple; t.0 = S(1); - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + //~^ ERROR E0381 t.1 = 2; println!("{:?} {:?}", t.0, t.1); } @@ -18,7 +18,7 @@ fn main() { { let u: Tpair; u.0 = S(1); - //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381] + //~^ ERROR E0381 u.1 = 2; println!("{:?} {:?}", u.0, u.1); } @@ -26,7 +26,7 @@ fn main() { { let v: Spair; v.x = S(1); - //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381] + //~^ ERROR E0381 v.y = 2; println!("{:?} {:?}", v.x, v.y); } diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr index 5f9c978c342..67a62583057 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr @@ -1,20 +1,32 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9 | +LL | let t: Tuple; + | - binding declared here but left uninitialized LL | t.0 = S(1); - | ^^^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `u` +error[E0381]: partially assigned binding `u` isn't fully initialized --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9 | +LL | let u: Tpair; + | - binding declared here but left uninitialized LL | u.0 = S(1); - | ^^^^^^^^^^ use of possibly-uninitialized `u` + | ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `v` +error[E0381]: partially assigned binding `v` isn't fully initialized --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9 | +LL | let v: Spair; + | - binding declared here but left uninitialized LL | v.x = S(1); - | ^^^^^^^^^^ use of possibly-uninitialized `v` + | ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs index f8efa8c891e..93ce34d2fe5 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs @@ -1,7 +1,7 @@ fn main() { let e: i32; match e { - //~^ ERROR use of possibly-uninitialized variable + //~^ ERROR E0381 ref u if true => {} ref v if true => { let tx = 0; diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr index 0eca447b551..f5d2eecfa91 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `e` +error[E0381]: used binding `e` isn't initialized --> $DIR/issue-62107-match-arm-scopes.rs:3:11 | +LL | let e: i32; + | - binding declared here but left uninitialized LL | match e { - | ^ use of possibly-uninitialized `e` + | ^ `e` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr index 29288be4934..1acabefb893 100644 --- a/src/test/ui/borrowck/issue-81899.stderr +++ b/src/test/ui/borrowck/issue-81899.stderr @@ -8,7 +8,7 @@ LL | panic!() | ^^^^^^^^ | | | the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:12:5 - | inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr index fd38ad7bb0a..039575a8d79 100644 --- a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr +++ b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr @@ -1,21 +1,17 @@ error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure --> $DIR/issue-87456-point-to-closure.rs:10:28 | -LL | let val = String::new(); - | --- captured outer variable +LL | let val = String::new(); + | --- captured outer variable LL | -LL | take_mut(|| { - | ______________- -LL | | -LL | | let _foo: String = val; - | | ^^^ - | | | - | | move occurs because `val` has type `String`, which does not implement the `Copy` trait - | | help: consider borrowing here: `&val` -LL | | -LL | | -LL | | }) - | |_____- captured by this `FnMut` closure +LL | take_mut(|| { + | -- captured by this `FnMut` closure +LL | +LL | let _foo: String = val; + | ^^^ + | | + | move occurs because `val` has type `String`, which does not implement the `Copy` trait + | help: consider borrowing here: `&val` error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr index daded200bd9..c7b5d773e82 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr +++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr @@ -8,7 +8,7 @@ LL | panic!() | ^^^^^^^^ | | | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:11:5 - | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` at $SRC_DIR/std/src/panic.rs:LL:COL | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index ce6a37ee418..f4bb895e6b5 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -8,7 +8,7 @@ LL | panic!() | ^^^^^^^^ | | | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:11:5 - | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr index edab22569b3..dd29ae492d6 100644 --- a/src/test/ui/borrowck/mutability-errors.stderr +++ b/src/test/ui/borrowck/mutability-errors.stderr @@ -119,146 +119,112 @@ LL | &mut (*f()).0; error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:40:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); - | | ^^^^^^^^ cannot assign -LL | | x.0 = 1; -LL | | &mut x; -LL | | &mut x.0; -LL | | }); - | |_____- in this closure +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); + | ^^^^^^^^ cannot assign error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:41:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); -LL | | x.0 = 1; - | | ^^^^^^^ cannot assign -LL | | &mut x; -LL | | &mut x.0; -LL | | }); - | |_____- in this closure +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); +LL | x.0 = 1; + | ^^^^^^^ cannot assign error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:42:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); -LL | | x.0 = 1; -LL | | &mut x; - | | ^^^^^^ cannot borrow as mutable -LL | | &mut x.0; -LL | | }); - | |_____- in this closure +LL | &mut x; + | ^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:43:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); -LL | | x.0 = 1; -LL | | &mut x; -LL | | &mut x.0; - | | ^^^^^^^^ cannot borrow as mutable -LL | | }); - | |_____- in this closure +LL | &mut x.0; + | ^^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:46:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); - | | ^^^^^^^^ cannot assign -LL | | x.0 = 1; -LL | | &mut x; -LL | | &mut x.0; -LL | | }); - | |_____- in this closure +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); + | ^^^^^^^^ cannot assign error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:47:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); -LL | | x.0 = 1; - | | ^^^^^^^ cannot assign -LL | | &mut x; -LL | | &mut x.0; -LL | | }); - | |_____- in this closure +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); +LL | x.0 = 1; + | ^^^^^^^ cannot assign error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:48:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); -LL | | x.0 = 1; -LL | | &mut x; - | | ^^^^^^ cannot borrow as mutable -LL | | &mut x.0; -LL | | }); - | |_____- in this closure +LL | &mut x; + | ^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:49:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | x = (1,); -LL | | x.0 = 1; -LL | | &mut x; -LL | | &mut x.0; - | | ^^^^^^^^ cannot borrow as mutable -LL | | }); - | |_____- in this closure +LL | &mut x.0; + | ^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/mutability-errors.rs:54:5 diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr index f09db378a75..e6b25573e70 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr @@ -1,14 +1,22 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/reassignment_immutable_fields.rs:7:5 | +LL | let x: (u32, u32); + | - binding declared here but left uninitialized LL | x.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/reassignment_immutable_fields.rs:15:5 | +LL | let x: (u32, u32); + | - binding declared here but left uninitialized LL | x.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr index 0eae2c71e4a..a3885b5f5ca 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -1,8 +1,12 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5 | +LL | let x: Foo; + | - binding declared here but left uninitialized LL | x.a = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5 diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr index f55e1a27f47..49c81adad49 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -7,11 +7,15 @@ LL | x = (22, 44); LL | x.0 = 1; | ^^^^^^^ cannot assign -error[E0381]: assign to part of possibly-uninitialized variable: `x` +error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/reassignment_immutable_fields_twice.rs:12:5 | +LL | let x: (u32, u32); + | - binding declared here but left uninitialized LL | x.0 = 1; - | ^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index 3ea72262003..0c151b09707 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -1,17 +1,14 @@ error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9 | -LL | let y = vec![format!("World")]; - | - captured outer variable -LL | call(|| { - | __________- -LL | | y.into_iter(); - | | ^ ----------- `y` moved due to this method call - | | | - | | move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait -LL | | -LL | | }); - | |_____- captured by this `Fn` closure +LL | let y = vec![format!("World")]; + | - captured outer variable +LL | call(|| { + | -- captured by this `Fn` closure +LL | y.into_iter(); + | ^ ----------- `y` moved due to this method call + | | + | move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves `y` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs index 0f288ffa95a..69cf920de94 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs +++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs @@ -6,14 +6,14 @@ fn test1() { let x: !; let c1 = || match x { }; - //~^ ERROR: use of possibly-uninitialized variable: `x` + //~^ ERROR E0381 } // Should fake read the discriminant and throw an error fn test2() { let x: !; let c2 = || match x { _ => () }; - //~^ ERROR: borrow of possibly-uninitialized variable: `x` + //~^ ERROR E0381 } // Testing single variant patterns @@ -25,7 +25,7 @@ enum SingleVariant { fn test3() { let variant: !; let c = || { - //~^ ERROR: borrow of possibly-uninitialized variable: `variant` + //~^ ERROR E0381 match variant { SingleVariant::Points(_) => {} } @@ -36,8 +36,7 @@ fn test3() { // Should fake read the discriminant and throw an error fn test4() { let variant: !; - let c = || { - //~^ ERROR: borrow of possibly-uninitialized variable: `variant` + let c = || { //~ ERROR E0381 match variant { SingleVariant::Points(a) => { println!("{:?}", a); @@ -52,11 +51,9 @@ fn test5() { let g: !; let a = || { - match g { }; - //~^ ERROR: use of possibly-uninitialized variable: `g` + match g { }; //~ ERROR E0381 let c = || { - match t { }; - //~^ ERROR: use of possibly-uninitialized variable: `t` + match t { }; //~ ERROR E0381 }; c(); @@ -68,7 +65,7 @@ fn test5() { fn test6() { let x: u8; let c1 = || match x { }; - //~^ ERROR: use of possibly-uninitialized variable: `x` + //~^ ERROR E0381 //~| ERROR: non-exhaustive patterns: type `u8` is non-empty } diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr index e55fb7ce4bb..fea5441ec67 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr +++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/pattern-matching-should-fail.rs:70:23 + --> $DIR/pattern-matching-should-fail.rs:67:23 | LL | let c1 = || match x { }; | ^ @@ -12,55 +12,70 @@ LL + _ => todo!(), LL ~ }; | -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/pattern-matching-should-fail.rs:8:23 | +LL | let x: !; + | - binding declared here but left uninitialized LL | let c1 = || match x { }; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/pattern-matching-should-fail.rs:15:14 | +LL | let x: !; + | - binding declared here but left uninitialized LL | let c2 = || match x { _ => () }; | ^^ - borrow occurs due to use in closure | | - | use of possibly-uninitialized `x` + | `x` used here but it isn't initialized -error[E0381]: borrow of possibly-uninitialized variable: `variant` +error[E0381]: used binding `variant` isn't initialized --> $DIR/pattern-matching-should-fail.rs:27:13 | +LL | let variant: !; + | ------- binding declared here but left uninitialized LL | let c = || { - | ^^ use of possibly-uninitialized `variant` + | ^^ `variant` used here but it isn't initialized LL | LL | match variant { | ------- borrow occurs due to use in closure -error[E0381]: borrow of possibly-uninitialized variable: `variant` +error[E0381]: used binding `variant` isn't initialized --> $DIR/pattern-matching-should-fail.rs:39:13 | +LL | let variant: !; + | ------- binding declared here but left uninitialized LL | let c = || { - | ^^ use of possibly-uninitialized `variant` -LL | + | ^^ `variant` used here but it isn't initialized LL | match variant { | ------- borrow occurs due to use in closure -error[E0381]: use of possibly-uninitialized variable: `g` - --> $DIR/pattern-matching-should-fail.rs:55:15 +error[E0381]: used binding `g` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:54:15 | +LL | let g: !; + | - binding declared here but left uninitialized +... LL | match g { }; - | ^ use of possibly-uninitialized `g` + | ^ `g` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `t` - --> $DIR/pattern-matching-should-fail.rs:58:19 +error[E0381]: used binding `t` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:56:19 | +LL | let t: !; + | - binding declared here but left uninitialized +... LL | match t { }; - | ^ use of possibly-uninitialized `t` + | ^ `t` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:70:23 +error[E0381]: used binding `x` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:67:23 | +LL | let x: u8; + | - binding declared here but left uninitialized LL | let c1 = || match x { }; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error: aborting due to 8 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index a3c43690f1f..d7104bafeb1 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -2,7 +2,7 @@ error: changes to closure capture in Rust 2021 will affect which traits the clos --> $DIR/auto_traits.rs:22:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send` + | ^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send` ... LL | *fptr.0 = 20; | ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` @@ -26,7 +26,7 @@ error: changes to closure capture in Rust 2021 will affect which traits the clos --> $DIR/auto_traits.rs:42:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ + | ^^^^^^^ | | | in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send` | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr index 675ba0313d7..c611daf13fd 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr @@ -2,14 +2,10 @@ warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/closure-body-macro-fragment.rs:16:17 | LL | let f = || $body; - | _________________^ -LL | | -LL | | f(); -LL | | }}; - | | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure -LL | | ($body:block) => {{ -LL | | m!(@ $body); - | |__________________^ + | ^^ +... +LL | }}; + | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure ... LL | / m!({ LL | | diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr index 5046a4bcbb4..2d0c56aad8d 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr @@ -2,9 +2,7 @@ error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/macro.rs:19:13 | LL | let _ = || dbg!(a.0); - | ^^^^^^^^---^ - | | - | in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` + | ^^ --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` ... LL | } | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr index 3589a6150d0..12760cc7256 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr @@ -26,9 +26,7 @@ error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/migrations_rustfix.rs:33:13 | LL | let c = || t.0; - | ^^^--- - | | - | in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + | ^^ --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` ... LL | } | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr index fa6082cbb59..96d5c936fa5 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -92,7 +92,7 @@ error: changes to closure capture in Rust 2021 will affect which traits the clos --> $DIR/multi_diagnostics.rs:133:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ + | ^^^^^^^ | | | in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send` | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr index fa1f83c3782..0d9f09ee354 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr @@ -199,9 +199,7 @@ error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/significant_drop.rs:201:18 | LL | let _c = || tup.0; - | ^^^----- - | | - | in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0` + | ^^ ----- in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0` ... LL | } | - in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr index cbc4e2e5231..1086cfa2947 100644 --- a/src/test/ui/closures/closure-move-sync.stderr +++ b/src/test/ui/closures/closure-move-sync.stderr @@ -9,12 +9,8 @@ LL | let t = thread::spawn(|| { note: required because it's used within this closure --> $DIR/closure-move-sync.rs:6:27 | -LL | let t = thread::spawn(|| { - | ___________________________^ -LL | | recv.recv().unwrap(); -LL | | -LL | | }); - | |_____^ +LL | let t = thread::spawn(|| { + | ^^ note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | @@ -33,7 +29,7 @@ note: required because it's used within this closure --> $DIR/closure-move-sync.rs:18:19 | LL | thread::spawn(|| tx.send(()).unwrap()); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | diff --git a/src/test/ui/closures/closure-no-fn-1.stderr b/src/test/ui/closures/closure-no-fn-1.stderr index 2b53802fea7..eab7482e6c4 100644 --- a/src/test/ui/closures/closure-no-fn-1.stderr +++ b/src/test/ui/closures/closure-no-fn-1.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:50]` + found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:36]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-1.rs:6:39 | diff --git a/src/test/ui/closures/closure-no-fn-2.stderr b/src/test/ui/closures/closure-no-fn-2.stderr index ed9f87a2c94..e1f0143abfe 100644 --- a/src/test/ui/closures/closure-no-fn-2.stderr +++ b/src/test/ui/closures/closure-no-fn-2.stderr @@ -7,7 +7,7 @@ LL | let bar: fn() -> u8 = || { b }; | expected due to this | = note: expected fn pointer `fn() -> u8` - found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:35]` + found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:29]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-2.rs:6:32 | diff --git a/src/test/ui/closures/closure-no-fn-3.stderr b/src/test/ui/closures/closure-no-fn-3.stderr index 95683a786ba..6009389b1bb 100644 --- a/src/test/ui/closures/closure-no-fn-3.stderr +++ b/src/test/ui/closures/closure-no-fn-3.stderr @@ -1,4 +1,4 @@ -error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:27: 6:37]` as `fn() -> u8` +error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:28: 6:30]` as `fn() -> u8` --> $DIR/closure-no-fn-3.rs:6:27 | LL | let baz: fn() -> u8 = (|| { b }) as fn() -> u8; diff --git a/src/test/ui/closures/closure-no-fn-4.stderr b/src/test/ui/closures/closure-no-fn-4.stderr index 89798ec5dd3..d1b7048841a 100644 --- a/src/test/ui/closures/closure-no-fn-4.stderr +++ b/src/test/ui/closures/closure-no-fn-4.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____- `match` arms have incompatible types | = note: expected fn pointer `fn(usize) -> usize` - found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:27]` + found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:21]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-4.rs:5:26 | diff --git a/src/test/ui/closures/closure-no-fn-5.stderr b/src/test/ui/closures/closure-no-fn-5.stderr index 1f373f10489..a33b847ea92 100644 --- a/src/test/ui/closures/closure-no-fn-5.stderr +++ b/src/test/ui/closures/closure-no-fn-5.stderr @@ -7,7 +7,7 @@ LL | let bar: fn() -> u8 = || { a; b; c; d; e }; | expected due to this | = note: expected fn pointer `fn() -> u8` - found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:47]` + found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:29]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-no-fn-5.rs:10:32 | diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr index 534828ab348..9dfff8499fd 100644 --- a/src/test/ui/closures/closure-reform-bad.stderr +++ b/src/test/ui/closures/closure-reform-bad.stderr @@ -2,14 +2,14 @@ error[E0308]: mismatched types --> $DIR/closure-reform-bad.rs:11:15 | LL | let f = |s: &str| println!("{}{}", s, string); - | ------------------------------------- the found closure + | --------- the found closure LL | call_bare(f) | --------- ^ expected fn pointer, found closure | | | arguments to this function are incorrect | = note: expected fn pointer `for<'r> fn(&'r str)` - found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50]` + found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:22]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-reform-bad.rs:10:43 | diff --git a/src/test/ui/closures/closure-wrong-kind.stderr b/src/test/ui/closures/closure-wrong-kind.stderr index 65026128ae6..35caf71a5e8 100644 --- a/src/test/ui/closures/closure-wrong-kind.stderr +++ b/src/test/ui/closures/closure-wrong-kind.stderr @@ -2,9 +2,8 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closur --> $DIR/closure-wrong-kind.rs:10:19 | LL | let closure = |_| foo(x); - | ^^^^^^^^-^ - | | | - | | closure is `FnOnce` because it moves the variable `x` out of its environment + | ^^^ - closure is `FnOnce` because it moves the variable `x` out of its environment + | | | this closure implements `FnOnce`, not `Fn` LL | bar(closure); | --- the requirement to implement `Fn` derives from here diff --git a/src/test/ui/closures/closure_cap_coerce_many_fail.stderr b/src/test/ui/closures/closure_cap_coerce_many_fail.stderr index e25b33bbcdb..ca8a43328a9 100644 --- a/src/test/ui/closures/closure_cap_coerce_many_fail.stderr +++ b/src/test/ui/closures/closure_cap_coerce_many_fail.stderr @@ -12,7 +12,7 @@ LL | | }; | |_____- `match` arms have incompatible types | = note: expected fn item `fn(i32, i32) -> i32 {add}` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:43]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:22]` error[E0308]: `match` arms have incompatible types --> $DIR/closure_cap_coerce_many_fail.rs:18:16 @@ -23,15 +23,15 @@ LL | | "+" => |a, b| (a + b) as i32, | | --------------------- | | | | | the expected closure - | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:37]` + | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22]` LL | | "-" => |a, b| (a - b + cap) as i32, | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure LL | | _ => unimplemented!(), LL | | }; | |_____- `match` arms have incompatible types | - = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:37]` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:43]` + = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:22]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object @@ -44,15 +44,15 @@ LL | | "+" => |a, b| (a + b + cap) as i32, | | --------------------------- | | | | | the expected closure - | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:43]` + | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22]` LL | | "-" => |a, b| (a - b) as i32, | | ^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure LL | | _ => unimplemented!(), LL | | }; | |_____- `match` arms have incompatible types | - = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:43]` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:37]` + = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:22]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object @@ -65,15 +65,15 @@ LL | | "+" => |a, b| (a + b + cap) as i32, | | --------------------------- | | | | | the expected closure - | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:43]` + | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22]` LL | | "-" => |a, b| (a - b + cap) as i32, | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure LL | | _ => unimplemented!(), LL | | }; | |_____- `match` arms have incompatible types | - = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:43]` - found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:43]` + = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:22]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object diff --git a/src/test/ui/closures/print/closure-print-generic-1.stderr b/src/test/ui/closures/print/closure-print-generic-1.stderr index 43a12f675f5..b21734f0257 100644 --- a/src/test/ui/closures/print/closure-print-generic-1.stderr +++ b/src/test/ui/closures/print/closure-print-generic-1.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `c` --> $DIR/closure-print-generic-1.rs:17:5 | LL | let c = to_fn_once(move || { - | - move occurs because `c` has type `[closure@$DIR/closure-print-generic-1.rs:12:24: 14:6]`, which does not implement the `Copy` trait + | - move occurs because `c` has type `[closure@$DIR/closure-print-generic-1.rs:12:24: 12:31]`, which does not implement the `Copy` trait ... LL | c(); | --- `c` moved due to this call diff --git a/src/test/ui/closures/print/closure-print-generic-2.stderr b/src/test/ui/closures/print/closure-print-generic-2.stderr index 9c75d5a9023..e53277a9396 100644 --- a/src/test/ui/closures/print/closure-print-generic-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-2.stderr @@ -2,14 +2,14 @@ error[E0308]: mismatched types --> $DIR/closure-print-generic-2.rs:6:22 | LL | let c = || println!("{} {}", t, x); - | -------------------------- the found closure + | -- the found closure LL | let c1: () = c; | -- ^ expected `()`, found closure | | | expected due to this | = note: expected unit type `()` - found closure `[closure@$DIR/closure-print-generic-2.rs:5:17: 5:43]` + found closure `[closure@$DIR/closure-print-generic-2.rs:5:17: 5:19]` help: use parentheses to call this closure | LL | let c1: () = c(); diff --git a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index aee782a1c5b..ff89dd34034 100644 --- a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/closure-print-generic-trim-off-verbose-2.rs:9:23 | LL | let c = || println!("{} {}", t, x); - | -------------------------- the found closure + | -- the found closure LL | let c1 : () = c; | -- ^ expected `()`, found closure | | diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr index 6a994ce718e..5bbf84f963d 100644 --- a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/closure-print-generic-verbose-2.rs:9:23 | LL | let c = || println!("{} {}", t, x); - | -------------------------- the found closure + | -- the found closure LL | let c1 : () = c; | -- ^ expected `()`, found closure | | diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr index f0109f22a2b..9d614e610ad 100644 --- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr +++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr @@ -32,7 +32,7 @@ LL | let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>; | ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure | = note: expected struct `Box<dyn Fn(i32) -> u8>` - found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>` + found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:22]>` error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:14:13 @@ -86,7 +86,7 @@ LL | let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; | ^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure | = note: expected reference `&dyn Fn(i32) -> u8` - found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]` + found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:19]` error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:22:13 @@ -122,7 +122,7 @@ LL | let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>; | ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure | = note: expected struct `Box<dyn Fn(i32) -> u8>` - found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>` + found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:25]>` error: aborting due to 14 previous errors diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr index 7c2e6b01533..34debb68317 100644 --- a/src/test/ui/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope +error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope --> $DIR/issue-33784.rs:27:7 | LL | p.closure(); @@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p LL | (p.closure)(); | + + -error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:48]>` in the current scope +error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope --> $DIR/issue-33784.rs:29:7 | LL | q.fn_ptr(); diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs b/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs index bb5a2f1766f..e64adacac9f 100644 --- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs +++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs @@ -1,6 +1,5 @@ struct X<const N: usize = { - let s: &'static str; s.len() - //~^ ERROR borrow of possibly-uninitialized variable + let s: &'static str; s.len() //~ ERROR E0381 }>; fn main() {} diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr index 6c25019b0ce..c62f1d1d230 100644 --- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr +++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -1,8 +1,10 @@ -error[E0381]: borrow of possibly-uninitialized variable: `s` +error[E0381]: used binding `s` isn't initialized --> $DIR/const-generic-default-wont-borrowck.rs:2:26 | LL | let s: &'static str; s.len() - | ^^^^^^^ use of possibly-uninitialized `*s` + | - ^^^^^^^ `*s` used here but it isn't initialized + | | + | binding declared here but left uninitialized error: aborting due to previous error diff --git a/src/test/ui/const-generics/issue-70408.rs b/src/test/ui/const-generics/issue-70408.rs new file mode 100644 index 00000000000..f7557cb492c --- /dev/null +++ b/src/test/ui/const-generics/issue-70408.rs @@ -0,0 +1,13 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] { + BYTES +} + +pub fn main() { + assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::<{ &[0x41, 0x41, 0x41, 0x41] }>(), b"AAAA"); +} diff --git a/src/test/ui/const-generics/issue-80471.rs b/src/test/ui/const-generics/issue-80471.rs new file mode 100644 index 00000000000..d0af8a5eaa8 --- /dev/null +++ b/src/test/ui/const-generics/issue-80471.rs @@ -0,0 +1,13 @@ +#![feature(adt_const_params)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +#[derive(PartialEq, Eq)] +enum Nat { + Z, + S(Box<Nat>), +} + +fn foo<const N: Nat>() {} +//~^ ERROR `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + +fn main() {} diff --git a/src/test/ui/const-generics/issue-80471.stderr b/src/test/ui/const-generics/issue-80471.stderr new file mode 100644 index 00000000000..dbcc0b7b600 --- /dev/null +++ b/src/test/ui/const-generics/issue-80471.stderr @@ -0,0 +1,18 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-80471.rs:1:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + +error[E0741]: `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-80471.rs:10:17 + | +LL | fn foo<const N: Nat>() {} + | ^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/consts/const-enum-cast.rs b/src/test/ui/consts/const-enum-cast.rs index a3255c2f601..39968495144 100644 --- a/src/test/ui/consts/const-enum-cast.rs +++ b/src/test/ui/consts/const-enum-cast.rs @@ -4,6 +4,19 @@ enum A { A1, A2 } enum B { B1=4, B2=2 } +#[allow(dead_code)] +#[repr(align(8))] +enum Aligned { + Zero = 0, + One = 1, +} + +// regression test for https://github.com/rust-lang/rust/issues/96185 +const X: u8 = { + let aligned = Aligned::Zero; + aligned as u8 +}; + pub fn main () { static c1: isize = A::A2 as isize; static c2: isize = B::B2 as isize; @@ -23,4 +36,6 @@ pub fn main () { assert_eq!(c2_2, 4); assert_eq!(a1_2, 0); assert_eq!(a2_2, 4); + + assert_eq!(X, 0); } diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr index b60e3337b44..2cae35bc4d0 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr @@ -158,11 +158,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:62:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc43, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc41, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc43─╼ │ ╾──╼ + ╾─alloc41─╼ │ ╾──╼ } error: aborting due to 16 previous errors diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr index 505ef2dd7d7..e2cd0e64db8 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr @@ -158,11 +158,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:62:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc43, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc41, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc43───────╼ │ ╾──────╼ + ╾───────alloc41───────╼ │ ╾──────╼ } error: aborting due to 16 previous errors diff --git a/src/test/ui/consts/issue-78655.rs b/src/test/ui/consts/issue-78655.rs index b85e6129925..82d2d7c21d8 100644 --- a/src/test/ui/consts/issue-78655.rs +++ b/src/test/ui/consts/issue-78655.rs @@ -1,6 +1,6 @@ const FOO: *const u32 = { let x; - &x //~ ERROR borrow of possibly-uninitialized variable: `x` + &x //~ ERROR E0381 }; fn main() { diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr index 734266a3453..f5b1123e7f3 100644 --- a/src/test/ui/consts/issue-78655.stderr +++ b/src/test/ui/consts/issue-78655.stderr @@ -1,8 +1,10 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/issue-78655.rs:3:5 | +LL | let x; + | - binding declared here but left uninitialized LL | &x - | ^^ use of possibly-uninitialized `x` + | ^^ `x` used here but it isn't initialized error: could not evaluate constant pattern --> $DIR/issue-78655.rs:7:9 diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index daa1d736758..94d778bc8a1 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -40,19 +40,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:52:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:61:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc23 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:69:14 | LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc26 has size 4, so pointer at offset 10 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc24 has size 4, so pointer at offset 10 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:78:27 diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr index 60bfbe94a8a..cfe1e62d931 100644 --- a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr +++ b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr @@ -17,12 +17,6 @@ LL | #[rustc_then_this_would_need(trait_def)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:32:9 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK --> $DIR/dep-graph-struct-signature.rs:36:5 | LL | #[rustc_then_this_would_need(fn_sig)] @@ -53,36 +47,12 @@ LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:48:9 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK - --> $DIR/dep-graph-struct-signature.rs:49:9 - | -LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK --> $DIR/dep-graph-struct-signature.rs:53:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:55:9 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK - --> $DIR/dep-graph-struct-signature.rs:56:9 - | -LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK --> $DIR/dep-graph-struct-signature.rs:61:9 | LL | #[rustc_then_this_would_need(type_of)] @@ -107,12 +77,6 @@ LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:77:9 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: no path from `WillChange` to `fn_sig` --> $DIR/dep-graph-struct-signature.rs:81:5 | LL | #[rustc_then_this_would_need(fn_sig)] @@ -130,5 +94,41 @@ error: no path from `WillChange` to `typeck` LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: OK + --> $DIR/dep-graph-struct-signature.rs:32:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `fn_sig` + --> $DIR/dep-graph-struct-signature.rs:77:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:48:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:49:9 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:55:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:56:9 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 22 previous errors diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.stderr b/src/test/ui/dep-graph/dep-graph-type-alias.stderr index c59cf8014c3..42ac803b22e 100644 --- a/src/test/ui/dep-graph/dep-graph-type-alias.stderr +++ b/src/test/ui/dep-graph/dep-graph-type-alias.stderr @@ -28,12 +28,6 @@ error: no path from `TypeAlias` to `type_of` LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: OK - --> $DIR/dep-graph-type-alias.rs:36:5 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: no path from `TypeAlias` to `type_of` --> $DIR/dep-graph-type-alias.rs:42:1 | @@ -41,18 +35,6 @@ LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:44:5 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK - --> $DIR/dep-graph-type-alias.rs:45:5 - | -LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: OK --> $DIR/dep-graph-type-alias.rs:49:1 | LL | #[rustc_then_this_would_need(type_of)] @@ -70,5 +52,23 @@ error: OK LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: OK + --> $DIR/dep-graph-type-alias.rs:36:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:44:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:45:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 12 previous errors diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs index 2e7855328ec..59d5ef20205 100644 --- a/src/test/ui/drop/repeat-drop-2.rs +++ b/src/test/ui/drop/repeat-drop-2.rs @@ -9,7 +9,7 @@ const _: [String; 0] = [String::new(); 0]; fn must_be_init() { let x: u8; - let _ = [x; 0]; //~ ERROR: use of possibly-uninitialized variable: `x` + let _ = [x; 0]; //~ ERROR E0381 } fn main() {} diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr index cdc58180c37..48fa2bfa975 100644 --- a/src/test/ui/drop/repeat-drop-2.stderr +++ b/src/test/ui/drop/repeat-drop-2.stderr @@ -17,11 +17,13 @@ LL | const _: [String; 0] = [String::new(); 0]; | |constants cannot evaluate destructors | value is dropped here -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/repeat-drop-2.rs:12:14 | +LL | let x: u8; + | - binding declared here but left uninitialized LL | let _ = [x; 0]; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error: aborting due to 3 previous errors diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr index 60266bb3580..615e7fb4aae 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr @@ -19,7 +19,7 @@ LL | XEmpty3 {}, | ------- `XE::XEmpty3` defined here LL | XEmpty4, LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ------- similarly named tuple variant `XEmpty5` defined here | help: use struct pattern syntax instead | @@ -51,7 +51,7 @@ LL | XEmpty3 {}, | ------- `XE::XEmpty3` defined here LL | XEmpty4, LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ------- similarly named tuple variant `XEmpty5` defined here | help: use struct pattern syntax instead | diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index e696b85c6cc..9f44747381a 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -36,7 +36,7 @@ LL | XE::XEmpty5 => (), LL | XEmpty4, | ------- similarly named unit variant `XEmpty4` defined here LL | XEmpty5(), - | --------- `XE::XEmpty5` defined here + | ------- `XE::XEmpty5` defined here | help: use the tuple variant pattern syntax instead | diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr index acd1070d5d6..5c0b4cffa94 100644 --- a/src/test/ui/empty/empty-struct-unit-pat.stderr +++ b/src/test/ui/empty/empty-struct-unit-pat.stderr @@ -108,7 +108,7 @@ LL | XE::XEmpty4() => (), LL | XEmpty4, | ------- `XE::XEmpty4` defined here LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ------- similarly named tuple variant `XEmpty5` defined here | help: use this syntax instead | @@ -139,7 +139,7 @@ LL | XE::XEmpty4(..) => (), LL | XEmpty4, | ------- `XE::XEmpty4` defined here LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ------- similarly named tuple variant `XEmpty5` defined here | help: use this syntax instead | diff --git a/src/test/ui/enum/suggest-default-attribute.rs b/src/test/ui/enum/suggest-default-attribute.rs index 33bd0d24081..1d7567e60a5 100644 --- a/src/test/ui/enum/suggest-default-attribute.rs +++ b/src/test/ui/enum/suggest-default-attribute.rs @@ -1,4 +1,4 @@ -pub enum Test { //~ HELP consider adding `#[derive(Default)]` to this enum +pub enum Test { //~ HELP consider adding a derive #[default] //~^ ERROR cannot find attribute `default` in this scope First, diff --git a/src/test/ui/enum/suggest-default-attribute.stderr b/src/test/ui/enum/suggest-default-attribute.stderr index 791f219e8f9..fb830d3f78b 100644 --- a/src/test/ui/enum/suggest-default-attribute.stderr +++ b/src/test/ui/enum/suggest-default-attribute.stderr @@ -4,11 +4,11 @@ error: cannot find attribute `default` in this scope LL | #[default] | ^^^^^^^ | -help: consider adding `#[derive(Default)]` to this enum - --> $DIR/suggest-default-attribute.rs:1:1 +help: consider adding a derive + | +LL + #[derive(Default)] +LL ~ pub enum Test { | -LL | pub enum Test { - | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extern/not-in-block.rs b/src/test/ui/extern/not-in-block.rs new file mode 100644 index 00000000000..d3bcafdef7b --- /dev/null +++ b/src/test/ui/extern/not-in-block.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +extern fn none_fn(x: bool) -> i32; +//~^ ERROR free function without a body +extern "C" fn c_fn(x: bool) -> i32; +//~^ ERROR free function without a body diff --git a/src/test/ui/extern/not-in-block.stderr b/src/test/ui/extern/not-in-block.stderr new file mode 100644 index 00000000000..2544949ab17 --- /dev/null +++ b/src/test/ui/extern/not-in-block.stderr @@ -0,0 +1,32 @@ +error: free function without a body + --> $DIR/not-in-block.rs:3:1 + | +LL | extern fn none_fn(x: bool) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: provide a definition for the function + | +LL | extern fn none_fn(x: bool) -> i32 { <body> } + | ~~~~~~~~~~ +help: if you meant to declare an externally defined function, use an `extern` block + | +LL | extern { fn none_fn(x: bool) -> i32; } + | ~~~~~~~~ + + +error: free function without a body + --> $DIR/not-in-block.rs:5:1 + | +LL | extern "C" fn c_fn(x: bool) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: provide a definition for the function + | +LL | extern "C" fn c_fn(x: bool) -> i32 { <body> } + | ~~~~~~~~~~ +help: if you meant to declare an externally defined function, use an `extern` block + | +LL | extern "C" { fn c_fn(x: bool) -> i32; } + | ~~~~~~~~~~~~ + + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/fn/fn-closure-mutable-capture.rs b/src/test/ui/fn/fn-closure-mutable-capture.rs index 0e427b9cf31..97141886fe7 100644 --- a/src/test/ui/fn/fn-closure-mutable-capture.rs +++ b/src/test/ui/fn/fn-closure-mutable-capture.rs @@ -6,6 +6,7 @@ pub fn foo() { //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure //~| NOTE cannot assign //~| NOTE expects `Fn` instead of `FnMut` + //~| NOTE in this closure } fn main() {} diff --git a/src/test/ui/fn/fn-closure-mutable-capture.stderr b/src/test/ui/fn/fn-closure-mutable-capture.stderr index d23c363ae15..03e3d545a99 100644 --- a/src/test/ui/fn/fn-closure-mutable-capture.stderr +++ b/src/test/ui/fn/fn-closure-mutable-capture.stderr @@ -5,8 +5,9 @@ LL | pub fn bar<F: Fn()>(_f: F) {} | - change this to accept `FnMut` instead of `Fn` ... LL | bar(move || x = 1); - | --- ^^^^^ cannot assign - | | + | --- ------- ^^^^^ cannot assign + | | | + | | in this closure | expects `Fn` instead of `FnMut` error: aborting due to previous error diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr index 3e42cb1fb6e..06e29daef45 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err.stderr @@ -10,11 +10,11 @@ error[E0599]: no method named `blablabla` found for struct `Arc<_>` in the curre LL | arc.blablabla(); | ^^^^^^^^^ method not found in `Arc<_>` -error[E0599]: no method named `blablabla` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:40]>` in the current scope +error[E0599]: no method named `blablabla` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:38]>` in the current scope --> $DIR/fn-help-with-err.rs:12:10 | LL | arc2.blablabla(); - | ---- ^^^^^^^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:40]>` + | ---- ^^^^^^^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:38]>` | | | this is a function, perhaps you wish to call it diff --git a/src/test/ui/generator/drop-yield-twice.stderr b/src/test/ui/generator/drop-yield-twice.stderr index f821f2f4005..5bc6ea5600f 100644 --- a/src/test/ui/generator/drop-yield-twice.stderr +++ b/src/test/ui/generator/drop-yield-twice.stderr @@ -4,7 +4,7 @@ error: generator cannot be sent between threads safely LL | assert_send(|| { | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[generator@$DIR/drop-yield-twice.rs:7:17: 12:6]`, the trait `Send` is not implemented for `Foo` + = help: within `[generator@$DIR/drop-yield-twice.rs:7:17: 7:19]`, the trait `Send` is not implemented for `Foo` note: generator is not `Send` as this value is used across a yield --> $DIR/drop-yield-twice.rs:9:9 | diff --git a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr index 62a7b37a5a3..2a39a08ee39 100644 --- a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr +++ b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6]` +error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36]` --> $DIR/generator-yielding-or-returning-itself.rs:15:5 | LL | want_cyclic_generator_return(|| { @@ -16,7 +16,7 @@ LL | pub fn want_cyclic_generator_return<T>(_: T) LL | where T: Generator<Yield = (), Return = T> | ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return` -error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6]` +error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35]` --> $DIR/generator-yielding-or-returning-itself.rs:28:5 | LL | want_cyclic_generator_yield(|| { diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index 83f068c2076..1d5b97e984f 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -33,11 +33,8 @@ LL | require_send(send_gen); note: required because it's used within this generator --> $DIR/issue-68112.rs:48:5 | -LL | / || { -LL | | yield; -LL | | t -LL | | } - | |_____^ +LL | || { + | ^^ note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>` --> $DIR/issue-68112.rs:45:30 | @@ -52,12 +49,8 @@ LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> note: required because it's used within this generator --> $DIR/issue-68112.rs:59:20 | -LL | let send_gen = || { - | ____________________^ -LL | | let _non_send_gen = make_non_send_generator2(); -LL | | yield; -LL | | }; - | |_____^ +LL | let send_gen = || { + | ^^ note: required by a bound in `require_send` --> $DIR/issue-68112.rs:22:25 | diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index edf9ee628a2..0b31bb4fdb1 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -9,13 +9,8 @@ LL | assert_send(|| { note: required because it's used within this generator --> $DIR/not-send-sync.rs:16:17 | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | drop(&a); -LL | | yield; -LL | | }); - | |_____^ +LL | assert_send(|| { + | ^^ note: required by a bound in `assert_send` --> $DIR/not-send-sync.rs:7:23 | @@ -28,7 +23,7 @@ error: generator cannot be shared between threads safely LL | assert_sync(|| { | ^^^^^^^^^^^ generator is not `Sync` | - = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6]`, the trait `Sync` is not implemented for `Cell<i32>` + = help: within `[generator@$DIR/not-send-sync.rs:9:17: 9:19]`, the trait `Sync` is not implemented for `Cell<i32>` note: generator is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:12:9 | diff --git a/src/test/ui/generator/partial-drop.stderr b/src/test/ui/generator/partial-drop.stderr index 16b34c917ec..1004fc64da9 100644 --- a/src/test/ui/generator/partial-drop.stderr +++ b/src/test/ui/generator/partial-drop.stderr @@ -4,7 +4,7 @@ error: generator cannot be sent between threads safely LL | assert_send(|| { | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[generator@$DIR/partial-drop.rs:14:17: 20:6]`, the trait `Send` is not implemented for `Foo` + = help: within `[generator@$DIR/partial-drop.rs:14:17: 14:19]`, the trait `Send` is not implemented for `Foo` note: generator is not `Send` as this value is used across a yield --> $DIR/partial-drop.rs:19:9 | @@ -27,7 +27,7 @@ error: generator cannot be sent between threads safely LL | assert_send(|| { | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[generator@$DIR/partial-drop.rs:22:17: 30:6]`, the trait `Send` is not implemented for `Foo` + = help: within `[generator@$DIR/partial-drop.rs:22:17: 22:19]`, the trait `Send` is not implemented for `Foo` note: generator is not `Send` as this value is used across a yield --> $DIR/partial-drop.rs:29:9 | @@ -50,7 +50,7 @@ error: generator cannot be sent between threads safely LL | assert_send(|| { | ^^^^^^^^^^^ generator is not `Send` | - = help: within `[generator@$DIR/partial-drop.rs:32:17: 39:6]`, the trait `Send` is not implemented for `Foo` + = help: within `[generator@$DIR/partial-drop.rs:32:17: 32:19]`, the trait `Send` is not implemented for `Foo` note: generator is not `Send` as this value is used across a yield --> $DIR/partial-drop.rs:38:9 | diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs index 8b757214203..65d9e6d39ca 100644 --- a/src/test/ui/generator/partial-initialization-across-yield.rs +++ b/src/test/ui/generator/partial-initialization-across-yield.rs @@ -9,8 +9,7 @@ struct T(i32, i32); fn test_tuple() { let _ = || { let mut t: (i32, i32); - t.0 = 42; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 42; //~ ERROR E0381 yield; t.1 = 88; let _ = t; @@ -20,8 +19,7 @@ fn test_tuple() { fn test_tuple_struct() { let _ = || { let mut t: T; - t.0 = 42; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 42; //~ ERROR E0381 yield; t.1 = 88; let _ = t; @@ -31,8 +29,7 @@ fn test_tuple_struct() { fn test_struct() { let _ = || { let mut t: S; - t.x = 42; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.x = 42; //~ ERROR E0381 yield; t.y = 88; let _ = t; diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr index 66b86488eae..3f9f1c046ba 100644 --- a/src/test/ui/generator/partial-initialization-across-yield.stderr +++ b/src/test/ui/generator/partial-initialization-across-yield.stderr @@ -1,20 +1,32 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `t` +error[E0381]: partially assigned binding `t` isn't fully initialized --> $DIR/partial-initialization-across-yield.rs:12:9 | +LL | let mut t: (i32, i32); + | ----- binding declared here but left uninitialized LL | t.0 = 42; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/partial-initialization-across-yield.rs:23:9 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-yield.rs:22:9 | +LL | let mut t: T; + | ----- binding declared here but left uninitialized LL | t.0 = 42; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/partial-initialization-across-yield.rs:34:9 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-yield.rs:32:9 | +LL | let mut t: S; + | ----- binding declared here but left uninitialized LL | t.x = 42; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error: aborting due to 3 previous errors diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr index 3ee4c1458ba..5b61f1e8f2d 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -31,11 +31,8 @@ LL | require_send(send_gen); note: required because it's used within this generator --> $DIR/generator-print-verbose-1.rs:42:5 | -LL | / || { -LL | | yield; -LL | | t -LL | | } - | |_____^ +LL | || { + | ^^ note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])` --> $DIR/generator-print-verbose-1.rs:41:30 | @@ -50,12 +47,8 @@ LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> note: required because it's used within this generator --> $DIR/generator-print-verbose-1.rs:52:20 | -LL | let send_gen = || { - | ____________________^ -LL | | let _non_send_gen = make_non_send_generator2(); -LL | | yield; -LL | | }; - | |_____^ +LL | let send_gen = || { + | ^^ note: required by a bound in `require_send` --> $DIR/generator-print-verbose-1.rs:26:25 | diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr index 1356fa5f152..eb79d2e6eed 100644 --- a/src/test/ui/generator/print/generator-print-verbose-2.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr @@ -9,13 +9,8 @@ LL | assert_send(|| { note: required because it's used within this generator --> $DIR/generator-print-verbose-2.rs:19:17 | -LL | assert_send(|| { - | _________________^ -LL | | -LL | | drop(&a); -LL | | yield; -LL | | }); - | |_____^ +LL | assert_send(|| { + | ^^ note: required by a bound in `assert_send` --> $DIR/generator-print-verbose-2.rs:10:23 | diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr index 4ae745b0ffe..e3859595fd2 100644 --- a/src/test/ui/generator/static-not-unpin.stderr +++ b/src/test/ui/generator/static-not-unpin.stderr @@ -1,8 +1,8 @@ -error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` cannot be unpinned +error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 11:34]` cannot be unpinned --> $DIR/static-not-unpin.rs:14:18 | LL | assert_unpin(generator); - | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 11:34]` | | | required by a bound introduced by this call | diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index d78a5929a89..7938fc8097c 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -12,7 +12,7 @@ note: return type inferred to be `Result<{integer}, _>` here LL | return Ok(6); | ^^^^^ -error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 15:6] as Generator>::Return == i32` +error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7] as Generator>::Return == i32` --> $DIR/type-mismatch-signature-deduction.rs:5:13 | LL | fn foo() -> impl Generator<Return = i32> { diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr index 43e609cc59e..c01ab8e347c 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed` + = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:11] well-formed` error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr index 0bfa7b3cc7c..eebce827d1c 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr @@ -10,7 +10,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:45:24 | LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/issue-71955.rs:25:9 | @@ -29,7 +29,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:45:24 | LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/issue-71955.rs:25:44 | @@ -48,7 +48,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:48:24 | LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/issue-71955.rs:25:9 | @@ -67,7 +67,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:48:24 | LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/issue-71955.rs:25:44 | diff --git a/src/test/ui/hrtb/issue-30786.stderr b/src/test/ui/hrtb/issue-30786.stderr index 5a10a38d08e..2ed86dfc236 100644 --- a/src/test/ui/hrtb/issue-30786.stderr +++ b/src/test/ui/hrtb/issue-30786.stderr @@ -1,4 +1,4 @@ -error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:36]>`, but its trait bounds were not satisfied +error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:118:22 | LL | pub struct Map<S, F> { @@ -8,12 +8,12 @@ LL | pub struct Map<S, F> { | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:36]>` due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:36]>: Stream` - `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:36]>: Stream` - `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:36]>: Stream` + `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream` + `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream` + `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream` --> $DIR/issue-30786.rs:96:50 | LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} @@ -23,7 +23,7 @@ help: one of the expressions' fields has a method of the same name LL | let filter = map.stream.filterx(|x: &_| true); | +++++++ -error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:42]>`, but its trait bounds were not satisfied +error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:130:24 | LL | pub struct Filter<S, F> { @@ -33,12 +33,12 @@ LL | pub struct Filter<S, F> { | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); - | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:42]>` due to unsatisfied trait bounds + | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:42]>: Stream` - `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:42]>: Stream` - `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:42]>: Stream` + `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` --> $DIR/issue-30786.rs:96:50 | LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 0ebba37e4ec..79ef56b9fa5 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -1,8 +1,8 @@ -error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` +error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` --> $DIR/issue-62203-hrtb-ice.rs:38:19 | LL | let v = Unit2.m( - | ^ type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + | ^ type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` | note: expected this to be `<_ as Ty<'_>>::V` --> $DIR/issue-62203-hrtb-ice.rs:21:14 @@ -22,7 +22,7 @@ LL | where LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20] as FnOnce<((&'r u8,),)>>::Output == Unit3` --> $DIR/issue-62203-hrtb-ice.rs:40:9 | LL | let v = Unit2.m( @@ -34,7 +34,7 @@ LL | | f : |x| { drop(x); Unit4 } LL | | }); | |_________^ expected struct `Unit3`, found struct `Unit4` | -note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>` +note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]>` --> $DIR/issue-62203-hrtb-ice.rs:17:16 | LL | impl<'a, A, T> T0<'a, A> for L<T> diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index d825843492d..52fa28145d6 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -14,7 +14,7 @@ note: required because it's used within this closure --> $DIR/auto-trait-leak2.rs:10:5 | LL | move |x| p.set(x) - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ note: required because it appears within the type `impl Fn(i32)` --> $DIR/auto-trait-leak2.rs:5:16 | @@ -42,7 +42,7 @@ note: required because it's used within this closure --> $DIR/auto-trait-leak2.rs:38:5 | LL | move |x| p.set(x) - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ note: required because it appears within the type `impl Fn(i32)` --> $DIR/auto-trait-leak2.rs:33:15 | diff --git a/src/test/ui/impl-trait/issues/issue-74282.stderr b/src/test/ui/impl-trait/issues/issue-74282.stderr index 0f855ef5792..5b05fb2810d 100644 --- a/src/test/ui/impl-trait/issues/issue-74282.stderr +++ b/src/test/ui/impl-trait/issues/issue-74282.stderr @@ -13,7 +13,7 @@ LL | | }) | |_____^ expected closure, found a different closure | = note: expected opaque type `Closure` - found closure `[closure@$DIR/issue-74282.rs:8:15: 10:6]` + found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object note: tuple struct defined here diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index f8ff2177bf5..586563c3906 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -100,7 +100,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/must_outlive_least_region_or_bound.rs:38:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:31]` captures the lifetime `'b` as defined here + | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr index 359fb909e54..1079a86ce9e 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> impl Trait<Assoc = Sendable> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `Sendable` | = help: the trait `Duh` is implemented for `i32` -note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:27:5: 27:10]` +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:27:5: 27:7]` --> $DIR/nested-return-type2-tait.rs:14:31 | LL | impl<R: Duh, F: FnMut() -> R> Trait for F { diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr index 3e19ad7b5c6..847b9400085 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> Traitable { | ^^^^^^^^^ the trait `Duh` is not implemented for `Sendable` | = help: the trait `Duh` is implemented for `i32` -note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:28:5: 28:10]` +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:28:5: 28:7]` --> $DIR/nested-return-type2-tait2.rs:14:31 | LL | impl<R: Duh, F: FnMut() -> R> Trait for F { diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr index 6185e4872a5..7b7f06b8e13 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> Traitable { | ^^^^^^^^^ the trait `Duh` is not implemented for `impl Send` | = help: the trait `Duh` is implemented for `i32` -note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:27:5: 27:10]` +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:27:5: 27:7]` --> $DIR/nested-return-type2-tait3.rs:14:31 | LL | impl<R: Duh, F: FnMut() -> R> Trait for F { diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr index f996e99de07..f28a084af89 100644 --- a/src/test/ui/impl-trait/nested-return-type2.stderr +++ b/src/test/ui/impl-trait/nested-return-type2.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> impl Trait<Assoc = impl Send> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send` | = help: the trait `Duh` is implemented for `i32` -note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:23:5: 23:10]` +note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:23:5: 23:7]` --> $DIR/nested-return-type2.rs:12:31 | LL | impl<R: Duh, F: FnMut() -> R> Trait for F { diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index b9b2ce249f7..2e34d3d4275 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -54,7 +54,7 @@ LL | fn closure_capture() -> impl Sized { LL | / move || { LL | | x; LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6]` + | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 35:12]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:40:29 @@ -65,7 +65,7 @@ LL | fn closure_ref_capture() -> impl Sized { LL | / move || { LL | | &x; LL | | } - | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6]` + | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 43:12]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:48:21 @@ -74,7 +74,7 @@ LL | fn closure_sig() -> impl Sized { | ^^^^^^^^^^ recursive opaque type LL | LL | || closure_sig() - | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]` + | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:7]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:53:23 @@ -83,7 +83,7 @@ LL | fn generator_sig() -> impl Sized { | ^^^^^^^^^^ recursive opaque type LL | LL | || generator_sig() - | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]` + | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:58:27 @@ -95,7 +95,7 @@ LL | / move || { LL | | yield; LL | | x; LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6]` + | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:67:35 @@ -117,7 +117,7 @@ LL | | let x = generator_hold(); LL | | yield; LL | | x; LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6]` + | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 74:12]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:86:26 diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index bc8e39f9c50..951abb127c1 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,7 +2,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/static-return-lifetime-infered.rs:7:9 | LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here + | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -15,7 +15,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/static-return-lifetime-infered.rs:7:9 | LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here + | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -28,7 +28,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/static-return-lifetime-infered.rs:12:9 | LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here + | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` captures the lifetime `'a` as defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -41,7 +41,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/static-return-lifetime-infered.rs:12:9 | LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here + | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` captures the lifetime `'a` as defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/imports/inaccessible_type_aliases.rs b/src/test/ui/imports/inaccessible_type_aliases.rs new file mode 100644 index 00000000000..c3d4214e282 --- /dev/null +++ b/src/test/ui/imports/inaccessible_type_aliases.rs @@ -0,0 +1,14 @@ +mod a { + type Foo = u64; + type Bar = u64; +} + +mod b { + type Foo = u64; +} + +fn main() { + let x: Foo = 100; //~ ERROR: cannot find type `Foo` in this scope + let y: Bar = 100; //~ ERROR: cannot find type `Bar` in this scope + println!("x: {}, y: {}", x, y); +} diff --git a/src/test/ui/imports/inaccessible_type_aliases.stderr b/src/test/ui/imports/inaccessible_type_aliases.stderr new file mode 100644 index 00000000000..ef224246061 --- /dev/null +++ b/src/test/ui/imports/inaccessible_type_aliases.stderr @@ -0,0 +1,30 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/inaccessible_type_aliases.rs:11:12 + | +LL | let x: Foo = 100; + | ^^^ not found in this scope + | +note: these type aliases exist but are inaccessible + --> $DIR/inaccessible_type_aliases.rs:2:5 + | +LL | type Foo = u64; + | ^^^^^^^^^^^^^^^ `a::Foo`: not accessible +... +LL | type Foo = u64; + | ^^^^^^^^^^^^^^^ `b::Foo`: not accessible + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/inaccessible_type_aliases.rs:12:12 + | +LL | let y: Bar = 100; + | ^^^ not found in this scope + | +note: type alias `a::Bar` exists but is inaccessible + --> $DIR/inaccessible_type_aliases.rs:3:5 + | +LL | type Bar = u64; + | ^^^^^^^^^^^^^^^ not accessible + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index 66fe3c74e2c..349fb6dafa3 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -11,7 +11,7 @@ note: required because it's used within this closure --> $DIR/interior-mutability.rs:5:18 | LL | catch_unwind(|| { x.set(23); }); - | ^^^^^^^^^^^^^^^^^ + | ^^ note: required by a bound in `catch_unwind` --> $SRC_DIR/std/src/panic.rs:LL:COL | diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 79f6a5850b5..1d3bff3a724 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -1,18 +1,18 @@ -error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]: ~const FnOnce<()>` is not satisfied +error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]: ~const FnOnce<()>` is not satisfied --> $DIR/const-eval-select-bad.rs:6:27 | LL | const_eval_select((), || {}, || {}); - | ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` + | ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]` | | | required by a bound introduced by this call | - = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` -note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`, but that implementation is not `const` + = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]` +note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]`, but that implementation is not `const` --> $DIR/const-eval-select-bad.rs:6:27 | LL | const_eval_select((), || {}, || {}); | ^^^^^ - = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` in a closure with no arguments: `|| { /* code */ }` + = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr index ff78c252731..9322654b292 100644 --- a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr +++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-padding.rs:6:5 | LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading 4 bytes of memory starting at alloc3, but 1 byte is uninitialized starting at alloc3+0x1, and this operation requires initialized memory + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory error: aborting due to previous error diff --git a/src/test/ui/issues/issue-12127.stderr b/src/test/ui/issues/issue-12127.stderr index e1559ab2fea..2c451b07fbe 100644 --- a/src/test/ui/issues/issue-12127.stderr +++ b/src/test/ui/issues/issue-12127.stderr @@ -11,7 +11,7 @@ note: this value implements `FnOnce`, which causes it to be moved when called | LL | f(); | ^ - = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:41]`, which does not implement the `Copy` trait + = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:30]`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21600.stderr b/src/test/ui/issues/issue-21600.stderr index dab3c3d1797..ea304f9367b 100644 --- a/src/test/ui/issues/issue-21600.stderr +++ b/src/test/ui/issues/issue-21600.stderr @@ -5,29 +5,26 @@ LL | fn call_it<F>(f: F) where F: Fn() { f(); } | - change this to accept `FnMut` instead of `Fn` ... LL | call_it(|| x.gen_mut()); - | ------- ^^^^^^^^^^^ cannot borrow as mutable - | | + | ------- -- ^^^^^^^^^^^ cannot borrow as mutable + | | | + | | in this closure | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/issue-21600.rs:14:17 | -LL | fn call_it<F>(f: F) where F: Fn() { f(); } - | - change this to accept `FnMut` instead of `Fn` +LL | fn call_it<F>(f: F) where F: Fn() { f(); } + | - change this to accept `FnMut` instead of `Fn` ... -LL | call_it(|| { - | _____-------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | call_it(|| x.gen()); -LL | | call_it(|| x.gen_mut()); - | | ^^ - mutable borrow occurs due to use of `x` in closure - | | | - | | cannot borrow as mutable -LL | | -LL | | -LL | | }); - | |_____- in this closure +LL | call_it(|| { + | ------- -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | call_it(|| x.gen()); +LL | call_it(|| x.gen_mut()); + | ^^ - mutable borrow occurs due to use of `x` in closure + | | + | cannot borrow as mutable error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr index 4622501f33e..a42e35c4cad 100644 --- a/src/test/ui/issues/issue-24036.stderr +++ b/src/test/ui/issues/issue-24036.stderr @@ -2,12 +2,12 @@ error[E0308]: mismatched types --> $DIR/issue-24036.rs:3:9 | LL | let mut x = |c| c + 1; - | --------- the expected closure + | --- the expected closure LL | x = |c| c + 1; | ^^^^^^^^^ expected closure, found a different closure | - = note: expected closure `[closure@$DIR/issue-24036.rs:2:17: 2:26]` - found closure `[closure@$DIR/issue-24036.rs:3:9: 3:18]` + = note: expected closure `[closure@$DIR/issue-24036.rs:2:17: 2:20]` + found closure `[closure@$DIR/issue-24036.rs:3:9: 3:12]` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr index 6dbe6b59391..7230079dcff 100644 --- a/src/test/ui/issues/issue-3044.stderr +++ b/src/test/ui/issues/issue-3044.stderr @@ -2,11 +2,13 @@ error[E0308]: mismatched types --> $DIR/issue-3044.rs:3:35 | LL | needlesArr.iter().fold(|x, y| { - | ___________________________________^ + | ____________________________------_^ + | | | + | | the expected closure LL | | }); | |_____^ expected closure, found `()` | - = note: expected closure `[closure@$DIR/issue-3044.rs:3:28: 4:6]` + = note: expected closure `[closure@$DIR/issue-3044.rs:3:28: 3:34]` found unit type `()` error[E0061]: this function takes 2 arguments but 1 argument was supplied diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 982b6118ce6..68337a715e1 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item == &_` +error[E0271]: type mismatch resolving `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]> as Iterator>::Item == &_` --> $DIR/issue-31173.rs:10:10 | LL | .cloned() @@ -12,11 +12,11 @@ note: required by a bound in `cloned` LL | Self: Sized + Iterator<Item = &'a T>, | ^^^^^^^^^^^^ required by this bound in `cloned` -error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>`, but its trait bounds were not satisfied +error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>`, but its trait bounds were not satisfied --> $DIR/issue-31173.rs:12:10 | LL | .collect(); - | ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>` due to unsatisfied trait bounds + | ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL | @@ -29,10 +29,10 @@ LL | pub struct TakeWhile<I, P> { | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_` | = note: the following trait bounds were not satisfied: - `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item = &_` - which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>: Iterator` - `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>: Iterator` - which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>: Iterator` + `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]> as Iterator>::Item = &_` + which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator` + `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator` + which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr index f9a25b69ff6..8de0edef076 100644 --- a/src/test/ui/issues/issue-34209.stderr +++ b/src/test/ui/issues/issue-34209.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant named `B` found for enum `S` --> $DIR/issue-34209.rs:7:12 | LL | enum S { - | ------ variant `B` not found here + | ------ variant `B` not found for this enum ... LL | S::B {} => {}, | ^ help: there is a variant with a similar name: `A` diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr index cd84b6ef484..e83590a8f59 100644 --- a/src/test/ui/issues/issue-37884.stderr +++ b/src/test/ui/issues/issue-37884.stderr @@ -1,13 +1,8 @@ error[E0308]: method not compatible with trait --> $DIR/issue-37884.rs:6:5 | -LL | / fn next(&'a mut self) -> Option<Self::Item> -LL | | -LL | | -LL | | { -LL | | Some(&mut self.0) -LL | | } - | |_____^ lifetime mismatch +LL | fn next(&'a mut self) -> Option<Self::Item> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>` found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>` diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr index a52dc0c9af0..7895fdb296d 100644 --- a/src/test/ui/issues/issue-41880.stderr +++ b/src/test/ui/issues/issue-41880.stderr @@ -5,7 +5,7 @@ LL | pub struct Iterate<T, F> { | ------- method `iter` not found for this struct ... LL | println!("{:?}", a.iter().take(10).collect::<Vec<usize>>()); - | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` + | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr index fa3b58e1279..ecc1fa52398 100644 --- a/src/test/ui/issues/issue-4335.stderr +++ b/src/test/ui/issues/issue-4335.stderr @@ -4,9 +4,8 @@ error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMu LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> { | - captured outer variable LL | id(Box::new(|| *v)) - | ---^^ - | | | - | | move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | -- ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | | | captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/issues/issue-48838.stderr b/src/test/ui/issues/issue-48838.stderr index 712a7bc33f8..3502af7028b 100644 --- a/src/test/ui/issues/issue-48838.stderr +++ b/src/test/ui/issues/issue-48838.stderr @@ -5,7 +5,7 @@ LL | Square = |x| x, | ^^^^^ expected `isize`, found closure | = note: expected type `isize` - found closure `[closure@$DIR/issue-48838.rs:2:14: 2:19]` + found closure `[closure@$DIR/issue-48838.rs:2:14: 2:17]` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50600.stderr b/src/test/ui/issues/issue-50600.stderr index 08d9a839920..7fea7e5c098 100644 --- a/src/test/ui/issues/issue-50600.stderr +++ b/src/test/ui/issues/issue-50600.stderr @@ -5,7 +5,7 @@ LL | fn([u8; |x: u8| {}]), | ^^^^^^^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/issue-50600.rs:2:13: 2:23]` + found closure `[closure@$DIR/issue-50600.rs:2:13: 2:20]` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50688.stderr b/src/test/ui/issues/issue-50688.stderr index 1f348c4cf1f..6973ad271b4 100644 --- a/src/test/ui/issues/issue-50688.stderr +++ b/src/test/ui/issues/issue-50688.stderr @@ -5,7 +5,7 @@ LL | [1; || {}]; | ^^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/issue-50688.rs:2:9: 2:14]` + found closure `[closure@$DIR/issue-50688.rs:2:9: 2:11]` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51154.stderr b/src/test/ui/issues/issue-51154.stderr index f2cbc3e6feb..44ec626dea5 100644 --- a/src/test/ui/issues/issue-51154.stderr +++ b/src/test/ui/issues/issue-51154.stderr @@ -9,7 +9,7 @@ LL | let _: Box<F> = Box::new(|| ()); | arguments to this function are incorrect | = note: expected type parameter `F` - found closure `[closure@$DIR/issue-51154.rs:2:30: 2:35]` + found closure `[closure@$DIR/issue-51154.rs:2:30: 2:32]` = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F` note: associated function defined here --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/test/ui/issues/issue-77919.stderr b/src/test/ui/issues/issue-77919.stderr index a55ac23e3ed..b4c877a2d74 100644 --- a/src/test/ui/issues/issue-77919.stderr +++ b/src/test/ui/issues/issue-77919.stderr @@ -24,7 +24,7 @@ LL | const VAL: T; | ------------ `VAL` from trait ... LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation error: constant expression depends on a generic parameter --> $DIR/issue-77919.rs:2:9 diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index 727573a0be4..eab003a1107 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -2,16 +2,16 @@ error[E0277]: `Rc<usize>` cannot be sent between threads safely --> $DIR/kindck-nonsendable-1.rs:9:5 | LL | bar(move|| foo(x)); - | ^^^ ------------- within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]` + | ^^^ ------ within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]` | | | `Rc<usize>` cannot be sent between threads safely | - = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`, the trait `Send` is not implemented for `Rc<usize>` + = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`, the trait `Send` is not implemented for `Rc<usize>` note: required because it's used within this closure --> $DIR/kindck-nonsendable-1.rs:9:9 | LL | bar(move|| foo(x)); - | ^^^^^^^^^^^^^ + | ^^^^^^ note: required by a bound in `bar` --> $DIR/kindck-nonsendable-1.rs:5:21 | diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr index 6d8f2f56683..9322e617176 100644 --- a/src/test/ui/lifetimes/issue-79187-2.stderr +++ b/src/test/ui/lifetimes/issue-79187-2.stderr @@ -37,7 +37,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-79187-2.rs:8:14 | LL | take_foo(|a| a); - | ^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/issue-79187-2.rs:5:21 | diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr index 1d89d4dac5e..3e75e7fed2c 100644 --- a/src/test/ui/lifetimes/issue-79187.stderr +++ b/src/test/ui/lifetimes/issue-79187.stderr @@ -10,7 +10,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-79187.rs:4:13 | LL | let f = |_| (); - | ^^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/issue-79187.rs:1:18 | diff --git a/src/test/ui/lint/lint-missing-doc.stderr b/src/test/ui/lint/lint-missing-doc.stderr index 56f8fc10e86..d68472d4b66 100644 --- a/src/test/ui/lint/lint-missing-doc.stderr +++ b/src/test/ui/lint/lint-missing-doc.stderr @@ -2,7 +2,7 @@ error: missing documentation for a type alias --> $DIR/lint-missing-doc.rs:11:1 | LL | pub type PubTypedef = String; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-missing-doc.rs:3:9 @@ -56,13 +56,13 @@ error: missing documentation for an associated type --> $DIR/lint-missing-doc.rs:64:5 | LL | type AssociatedType; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type --> $DIR/lint-missing-doc.rs:65:5 | LL | type AssociatedTypeDef = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:81:5 @@ -92,13 +92,13 @@ error: missing documentation for a constant --> $DIR/lint-missing-doc.rs:151:1 | LL | pub const FOO4: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static --> $DIR/lint-missing-doc.rs:161:1 | LL | pub static BAR4: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function --> $DIR/lint-missing-doc.rs:167:5 @@ -122,19 +122,19 @@ error: missing documentation for a function --> $DIR/lint-missing-doc.rs:189:5 | LL | pub fn extern_fn_undocumented(f: f32) -> f32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static --> $DIR/lint-missing-doc.rs:194:5 | LL | pub static EXTERN_STATIC_UNDOCUMENTED: u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a foreign type --> $DIR/lint-missing-doc.rs:199:5 | LL | pub type ExternTyUndocumented; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 22 previous errors diff --git a/src/test/ui/lint/trivial_casts.stderr b/src/test/ui/lint/trivial_casts.stderr index 141703460ba..8a216360f4e 100644 --- a/src/test/ui/lint/trivial_casts.stderr +++ b/src/test/ui/lint/trivial_casts.stderr @@ -128,7 +128,7 @@ LL | let _ = &baz as &dyn Fn(i32); | = help: cast can be replaced by coercion; this might require a temporary variable -error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:25]` as `&dyn Fn(i32)` +error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:22]` as `&dyn Fn(i32)` --> $DIR/trivial_casts.rs:73:13 | LL | let _ = &x as &dyn Fn(i32); diff --git a/src/test/ui/loops/loop-proper-liveness.rs b/src/test/ui/loops/loop-proper-liveness.rs index b242ec4296d..6546e397785 100644 --- a/src/test/ui/loops/loop-proper-liveness.rs +++ b/src/test/ui/loops/loop-proper-liveness.rs @@ -6,7 +6,7 @@ fn test1() { 'a: loop { x = loop { break 'a }; } - println!("{:?}", x); //~ ERROR borrow of possibly-uninitialized variable + println!("{:?}", x); //~ ERROR E0381 } // test2 and test3 should not fail. diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr index 20d5c66a3f2..75041031736 100644 --- a/src/test/ui/loops/loop-proper-liveness.stderr +++ b/src/test/ui/loops/loop-proper-liveness.stderr @@ -1,8 +1,11 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/loop-proper-liveness.rs:9:22 | +LL | let x: i32; + | - binding declared here but left uninitialized +... LL | println!("{:?}", x); - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/methods/method-missing-call.stderr b/src/test/ui/methods/method-missing-call.stderr index 045f9ab7004..040a65d1680 100644 --- a/src/test/ui/methods/method-missing-call.stderr +++ b/src/test/ui/methods/method-missing-call.stderr @@ -9,7 +9,7 @@ help: use parentheses to call the method LL | .get_x(); | ++ -error[E0615]: attempted to take value of method `filter_map` on type `Filter<Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>` +error[E0615]: attempted to take value of method `filter_map` on type `Filter<Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/method-missing-call.rs:27:20: 27:23]>, [closure@$DIR/method-missing-call.rs:28:23: 28:28]>` --> $DIR/method-missing-call.rs:29:16 | LL | .filter_map; diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr index 492d480e13e..39abd14990b 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr @@ -23,7 +23,7 @@ error[E0599]: no method named `extend` found for struct `Map` in the current sco --> $DIR/method-not-found-generic-arg-elision.rs:87:29 | LL | v.iter().map(|x| x * x).extend(std::iter::once(100)); - | ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:27]>` + | ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>` error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope --> $DIR/method-not-found-generic-arg-elision.rs:90:13 diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs index c44dd51a5ec..fc7341a563b 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -6,7 +6,7 @@ static A: () = { //~^ ERROR destructors cannot be evaluated at compile-time a[0] = String::new(); //~^ ERROR destructors cannot be evaluated at compile-time - //~| ERROR use of possibly-uninitialized variable + //~| ERROR binding `a` isn't initialized }; struct B<T>([T; 1]); diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr index 80d5fc7ec67..d8154f8d2cb 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -16,11 +16,14 @@ LL | let a: [String; 1]; LL | }; | - value is dropped here -error[E0381]: use of possibly-uninitialized variable: `a` +error[E0381]: used binding `a` isn't initialized --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 | +LL | let a: [String; 1]; + | - binding declared here but left uninitialized +LL | LL | a[0] = String::new(); - | ^^^^ use of possibly-uninitialized `a` + | ^^^^ `a` used here but it isn't initialized error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 diff --git a/src/test/ui/mir/ssa-analysis-regression-50041.rs b/src/test/ui/mir/ssa-analysis-regression-50041.rs index 8e9c14a03c3..ebc3e2f8c0e 100644 --- a/src/test/ui/mir/ssa-analysis-regression-50041.rs +++ b/src/test/ui/mir/ssa-analysis-regression-50041.rs @@ -5,7 +5,7 @@ #![feature(lang_items)] #![no_std] -struct NonNull<T: ?Sized>(*mut T); +struct NonNull<T: ?Sized>(*const T); struct Unique<T: ?Sized>(NonNull<T>); @@ -23,7 +23,7 @@ unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) { } #[inline(never)] -fn dealloc<T: ?Sized>(_: *mut T) {} +fn dealloc<T: ?Sized>(_: *const T) {} pub struct Foo<T>(T); diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 1f46229cb5a..d9578f6c8dc 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -2,7 +2,7 @@ error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:3:14 | LL | a.iter().map(|_: (u32, u32)| 45); - | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` + | ^^^ --------------- found signature of `fn((u32, u32)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` | @@ -16,7 +16,7 @@ error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:4:14 | LL | a.iter().map(|_: &(u16, u16)| 45); - | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` + | ^^^ ---------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` | @@ -30,7 +30,7 @@ error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:5:14 | LL | a.iter().map(|_: (u16, u16)| 45); - | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` + | ^^^ --------------- found signature of `fn((u16, u16)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` | diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index c1a29dfc933..ef76ec63fda 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -19,7 +19,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/closure-mismatch.rs:8:9 | LL | baz(|_| ()); - | ^^^^^^ + | ^^^ note: the lifetime requirement is introduced here --> $DIR/closure-mismatch.rs:5:11 | diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index a8bcdf5efe9..9d1ea70f8a4 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -2,7 +2,7 @@ error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:7:32 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` + | ^^^^^^ --------- found signature of `for<'r> fn(&'r str) -> _` | | | expected signature of `for<'r> fn(&'r &str) -> _` | @@ -12,11 +12,11 @@ note: required by a bound in `filter` LL | P: FnMut(&Self::Item) -> bool, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter` -error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied +error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, 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 cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds + | --------- ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>` due to unsatisfied trait bounds | | | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` | doesn't satisfy `_: FnMut<(&&str,)>` @@ -27,12 +27,12 @@ LL | pub struct Filter<I, P> { | ----------------------- doesn't satisfy `_: Iterator` | = 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<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` - `[closure@$DIR/issue-36053-2.rs:7:39: 7:53]: FnMut<(&&str,)>` - which is required by `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` - `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` - which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>: Iterator` + `<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool` + which is required by `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + `[closure@$DIR/issue-36053-2.rs:7:39: 7:48]: FnMut<(&&str,)>` + which is required by `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-47706.stderr b/src/test/ui/mismatched_types/issue-47706.stderr index 0b4f84a330a..8b856368401 100644 --- a/src/test/ui/mismatched_types/issue-47706.stderr +++ b/src/test/ui/mismatched_types/issue-47706.stderr @@ -19,7 +19,7 @@ error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/issue-47706.rs:27:9 | LL | Bar(i32), - | -------- takes 1 argument + | --- takes 1 argument ... LL | foo(Qux::Bar); | --- ^^^^^^^^ expected function that takes 0 arguments diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.rs b/src/test/ui/moves/issue-72649-uninit-in-loop.rs index e6bc4e22ec2..d76b69ecdc8 100644 --- a/src/test/ui/moves/issue-72649-uninit-in-loop.rs +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.rs @@ -57,17 +57,17 @@ fn moved_loop_2() { fn uninit_1() { loop { - let value: NonCopy; - let _used = value; //~ ERROR use of possibly-uninitialized variable: `value` - //~^ NOTE use of possibly-uninitialized `value` + let value: NonCopy; //~ NOTE declared here + let _used = value; //~ ERROR binding `value` isn't initialized + //~^ NOTE `value` used here but it isn't initialized } } fn uninit_2() { - let mut value: NonCopy; + let mut value: NonCopy; //~ NOTE declared here loop { - let _used = value; //~ ERROR use of possibly-uninitialized variable: `value` - //~^ NOTE use of possibly-uninitialized `value` + let _used = value; //~ ERROR binding `value` isn't initialized + //~^ NOTE `value` used here but it isn't initialized } } diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr index 076d3dff140..c7373b5be9d 100644 --- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr @@ -40,17 +40,22 @@ LL | let mut value = NonCopy{}; LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop -error[E0381]: use of possibly-uninitialized variable: `value` +error[E0381]: used binding `value` isn't initialized --> $DIR/issue-72649-uninit-in-loop.rs:61:21 | +LL | let value: NonCopy; + | ----- binding declared here but left uninitialized LL | let _used = value; - | ^^^^^ use of possibly-uninitialized `value` + | ^^^^^ `value` used here but it isn't initialized -error[E0381]: use of possibly-uninitialized variable: `value` +error[E0381]: used binding `value` isn't initialized --> $DIR/issue-72649-uninit-in-loop.rs:69:21 | +LL | let mut value: NonCopy; + | --------- binding declared here but left uninitialized +LL | loop { LL | let _used = value; - | ^^^^^ use of possibly-uninitialized `value` + | ^^^^^ `value` used here but it isn't initialized error: aborting due to 6 previous errors diff --git a/src/test/ui/moves/move-into-dead-array-1.rs b/src/test/ui/moves/move-into-dead-array-1.rs index 2d0ff585263..0b8d76def87 100644 --- a/src/test/ui/moves/move-into-dead-array-1.rs +++ b/src/test/ui/moves/move-into-dead-array-1.rs @@ -11,5 +11,5 @@ fn main() { fn foo(i: usize) { let mut a: [D; 4]; - a[i] = d(); //~ ERROR use of possibly-uninitialized variable: `a` + a[i] = d(); //~ ERROR E0381 } diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr index 5f20ccfeddf..344a6bbf0c9 100644 --- a/src/test/ui/moves/move-into-dead-array-1.stderr +++ b/src/test/ui/moves/move-into-dead-array-1.stderr @@ -1,8 +1,10 @@ -error[E0381]: use of possibly-uninitialized variable: `a` +error[E0381]: used binding `a` isn't initialized --> $DIR/move-into-dead-array-1.rs:14:5 | +LL | let mut a: [D; 4]; + | ----- binding declared here but left uninitialized LL | a[i] = d(); - | ^^^^ use of possibly-uninitialized `a` + | ^^^^ `a` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/moves/move-of-addr-of-mut.rs b/src/test/ui/moves/move-of-addr-of-mut.rs index f2f64e43cd2..19fd7028692 100644 --- a/src/test/ui/moves/move-of-addr-of-mut.rs +++ b/src/test/ui/moves/move-of-addr-of-mut.rs @@ -5,7 +5,7 @@ struct S; fn main() { let mut x: S; - std::ptr::addr_of_mut!(x); //~ borrow of + std::ptr::addr_of_mut!(x); //~ ERROR E0381 let y = x; // Should error here if `addr_of_mut` is ever allowed on uninitialized variables drop(y); diff --git a/src/test/ui/moves/move-of-addr-of-mut.stderr b/src/test/ui/moves/move-of-addr-of-mut.stderr index ce8fb028316..e75f2b1c089 100644 --- a/src/test/ui/moves/move-of-addr-of-mut.stderr +++ b/src/test/ui/moves/move-of-addr-of-mut.stderr @@ -1,8 +1,10 @@ -error[E0381]: borrow of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/move-of-addr-of-mut.rs:8:5 | +LL | let mut x: S; + | ----- binding declared here but left uninitialized LL | std::ptr::addr_of_mut!(x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `x` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` used here but it isn't initialized | = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr index ce930eee2e9..125e446c332 100644 --- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr +++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr @@ -4,9 +4,8 @@ error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure LL | let i = Box::new(3); | - captured outer variable LL | let _f = to_fn(|| test(i)); - | --------^- - | | | - | | move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait + | -- ^ move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait + | | | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index fbd86bdb661..b04ea14d1a5 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -94,7 +94,7 @@ LL | check(xm7::V); LL | V {}, | - `xm7::V` defined here LL | TV(), - | ---- similarly named tuple variant `TV` defined here + | -- similarly named tuple variant `TV` defined here | help: use struct literal syntax instead | diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 6b9635d4a60..2acf44432c6 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6] as FnOnce<()>>::Output == ()` +error[E0271]: type mismatch resolving `<[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47] as FnOnce<()>>::Output == ()` --> $DIR/fallback-closure-wrap.rs:18:31 | LL | let error = Closure::wrap(Box::new(move || { @@ -10,7 +10,7 @@ LL | | }) as Box<dyn FnMut()>); | = note: expected unit type `()` found type `!` - = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6]` to the object type `dyn FnMut()` + = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to the object type `dyn FnMut()` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-captures.stderr b/src/test/ui/nll/closure-captures.stderr index a59e553315a..5233f0b2462 100644 --- a/src/test/ui/nll/closure-captures.stderr +++ b/src/test/ui/nll/closure-captures.stderr @@ -37,36 +37,32 @@ LL | x = 1; error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:27:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | || - | | ^^ cannot borrow as mutable -LL | | x = 1;} - | |__________-_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;} + | - mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:31:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | || - | | ^^ cannot borrow as mutable -LL | | x = 1;}); - | |_____-_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;}); + | - mutable borrow occurs due to use of `x` in closure error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/closure-captures.rs:39:10 @@ -80,19 +76,17 @@ LL | x = 1;} error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:38:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | || - | | ^^ cannot borrow as mutable -LL | | x = 1;} - | |__________-_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;} + | - mutable borrow occurs due to use of `x` in closure error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/closure-captures.rs:43:5 @@ -106,53 +100,47 @@ LL | x = 1;}); error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:42:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | || - | | ^^ cannot borrow as mutable -LL | | x = 1;}); - | |_____-_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;}); + | - mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:48:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(|| { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | || - | | ^^ cannot borrow as mutable -LL | | *x = 1;}); - | |_________--_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | *x = 1;}); + | -- mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:51:9 | -LL | fn fn_ref<F: Fn()>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn fn_ref<F: Fn()>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | fn_ref(move || { - | _____------_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | || - | | ^^ cannot borrow as mutable -LL | | *x = 1;}); - | |_________--_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | *x = 1;}); + | -- mutable borrow occurs due to use of `x` in closure error: aborting due to 12 previous errors diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index ff16bf0e078..f86a19fff84 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -2,7 +2,7 @@ note: no external requirements --> $DIR/escape-argument-callee.rs:26:38 | LL | let mut closure = expect_sig(|p, y| *p = y); - | ^^^^^^^^^^^^^ + | ^^^^^^ | = note: defining type: test::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index 49ec0dd931a..8cd8b43cabe 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -2,7 +2,7 @@ note: no external requirements --> $DIR/escape-argument.rs:26:38 | LL | let mut closure = expect_sig(|p, y| *p = y); - | ^^^^^^^^^^^^^ + | ^^^^^^ | = note: defining type: test::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index f0ae4c7fb04..abf80e03928 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/escape-upvar-nested.rs:21:32 | LL | let mut closure1 = || p = &y; - | ^^^^^^^^^ + | ^^ | = note: defining type: test::{closure#0}::{closure#0} with closure substs [ i16, @@ -15,12 +15,8 @@ LL | let mut closure1 = || p = &y; note: external requirements --> $DIR/escape-upvar-nested.rs:20:27 | -LL | let mut closure = || { - | ___________________________^ -LL | | let mut closure1 = || p = &y; -LL | | closure1(); -LL | | }; - | |_________^ +LL | let mut closure = || { + | ^^ | = note: defining type: test::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index e99fc4b43a2..bc754642173 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/escape-upvar-ref.rs:23:27 | LL | let mut closure = || p = &y; - | ^^^^^^^^^ + | ^^ | = note: defining type: test::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 11420efaa06..b9b0f3ad257 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -1,12 +1,8 @@ note: no external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:43:9 | -LL | / |_outlives1, _outlives2, _outlives3, x, y| { -LL | | // Only works if 'x: 'y: -LL | | let p = x.get(); -LL | | demand_y(x, y, p) -LL | | }, - | |_________^ +LL | |_outlives1, _outlives2, _outlives3, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 98c3c28fb43..a2371ee314a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -1,13 +1,8 @@ note: external requirements --> $DIR/propagate-approximated-ref.rs:43:47 | -LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | _______________________________________________^ -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) -LL | | -LL | | }); - | |_____^ +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 3ab55b370c2..e53ae167f12 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -1,12 +1,8 @@ note: no external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:21:15 | -LL | foo(cell, |cell_a, cell_x| { - | _______________^ -LL | | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure -LL | | -LL | | }) - | |_____^ +LL | foo(cell, |cell_a, cell_x| { + | ^^^^^^^^^^^^^^^^ | = note: defining type: case1::{closure#0} with closure substs [ i32, @@ -41,11 +37,8 @@ LL | | } note: external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15 | -LL | foo(cell, |cell_a, cell_x| { - | _______________^ -LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error -LL | | }) - | |_____^ +LL | foo(cell, |cell_a, cell_x| { + | ^^^^^^^^^^^^^^^^ | = note: defining type: case2::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index ec2c220b6b8..c3c7eb1bd9e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -1,14 +1,8 @@ note: external requirements --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:47 | -LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | _______________________________________________^ -LL | | -LL | | -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) -LL | | }); - | |_____^ +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | ^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 234212c8876..846e5aedb3e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -1,14 +1,8 @@ note: external requirements --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:47 | -LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | _______________________________________________^ -LL | | -LL | | -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) -LL | | }); - | |_____^ +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 2ec9d4d8db1..a570932eda9 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -1,13 +1,8 @@ note: external requirements --> $DIR/propagate-approximated-val.rs:36:45 | -LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { - | _____________________________________________^ -LL | | // Only works if 'x: 'y: -LL | | demand_y(outlives1, outlives2, x.get()) -LL | | -LL | | }); - | |_____^ +LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defining type: test::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index 21e4232c788..407bc6764d6 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -1,12 +1,8 @@ note: external requirements --> $DIR/propagate-despite-same-free-region.rs:42:9 | -LL | / |_outlives1, _outlives2, x, y| { -LL | | // Only works if 'x: 'y: -LL | | let p = x.get(); -LL | | demand_y(x, y, p) -LL | | }, - | |_________^ +LL | |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 8b9b0435420..fcb55d37f31 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -1,13 +1,8 @@ note: no external requirements --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:35:47 | -LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | _______________________________________________^ -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) -LL | | -LL | | }); - | |_____^ +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | ^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 060ce690f03..75beae39e23 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -1,13 +1,8 @@ note: no external requirements --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:39:47 | -LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | _______________________________________________^ -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) -LL | | -LL | | }); - | |_____^ +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: defining type: supply::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 08605efa2ea..58aced2bfcd 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -1,15 +1,8 @@ note: external requirements --> $DIR/propagate-from-trait-match.rs:32:36 | -LL | establish_relationships(value, |value| { - | ____________________________________^ -LL | | -LL | | -LL | | // This function call requires that -... | -LL | | require(value); -LL | | }); - | |_____^ +LL | establish_relationships(value, |value| { + | ^^^^^^^ | = note: defining type: supply::<'_#1r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 5fc1d5c4361..1c9d0c83549 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -2,7 +2,7 @@ note: no external requirements --> $DIR/return-wrong-bound-region.rs:11:16 | LL | expect_sig(|a, b| b); // ought to return `a` - | ^^^^^^^^ + | ^^^^^^ | = note: defining type: test::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs index ebea6d3d9d1..46a156d2af9 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs @@ -25,14 +25,12 @@ impl Drop for D { fn cannot_partially_init_adt_with_drop() { let d: D; - d.x = 10; - //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381] + d.x = 10; //~ ERROR E0381 } fn cannot_partially_init_mutable_adt_with_drop() { let mut d: D; - d.x = 10; - //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381] + d.x = 10; //~ ERROR E0381 } fn cannot_partially_reinit_adt_with_drop() { @@ -44,14 +42,12 @@ fn cannot_partially_reinit_adt_with_drop() { fn cannot_partially_init_inner_adt_via_outer_with_drop() { let d: D; - d.s.y = 20; - //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381] + d.s.y = 20; //~ ERROR E0381 } fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() { let mut d: D; - d.s.y = 20; - //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381] + d.s.y = 20; //~ ERROR E0381 } fn cannot_partially_reinit_inner_adt_via_outer_with_drop() { diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr index 1b66e034d37..63f230be7d4 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr @@ -1,17 +1,25 @@ -error[E0381]: assign of possibly-uninitialized variable: `d` +error[E0381]: assigned binding `d` isn't fully initialized --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5 | +LL | let d: D; + | - binding declared here but left uninitialized LL | d.x = 10; - | ^^^^^^^^ use of possibly-uninitialized `d` + | ^^^^^^^^ `d` assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign of possibly-uninitialized variable: `d` - --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:34:5 +error[E0381]: assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:33:5 | +LL | let mut d: D; + | ----- binding declared here but left uninitialized LL | d.x = 10; - | ^^^^^^^^ use of possibly-uninitialized `d` + | ^^^^^^^^ `d` assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign of moved value: `d` - --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:41:5 + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:39:5 | LL | let mut d = D { x: 0, s: S{ y: 0, z: 0 } }; | ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait @@ -20,20 +28,28 @@ LL | drop(d); LL | d.x = 10; | ^^^^^^^^ value assigned here after move -error[E0381]: assign to part of possibly-uninitialized variable: `d` - --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:47:5 +error[E0381]: partially assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:45:5 | +LL | let d: D; + | - binding declared here but left uninitialized LL | d.s.y = 20; - | ^^^^^^^^^^ use of possibly-uninitialized `d.s` + | ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `d` - --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:53:5 +error[E0381]: partially assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:50:5 | +LL | let mut d: D; + | ----- binding declared here but left uninitialized LL | d.s.y = 20; - | ^^^^^^^^^^ use of possibly-uninitialized `d.s` + | ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign to part of moved value: `d` - --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:60:5 + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:56:5 | LL | let mut d = D { x: 0, s: S{ y: 0, z: 0} }; | ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs index 1836f766cc7..4cd1e406f94 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -94,15 +94,13 @@ macro_rules! use_part { fn test_0000_local_fully_init_and_use_struct() { let s: S<B>; - s.x = 10; s.y = Box::new(20); - //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] + s.x = 10; s.y = Box::new(20); //~ ERROR E0381 use_fully!(struct s); } fn test_0001_local_fully_init_and_use_tuple() { let t: T; - t.0 = 10; t.1 = Box::new(20); - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 10; t.1 = Box::new(20); //~ ERROR E0381 use_fully!(tuple t); } @@ -122,15 +120,13 @@ fn test_0011_local_fully_reinit_and_use_tuple() { fn test_0100_local_partial_init_and_use_struct() { let s: S<B>; - s.x = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] + s.x = 10; //~ ERROR E0381 use_part!(struct s); } fn test_0101_local_partial_init_and_use_tuple() { let t: T; - t.0 = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 10; //~ ERROR E0381 use_part!(tuple t); } @@ -150,15 +146,13 @@ fn test_0111_local_partial_reinit_and_use_tuple() { fn test_0200_local_void_init_and_use_struct() { let s: S<Void>; - s.x = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381] + s.x = 10; //~ ERROR E0381 use_part!(struct s); } fn test_0201_local_void_init_and_use_tuple() { let t: Tvoid; - t.0 = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381] + t.0 = 10; //~ ERROR E0381 use_part!(tuple t); } @@ -173,15 +167,13 @@ fn test_0201_local_void_init_and_use_tuple() { fn test_1000_field_fully_init_and_use_struct() { let q: Q<S<B>>; - q.r.f.x = 10; q.r.f.y = Box::new(20); - //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] + q.r.f.x = 10; q.r.f.y = Box::new(20); //~ ERROR E0381 use_fully!(struct q.r.f); } fn test_1001_field_fully_init_and_use_tuple() { let q: Q<T>; - q.r.f.0 = 10; q.r.f.1 = Box::new(20); - //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] + q.r.f.0 = 10; q.r.f.1 = Box::new(20); //~ ERROR E0381 use_fully!(tuple q.r.f); } @@ -201,15 +193,13 @@ fn test_1011_field_fully_reinit_and_use_tuple() { fn test_1100_field_partial_init_and_use_struct() { let q: Q<S<B>>; - q.r.f.x = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] + q.r.f.x = 10; //~ ERROR E0381 use_part!(struct q.r.f); } fn test_1101_field_partial_init_and_use_tuple() { let q: Q<T>; - q.r.f.0 = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] + q.r.f.0 = 10; //~ ERROR E0381 use_part!(tuple q.r.f); } @@ -229,15 +219,13 @@ fn test_1111_field_partial_reinit_and_use_tuple() { fn test_1200_field_void_init_and_use_struct() { let mut q: Q<S<Void>>; - q.r.f.x = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] + q.r.f.x = 10; //~ ERROR E0381 use_part!(struct q.r.f); } fn test_1201_field_void_init_and_use_tuple() { let mut q: Q<Tvoid>; - q.r.f.0 = 10; - //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381] + q.r.f.0 = 10; //~ ERROR E0381 use_part!(tuple q.r.f); } diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr index 77fa484c21d..947c9e29b45 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr @@ -1,17 +1,25 @@ -error[E0381]: assign to part of possibly-uninitialized variable: `s` +error[E0381]: partially assigned binding `s` isn't fully initialized --> $DIR/issue-21232-partial-init-and-use.rs:97:5 | +LL | let s: S<B>; + | - binding declared here but left uninitialized LL | s.x = 10; s.y = Box::new(20); - | ^^^^^^^^ use of possibly-uninitialized `s` + | ^^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/issue-21232-partial-init-and-use.rs:104:5 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:103:5 | +LL | let t: T; + | - binding declared here but left uninitialized LL | t.0 = 10; t.1 = Box::new(20); - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign to part of moved value: `s` - --> $DIR/issue-21232-partial-init-and-use.rs:111:5 + --> $DIR/issue-21232-partial-init-and-use.rs:109:5 | LL | let mut s: S<B> = S::new(); drop(s); | ----- - value moved here @@ -21,7 +29,7 @@ LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move error[E0382]: assign to part of moved value: `t` - --> $DIR/issue-21232-partial-init-and-use.rs:118:5 + --> $DIR/issue-21232-partial-init-and-use.rs:116:5 | LL | let mut t: T = (0, Box::new(0)); drop(t); | ----- - value moved here @@ -30,20 +38,28 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); LL | t.0 = 10; t.1 = Box::new(20); | ^^^^^^^^ value partially assigned here after move -error[E0381]: assign to part of possibly-uninitialized variable: `s` - --> $DIR/issue-21232-partial-init-and-use.rs:125:5 +error[E0381]: partially assigned binding `s` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:123:5 | +LL | let s: S<B>; + | - binding declared here but left uninitialized LL | s.x = 10; - | ^^^^^^^^ use of possibly-uninitialized `s` + | ^^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/issue-21232-partial-init-and-use.rs:132:5 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:129:5 | +LL | let t: T; + | - binding declared here but left uninitialized LL | t.0 = 10; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign to part of moved value: `s` - --> $DIR/issue-21232-partial-init-and-use.rs:139:5 + --> $DIR/issue-21232-partial-init-and-use.rs:135:5 | LL | let mut s: S<B> = S::new(); drop(s); | ----- - value moved here @@ -53,7 +69,7 @@ LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move error[E0382]: assign to part of moved value: `t` - --> $DIR/issue-21232-partial-init-and-use.rs:146:5 + --> $DIR/issue-21232-partial-init-and-use.rs:142:5 | LL | let mut t: T = (0, Box::new(0)); drop(t); | ----- - value moved here @@ -62,32 +78,48 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); LL | t.0 = 10; | ^^^^^^^^ value partially assigned here after move -error[E0381]: assign to part of possibly-uninitialized variable: `s` - --> $DIR/issue-21232-partial-init-and-use.rs:153:5 +error[E0381]: partially assigned binding `s` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:149:5 | +LL | let s: S<Void>; + | - binding declared here but left uninitialized LL | s.x = 10; - | ^^^^^^^^ use of possibly-uninitialized `s` + | ^^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `t` - --> $DIR/issue-21232-partial-init-and-use.rs:160:5 +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:155:5 | +LL | let t: Tvoid; + | - binding declared here but left uninitialized LL | t.0 = 10; - | ^^^^^^^^ use of possibly-uninitialized `t` + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `q` - --> $DIR/issue-21232-partial-init-and-use.rs:176:5 +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:170:5 | +LL | let q: Q<S<B>>; + | - binding declared here but left uninitialized LL | q.r.f.x = 10; q.r.f.y = Box::new(20); - | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `q` - --> $DIR/issue-21232-partial-init-and-use.rs:183:5 +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:176:5 | +LL | let q: Q<T>; + | - binding declared here but left uninitialized LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); - | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign to part of moved value: `q.r` - --> $DIR/issue-21232-partial-init-and-use.rs:190:5 + --> $DIR/issue-21232-partial-init-and-use.rs:182:5 | LL | let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r); | --- value moved here @@ -97,7 +129,7 @@ LL | q.r.f.x = 10; q.r.f.y = Box::new(20); = note: move occurs because `q.r` has type `R<S<Box<u32>>>`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `q.r` - --> $DIR/issue-21232-partial-init-and-use.rs:197:5 + --> $DIR/issue-21232-partial-init-and-use.rs:189:5 | LL | let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r); | --- value moved here @@ -106,20 +138,28 @@ LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); | = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly-uninitialized variable: `q` - --> $DIR/issue-21232-partial-init-and-use.rs:204:5 +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:196:5 | +LL | let q: Q<S<B>>; + | - binding declared here but left uninitialized LL | q.r.f.x = 10; - | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `q` - --> $DIR/issue-21232-partial-init-and-use.rs:211:5 +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:202:5 | +LL | let q: Q<T>; + | - binding declared here but left uninitialized LL | q.r.f.0 = 10; - | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign to part of moved value: `q.r` - --> $DIR/issue-21232-partial-init-and-use.rs:218:5 + --> $DIR/issue-21232-partial-init-and-use.rs:208:5 | LL | let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r); | --- value moved here @@ -129,7 +169,7 @@ LL | q.r.f.x = 10; = note: move occurs because `q.r` has type `R<S<Box<u32>>>`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `q.r` - --> $DIR/issue-21232-partial-init-and-use.rs:225:5 + --> $DIR/issue-21232-partial-init-and-use.rs:215:5 | LL | let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r); | --- value moved here @@ -138,20 +178,28 @@ LL | q.r.f.0 = 10; | = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait -error[E0381]: assign to part of possibly-uninitialized variable: `q` - --> $DIR/issue-21232-partial-init-and-use.rs:232:5 +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:222:5 | +LL | let mut q: Q<S<Void>>; + | ----- binding declared here but left uninitialized LL | q.r.f.x = 10; - | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error[E0381]: assign to part of possibly-uninitialized variable: `q` - --> $DIR/issue-21232-partial-init-and-use.rs:239:5 +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:228:5 | +LL | let mut q: Q<Tvoid>; + | ----- binding declared here but left uninitialized LL | q.r.f.0 = 10; - | ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f` + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` error[E0382]: assign to part of moved value: `c` - --> $DIR/issue-21232-partial-init-and-use.rs:257:13 + --> $DIR/issue-21232-partial-init-and-use.rs:245:13 | LL | let mut c = (1, "".to_owned()); | ----- move occurs because `c` has type `(i32, String)`, which does not implement the `Copy` trait @@ -162,7 +210,7 @@ LL | c.0 = 2; | ^^^^^^^ value partially assigned here after move error[E0382]: assign to part of moved value: `c` - --> $DIR/issue-21232-partial-init-and-use.rs:267:13 + --> $DIR/issue-21232-partial-init-and-use.rs:255:13 | LL | let mut c = (1, (1, "".to_owned())); | ----- move occurs because `c` has type `(i32, (i32, String))`, which does not implement the `Copy` trait @@ -173,7 +221,7 @@ LL | (c.1).0 = 2; | ^^^^^^^^^^^ value partially assigned here after move error[E0382]: assign to part of moved value: `c.1` - --> $DIR/issue-21232-partial-init-and-use.rs:275:13 + --> $DIR/issue-21232-partial-init-and-use.rs:263:13 | LL | c2 => { | -- value moved here diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr index c9324f0422c..fb61b30f09d 100644 --- a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -4,9 +4,8 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` LL | let x = (vec![22], vec![44]); | - captured outer variable LL | expect_fn(|| drop(x.0)); - | --------^^^- - | | | - | | move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait + | -- ^^^ move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait + | | | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.stderr index a5a0fc415bb..036a7a0abfd 100644 --- a/src/test/ui/nll/issue-54556-stephaneyfx.stderr +++ b/src/test/ui/nll/issue-54556-stephaneyfx.stderr @@ -10,7 +10,7 @@ LL | } | - | | | `stmt` dropped here while still borrowed - | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Map<Rows<'_>, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:23]>` + | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Map<Rows<'_>, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:19]>` | = note: the temporary is part of an expression at the end of a block; consider forcing this temporary to be dropped sooner, before the block's local variables are dropped diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index 2e6d675fb64..252f7f8ba07 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -18,7 +18,7 @@ fn guard_may_be_skipped(y: i32) { match y { _ if { x = 2; true } => 1, _ if { - x; //~ ERROR use of possibly-uninitialized variable: `x` + x; //~ ERROR E0381 false } => 2, _ => 3, diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index 4b3817929fd..250aa482e5c 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -1,8 +1,14 @@ -error[E0381]: use of possibly-uninitialized variable: `x` +error[E0381]: used binding `x` isn't initialized --> $DIR/match-cfg-fake-edges.rs:21:13 | +LL | let x; + | - binding declared here but left uninitialized +... +LL | _ if { x = 2; true } => 1, + | ----- binding initialized here in some conditions +LL | _ if { LL | x; - | ^ use of possibly-uninitialized `x` + | ^ `x` used here but it isn't initialized error[E0382]: use of moved value: `x` --> $DIR/match-cfg-fake-edges.rs:35:13 diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr index 2121b59b02d..664f36f695c 100644 --- a/src/test/ui/nll/match-on-borrowed.stderr +++ b/src/test/ui/nll/match-on-borrowed.stderr @@ -33,11 +33,13 @@ LL | match t { LL | x; | - borrow later used here -error[E0381]: use of possibly-uninitialized variable: `n` +error[E0381]: used binding `n` isn't initialized --> $DIR/match-on-borrowed.rs:93:11 | +LL | let n: Never; + | - binding declared here but left uninitialized LL | match n {} - | ^ use of possibly-uninitialized `n` + | ^ `n` used here but it isn't initialized error: aborting due to 4 previous errors diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index 8fe25181da1..feab2476970 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/projection-no-regions-closure.rs:25:23 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ | = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -39,7 +39,7 @@ note: external requirements --> $DIR/projection-no-regions-closure.rs:34:23 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ | = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -66,7 +66,7 @@ note: external requirements --> $DIR/projection-no-regions-closure.rs:42:23 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ | = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -103,7 +103,7 @@ note: external requirements --> $DIR/projection-no-regions-closure.rs:52:23 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ | = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index caf2e3c4747..98063bd0a76 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/projection-one-region-closure.rs:45:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -56,7 +56,7 @@ note: external requirements --> $DIR/projection-one-region-closure.rs:56:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -109,7 +109,7 @@ note: external requirements --> $DIR/projection-one-region-closure.rs:70:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -137,7 +137,7 @@ note: external requirements --> $DIR/projection-one-region-closure.rs:80:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 4eebe682d4f..45e61bcbda8 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:37:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -44,7 +44,7 @@ note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:47:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -85,7 +85,7 @@ note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:60:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -113,7 +113,7 @@ note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:69:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -141,7 +141,7 @@ note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:81:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr index 46a02598e19..f2549205b81 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -2,7 +2,7 @@ note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:36:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -28,7 +28,7 @@ note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -54,7 +54,7 @@ note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -80,7 +80,7 @@ note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -106,7 +106,7 @@ note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 1ee788b40ab..8e1b6fa2e46 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -40,7 +40,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ i32, @@ -77,7 +77,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ i32, @@ -105,7 +105,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:70:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ i32, @@ -133,7 +133,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:79:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ i32, @@ -161,7 +161,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: two_regions::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -203,7 +203,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:97:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, @@ -231,7 +231,7 @@ note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:109:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index a4588730b3f..12c76d198e7 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:24:24 | LL | twice(cell, value, |a, b| invoke(a, b)); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ | = note: defining type: generic::<T>::{closure#0} with closure substs [ i16, @@ -27,7 +27,7 @@ note: external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 | LL | twice(cell, value, |a, b| invoke(a, b)); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ | = note: defining type: generic_fail::<T>::{closure#0} with closure substs [ i16, diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 084dd93cb86..35741859dff 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -2,7 +2,7 @@ note: external requirements --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 | LL | with_signature(x, |y| y) - | ^^^^^ + | ^^^ | = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 11a737ba291..0261bc39e71 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -1,15 +1,8 @@ note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | -LL | | // -LL | | // See `correct_region`, which explains the point of this -... | -LL | | require(&x, &y) -LL | | }) - | |_____^ +LL | with_signature(a, b, |x, y| { + | ^^^^^^ | = note: defining type: no_region::<T>::{closure#0} with closure substs [ i32, @@ -55,15 +48,8 @@ LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) { note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | // Key point of this test: -LL | | // -LL | | // The *closure* is being type-checked with all of its free -... | -LL | | require(&x, &y) -LL | | }) - | |_____^ +LL | with_signature(a, b, |x, y| { + | ^^^^^^ | = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -90,13 +76,8 @@ LL | | } note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | -LL | | // See `correct_region` -LL | | require(&x, &y) -LL | | }) - | |_____^ +LL | with_signature(a, b, |x, y| { + | ^^^^^^ | = note: defining type: wrong_region::<'_#1r, T>::{closure#0} with closure substs [ i32, @@ -140,12 +121,8 @@ LL | T: 'b + 'a, note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | // See `correct_region` -LL | | require(&x, &y) -LL | | }) - | |_____^ +LL | with_signature(a, b, |x, y| { + | ^^^^^^ | = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ i32, diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr index 3326fa521fc..ee332278c30 100644 --- a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -30,15 +30,14 @@ error[E0597]: `c` does not live long enough | LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here +LL | let _closure = || { + | - `c` dropped here while still borrowed ... LL | SomeEnum::SomeVariant(Cell::new(&c)), | ----------^^- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` -... -LL | }; - | - `c` dropped here while still borrowed error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/src/test/ui/nll/user-annotations/adt-tuple-struct-calls.stderr index 9664fb9f548..95bbd62c4fb 100644 --- a/src/test/ui/nll/user-annotations/adt-tuple-struct-calls.stderr +++ b/src/test/ui/nll/user-annotations/adt-tuple-struct-calls.stderr @@ -28,28 +28,28 @@ error[E0597]: `c` does not live long enough | LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here +LL | let _closure = || { + | - `c` dropped here while still borrowed ... LL | f(&c); | --^^- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` -LL | }; - | - `c` dropped here while still borrowed error[E0597]: `c` does not live long enough --> $DIR/adt-tuple-struct-calls.rs:53:11 | LL | let f = SomeStruct::<&'a u32>; | - lifetime `'1` appears in the type of `f` -... +LL | let _closure = || { + | - `c` dropped here while still borrowed +LL | let c = 66; LL | f(&c); | --^^- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'1` -LL | }; - | - `c` dropped here while still borrowed error: aborting due to 4 previous errors diff --git a/src/test/ui/nll/user-annotations/fns.stderr b/src/test/ui/nll/user-annotations/fns.stderr index e0640da39e2..bd4d121d569 100644 --- a/src/test/ui/nll/user-annotations/fns.stderr +++ b/src/test/ui/nll/user-annotations/fns.stderr @@ -28,14 +28,14 @@ error[E0597]: `c` does not live long enough | LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here -... +LL | let _closure = || { + | - `c` dropped here while still borrowed +LL | let c = 66; LL | some_fn::<&'a u32>(&c); | -------------------^^- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` -LL | }; - | - `c` dropped here while still borrowed error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/user-annotations/method-call.stderr b/src/test/ui/nll/user-annotations/method-call.stderr index 10447e45a6d..fcaeb465d14 100644 --- a/src/test/ui/nll/user-annotations/method-call.stderr +++ b/src/test/ui/nll/user-annotations/method-call.stderr @@ -29,13 +29,14 @@ error[E0597]: `c` does not live long enough LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here ... +LL | let _closure = || { + | - `c` dropped here while still borrowed +LL | let c = 66; LL | a.method::<&'a u32>(b, &c); | ------------------------^^- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` -LL | }; - | - `c` dropped here while still borrowed error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/user-annotations/method-ufcs-3.stderr b/src/test/ui/nll/user-annotations/method-ufcs-3.stderr index e7851833e93..328dde9805a 100644 --- a/src/test/ui/nll/user-annotations/method-ufcs-3.stderr +++ b/src/test/ui/nll/user-annotations/method-ufcs-3.stderr @@ -29,13 +29,14 @@ error[E0597]: `c` does not live long enough LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here ... +LL | let _closure = || { + | - `c` dropped here while still borrowed +LL | let c = 66; LL | <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); | -------------------------------------------^^- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` -LL | }; - | - `c` dropped here while still borrowed error: aborting due to 3 previous errors diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index e4c57c04e72..249c2fe2fa7 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -1,17 +1,12 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely --> $DIR/no-send-res-ports.rs:25:5 | -LL | thread::spawn(move|| { - | _____^^^^^^^^^^^^^_- - | | | - | | `Rc<()>` cannot be sent between threads safely -LL | | -LL | | let y = x; -LL | | println!("{:?}", y); -LL | | }); - | |_____- within this `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]` +LL | thread::spawn(move|| { + | ^^^^^^^^^^^^^ ------ within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]` + | | + | `Rc<()>` cannot be sent between threads safely | - = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]`, the trait `Send` is not implemented for `Rc<()>` + = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`, the trait `Send` is not implemented for `Rc<()>` note: required because it appears within the type `Port<()>` --> $DIR/no-send-res-ports.rs:5:8 | @@ -25,13 +20,8 @@ LL | struct Foo { note: required because it's used within this closure --> $DIR/no-send-res-ports.rs:25:19 | -LL | thread::spawn(move|| { - | ___________________^ -LL | | -LL | | let y = x; -LL | | println!("{:?}", y); -LL | | }); - | |_____^ +LL | thread::spawn(move|| { + | ^^^^^^ note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr index bebf561b120..37d94cf0ebd 100644 --- a/src/test/ui/not-clone-closure.stderr +++ b/src/test/ui/not-clone-closure.stderr @@ -1,23 +1,17 @@ -error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` +error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` --> $DIR/not-clone-closure.rs:11:23 | -LL | let hello = move || { - | _________________- -LL | | println!("Hello {}", a.0); -LL | | }; - | |_____- within this `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` -LL | -LL | let hello = hello.clone(); - | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S` +LL | let hello = move || { + | ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` +... +LL | let hello = hello.clone(); + | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S` | note: required because it's used within this closure --> $DIR/not-clone-closure.rs:7:17 | -LL | let hello = move || { - | _________________^ -LL | | println!("Hello {}", a.0); -LL | | }; - | |_____^ +LL | let hello = move || { + | ^^^^^^^ help: consider annotating `S` with `#[derive(Clone)]` | LL | #[derive(Clone)] diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index d4f64a7de5b..858b4e8db05 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -200,7 +200,7 @@ LL | { true } || { true } | ^^^^^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/expr-as-stmt.rs:51:14: 51:25]` + found closure `[closure@$DIR/expr-as-stmt.rs:51:14: 51:16]` help: use parentheses to call this closure | LL | { true } (|| { true })() diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr index e71f15ebfd2..0852c7cb470 100644 --- a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr +++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr @@ -24,7 +24,7 @@ LL | | }.hi() { | |__________^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 14:11]` + found closure `[closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 12:13]` help: use parentheses to call this closure | LL ~ while (|| Foo { diff --git a/src/test/ui/pattern/non-structural-match-types.stderr b/src/test/ui/pattern/non-structural-match-types.stderr index e9b56cdc05d..45e16264973 100644 --- a/src/test/ui/pattern/non-structural-match-types.stderr +++ b/src/test/ui/pattern/non-structural-match-types.stderr @@ -1,4 +1,4 @@ -error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:22]` cannot be used in patterns +error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used in patterns --> $DIR/non-structural-match-types.rs:9:9 | LL | const { || {} } => {}, diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr index 019cd414d2e..c0cc56aa86e 100644 --- a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr +++ b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr @@ -60,7 +60,7 @@ LL | E1::Z0() => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15 | LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } - | -- ---- similarly named tuple variant `Z1` defined here + | -- -- similarly named tuple variant `Z1` defined here | | | `E1::Z0` defined here | @@ -82,7 +82,7 @@ LL | E1::Z0(x) => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15 | LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } - | -- ---- similarly named tuple variant `Z1` defined here + | -- -- similarly named tuple variant `Z1` defined here | | | `E1::Z0` defined here | @@ -104,7 +104,7 @@ LL | E1::Z1 => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19 | LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } - | -- ---- `E1::Z1` defined here + | -- -- `E1::Z1` defined here | | | similarly named unit variant `Z0` defined here | @@ -295,7 +295,7 @@ LL | E1::Z1(x) => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19 | LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } - | ---- tuple variant has 0 fields + | -- tuple variant has 0 fields error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields --> $DIR/pat-tuple-field-count-cross.rs:39:9 diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr index 9e13a2dc9fb..856e7918cb7 100644 --- a/src/test/ui/pattern/pat-tuple-overfield.stderr +++ b/src/test/ui/pattern/pat-tuple-overfield.stderr @@ -289,7 +289,7 @@ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has --> $DIR/pat-tuple-overfield.rs:71:16 | LL | Z1(), - | ---- tuple variant has 0 fields + | -- tuple variant has 0 fields ... LL | E1::Z1(_) => {} | ^ expected 0 fields, found 1 @@ -298,7 +298,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has --> $DIR/pat-tuple-overfield.rs:72:16 | LL | Z1(), - | ---- tuple variant has 0 fields + | -- tuple variant has 0 fields ... LL | E1::Z1(_, _) => {} | ^ ^ expected 0 fields, found 2 diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr index f174215f257..fdf817caea7 100644 --- a/src/test/ui/polymorphization/const_parameters/closures.stderr +++ b/src/test/ui/polymorphization/const_parameters/closures.stderr @@ -14,7 +14,7 @@ LL | pub fn unused<const T: usize>() -> usize { | -------------- generic parameter `T` is unused LL | LL | let add_one = |x: usize| x + 1; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:17:8 @@ -29,7 +29,7 @@ LL | pub fn used_parent<const T: usize>() -> usize { | -------------- generic parameter `T` is unused LL | let x: usize = T; LL | let add_one = |x: usize| x + 1; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:48:13 @@ -38,7 +38,7 @@ LL | pub fn unused_upvar<const T: usize>() -> usize { | -------------- generic parameter `T` is unused LL | let x: usize = T; LL | let y = || x; - | ^^^^ + | ^^ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr index 5edbb119f78..a24eee5fed1 100644 --- a/src/test/ui/polymorphization/generators.stderr +++ b/src/test/ui/polymorphization/generators.stderr @@ -10,16 +10,12 @@ LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)] error: item has unused generic parameters --> $DIR/generators.rs:35:5 | -LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | - generic parameter `T` is unused -LL | / || { -LL | | -LL | | yield 1; -LL | | 2 -LL | | } - | |_____^ +LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | - generic parameter `T` is unused +LL | || { + | ^^ -note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:35:5: 39:6], u32, u32>` +note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:35:5: 35:7], u32, u32>` --> $DIR/generators.rs:86:5 | LL | finish(unused_type::<u32>()); @@ -28,16 +24,12 @@ LL | finish(unused_type::<u32>()); error: item has unused generic parameters --> $DIR/generators.rs:60:5 | -LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | ------------ generic parameter `T` is unused -LL | / || { -LL | | -LL | | yield 1; -LL | | 2 -LL | | } - | |_____^ +LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | ------------ generic parameter `T` is unused +LL | || { + | ^^ -note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:60:5: 64:6], u32, u32>` +note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:60:5: 60:7], u32, u32>` --> $DIR/generators.rs:89:5 | LL | finish(unused_const::<1u32>()); diff --git a/src/test/ui/polymorphization/lifetimes.stderr b/src/test/ui/polymorphization/lifetimes.stderr index 2020256717c..4773dd4fa2e 100644 --- a/src/test/ui/polymorphization/lifetimes.stderr +++ b/src/test/ui/polymorphization/lifetimes.stderr @@ -11,7 +11,7 @@ LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 { | - generic parameter `T` is unused LL | let _: T = Default::default(); LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr index 6a74e63fdfe..e5af1d7515f 100644 --- a/src/test/ui/polymorphization/predicates.stderr +++ b/src/test/ui/polymorphization/predicates.stderr @@ -19,7 +19,7 @@ LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> | generic parameter `I` is unused ... LL | self.find(|_| true) - | ^^^^^^^^ + | ^^^ error: item has unused generic parameters --> $DIR/predicates.rs:59:4 diff --git a/src/test/ui/polymorphization/type_parameters/closures.stderr b/src/test/ui/polymorphization/type_parameters/closures.stderr index 417feebbc55..94a4a08bd2f 100644 --- a/src/test/ui/polymorphization/type_parameters/closures.stderr +++ b/src/test/ui/polymorphization/type_parameters/closures.stderr @@ -5,7 +5,7 @@ LL | pub fn unused<T>() -> u32 { | - generic parameter `T` is unused ... LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:16:8 @@ -20,7 +20,7 @@ LL | pub fn used_parent<T: Default>() -> u32 { | - generic parameter `T` is unused LL | let _: T = Default::default(); LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:94:23 @@ -32,7 +32,7 @@ LL | pub fn unused_all<G: Default>() -> u32 { | - generic parameter `G` is unused LL | LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:92:12 @@ -46,16 +46,11 @@ LL | pub fn unused_all<G: Default>() -> u32 { error: item has unused generic parameters --> $DIR/closures.rs:128:23 | -LL | pub fn used_impl<G: Default>() -> u32 { - | - generic parameter `G` is unused +LL | pub fn used_impl<G: Default>() -> u32 { + | - generic parameter `G` is unused LL | -LL | let add_one = |x: u32| { - | _______________________^ -LL | | -LL | | let _: F = Default::default(); -LL | | x + 1 -LL | | }; - | |_________^ +LL | let add_one = |x: u32| { + | ^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:126:12 @@ -66,16 +61,11 @@ LL | pub fn used_impl<G: Default>() -> u32 { error: item has unused generic parameters --> $DIR/closures.rs:115:23 | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused +LL | impl<F: Default> Foo<F> { + | - generic parameter `F` is unused ... -LL | let add_one = |x: u32| { - | _______________________^ -LL | | -LL | | let _: G = Default::default(); -LL | | x + 1 -LL | | }; - | |_________^ +LL | let add_one = |x: u32| { + | ^^^^^^^^ error: item has unused generic parameters --> $DIR/closures.rs:113:12 diff --git a/src/test/ui/polymorphization/unsized_cast.stderr b/src/test/ui/polymorphization/unsized_cast.stderr index b51cc5c719f..27f88d28174 100644 --- a/src/test/ui/polymorphization/unsized_cast.stderr +++ b/src/test/ui/polymorphization/unsized_cast.stderr @@ -5,16 +5,16 @@ LL | fn foo<T: Default>() { | - generic parameter `T` is unused LL | let _: T = Default::default(); LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); - | ^^^^^ + | ^^ error: item has unused generic parameters - --> $DIR/unsized_cast.rs:11:5 + --> $DIR/unsized_cast.rs:11:6 | LL | fn foo<T: Default>() { | - generic parameter `T` is unused LL | let _: T = Default::default(); LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ error: item has unused generic parameters --> $DIR/unsized_cast.rs:22:15 @@ -23,21 +23,16 @@ LL | fn foo2<T: Default>() { | - generic parameter `T` is unused ... LL | call(&|| {}, ()); - | ^^^^^ + | ^^ error: item has unused generic parameters - --> $DIR/unsized_cast.rs:19:5 + --> $DIR/unsized_cast.rs:19:6 | -LL | fn foo2<T: Default>() { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | / (|| { -LL | | -LL | | let call: extern "rust-call" fn(_, _) = Fn::call; -LL | | call(&|| {}, ()); -LL | | -LL | | })(); - | |______^ +LL | fn foo2<T: Default>() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| { + | ^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr index 4548269b507..3c46b95cbc6 100644 --- a/src/test/ui/proc-macro/parent-source-spans.stderr +++ b/src/test/ui/proc-macro/parent-source-spans.stderr @@ -148,7 +148,7 @@ LL | one!("hello", "world"); ::: $SRC_DIR/core/src/result.rs:LL:COL | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here + | -- similarly named tuple variant `Ok` defined here | = note: this error originates in the macro `parent_source_spans` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -164,7 +164,7 @@ LL | two!("yay", "rust"); ::: $SRC_DIR/core/src/result.rs:LL:COL | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here + | -- similarly named tuple variant `Ok` defined here | = note: this error originates in the macro `parent_source_spans` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -180,7 +180,7 @@ LL | three!("hip", "hop"); ::: $SRC_DIR/core/src/result.rs:LL:COL | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here + | -- similarly named tuple variant `Ok` defined here | = note: this error originates in the macro `parent_source_spans` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index aaa5884c60c..89a83298471 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -9,10 +9,10 @@ LL | func(&mut iter.map(|x| x + 1)) = note: `#[warn(unconditional_recursion)]` on by default = help: a `loop` may express intention better if this is on purpose -error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>: Iterator` +error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>` + = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr index 6ff3641bc15..d85661f6faa 100644 --- a/src/test/ui/repr/repr-transparent.stderr +++ b/src/test/ui/repr/repr-transparent.stderr @@ -58,7 +58,7 @@ error[E0731]: transparent enum needs exactly one variant, but has 2 LL | enum MultipleVariants { | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 LL | Foo(String), - | ----------- + | --- LL | Bar, | --- too many variants in `MultipleVariants` diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 81d8a34881c..e546d9f64ec 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -318,7 +318,7 @@ error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:27:20 | LL | Fn(u8), - | ------ fn(u8) -> Z {Z::Fn} defined here + | -- fn(u8) -> Z {Z::Fn} defined here ... LL | let _: Z = Z::Fn; | - ^^^^^ expected enum `Z`, found fn item @@ -353,7 +353,7 @@ error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:43:16 | LL | Fn(u8), - | ------ fn(u8) -> E {E::Fn} defined here + | -- fn(u8) -> E {E::Fn} defined here ... LL | let _: E = m::E::Fn; | - ^^^^^^^^ expected enum `E`, found fn item @@ -388,7 +388,7 @@ error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:51:16 | LL | Fn(u8), - | ------ fn(u8) -> E {E::Fn} defined here + | -- fn(u8) -> E {E::Fn} defined here ... LL | let _: E = E::Fn; | - ^^^^^ expected enum `E`, found fn item diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index 64cae3748c9..720b7b119ce 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -8,7 +8,7 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ + | ^^^^^ error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 @@ -44,7 +44,7 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ + | ^^^^^ error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 @@ -56,7 +56,7 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ + | ^^^^^ error[E0639]: cannot create non-exhaustive variant using struct expression --> $DIR/variant.rs:8:26 diff --git a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs index a7e108d72d1..e0dded15217 100644 --- a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs +++ b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs @@ -1,19 +1,19 @@ fn and_chain() { let z; if true && { z = 3; true} && z == 3 {} - //~^ ERROR use of possibly-uninitialized + //~^ ERROR E0381 } fn and_chain_2() { let z; true && { z = 3; true} && z == 3; - //~^ ERROR use of possibly-uninitialized + //~^ ERROR E0381 } fn or_chain() { let z; if false || { z = 3; false} || z == 3 {} - //~^ ERROR use of possibly-uninitialized + //~^ ERROR E0381 } fn main() { diff --git a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr index 3c47040cc8c..30d5a6779fc 100644 --- a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr @@ -1,20 +1,32 @@ -error[E0381]: use of possibly-uninitialized variable: `z` +error[E0381]: used binding `z` is possibly-uninitialized --> $DIR/chains-without-let.rs:3:34 | +LL | let z; + | - binding declared here but left uninitialized LL | if true && { z = 3; true} && z == 3 {} - | ^ use of possibly-uninitialized `z` + | ----- ^ `z` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions -error[E0381]: use of possibly-uninitialized variable: `z` +error[E0381]: used binding `z` is possibly-uninitialized --> $DIR/chains-without-let.rs:9:31 | +LL | let z; + | - binding declared here but left uninitialized LL | true && { z = 3; true} && z == 3; - | ^ use of possibly-uninitialized `z` + | ----- ^ `z` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions -error[E0381]: use of possibly-uninitialized variable: `z` +error[E0381]: used binding `z` is possibly-uninitialized --> $DIR/chains-without-let.rs:15:36 | +LL | let z; + | - binding declared here but left uninitialized LL | if false || { z = 3; false} || z == 3 {} - | ^ use of possibly-uninitialized `z` + | ----- ^ `z` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 5cf06cf4b27..93a1f691c8e 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -1249,7 +1249,7 @@ LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:138:41: 138:48]` + found closure `[closure@$DIR/disallowed-positions.rs:138:41: 138:43]` help: use parentheses to call this closure | LL | if let Range { start: F, end } = F..(|| true)() {} @@ -1449,7 +1449,7 @@ LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:203:44: 203:51]` + found closure `[closure@$DIR/disallowed-positions.rs:203:44: 203:46]` help: use parentheses to call this closure | LL | while let Range { start: F, end } = F..(|| true)() {} diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index b4693b7242a..6b43801b5e0 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -29,17 +29,14 @@ LL | f.f.call_mut(()) error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 | -LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| { - | ----- captured outer variable +LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| { + | ----- captured outer variable ... -LL | f(Box::new(|a| { - | ________________- -LL | | -LL | | foo(f); - | | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait -LL | | -LL | | }), 3); - | |_____- captured by this `FnMut` closure +LL | f(Box::new(|a| { + | --- captured by this `FnMut` closure +LL | +LL | foo(f); + | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58]`, which does not implement the `Copy` trait error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16 diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr index 3e7041f02b3..dcc60789694 100644 --- a/src/test/ui/span/move-closure.stderr +++ b/src/test/ui/span/move-closure.stderr @@ -7,7 +7,7 @@ LL | let x: () = move || (); | expected due to this | = note: expected unit type `()` - found closure `[closure@$DIR/move-closure.rs:5:17: 5:27]` + found closure `[closure@$DIR/move-closure.rs:5:17: 5:24]` help: use parentheses to call this closure | LL | let x: () = (move || ())(); diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr index 6f2ade0d0ab..10978728fa3 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.stderr +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -4,12 +4,6 @@ error: function has missing const stability attribute LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: associated function has missing const stability attribute - --> $DIR/missing-const-stability.rs:15:5 - | -LL | pub const fn foo() {} - | ^^^^^^^^^^^^^^^^^^^^^ - error: implementation has missing const stability attribute --> $DIR/missing-const-stability.rs:27:1 | @@ -19,5 +13,11 @@ LL | | fn fun() {} LL | | } | |_^ +error: associated function has missing const stability attribute + --> $DIR/missing-const-stability.rs:15:5 + | +LL | pub const fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 766db2a8356..c7d420e0aae 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -21,18 +21,18 @@ help: use parentheses to call the function LL | bar(foo()); | ++ -error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future +error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 | LL | let async_closure = async || (); | -------- consider calling this closure LL | bar(async_closure); - | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future + | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` - = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36] must be a future or must implement `IntoFuture` to be awaited + = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` + = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr index fb1055c9c30..e06ee4290ab 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -1,487 +1,342 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:28:21 | -LL | let x = X(Y); - | - captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; - | | -- ^ help: consider borrowing here: `&x` - | | | - | | data moved here - | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait -LL | | -LL | | -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +LL | let X(_t) = x; + | -- ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:32:34 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -LL | | -LL | | if let Either::One(_t) = e { } - | | -- ^ help: consider borrowing here: `&e` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | if let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:36:37 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | while let Either::One(_t) = e { } - | | -- ^ help: consider borrowing here: `&e` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | while let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:40:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match e { - | | ^ help: consider borrowing here: `&e` -... | -LL | | Either::One(_t) - | | -- - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:47:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match e { - | | ^ help: consider borrowing here: `&e` -... | -LL | | Either::One(_t) => (), - | | -- - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:56:25 | -LL | let x = X(Y); - | - captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | let X(mut _t) = x; - | | ------ ^ help: consider borrowing here: `&x` - | | | - | | data moved here - | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | let X(mut _t) = x; + | ------ ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:60:38 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | if let Either::One(mut _t) = em { } - | | ------ ^^ help: consider borrowing here: `&em` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | if let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:64:41 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | while let Either::One(mut _t) = em { } - | | ------ ^^ help: consider borrowing here: `&em` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | while let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:68:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match em { - | | ^^ help: consider borrowing here: `&em` -... | -LL | | Either::One(mut _t) - | | ------ - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:75:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fn(|| { - | ________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match em { - | | ^^ help: consider borrowing here: `&em` -... | -LL | | Either::One(mut _t) => (), - | | ------ - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `Fn` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:95:21 | -LL | let x = X(Y); - | - captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; - | | -- ^ help: consider borrowing here: `&x` - | | | - | | data moved here - | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait -LL | | -LL | | -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +LL | let X(_t) = x; + | -- ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:99:34 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -LL | | -LL | | if let Either::One(_t) = e { } - | | -- ^ help: consider borrowing here: `&e` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | if let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:103:37 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | while let Either::One(_t) = e { } - | | -- ^ help: consider borrowing here: `&e` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | while let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:107:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match e { - | | ^ help: consider borrowing here: `&e` -... | -LL | | Either::One(_t) - | | -- - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:114:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match e { - | | ^ help: consider borrowing here: `&e` -... | -LL | | Either::One(_t) => (), - | | -- - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:123:25 | -LL | let x = X(Y); - | - captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | let X(mut _t) = x; - | | ------ ^ help: consider borrowing here: `&x` - | | | - | | data moved here - | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | let X(mut _t) = x; + | ------ ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:127:38 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | if let Either::One(mut _t) = em { } - | | ------ ^^ help: consider borrowing here: `&em` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | if let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:131:41 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | while let Either::One(mut _t) = em { } - | | ------ ^^ help: consider borrowing here: `&em` - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | while let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:135:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match em { - | | ^^ help: consider borrowing here: `&em` -... | -LL | | Either::One(mut _t) - | | ------ - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:142:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match em { - | | ^^ help: consider borrowing here: `&em` -... | -LL | | Either::One(mut _t) => (), - | | ------ - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:150:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | consume_fnmut(|| { - | ___________________- -LL | | let X(_t) = x; -LL | | -LL | | -... | -LL | | match em { - | | ^^ help: consider borrowing here: `&em` -... | -LL | | Either::One(mut _t) => (), - | | ------ - | | | - | | data moved here - | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait -... | -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait error: aborting due to 21 previous errors diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 101e7aecc02..fb0a6f70bfb 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -19,13 +19,13 @@ help: use parentheses to call the function LL | bar(foo()); | ++ -error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]: T` is not satisfied +error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 | LL | let closure = || S; | -- consider calling this closure LL | bar(closure); - | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]` + | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` | | | required by a bound introduced by this call | diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 505ed2ad7b3..e75ce0da82e 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -130,7 +130,7 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 | LL | A(usize), - | -------- fn(usize) -> E {E::A} defined here + | - fn(usize) -> E {E::A} defined here ... LL | let _: E = E::A; | - ^^^^ expected enum `E`, found fn item @@ -278,14 +278,14 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:46:20 | LL | let closure = || 42; - | ----- the found closure + | -- the found closure LL | let _: usize = closure; | ----- ^^^^^^^ expected `usize`, found closure | | | expected due to this | = note: expected type `usize` - found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:24]` + found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:21]` help: use parentheses to call this closure | LL | let _: usize = closure(); diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr index 5d8d688a073..ae0d3efca47 100644 --- a/src/test/ui/suggestions/issue-84973-blacklist.stderr +++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr @@ -30,11 +30,11 @@ help: consider annotating `S` with `#[derive(Clone)]` LL | #[derive(Clone)] | -error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:33]` cannot be unpinned +error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned --> $DIR/issue-84973-blacklist.rs:17:5 | LL | f_unpin(static || { yield; }); - | ^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:33]` + | ^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` | = note: consider using `Box::pin` note: required by a bound in `f_unpin` diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 85c534364b6..e3fe25d5f9c 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,7 +10,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() - | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here + | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here ... LL | / move || { LL | | diff --git a/src/test/ui/suggestions/option-content-move2.stderr b/src/test/ui/suggestions/option-content-move2.stderr index 16cbbaba512..1d3dff3be34 100644 --- a/src/test/ui/suggestions/option-content-move2.stderr +++ b/src/test/ui/suggestions/option-content-move2.stderr @@ -1,22 +1,19 @@ error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure --> $DIR/option-content-move2.rs:9:9 | -LL | let mut var = None; - | ------- captured outer variable -LL | func(|| { - | __________- -LL | | // Shouldn't suggest `move ||.as_ref()` here -LL | | move || { - | | ^^^^^^^ move out of `var` occurs here -LL | | -LL | | var = Some(NotCopyable); - | | --- - | | | - | | variable moved due to use in closure - | | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait -LL | | } -LL | | }); - | |_____- captured by this `FnMut` closure +LL | let mut var = None; + | ------- captured outer variable +LL | func(|| { + | -- captured by this `FnMut` closure +LL | // Shouldn't suggest `move ||.as_ref()` here +LL | move || { + | ^^^^^^^ move out of `var` occurs here +LL | +LL | var = Some(NotCopyable); + | --- + | | + | variable moved due to use in closure + | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/parenthesized-deref-suggestion.rs b/src/test/ui/suggestions/parenthesized-deref-suggestion.rs index 0b4ccdd5a56..0b4ccdd5a56 100644 --- a/src/test/ui/parenthesized-deref-suggestion.rs +++ b/src/test/ui/suggestions/parenthesized-deref-suggestion.rs diff --git a/src/test/ui/parenthesized-deref-suggestion.stderr b/src/test/ui/suggestions/parenthesized-deref-suggestion.stderr index cafddbe2624..cafddbe2624 100644 --- a/src/test/ui/parenthesized-deref-suggestion.stderr +++ b/src/test/ui/suggestions/parenthesized-deref-suggestion.stderr diff --git a/src/test/ui/suggestions/suggest-box.stderr b/src/test/ui/suggestions/suggest-box.stderr index d5c49a477b0..2bdaa4e9780 100644 --- a/src/test/ui/suggestions/suggest-box.stderr +++ b/src/test/ui/suggestions/suggest-box.stderr @@ -11,7 +11,7 @@ LL | | }; | |_____^ expected struct `Box`, found closure | = note: expected struct `Box<dyn Fn() -> Result<(), ()>>` - found closure `[closure@$DIR/suggest-box.rs:4:47: 7:6]` + found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]` = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html help: store this in the heap by calling `Box::new` | diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr index cccf9378d4d..1a5833f6429 100644 --- a/src/test/ui/suggestions/suggest-variants.stderr +++ b/src/test/ui/suggestions/suggest-variants.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant named `Squareee` found for enum `Shape` --> $DIR/suggest-variants.rs:12:41 | LL | enum Shape { - | ---------- variant `Squareee` not found here + | ---------- variant `Squareee` not found for this enum ... LL | println!("My shape is {:?}", Shape::Squareee { size: 5}); | ^^^^^^^^ help: there is a variant with a similar name: `Square` @@ -11,7 +11,7 @@ error[E0599]: no variant named `Circl` found for enum `Shape` --> $DIR/suggest-variants.rs:13:41 | LL | enum Shape { - | ---------- variant `Circl` not found here + | ---------- variant `Circl` not found for this enum ... LL | println!("My shape is {:?}", Shape::Circl { size: 5}); | ^^^^^ help: there is a variant with a similar name: `Circle` @@ -20,7 +20,7 @@ error[E0599]: no variant named `Rombus` found for enum `Shape` --> $DIR/suggest-variants.rs:14:41 | LL | enum Shape { - | ---------- variant `Rombus` not found here + | ---------- variant `Rombus` not found for this enum ... LL | println!("My shape is {:?}", Shape::Rombus{ size: 5}); | ^^^^^^ variant not found in `Shape` diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr index 6127446c83e..de64269d1f1 100644 --- a/src/test/ui/suggestions/unnamable-types.stderr +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -19,7 +19,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const C: _ = || 42; | ^ not allowed in type signatures | -note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:19]` cannot be named +note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:16]` cannot be named --> $DIR/unnamable-types.rs:17:14 | LL | const C: _ = || 42; @@ -31,7 +31,7 @@ error: missing type for `const` item LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; | ^ | -note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:51]>` cannot be named +note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named --> $DIR/unnamable-types.rs:23:11 | LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; @@ -55,7 +55,7 @@ error: missing type for `const` item LL | const G = || -> i32 { yield 0; return 1; }; | ^ | -note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:43]` cannot be named +note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named --> $DIR/unnamable-types.rs:37:11 | LL | const G = || -> i32 { yield 0; return 1; }; diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr index f34e7d270f9..86dbd0aac03 100644 --- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -18,7 +18,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) = note: required because of the requirements on the impl of `Iterator` for `std::iter::Empty<()>` = note: 171 redundant requirements hidden - = note: required because of the requirements on the impl of `Iterator` for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>` + = note: required because of the requirements on the impl of `Iterator` for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs index ef10b47fd13..f4f45abcc75 100644 --- a/src/test/ui/try-block/try-block-opt-init.rs +++ b/src/test/ui/try-block/try-block-opt-init.rs @@ -12,5 +12,5 @@ pub fn main() { Ok::<(), ()>(())?; use_val(cfg_res); }; - assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly-uninitialized variable: `cfg_res` + assert_eq!(cfg_res, 5); //~ ERROR E0381 } diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr index bd145fd64e7..c397385017f 100644 --- a/src/test/ui/try-block/try-block-opt-init.stderr +++ b/src/test/ui/try-block/try-block-opt-init.stderr @@ -1,8 +1,14 @@ -error[E0381]: borrow of possibly-uninitialized variable: `cfg_res` +error[E0381]: used binding `cfg_res` is possibly-uninitialized --> $DIR/try-block-opt-init.rs:15:5 | +LL | let cfg_res; + | ------- binding declared here but left uninitialized +... +LL | cfg_res = 5; + | ----------- binding initialized here in some conditions +... LL | assert_eq!(cfg_res, 5); - | ^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res` + | ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` used here but it is possibly-uninitialized | = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/tuple/wrong_argument_ice-4.stderr b/src/test/ui/tuple/wrong_argument_ice-4.stderr index 3645d11842f..828ae21b480 100644 --- a/src/test/ui/tuple/wrong_argument_ice-4.stderr +++ b/src/test/ui/tuple/wrong_argument_ice-4.stderr @@ -6,7 +6,7 @@ LL | (|| {})(|| { LL | | LL | | let b = 1; LL | | }); - | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 5:6]` unexpected + | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]` unexpected | note: closure defined here --> $DIR/wrong_argument_ice-4.rs:2:6 diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr index 6745b8ef69c..1b89d55711d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -30,7 +30,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:71]` (0 bits) + = note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:68]` (0 bits) = note: target type: `Bug<u8, ()>` (size can vary because of [type error]) error[E0277]: the trait bound `U: From<T>` is not satisfied diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index ed1cf1852e7..f14bf6b0f7f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -10,7 +10,7 @@ note: this closure does not fulfill the lifetime requirements --> $DIR/issue-57611-trait-alias.rs:21:9 | LL | |x| x - | ^^^^^ + | ^^^ error: implementation of `FnOnce` is not general enough --> $DIR/issue-57611-trait-alias.rs:21:9 diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 57fc660901c..110b8d1eea4 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -23,7 +23,7 @@ LL | || -> Closure { || () } | ^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-63279.rs:9:21: 9:26]` + found closure `[closure@$DIR/issue-63279.rs:9:21: 9:23]` help: use parentheses to call this closure | LL | || -> Closure { (|| ())() } @@ -36,7 +36,7 @@ LL | || -> Closure { || () } | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | = note: expected unit type `()` - found closure `[closure@$DIR/issue-63279.rs:9:5: 9:28]` + found closure `[closure@$DIR/issue-63279.rs:9:5: 9:18]` help: use parentheses to call this closure | LL | (|| -> Closure { || () })() diff --git a/src/test/ui/type-alias-impl-trait/issue-94429.stderr b/src/test/ui/type-alias-impl-trait/issue-94429.stderr index 57550104087..8d7f7a07b60 100644 --- a/src/test/ui/type-alias-impl-trait/issue-94429.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-94429.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<[generator@$DIR/issue-94429.rs:17:9: 19:10] as Generator>::Yield == ()` +error[E0271]: type mismatch resolving `<[generator@$DIR/issue-94429.rs:17:9: 17:16] as Generator>::Yield == ()` --> $DIR/issue-94429.rs:15:26 | LL | fn run(&mut self) -> Self::Gen { diff --git a/src/test/ui/typeck/issue-91334.stderr b/src/test/ui/typeck/issue-91334.stderr index 633c7b11aa2..8508f7a38e2 100644 --- a/src/test/ui/typeck/issue-91334.stderr +++ b/src/test/ui/typeck/issue-91334.stderr @@ -43,7 +43,7 @@ LL | fn f(){||yield(((){), | help: a return type might be missing here: `-> _` | = note: expected unit type `()` - found generator `[generator@$DIR/issue-91334.rs:10:8: 10:23]` + found generator `[generator@$DIR/issue-91334.rs:10:8: 10:10]` error: aborting due to 5 previous errors diff --git a/src/test/ui/typeck/return_type_containing_closure.stderr b/src/test/ui/typeck/return_type_containing_closure.stderr index ae72b1477c8..101aee39559 100644 --- a/src/test/ui/typeck/return_type_containing_closure.stderr +++ b/src/test/ui/typeck/return_type_containing_closure.stderr @@ -5,7 +5,7 @@ LL | vec!['a'].iter().map(|c| c) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map` | = note: expected unit type `()` - found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:31]>` + found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>` help: consider using a semicolon here | LL | vec!['a'].iter().map(|c| c); diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr index 482d3e44fe4..bfa3061de08 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr @@ -4,9 +4,8 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn(|| drop(x)); - | --------^- - | | | - | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | -- ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | | | captured by this `Fn` closure error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure @@ -15,9 +14,8 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn_mut(|| drop(x)); - | --------^- - | | | - | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | -- ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | | | captured by this `FnMut` closure error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure @@ -26,9 +24,8 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn(move || drop(x)); - | -------------^- - | | | - | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | ------- ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | | | captured by this `Fn` closure error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure @@ -37,9 +34,8 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn_mut(move || drop(x)); - | -------------^- - | | | - | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | ------- ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | | | captured by this `FnMut` closure error: aborting due to 4 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr index 68ec8d2ba82..85ff49d61a3 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -2,9 +2,8 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closur --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13 | LL | let c = || drop(y.0); - | ^^^^^^^^---^ - | | | - | | closure is `FnOnce` because it moves the variable `y` out of its environment + | ^^ --- closure is `FnOnce` because it moves the variable `y` out of its environment + | | | this closure implements `FnOnce`, not `Fn` LL | foo(c); | --- the requirement to implement `Fn` derives from here diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr index 48ec620d92e..d6e74b5b8b9 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr @@ -28,17 +28,15 @@ LL | n += 1; error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure --> $DIR/unboxed-closures-mutate-upvar.rs:53:9 | -LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... -LL | let mut f = to_fn(move || { - | _________________-----_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | n += 1; - | | ^^^^^^ cannot assign -LL | | }); - | |_____- in this closure +LL | let mut f = to_fn(move || { + | ----- ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | n += 1; + | ^^^^^^ cannot assign error: aborting due to 4 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr index 80e84fb7cad..7d15cd0c882 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr @@ -1,18 +1,15 @@ error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:11:9 | -LL | fn call<F>(f: F) where F : Fn() { - | - change this to accept `FnMut` instead of `Fn` +LL | fn call<F>(f: F) where F : Fn() { + | - change this to accept `FnMut` instead of `Fn` ... -LL | call(|| { - | _____----_- - | | | - | | expects `Fn` instead of `FnMut` -LL | | counter += 1; - | | ^^^^^^^^^^^^ cannot assign -LL | | -LL | | }); - | |_____- in this closure +LL | call(|| { + | ---- -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | counter += 1; + | ^^^^^^^^^^^^ cannot assign error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr index e9883903674..4f89afa320d 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -1,8 +1,8 @@ -error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` in the current scope +error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10 | LL | mut_.call((0, )); - | ---- ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]` + | ---- ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` | | | this is a function, perhaps you wish to call it diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs index b37ec2696de..2764bb563d3 100644 --- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs +++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs @@ -25,5 +25,5 @@ fn main() { widget::Widget::new(); // Error. Widget type is not known to be uninhabited here, // so the following code is considered reachable. - *y = 2; //~ ERROR use of possibly-uninitialized variable + *y = 2; //~ ERROR E0381 } diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr index fb195341168..95c209f47c9 100644 --- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr +++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr @@ -1,8 +1,11 @@ -error[E0381]: use of possibly-uninitialized variable: `y` +error[E0381]: used binding `y` isn't initialized --> $DIR/privately-uninhabited-mir-call.rs:28:5 | +LL | let y: &mut u32; + | - binding declared here but left uninitialized +... LL | *y = 2; - | ^^^^^^ use of possibly-uninitialized `y` + | ^^^^^^ `y` used here but it isn't initialized error: aborting due to previous error diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.stderr b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr index b9d51d21e9a..c96c59afc5a 100644 --- a/src/test/ui/unsized/box-instead-of-dyn-fn.stderr +++ b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr @@ -14,8 +14,8 @@ LL | | LL | | } | |_____- `if` and `else` have incompatible types | - = note: expected closure `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:32]` - found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:43]>` + = note: expected closure `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:16]` + found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:25]>` error[E0746]: return type cannot have an unboxed trait object --> $DIR/box-instead-of-dyn-fn.rs:5:56 diff --git a/src/test/ui/unsized/issue-91801.stderr b/src/test/ui/unsized/issue-91801.stderr index e8545149586..8795aa1687f 100644 --- a/src/test/ui/unsized/issue-91801.stderr +++ b/src/test/ui/unsized/issue-91801.stderr @@ -5,7 +5,7 @@ LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> -help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 12:6]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` +help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 10:70]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` | LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index c6c7b959d4f..4f49bb879f5 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind}; use rustc_errors::MultiSpan; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext, Level}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{FileName, Span}; use std::collections::BTreeMap; @@ -49,6 +49,7 @@ declare_clippy_lint! { struct Modules { local_path: PathBuf, spans: Vec<Span>, + lint_levels: Vec<Level>, } #[derive(Default)] @@ -70,13 +71,30 @@ impl EarlyLintPass for DuplicateMod { let modules = self.modules.entry(absolute_path).or_insert(Modules { local_path, spans: Vec::new(), + lint_levels: Vec::new(), }); modules.spans.push(item.span_with_attributes()); + modules.lint_levels.push(cx.get_lint_level(DUPLICATE_MOD)); } } fn check_crate_post(&mut self, cx: &EarlyContext<'_>, _: &Crate) { - for Modules { local_path, spans } in self.modules.values() { + for Modules { local_path, spans, lint_levels } in self.modules.values() { + if spans.len() < 2 { + continue; + } + + // At this point the lint would be emitted + assert_eq!(spans.len(), lint_levels.len()); + let spans: Vec<_> = spans.into_iter().zip(lint_levels).filter_map(|(span, lvl)|{ + if let Some(id) = lvl.get_expectation_id() { + cx.fulfill_expectation(id); + } + + (!matches!(lvl, Level::Allow | Level::Expect(_))).then_some(*span) + }) + .collect(); + if spans.len() < 2 { continue; } diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index f7a92bc0795..453471c8cdd 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -94,7 +94,7 @@ impl ExcessiveBools { fn check_fn_sig(&self, cx: &EarlyContext<'_>, fn_sig: &FnSig, span: Span) { match fn_sig.header.ext { - Extern::Implicit | Extern::Explicit(_) => return, + Extern::Implicit(_) | Extern::Explicit(_, _) => return, Extern::None => (), } diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 6d0b9a0f03f..eddca604575 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { // `arg` is a reference as it is `.deref()`ed in the previous block. // Look into the predecessor block and find out the source of deref. - let ps = &mir.predecessors()[bb]; + let ps = &mir.basic_blocks.predecessors()[bb]; if ps.len() != 1 { continue; } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 6487199172e..177e754ee09 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -600,8 +600,8 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { pub fn eq_ext(l: &Extern, r: &Extern) -> bool { use Extern::*; match (l, r) { - (None, None) | (Implicit, Implicit) => true, - (Explicit(l), Explicit(r)) => eq_str_lit(l, r), + (None, None) | (Implicit(_), Implicit(_)) => true, + (Explicit(l,_), Explicit(r,_)) => eq_str_lit(l, r), _ => false, } } diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/d.rs b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/d.rs new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/d.rs diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs index 79b343da247..99ca538b6e4 100644 --- a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs +++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs @@ -1,3 +1,5 @@ +#[feature(lint_reasons)] + mod a; mod b; @@ -13,4 +15,15 @@ mod c3; mod from_other_module; mod other_module; +mod d; +#[path = "d.rs"] +mod d2; +#[path = "d.rs"] +#[expect(clippy::duplicate_mod)] +mod d3; +#[path = "d.rs"] +#[allow(clippy::duplicate_mod)] +mod d4; + + fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr index 00d7739c8a2..61df1ad5d50 100644 --- a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr @@ -1,5 +1,5 @@ error: file is loaded as a module multiple times: `$DIR/b.rs` - --> $DIR/main.rs:3:1 + --> $DIR/main.rs:5:1 | LL | mod b; | ^^^^^^ first loaded here @@ -11,7 +11,7 @@ LL | | mod b2; = help: replace all but one `mod` item with `use` items error: file is loaded as a module multiple times: `$DIR/c.rs` - --> $DIR/main.rs:7:1 + --> $DIR/main.rs:9:1 | LL | mod c; | ^^^^^^ first loaded here @@ -25,7 +25,7 @@ LL | | mod c3; = help: replace all but one `mod` item with `use` items error: file is loaded as a module multiple times: `$DIR/from_other_module.rs` - --> $DIR/main.rs:13:1 + --> $DIR/main.rs:15:1 | LL | mod from_other_module; | ^^^^^^^^^^^^^^^^^^^^^^ first loaded here @@ -38,5 +38,16 @@ LL | | mod m; | = help: replace all but one `mod` item with `use` items -error: aborting due to 3 previous errors +error: file is loaded as a module multiple times: `$DIR/b.rs` + --> $DIR/main.rs:18:1 + | +LL | mod d; + | ^^^^^^ first loaded here +LL | / #[path = "d.rs"] +LL | | mod d2; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr index 77a3c2ba4ad..8da2965c635 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr @@ -33,7 +33,7 @@ LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> { | ^^^^^^^^^^^ expected `usize`, found closure | = note: expected type `usize` - found closure `[closure@$DIR/ice-6251.rs:4:44: 4:55]` + found closure `[closure@$DIR/ice-6251.rs:4:44: 4:53]` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr index a6a767483ed..a1e37e7317b 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr @@ -28,7 +28,7 @@ LL | const VAL: T; | ------------ `VAL` from trait ... LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation error: constant expression depends on a generic parameter --> $DIR/ice-6252.rs:13:9 diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index bab881f4b4e..8f35068e35f 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -148,7 +148,7 @@ impl<'a> Item<'a> { Item { unsafety: fm.unsafety, abi: format_extern( - ast::Extern::from_abi(fm.abi), + ast::Extern::from_abi(fm.abi, DUMMY_SP), config.force_explicit_abi(), true, ), diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 58fd95c656e..4b26f4e40df 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -138,8 +138,8 @@ pub(crate) fn format_extern( ) -> Cow<'static, str> { let abi = match ext { ast::Extern::None => "Rust".to_owned(), - ast::Extern::Implicit => "C".to_owned(), - ast::Extern::Explicit(abi) => abi.symbol_unescaped.to_string(), + ast::Extern::Implicit(_) => "C".to_owned(), + ast::Extern::Explicit(abi, _) => abi.symbol_unescaped.to_string(), }; if abi == "Rust" && !is_mod { |
