diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 6ecba865c8156..0a2a34d932f61 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -235,6 +235,34 @@ impl AttributeExt for Attribute { } } + fn deprecation_note(&self) -> Option { + match &self.kind { + AttrKind::Normal(normal) if normal.item.path == sym::deprecated => { + let meta = &normal.item; + + // #[deprecated = "..."] + if let Some(s) = meta.value_str() { + return Some(s); + } + + // #[deprecated(note = "...")] + if let Some(list) = meta.meta_item_list() { + for nested in list { + if let Some(mi) = nested.meta_item() + && mi.path == sym::note + && let Some(s) = mi.value_str() + { + return Some(s); + } + } + } + + None + } + _ => None, + } + } + fn doc_resolution_scope(&self) -> Option { match &self.kind { AttrKind::DocComment(..) => Some(self.style), @@ -277,6 +305,7 @@ impl Attribute { pub fn may_have_doc_links(&self) -> bool { self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str())) + || self.deprecation_note().is_some_and(|s| comments::may_have_doc_links(s.as_str())) } /// Extracts the MetaItem from inside this Attribute. @@ -873,6 +902,11 @@ pub trait AttributeExt: Debug { /// * `#[doc(...)]` returns `None`. fn doc_str(&self) -> Option; + /// Returns the deprecation note if this is deprecation attribute. + /// * `#[deprecated = "note"]` returns `Some("note")`. + /// * `#[deprecated(note = "note", ...)]` returns `Some("note")`. + fn deprecation_note(&self) -> Option; + fn is_proc_macro_attr(&self) -> bool { [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] .iter() diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index f6edcaa64dfef..be0a1d490da6a 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -312,7 +312,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir, AmbigArg>) { self.insert( - const_arg.as_unambig_ct().span(), + const_arg.as_unambig_ct().span, const_arg.hir_id, Node::ConstArg(const_arg.as_unambig_ct()), ); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e11e24c0263f4..a81d2297ef85b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2285,8 +2285,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `ExprKind::Paren(ExprKind::Underscore)` and should also be lowered to `GenericArg::Infer` match c.value.peel_parens().kind { ExprKind::Underscore => { - let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span), ()); - self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) + let ct_kind = hir::ConstArgKind::Infer(()); + self.arena.alloc(hir::ConstArg { + hir_id: self.lower_node_id(c.id), + kind: ct_kind, + span: self.lower_span(c.value.span), + }) } _ => self.lower_anon_const_to_const_arg_and_alloc(c), } @@ -2356,7 +2360,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::ConstArgKind::Anon(ct) }; - self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind }) + self.arena.alloc(hir::ConstArg { + hir_id: self.next_id(), + kind: ct_kind, + span: self.lower_span(span), + }) } fn lower_const_item_rhs( @@ -2373,9 +2381,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let const_arg = ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Error( - DUMMY_SP, self.dcx().span_delayed_bug(DUMMY_SP, "no block"), ), + span: DUMMY_SP, }; hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg)) } @@ -2388,13 +2396,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "debug", skip(self), ret)] fn lower_expr_to_const_arg_direct(&mut self, expr: &Expr) -> hir::ConstArg<'hir> { + let span = self.lower_span(expr.span); + let overly_complex_const = |this: &mut Self| { let e = this.dcx().struct_span_err( expr.span, "complex const arguments must be placed inside of a `const` block", ); - ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(expr.span, e.emit()) } + ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(e.emit()), span } }; match &expr.kind { @@ -2425,8 +2435,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::TupleCall(qpath, lowered_args), + span, } } + ExprKind::Tup(exprs) => { + let exprs = self.arena.alloc_from_iter(exprs.iter().map(|expr| { + let expr = if let ExprKind::ConstBlock(anon_const) = &expr.kind { + let def_id = self.local_def_id(anon_const.id); + let def_kind = self.tcx.def_kind(def_id); + assert_eq!(DefKind::AnonConst, def_kind); + + self.lower_anon_const_to_const_arg(anon_const) + } else { + self.lower_expr_to_const_arg_direct(&expr) + }; + + &*self.arena.alloc(expr) + })); + + ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Tup(exprs), span } + } ExprKind::Path(qself, path) => { let qpath = self.lower_qpath( expr.id, @@ -2439,7 +2467,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, ); - ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) } + ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath), span } } ExprKind::Struct(se) => { let path = self.lower_qpath( @@ -2480,11 +2508,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) })); - ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Struct(path, fields) } + ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Struct(path, fields), + span, + } } ExprKind::Underscore => ConstArg { hir_id: self.lower_node_id(expr.id), - kind: hir::ConstArgKind::Infer(expr.span, ()), + kind: hir::ConstArgKind::Infer(()), + span, }, ExprKind::Block(block, _) => { if let [stmt] = block.stmts.as_slice() @@ -2495,6 +2528,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | ExprKind::Path(..) | ExprKind::Struct(..) | ExprKind::Call(..) + | ExprKind::Tup(..) ) { return self.lower_expr_to_const_arg_direct(expr); @@ -2528,7 +2562,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return match anon.mgca_disambiguation { MgcaDisambiguation::AnonConst => { let lowered_anon = self.lower_anon_const_to_anon_const(anon); - ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon) } + ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Anon(lowered_anon), + span: lowered_anon.span, + } } MgcaDisambiguation::Direct => self.lower_expr_to_const_arg_direct(&anon.value), }; @@ -2565,11 +2603,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return ConstArg { hir_id: self.lower_node_id(anon.id), kind: hir::ConstArgKind::Path(qpath), + span: self.lower_span(expr.span), }; } let lowered_anon = self.lower_anon_const_to_anon_const(anon); - ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon) } + ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Anon(lowered_anon), + span: self.lower_span(expr.span), + } } /// See [`hir::ConstArg`] for when to use this function vs diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index f09bbb9c4972f..e066bce95158d 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -513,6 +513,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(self.arena.alloc(anon_const)), + span, }) } @@ -557,6 +558,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) }); let hir_id = self.next_id(); - self.arena.alloc(hir::ConstArg { kind: hir::ConstArgKind::Anon(ct), hir_id }) + self.arena.alloc(hir::ConstArg { kind: hir::ConstArgKind::Anon(ct), hir_id, span }) } } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index a637ae8184b4f..85cb7499cca4e 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -1,4 +1,7 @@ -codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend. Did you install it via rustup? +codegen_llvm_autodiff_component_missing = autodiff backend not found in the sysroot: {$err} + .note = it will be distributed via rustup in the future + +codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend: {$err} codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable codegen_llvm_autodiff_without_lto = using the autodiff feature requires setting `lto="fat"` in your Cargo.toml diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index c73140e041b60..bd42cf5569664 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -34,7 +34,16 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { #[derive(Diagnostic)] #[diag(codegen_llvm_autodiff_component_unavailable)] -pub(crate) struct AutoDiffComponentUnavailable; +pub(crate) struct AutoDiffComponentUnavailable { + pub err: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_llvm_autodiff_component_missing)] +#[note] +pub(crate) struct AutoDiffComponentMissing { + pub err: String, +} #[derive(Diagnostic)] #[diag(codegen_llvm_autodiff_without_lto)] diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 0952747449932..438a74e0a0912 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -249,8 +249,14 @@ impl CodegenBackend for LlvmCodegenBackend { use crate::back::lto::enable_autodiff_settings; if sess.opts.unstable_opts.autodiff.contains(&AutoDiff::Enable) { - if let Err(_) = llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) { - sess.dcx().emit_fatal(crate::errors::AutoDiffComponentUnavailable); + match llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) { + Ok(_) => {} + Err(llvm::EnzymeLibraryError::NotFound { err }) => { + sess.dcx().emit_fatal(crate::errors::AutoDiffComponentMissing { err }); + } + Err(llvm::EnzymeLibraryError::LoadFailed { err }) => { + sess.dcx().emit_fatal(crate::errors::AutoDiffComponentUnavailable { err }); + } } enable_autodiff_settings(&sess.opts.unstable_opts.autodiff); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index b11310b970d03..67fbc0f53adc9 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -153,7 +153,7 @@ pub(crate) mod Enzyme_AD { fn load_ptr_by_symbol_mut_void( lib: &libloading::Library, bytes: &[u8], - ) -> Result<*mut c_void, Box> { + ) -> Result<*mut c_void, libloading::Error> { unsafe { let s: libloading::Symbol<'_, *mut c_void> = lib.get(bytes)?; // libloading = 0.9.0: try_as_raw_ptr always succeeds and returns Some @@ -192,15 +192,27 @@ pub(crate) mod Enzyme_AD { static ENZYME_INSTANCE: OnceLock> = OnceLock::new(); + #[derive(Debug)] + pub(crate) enum EnzymeLibraryError { + NotFound { err: String }, + LoadFailed { err: String }, + } + + impl From for EnzymeLibraryError { + fn from(err: libloading::Error) -> Self { + Self::LoadFailed { err: format!("{err:?}") } + } + } + impl EnzymeWrapper { /// Initialize EnzymeWrapper with the given sysroot if not already initialized. /// Safe to call multiple times - subsequent calls are no-ops due to OnceLock. pub(crate) fn get_or_init( sysroot: &rustc_session::config::Sysroot, - ) -> Result, Box> { + ) -> Result, EnzymeLibraryError> { let mtx: &'static Mutex = ENZYME_INSTANCE.get_or_try_init(|| { let w = Self::call_dynamic(sysroot)?; - Ok::<_, Box>(Mutex::new(w)) + Ok::<_, EnzymeLibraryError>(Mutex::new(w)) })?; Ok(mtx.lock().unwrap()) @@ -351,7 +363,7 @@ pub(crate) mod Enzyme_AD { #[allow(non_snake_case)] fn call_dynamic( sysroot: &rustc_session::config::Sysroot, - ) -> Result> { + ) -> Result { let enzyme_path = Self::get_enzyme_path(sysroot)?; let lib = unsafe { libloading::Library::new(enzyme_path)? }; @@ -416,7 +428,7 @@ pub(crate) mod Enzyme_AD { }) } - fn get_enzyme_path(sysroot: &Sysroot) -> Result { + fn get_enzyme_path(sysroot: &Sysroot) -> Result { let llvm_version_major = unsafe { LLVMRustVersionMajor() }; let path_buf = sysroot @@ -434,15 +446,19 @@ pub(crate) mod Enzyme_AD { .map(|p| p.join("lib").display().to_string()) .collect::>() .join("\n* "); - format!( - "failed to find a `libEnzyme-{llvm_version_major}` folder \ + EnzymeLibraryError::NotFound { + err: format!( + "failed to find a `libEnzyme-{llvm_version_major}` folder \ in the sysroot candidates:\n* {candidates}" - ) + ), + } })?; Ok(path_buf .to_str() - .ok_or_else(|| format!("invalid UTF-8 in path: {}", path_buf.display()))? + .ok_or_else(|| EnzymeLibraryError::LoadFailed { + err: format!("invalid UTF-8 in path: {}", path_buf.display()), + })? .to_string()) } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 8ab0b367f08a6..c8aa7c04585c8 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -6,7 +6,8 @@ use std::time::{Duration, Instant}; use itertools::Itertools; use rustc_abi::FIRST_VARIANT; use rustc_ast::expand::allocator::{ - ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorMethod, AllocatorTy, + ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorMethod, AllocatorMethodInput, + AllocatorTy, }; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; @@ -671,7 +672,7 @@ pub fn allocator_shim_contents(tcx: TyCtxt<'_>, kind: AllocatorKind) -> Vec ConstItemRhs<'hir> { pub fn span<'tcx>(&self, tcx: impl crate::intravisit::HirTyCtxt<'tcx>) -> Span { match self { ConstItemRhs::Body(body_id) => tcx.hir_body(*body_id).value.span, - ConstItemRhs::TypeConst(ct_arg) => ct_arg.span(), + ConstItemRhs::TypeConst(ct_arg) => ct_arg.span, } } } @@ -447,6 +447,7 @@ pub struct ConstArg<'hir, Unambig = ()> { #[stable_hasher(ignore)] pub hir_id: HirId, pub kind: ConstArgKind<'hir, Unambig>, + pub span: Span, } impl<'hir> ConstArg<'hir, AmbigArg> { @@ -475,7 +476,7 @@ impl<'hir> ConstArg<'hir> { /// Functions accepting ambiguous consts will not handle the [`ConstArgKind::Infer`] variant, if /// infer consts are relevant to you then care should be taken to handle them separately. pub fn try_as_ambig_ct(&self) -> Option<&ConstArg<'hir, AmbigArg>> { - if let ConstArgKind::Infer(_, ()) = self.kind { + if let ConstArgKind::Infer(()) = self.kind { return None; } @@ -494,23 +495,13 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> { _ => None, } } - - pub fn span(&self) -> Span { - match self.kind { - ConstArgKind::Struct(path, _) => path.span(), - ConstArgKind::Path(path) => path.span(), - ConstArgKind::TupleCall(path, _) => path.span(), - ConstArgKind::Anon(anon) => anon.span, - ConstArgKind::Error(span, _) => span, - ConstArgKind::Infer(span, _) => span, - } - } } /// See [`ConstArg`]. #[derive(Clone, Copy, Debug, HashStable_Generic)] #[repr(u8, C)] pub enum ConstArgKind<'hir, Unambig = ()> { + Tup(&'hir [&'hir ConstArg<'hir, Unambig>]), /// **Note:** Currently this is only used for bare const params /// (`N` where `fn foo(...)`), /// not paths to any const (`N` where `const N: usize = ...`). @@ -523,10 +514,10 @@ pub enum ConstArgKind<'hir, Unambig = ()> { /// Tuple constructor variant TupleCall(QPath<'hir>, &'hir [&'hir ConstArg<'hir>]), /// Error const - Error(Span, ErrorGuaranteed), + Error(ErrorGuaranteed), /// This variant is not always used to represent inference consts, sometimes /// [`GenericArg::Infer`] is used instead. - Infer(Span, Unambig), + Infer(Unambig), } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -572,7 +563,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.ident.span, GenericArg::Type(t) => t.span, - GenericArg::Const(c) => c.span(), + GenericArg::Const(c) => c.span, GenericArg::Infer(i) => i.span, } } @@ -1409,6 +1400,14 @@ impl AttributeExt for Attribute { } } + #[inline] + fn deprecation_note(&self) -> Option { + match &self { + Attribute::Parsed(AttributeKind::Deprecation { deprecation, .. }) => deprecation.note, + _ => None, + } + } + fn is_automatically_derived_attr(&self) -> bool { matches!(self, Attribute::Parsed(AttributeKind::AutomaticallyDerived(..))) } diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index 4f9609fd360d7..2ac33a369cbdd 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -24,12 +24,16 @@ define_tests! { cast_ptr TyKind Ptr { 0: MutTy { ty: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, mutbl: Mutability::Not }} cast_array TyKind Array { 0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, - 1: &ConstArg { hir_id: HirId::INVALID, kind: ConstArgKind::Anon(&AnonConst { + 1: &ConstArg { hir_id: HirId::INVALID, - def_id: LocalDefId { local_def_index: DefIndex::ZERO }, - body: BodyId { hir_id: HirId::INVALID }, + kind: ConstArgKind::Anon(&AnonConst { + hir_id: HirId::INVALID, + def_id: LocalDefId { local_def_index: DefIndex::ZERO }, + body: BodyId { hir_id: HirId::INVALID }, + span: DUMMY_SP, + }), span: DUMMY_SP, - })} + }, } cast_anon ConstArgKind Anon { diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 853e7db0757a4..59db60fdc55c4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1068,8 +1068,8 @@ pub fn walk_unambig_const_arg<'v, V: Visitor<'v>>( match const_arg.try_as_ambig_ct() { Some(ambig_ct) => visitor.visit_const_arg(ambig_ct), None => { - let ConstArg { hir_id, kind: _ } = const_arg; - visitor.visit_infer(*hir_id, const_arg.span(), InferKind::Const(const_arg)) + let ConstArg { hir_id, kind: _, span } = const_arg; + visitor.visit_infer(*hir_id, *span, InferKind::Const(const_arg)) } } } @@ -1078,9 +1078,13 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( visitor: &mut V, const_arg: &'v ConstArg<'v, AmbigArg>, ) -> V::Result { - let ConstArg { hir_id, kind } = const_arg; + let ConstArg { hir_id, kind, span: _ } = const_arg; try_visit!(visitor.visit_id(*hir_id)); match kind { + ConstArgKind::Tup(exprs) => { + walk_list!(visitor, visit_const_arg, *exprs); + V::Result::output() + } ConstArgKind::Struct(qpath, field_exprs) => { try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span())); @@ -1099,7 +1103,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( } ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()), ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), - ConstArgKind::Error(_, _) => V::Result::output(), // errors and spans are not important + ConstArgKind::Error(_) => V::Result::output(), // errors and spans are not important } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9343bcd27a339..bacdf0049806e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1479,23 +1479,27 @@ fn rendered_precise_capturing_args<'tcx>( fn const_param_default<'tcx>( tcx: TyCtxt<'tcx>, - def_id: LocalDefId, + local_def_id: LocalDefId, ) -> ty::EarlyBinder<'tcx, Const<'tcx>> { let hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { default: Some(default_ct), .. }, .. - }) = tcx.hir_node_by_def_id(def_id) + }) = tcx.hir_node_by_def_id(local_def_id) else { span_bug!( - tcx.def_span(def_id), + tcx.def_span(local_def_id), "`const_param_default` expected a generic parameter with a constant" ) }; - let icx = ItemCtxt::new(tcx, def_id); - let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); + + let icx = ItemCtxt::new(tcx, local_def_id); + + let def_id = local_def_id.to_def_id(); + let identity_args = ty::GenericArgs::identity_for_item(tcx, tcx.parent(def_id)); + let ct = icx .lowerer() - .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args)); + .lower_const_arg(default_ct, FeedConstTy::with_type_of(tcx, def_id, identity_args)); ty::EarlyBinder::bind(ct) } @@ -1553,7 +1557,7 @@ fn const_of_item<'tcx>( let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let ct = icx .lowerer() - .lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args)); + .lower_const_arg(ct_arg, FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args)); if let Err(e) = icx.check_tainted_by_errors() && !ct.references_error() { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 51c6649218045..92b77a2042b18 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -381,7 +381,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { let span = match term { hir::Term::Ty(ty) => ty.span, - hir::Term::Const(ct) => ct.span(), + hir::Term::Const(ct) => ct.span, }; (span, Some(ident.span), assoc_item.as_tag(), assoc_tag) } else { @@ -1466,7 +1466,7 @@ pub fn prohibit_assoc_item_constraint( hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) }, GenericParamDefKind::Const { .. }, ) => { - suggest_direct_use(&mut err, c.span()); + suggest_direct_use(&mut err, c.span); } (hir::AssocItemConstraintKind::Bound { bounds }, _) => { // Suggest `impl Trait for Foo` when finding diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a22729fd287e2..aaa566760013c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -259,17 +259,26 @@ impl AssocItemQSelf { /// Use this enum with `::lower_const_arg` to instruct it with the /// desired behavior. #[derive(Debug, Clone, Copy)] -pub enum FeedConstTy<'a, 'tcx> { - /// Feed the type. - /// +pub enum FeedConstTy<'tcx> { + /// Feed the type to the (anno) const arg. + WithTy(Ty<'tcx>), + /// Don't feed the type. + No, +} + +impl<'tcx> FeedConstTy<'tcx> { /// The `DefId` belongs to the const param that we are supplying /// this (anon) const arg to. /// /// The list of generic args is used to instantiate the parameters /// used by the type of the const param specified by `DefId`. - Param(DefId, &'a [ty::GenericArg<'tcx>]), - /// Don't feed the type. - No, + pub fn with_type_of( + tcx: TyCtxt<'tcx>, + def_id: DefId, + generic_args: &[ty::GenericArg<'tcx>], + ) -> Self { + Self::WithTy(tcx.type_of(def_id).instantiate(tcx, generic_args)) + } } #[derive(Debug, Clone, Copy)] @@ -723,7 +732,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Ambig portions of `ConstArg` are handled in the match arm below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::Param(param.def_id, preceding_args), + FeedConstTy::with_type_of(tcx, param.def_id, preceding_args), ) .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { @@ -2303,15 +2312,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn lower_const_arg( &self, const_arg: &hir::ConstArg<'tcx>, - feed: FeedConstTy<'_, 'tcx>, + feed: FeedConstTy<'tcx>, ) -> Const<'tcx> { let tcx = self.tcx(); - if let FeedConstTy::Param(param_def_id, args) = feed + if let FeedConstTy::WithTy(anon_const_type) = feed && let hir::ConstArgKind::Anon(anon) = &const_arg.kind { - let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args); - // FIXME(generic_const_parameter_types): Ideally we remove these errors below when // we have the ability to intermix typeck of anon const const args with the parent // bodies typeck. @@ -2324,7 +2331,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions()) { let e = self.dcx().span_err( - const_arg.span(), + const_arg.span, "anonymous constants with lifetimes in their type are not yet supported", ); tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e))); @@ -2335,7 +2342,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // variables otherwise we will ICE. if anon_const_type.has_non_region_infer() { let e = self.dcx().span_err( - const_arg.span(), + const_arg.span, "anonymous constants with inferred types are not yet supported", ); tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e))); @@ -2345,21 +2352,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // give the anon const any of the generics from the parent. if anon_const_type.has_non_region_param() { let e = self.dcx().span_err( - const_arg.span(), + const_arg.span, "anonymous constants referencing generics are not yet supported", ); tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e))); return ty::Const::new_error(tcx, e); } - tcx.feed_anon_const_type( - anon.def_id, - ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)), - ); + tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(anon_const_type)); } let hir_id = const_arg.hir_id; match const_arg.kind { + hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, feed, const_arg.span), hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself)); @@ -2373,19 +2378,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_self_ty, segment, hir_id, - const_arg.span(), + const_arg.span, ) .unwrap_or_else(|guar| Const::new_error(tcx, guar)) } hir::ConstArgKind::Struct(qpath, inits) => { - self.lower_const_arg_struct(hir_id, qpath, inits, const_arg.span()) + self.lower_const_arg_struct(hir_id, qpath, inits, const_arg.span) } hir::ConstArgKind::TupleCall(qpath, args) => { - self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span()) + self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span) } hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon), - hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span), - hir::ConstArgKind::Error(_, e) => ty::Const::new_error(tcx, e), + hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span), + hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e), } } @@ -2464,7 +2469,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .zip(args) .map(|(field_def, arg)| { - self.lower_const_arg(arg, FeedConstTy::Param(field_def.did, adt_args)) + self.lower_const_arg(arg, FeedConstTy::with_type_of(tcx, field_def.did, adt_args)) }) .collect::>(); @@ -2480,6 +2485,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Const::new_value(tcx, valtree, adt_ty) } + fn lower_const_arg_tup( + &self, + exprs: &'tcx [&'tcx hir::ConstArg<'tcx>], + feed: FeedConstTy<'tcx>, + span: Span, + ) -> Const<'tcx> { + let tcx = self.tcx(); + + let FeedConstTy::WithTy(ty) = feed else { + return Const::new_error_with_message(tcx, span, "unsupported const tuple"); + }; + + let ty::Tuple(tys) = ty.kind() else { + return Const::new_error_with_message(tcx, span, "const tuple must have a tuple type"); + }; + + let exprs = exprs + .iter() + .zip(tys.iter()) + .map(|(expr, ty)| self.lower_const_arg(expr, FeedConstTy::WithTy(ty))) + .collect::>(); + + let valtree = ty::ValTree::from_branches(tcx, exprs); + ty::Const::new_value(tcx, valtree, ty) + } + fn lower_const_arg_struct( &self, hir_id: HirId, @@ -2558,7 +2589,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return ty::Const::new_error(tcx, e); } - self.lower_const_arg(expr.expr, FeedConstTy::Param(field_def.did, adt_args)) + self.lower_const_arg( + expr.expr, + FeedConstTy::with_type_of(tcx, field_def.did, adt_args), + ) } None => { let e = tcx.dcx().span_err( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 65f6a11e8e9b9..7296ba6f964a4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -301,7 +301,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { pub fn lower_const_arg_for_rustdoc<'tcx>( tcx: TyCtxt<'tcx>, hir_ct: &hir::ConstArg<'tcx>, - feed: FeedConstTy<'_, 'tcx>, + feed: FeedConstTy<'tcx>, ) -> Const<'tcx> { let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id); collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 932e78958345c..2c160ccef2b62 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1141,11 +1141,21 @@ impl<'a> State<'a> { fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) { match &const_arg.kind { + ConstArgKind::Tup(exprs) => { + self.popen(); + self.commasep_cmnt( + Inconsistent, + exprs, + |s, arg| s.print_const_arg(arg), + |arg| arg.span, + ); + self.pclose(); + } ConstArgKind::Struct(qpath, fields) => self.print_const_struct(qpath, fields), ConstArgKind::TupleCall(qpath, args) => self.print_const_ctor(qpath, args), ConstArgKind::Path(qpath) => self.print_qpath(qpath, true), ConstArgKind::Anon(anon) => self.print_anon_const(anon), - ConstArgKind::Error(_, _) => self.word("/*ERROR*/"), + ConstArgKind::Error(_) => self.word("/*ERROR*/"), ConstArgKind::Infer(..) => self.word("_"), } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index c4fa39c6c2c84..9d7e09b020a75 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1705,7 +1705,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind { - let span = ct.span(); + let span = ct.span; self.dcx().try_steal_modify_and_emit_err( span, StashKey::UnderscoreForArrayLengths, @@ -1746,7 +1746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let count_span = count.span(); + let count_span = count.span; let count = self.try_structurally_resolve_const( count_span, self.normalize(count_span, self.lower_const_arg(count, FeedConstTy::No)), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 339e77ac6edd6..a66ff2a23c250 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -525,7 +525,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, - feed: FeedConstTy<'_, 'tcx>, + feed: FeedConstTy<'tcx>, ) -> ty::Const<'tcx> { let ct = self.lowerer().lower_const_arg(const_arg, feed); self.register_wf_obligation( @@ -1228,7 +1228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Ambiguous parts of `ConstArg` are handled in the match arms below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::Param(param.def_id, preceding_args), + FeedConstTy::with_type_of(self.fcx.tcx, param.def_id, preceding_args), ) .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index e81537008bb5e..aab4e39855557 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -447,7 +447,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We handle the ambig portions of `ConstArg` in the match arms below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::Param(param.def_id, preceding_args), + FeedConstTy::with_type_of(self.cfcx.tcx, param.def_id, preceding_args), ) .into(), (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 29006732aade5..f4a506d50a41b 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -74,12 +74,9 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String { GenericArg::Type(ty) => { cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into()) } - GenericArg::Const(c) => cx - .tcx - .sess - .source_map() - .span_to_snippet(c.span()) - .unwrap_or_else(|_| "_".into()), + GenericArg::Const(c) => { + cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_else(|_| "_".into()) + } GenericArg::Infer(_) => String::from("_"), }) .collect::>(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d79ab9eaf7597..d0e8bc50c4957 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1442,6 +1442,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ConstArgKind::Error(..) | hir::ConstArgKind::Struct(..) | hir::ConstArgKind::TupleCall(..) + | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true, hir::ConstArgKind::Anon(..) => false, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 8cc66802e4353..ca783311586f1 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1003,7 +1003,7 @@ impl<'tcx> TyCtxt<'tcx> { Node::Field(field) => field.span, Node::AnonConst(constant) => constant.span, Node::ConstBlock(constant) => self.hir_body(constant.body).value.span, - Node::ConstArg(const_arg) => const_arg.span(), + Node::ConstArg(const_arg) => const_arg.span, Node::Expr(expr) => expr.span, Node::ExprField(field) => field.span, Node::ConstArgExprField(field) => field.span, diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index a46fcd30fef40..62e97c0c308c1 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2666,7 +2666,6 @@ fn look_ahead_non_outermost_stream() { }); } -// FIXME(nnethercote) All the output is currently wrong. #[test] fn debug_lookahead() { create_default_session_globals_then(|| { diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index f7b85453448c4..b392b7747b554 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -419,7 +419,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { // Avoid overwriting `const_arg_context` as we may want to treat const blocks // as being anon consts if we are inside a const argument. - ExprKind::Struct(_) | ExprKind::Call(..) => return visit::walk_expr(self, expr), + ExprKind::Struct(_) | ExprKind::Call(..) | ExprKind::Tup(..) => { + return visit::walk_expr(self, expr); + } // FIXME(mgca): we may want to handle block labels in some manner ExprKind::Block(block, _) if let [stmt] = block.stmts.as_slice() => match stmt.kind { // FIXME(mgca): this probably means that mac calls that expand diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 7f7c423acb40a..9f74a7801d2ee 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -410,8 +410,17 @@ pub fn may_be_doc_link(link_type: LinkType) -> bool { /// Simplified version of `preprocessed_markdown_links` from rustdoc. /// Must return at least the same links as it, but may add some more links on top of that. pub(crate) fn attrs_to_preprocessed_links(attrs: &[A]) -> Vec> { - let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true); - let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap(); + let (doc_fragments, other_attrs) = + attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), false); + let mut doc = + prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap_or_default(); + + for attr in other_attrs { + if let Some(note) = attr.deprecation_note() { + doc += note.as_str(); + doc += "\n"; + } + } parse_links(&doc) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index cea69c6996281..47810e2578df6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1879,7 +1879,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some(length_val) = sz.found.try_to_target_usize(self.tcx) { Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { - span: length_arg.span(), + span: length_arg.span, length: length_val, }) } else { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 889fd4cd65df5..1bca13b14ed4c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4809,8 +4809,6 @@ impl [T] { /// # Examples /// Basic usage: /// ``` - /// #![feature(substr_range)] - /// /// let nums: &[u32] = &[1, 7, 1, 1]; /// let num = &nums[2]; /// @@ -4819,8 +4817,6 @@ impl [T] { /// ``` /// Returning `None` with an unaligned element: /// ``` - /// #![feature(substr_range)] - /// /// let arr: &[[u32; 2]] = &[[0, 1], [2, 3]]; /// let flat_arr: &[u32] = arr.as_flattened(); /// @@ -4834,7 +4830,7 @@ impl [T] { /// assert_eq!(arr.element_offset(weird_elm), None); // Points between element 0 and 1 /// ``` #[must_use] - #[unstable(feature = "substr_range", issue = "126769")] + #[stable(feature = "element_offset", since = "CURRENT_RUSTC_VERSION")] pub fn element_offset(&self, element: &T) -> Option { if T::IS_ZST { panic!("elements are zero-sized"); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8de3722fa69d4..e05d3e4164306 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -326,6 +326,10 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind hir::ConstArgKind::TupleCall(..) => { ConstantKind::Path { path: "/* TUPLE CALL */".to_string().into() } } + hir::ConstArgKind::Tup(..) => { + // FIXME(mgca): proper printing :3 + ConstantKind::Path { path: "/* TUPLE EXPR */".to_string().into() } + } hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer, } @@ -1809,7 +1813,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } hir::ConstArgKind::Struct(..) | hir::ConstArgKind::Path(..) - | hir::ConstArgKind::TupleCall(..) => { + | hir::ConstArgKind::TupleCall(..) + | hir::ConstArgKind::Tup(..) => { let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); print_const(cx, ct) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a390a03ff1144..c3bafd3db13ac 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -7,6 +7,7 @@ use std::{fmt, iter}; use arrayvec::ArrayVec; use itertools::Either; use rustc_abi::{ExternAbi, VariantIdx}; +use rustc_ast::attr::AttributeExt; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation, DocAttribute}; @@ -450,7 +451,16 @@ impl Item { } pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span { + let deprecation_notes = self + .attrs + .other_attrs + .iter() + .filter_map(|attr| attr.deprecation_note().map(|_| attr.span())); + span_of_fragments(&self.attrs.doc_strings) + .into_iter() + .chain(deprecation_notes) + .reduce(|a, b| a.to(b)) .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner())) } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a4d377432c914..c472c20a7dc71 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -111,7 +111,11 @@ pub(crate) struct MarkdownWithToc<'a> { } /// A tuple struct like `Markdown` that renders the markdown escaping HTML tags /// and includes no paragraph tags. -pub(crate) struct MarkdownItemInfo<'a>(pub(crate) &'a str, pub(crate) &'a mut IdMap); +pub(crate) struct MarkdownItemInfo<'a> { + pub(crate) content: &'a str, + pub(crate) links: &'a [RenderedLink], + pub(crate) ids: &'a mut IdMap, +} /// A tuple struct like `Markdown` that renders only the first paragraph. pub(crate) struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [RenderedLink]); @@ -1459,15 +1463,28 @@ impl MarkdownWithToc<'_> { } } -impl MarkdownItemInfo<'_> { +impl<'a> MarkdownItemInfo<'a> { + pub(crate) fn new(content: &'a str, links: &'a [RenderedLink], ids: &'a mut IdMap) -> Self { + Self { content, links, ids } + } + pub(crate) fn write_into(self, mut f: impl fmt::Write) -> fmt::Result { - let MarkdownItemInfo(md, ids) = self; + let MarkdownItemInfo { content: md, links, ids } = self; // This is actually common enough to special-case if md.is_empty() { return Ok(()); } - let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); + + let replacer = move |broken_link: BrokenLink<'_>| { + links + .iter() + .find(|link| *link.original_text == *broken_link.reference) + .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) + }; + + let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(replacer)); + let p = p.into_offset_iter(); // Treat inline HTML as plain text. let p = p.map(|event| match event.0 { @@ -1477,6 +1494,7 @@ impl MarkdownItemInfo<'_> { ids.handle_footnotes(|ids, existing_footnotes| { let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1); + let p = SpannedLinkReplacer::new(p, links); let p = footnotes::Footnotes::new(p, existing_footnotes); let p = TableWrapper::new(p.map(|(ev, _)| ev)); let p = p.filter(|event| { diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 61fd428746332..1c99ccc5228b1 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -471,7 +471,7 @@ fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { let mut idmap = IdMap::new(); let mut output = String::new(); - MarkdownItemInfo(input, &mut idmap).write_into(&mut output).unwrap(); + MarkdownItemInfo::new(input, &[], &mut idmap).write_into(&mut output).unwrap(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 4529f5a8c0163..63de870f07f45 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -877,7 +877,8 @@ fn short_item_info( if let Some(note) = note { let note = note.as_str(); let mut id_map = cx.id_map.borrow_mut(); - let html = MarkdownItemInfo(note, &mut id_map); + let links = item.links(cx); + let html = MarkdownItemInfo::new(note, &links, &mut id_map); message.push_str(": "); html.write_into(&mut message).unwrap(); } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3abf0fee3959a..07d6efaa97e15 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -7,6 +7,7 @@ use std::fmt::Display; use std::mem; use std::ops::Range; +use rustc_ast::attr::AttributeExt; use rustc_ast::util::comments::may_have_doc_links; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -1047,18 +1048,7 @@ impl LinkCollector<'_, '_> { return; } - // We want to resolve in the lexical scope of the documentation. - // In the presence of re-exports, this is not the same as the module of the item. - // Rather than merging all documentation into one, resolve it one attribute at a time - // so we know which module it came from. - for (item_id, doc) in prepare_to_doc_link_resolution(&item.attrs.doc_strings) { - if !may_have_doc_links(&doc) { - continue; - } - debug!("combined_docs={doc}"); - // NOTE: if there are links that start in one crate and end in another, this will not resolve them. - // This is a degenerate case and it's not supported by rustdoc. - let item_id = item_id.unwrap_or_else(|| item.item_id.expect_def_id()); + let mut insert_links = |item_id, doc: &str| { let module_id = match self.cx.tcx.def_kind(item_id) { DefKind::Mod if item.inner_docs(self.cx.tcx) => item_id, _ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(), @@ -1074,6 +1064,35 @@ impl LinkCollector<'_, '_> { .insert(link); } } + }; + + // We want to resolve in the lexical scope of the documentation. + // In the presence of re-exports, this is not the same as the module of the item. + // Rather than merging all documentation into one, resolve it one attribute at a time + // so we know which module it came from. + for (item_id, doc) in prepare_to_doc_link_resolution(&item.attrs.doc_strings) { + if !may_have_doc_links(&doc) { + continue; + } + + debug!("combined_docs={doc}"); + // NOTE: if there are links that start in one crate and end in another, this will not resolve them. + // This is a degenerate case and it's not supported by rustdoc. + let item_id = item_id.unwrap_or_else(|| item.item_id.expect_def_id()); + insert_links(item_id, &doc) + } + + // Also resolve links in the note text of `#[deprecated]`. + for attr in &item.attrs.other_attrs { + let Some(note_sym) = attr.deprecation_note() else { continue }; + let note = note_sym.as_str(); + + if !may_have_doc_links(note) { + continue; + } + + debug!("deprecated_note={note}"); + insert_links(item.item_id.expect_def_id(), note) } } @@ -1086,7 +1105,7 @@ impl LinkCollector<'_, '_> { /// FIXME(jynelson): this is way too many arguments fn resolve_link( &mut self, - dox: &String, + dox: &str, item: &Item, item_id: DefId, module_id: DefId, diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 620e27fa67c62..261b03abba171 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -126,7 +126,7 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { let ExprKind::Repeat(_, len_ct) = expr.kind else { return false; }; - !expr.span.contains(len_ct.span()) + !expr.span.contains(len_ct.span) } expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr) diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index f515f9987a802..455f76edc9047 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -321,6 +321,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { }, ConstArgKind::Struct(..) => chain!(self, "let ConstArgKind::Struct(..) = {const_arg}.kind"), ConstArgKind::TupleCall(..) => chain!(self, "let ConstArgKind::TupleCall(..) = {const_arg}.kind"), + ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"), ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index a44cd31dc1233..46b87fd5df961 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1140,7 +1140,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value), ConstItemRhs::TypeConst(const_arg) => match const_arg.kind { ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), - ConstArgKind::Struct(..) | ConstArgKind::TupleCall(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => { + ConstArgKind::Struct(..) | ConstArgKind::TupleCall(..) | ConstArgKind::Tup(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => { None }, }, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f1ee534c500d3..57c896c971722 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -661,6 +661,10 @@ impl HirEqInterExpr<'_, '_, '_> { } fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool { + if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) { + return false; + } + match (&left.kind, &right.kind) { (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), @@ -679,11 +683,18 @@ impl HirEqInterExpr<'_, '_, '_> { .zip(*args_b) .all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b)) } + (ConstArgKind::Tup(args_a), ConstArgKind::Tup(args_b)) => { + args_a + .iter() + .zip(*args_b) + .all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b)) + } // Use explicit match for now since ConstArg is undergoing flux. ( ConstArgKind::Path(..) | ConstArgKind::Anon(..) | ConstArgKind::TupleCall(..) + | ConstArgKind::Tup(..) | ConstArgKind::Infer(..) | ConstArgKind::Struct(..) | ConstArgKind::Error(..), @@ -1560,6 +1571,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_const_arg(arg); } }, + ConstArgKind::Tup(args) => { + for arg in *args { + self.hash_const_arg(arg); + } + }, ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {}, } } diff --git a/tests/crashes/133965.rs b/tests/crashes/133965.rs deleted file mode 100644 index 69f533ccbe987..0000000000000 --- a/tests/crashes/133965.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #133965 -//@ needs-rustc-debug-assertions - -struct NonGeneric {} - -#[derive(Default)] -struct NonGeneric<'a, const N: usize> {} - -pub fn main() {} diff --git a/tests/incremental/const-generic-type-cycle.rs b/tests/incremental/const-generic-type-cycle.rs index 40a40ebd13fe5..5bcbc1d5dafef 100644 --- a/tests/incremental/const-generic-type-cycle.rs +++ b/tests/incremental/const-generic-type-cycle.rs @@ -14,7 +14,6 @@ trait Bar {} trait Bar {} //[cfail]~^ ERROR cycle detected when computing type of `Bar::N` //[cfail]~| ERROR cycle detected when computing type of `Bar::N` -//[cfail]~| ERROR cycle detected when computing type of `Bar::N` //[cfail]~| ERROR `(dyn Bar<{ 2 + 1 }> + 'static)` is forbidden as the type of a const generic parameter trait BB = Bar<{ 2 + 1 }>; diff --git a/tests/rustdoc-ui/intra-doc/deprecated.rs b/tests/rustdoc-ui/intra-doc/deprecated.rs new file mode 100644 index 0000000000000..37c27dcde598a --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/deprecated.rs @@ -0,0 +1,10 @@ +#![deny(rustdoc::broken_intra_doc_links)] + +#[deprecated = "[broken cross-reference](TypeAlias::hoge)"] //~ ERROR +pub struct A; + +#[deprecated(since = "0.0.0", note = "[broken cross-reference](TypeAlias::hoge)")] //~ ERROR +pub struct B1; + +#[deprecated(note = "[broken cross-reference](TypeAlias::hoge)", since = "0.0.0")] //~ ERROR +pub struct B2; diff --git a/tests/rustdoc-ui/intra-doc/deprecated.stderr b/tests/rustdoc-ui/intra-doc/deprecated.stderr new file mode 100644 index 0000000000000..9bd64544eef82 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/deprecated.stderr @@ -0,0 +1,43 @@ +error: unresolved link to `TypeAlias::hoge` + --> $DIR/deprecated.rs:3:1 + | +LL | #[deprecated = "[broken cross-reference](TypeAlias::hoge)"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + [broken cross-reference](TypeAlias::hoge) + ^^^^^^^^^^^^^^^ + = note: no item named `TypeAlias` in scope +note: the lint level is defined here + --> $DIR/deprecated.rs:1:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unresolved link to `TypeAlias::hoge` + --> $DIR/deprecated.rs:6:1 + | +LL | #[deprecated(since = "0.0.0", note = "[broken cross-reference](TypeAlias::hoge)")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + [broken cross-reference](TypeAlias::hoge) + ^^^^^^^^^^^^^^^ + = note: no item named `TypeAlias` in scope + +error: unresolved link to `TypeAlias::hoge` + --> $DIR/deprecated.rs:9:1 + | +LL | #[deprecated(note = "[broken cross-reference](TypeAlias::hoge)", since = "0.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + [broken cross-reference](TypeAlias::hoge) + ^^^^^^^^^^^^^^^ + = note: no item named `TypeAlias` in scope + +error: aborting due to 3 previous errors + diff --git a/tests/rustdoc/intra-doc/deprecated.rs b/tests/rustdoc/intra-doc/deprecated.rs new file mode 100644 index 0000000000000..6f8639593a2d4 --- /dev/null +++ b/tests/rustdoc/intra-doc/deprecated.rs @@ -0,0 +1,12 @@ +//@ has deprecated/struct.A.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start' +//@ has deprecated/struct.B1.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' +//@ has deprecated/struct.B2.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' + +#[deprecated = "[start][std::ops::Range::start]"] +pub struct A; + +#[deprecated(since = "0.0.0", note = "[not_found][std::io::ErrorKind::NotFound]")] +pub struct B1; + +#[deprecated(note = "[not_found][std::io::ErrorKind::NotFound]", since = "0.0.0")] +pub struct B2; diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr index 6cf4e881adae8..62bebd53b14a6 100644 --- a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr @@ -1,8 +1,8 @@ error: unconstrained generic constant - --> $DIR/doesnt_unify_evaluatable.rs:9:11 + --> $DIR/doesnt_unify_evaluatable.rs:9:13 | LL | bar::<{ T::ASSOC }>(); - | ^^^^^^^^^^^^ + | ^^^^^^^^ | help: try adding a `where` bound | diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_complex.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_complex.rs new file mode 100644 index 0000000000000..e47052523fa39 --- /dev/null +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_complex.rs @@ -0,0 +1,20 @@ +#![feature(min_generic_const_args, adt_const_params, unsized_const_params)] +#![expect(incomplete_features)] + +trait Trait { + #[type_const] + const ASSOC: usize; +} + +fn takes_tuple() {} +fn takes_nested_tuple() {} + +fn generic_caller() { + takes_tuple::<{ (N, N + 1) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_tuple::<{ (N, T::ASSOC + 1) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + + takes_nested_tuple::<{ (N, (N, N + 1)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_nested_tuple::<{ (N, (N, const { N + 1 })) }>(); //~ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_complex.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_complex.stderr new file mode 100644 index 0000000000000..dbc64a1bf59d3 --- /dev/null +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_complex.stderr @@ -0,0 +1,26 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/adt_expr_arg_tuple_expr_complex.rs:13:25 + | +LL | takes_tuple::<{ (N, N + 1) }>(); + | ^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/adt_expr_arg_tuple_expr_complex.rs:14:25 + | +LL | takes_tuple::<{ (N, T::ASSOC + 1) }>(); + | ^^^^^^^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/adt_expr_arg_tuple_expr_complex.rs:16:36 + | +LL | takes_nested_tuple::<{ (N, (N, N + 1)) }>(); + | ^^^^^ + +error: generic parameters may not be used in const operations + --> $DIR/adt_expr_arg_tuple_expr_complex.rs:17:44 + | +LL | takes_nested_tuple::<{ (N, (N, const { N + 1 })) }>(); + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_simple.rs new file mode 100644 index 0000000000000..60c4c6e952cf2 --- /dev/null +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_simple.rs @@ -0,0 +1,22 @@ +//@ check-pass + +#![feature(min_generic_const_args, adt_const_params, unsized_const_params)] +#![expect(incomplete_features)] + +trait Trait { + #[type_const] + const ASSOC: usize; +} + +fn takes_tuple() {} +fn takes_nested_tuple() {} + +fn generic_caller() { + takes_tuple::<{ (N, N2) }>(); + takes_tuple::<{ (N, T::ASSOC) }>(); + + takes_nested_tuple::<{ (N, (N, N2)) }>(); + takes_nested_tuple::<{ (N, (N, T::ASSOC)) }>(); +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr index 49d3f67003dc0..72e0e94ff625b 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr @@ -23,7 +23,7 @@ error: struct expression with missing field initialiser for `field` --> $DIR/adt_expr_erroneuous_inits.rs:16:17 | LL | accepts::<{ Foo:: { }}>(); - | ^^^^^^^^^ + | ^^^^^^^^^^^^^ error: struct expression with multiple initialisers for `field` --> $DIR/adt_expr_erroneuous_inits.rs:18:49 @@ -35,13 +35,13 @@ error: struct expression with invalid base path --> $DIR/adt_expr_erroneuous_inits.rs:20:17 | LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path --> $DIR/adt_expr_erroneuous_inits.rs:23:17 | LL | accepts::<{ NonStruct { }}>(); - | ^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr index b4f03e07b5690..bd21624689448 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr @@ -2,7 +2,7 @@ error: the constant `Option::::Some(N)` is not of type `Foo` --> $DIR/printing_valtrees_supports_non_values.rs:18:13 | LL | foo::<{ Option::Some:: { 0: N } }>; - | ^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` --> $DIR/printing_valtrees_supports_non_values.rs:15:8 @@ -14,7 +14,7 @@ error: the constant `Option::::Some(::ASSOC)` is not of type `F --> $DIR/printing_valtrees_supports_non_values.rs:23:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); - | ^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` --> $DIR/printing_valtrees_supports_non_values.rs:15:8 @@ -37,7 +37,7 @@ error: the constant `Option::::Some(_)` is not of type `Foo` --> $DIR/printing_valtrees_supports_non_values.rs:30:12 | LL | foo::<{Option::Some::{0: ::ASSOC}}>(); - | ^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` --> $DIR/printing_valtrees_supports_non_values.rs:15:8 @@ -49,7 +49,7 @@ error: the constant `Option::::Some(_)` is not of type `Foo` --> $DIR/printing_valtrees_supports_non_values.rs:36:13 | LL | foo::<{ Option::Some:: { 0: _ } }>(); - | ^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` --> $DIR/printing_valtrees_supports_non_values.rs:15:8 diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index fbcdf35461ec9..cc6144b9c88af 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -13,31 +13,31 @@ error: tuple constructor has 2 arguments but 1 were provided --> $DIR/tuple_ctor_erroneous.rs:23:23 | LL | accepts_point::<{ Point(N) }>(); - | ^^^^^ + | ^^^^^^^^ error: tuple constructor has 2 arguments but 3 were provided --> $DIR/tuple_ctor_erroneous.rs:26:23 | LL | accepts_point::<{ Point(N, N, N) }>(); - | ^^^^^ + | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: tuple constructor with invalid base path --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); - | ^^^^^^^^ + | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path --> $DIR/tuple_ctor_erroneous.rs:36:23 | LL | accepts_point::<{ CONST_ITEM(N, N) }>(); - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: the constant `Point` is not of type `Point` --> $DIR/tuple_ctor_erroneous.rs:39:23 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs new file mode 100644 index 0000000000000..8e5cd4248f149 --- /dev/null +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -0,0 +1,14 @@ +//@ needs-rustc-debug-assertions + +struct NonGeneric {} + +#[derive(Default)] +//~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~^^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied +//~^^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied +struct NonGeneric<'a, const N: usize> {} +//~^ ERROR lifetime parameter `'a` is never used +//~^^ ERROR the name `NonGeneric` is defined multiple times + +pub fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr new file mode 100644 index 0000000000000..cf9c0d0ad3bee --- /dev/null +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -0,0 +1,81 @@ +error[E0428]: the name `NonGeneric` is defined multiple times + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:1 + | +LL | struct NonGeneric {} + | ----------------- previous definition of the type `NonGeneric` here +... +LL | struct NonGeneric<'a, const N: usize> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NonGeneric` redefined here + | + = note: `NonGeneric` must be defined only once in the type namespace of this module + +error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + | +LL | #[derive(Default)] + | ^^^^^^^ expected 0 lifetime arguments +... +LL | struct NonGeneric<'a, const N: usize> {} + | -- help: remove the lifetime argument + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 + | +LL | struct NonGeneric {} + | ^^^^^^^^^^ + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + | +LL | #[derive(Default)] + | ^^^^^^^ expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 + | +LL | struct NonGeneric {} + | ^^^^^^^^^^ + +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:19 + | +LL | struct NonGeneric<'a, const N: usize> {} + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + | +LL | #[derive(Default)] + | ^^^^^^^ expected 0 lifetime arguments +... +LL | struct NonGeneric<'a, const N: usize> {} + | -- help: remove the lifetime argument + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 + | +LL | struct NonGeneric {} + | ^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + | +LL | #[derive(Default)] + | ^^^^^^^ expected 0 generic arguments +... +LL | struct NonGeneric<'a, const N: usize> {} + | - help: remove the unnecessary generic argument + | +note: struct defined here, with 0 generic parameters + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 + | +LL | struct NonGeneric {} + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0107, E0392, E0428. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs deleted file mode 100644 index c40590ad87f47..0000000000000 --- a/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ run-pass -//@ aux-build:sigpipe-utils.rs -//@ compile-flags: -Zon-broken-pipe=kill -//@ only-unix because SIGPIPE is a unix thing - -#![feature(rustc_attrs)] - -#[rustc_main] -fn rustc_main() { - extern crate sigpipe_utils; - - // `-Zon-broken-pipe=kill` is active, so SIGPIPE handler shall be - // SIG_DFL. Note that we have a #[rustc_main], but it should still work. - sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); -} diff --git a/tests/ui/transmutability/non_scalar_alignment_value.stderr b/tests/ui/transmutability/non_scalar_alignment_value.stderr index 06487dea82e00..d22c6d0b27e82 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.stderr +++ b/tests/ui/transmutability/non_scalar_alignment_value.stderr @@ -11,25 +11,25 @@ error: struct expression with missing field initialiser for `alignment` --> $DIR/non_scalar_alignment_value.rs:15:32 | LL | alignment: Assume {}, - | ^^^^^^ + | ^^^^^^^^^ error: struct expression with missing field initialiser for `lifetimes` --> $DIR/non_scalar_alignment_value.rs:15:32 | LL | alignment: Assume {}, - | ^^^^^^ + | ^^^^^^^^^ error: struct expression with missing field initialiser for `safety` --> $DIR/non_scalar_alignment_value.rs:15:32 | LL | alignment: Assume {}, - | ^^^^^^ + | ^^^^^^^^^ error: struct expression with missing field initialiser for `validity` --> $DIR/non_scalar_alignment_value.rs:15:32 | LL | alignment: Assume {}, - | ^^^^^^ + | ^^^^^^^^^ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs index 519e913480ec3..f2b9f037ea5f3 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs @@ -4,7 +4,6 @@ trait Foo> { //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| ERROR cycle detected when computing type of `Foo::N` - //~| ERROR cycle detected when computing type of `Foo::N` fn func() {} } diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index 0ecb3e74eb571..4024f57af4ffd 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -13,7 +13,7 @@ LL | trait Foo> { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:20 | LL | trait Bar> {} | ^^^^^^ @@ -32,7 +32,7 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^ | note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:11 | LL | trait Bar> {} | ^^^^^^^^^^^^^^^ @@ -44,26 +44,6 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `Foo::N` - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:3:11 - | -LL | trait Foo> { - | ^^^^^^^^^^^^^^^ - | -note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 - | -LL | trait Bar> {} - | ^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::N`, completing the cycle -note: cycle used when checking that `Foo` is well-formed - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:3:1 - | -LL | trait Foo> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0391`.