diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a6e88f21ba74f..4354adb188e3b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1071,11 +1071,19 @@ impl<'a> AstValidator<'a> { } } - fn check_item_named(&self, ident: Ident, kind: &str) { + fn check_item_named(&self, ident: Ident, kind: &str, ctxt: AssocCtxt) { if ident.name != kw::Underscore { return; } - self.dcx().emit_err(diagnostics::ItemUnderscore { span: ident.span, kind }); + + if !self.features.associated_const_underscore() + && matches!(ctxt, AssocCtxt::Impl { of_trait: false }) + { + let msg = format!("naming associated constants with `_` is unstable"); + feature_err(&self.sess, sym::associated_const_underscore, ident.span, msg).emit(); + } else if !matches!(ctxt, AssocCtxt::Impl { of_trait: false }) { + self.dcx().emit_err(diagnostics::ItemUnderscore { span: ident.span, kind }); + } } fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) { @@ -2162,7 +2170,7 @@ impl Visitor<'_> for AstValidator<'_> { } if let AssocItemKind::Const(ci) = &item.kind { - self.check_item_named(ci.ident, "const"); + self.check_item_named(ci.ident, "const", ctxt); } let parent_is_const = diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 8c2889e90f4c0..9301780ee734c 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1335,10 +1335,9 @@ pub(crate) struct UnknownVersionLiteral { pub span: Span, } -// FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated. #[derive(Diagnostic)] #[diag("multiple `{$name}` attributes")] -pub(crate) struct UnusedMultiple { +pub struct UnusedMultiple { #[primary_span] #[suggestion("remove this attribute", code = "", applicability = "unspecified")] pub this: Span, diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 4e6b8b2d38f3b..e749fce53bd14 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -118,7 +118,7 @@ pub use attributes::cfg::{ pub use attributes::cfg_select::*; pub use attributes::util::{is_builtin_attr, parse_version}; pub use context::ShouldEmit; -pub use diagnostics::ParsedDescription; +pub use diagnostics::{ParsedDescription, UnusedMultiple}; pub use interface::{AttributeParser, EmitAttribute}; pub use rustc_parse::parser::Recovery; pub use template::AttributeTemplate; diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 0aa3a52fdd808..210b9ee895c0f 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -19,12 +19,12 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; pub(crate) fn expand( ecx: &mut ExtCtxt<'_>, - _span: Span, + span: Span, meta_item: &ast::MetaItem, annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); - warn_on_duplicate_attribute(ecx, &annotatable, sym::cfg_eval); + warn_on_duplicate_attribute(ecx, &annotatable, span, sym::cfg_eval); vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable, ecx.current_expansion.lint_node_id)] } diff --git a/compiler/rustc_builtin_macros/src/diagnostics.rs b/compiler/rustc_builtin_macros/src/diagnostics.rs index d85bb972f4a86..30c332109df5c 100644 --- a/compiler/rustc_builtin_macros/src/diagnostics.rs +++ b/compiler/rustc_builtin_macros/src/diagnostics.rs @@ -22,10 +22,6 @@ pub(crate) struct IncompleteInclude; #[diag("cannot test inner items")] pub(crate) struct UnnameableTestItems; -#[derive(Diagnostic)] -#[diag("duplicated attribute")] -pub(crate) struct DuplicateMacroAttribute; - #[derive(Diagnostic)] #[diag("macro requires a cfg-pattern as an argument")] pub(crate) struct RequiresCfgPattern { diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 5f86842ae75e8..b54ae300b4d80 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -30,7 +30,7 @@ pub(crate) fn expand_test_case( anno_item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::test_case); - warn_on_duplicate_attribute(ecx, &anno_item, sym::test_case); + warn_on_duplicate_attribute(ecx, &anno_item, attr_sp, sym::test_case); let sp = ecx.with_def_site_ctxt(attr_sp); let (mut item, is_stmt) = match anno_item { @@ -88,7 +88,7 @@ pub(crate) fn expand_test( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::test); - warn_on_duplicate_attribute(cx, &item, sym::test); + warn_on_duplicate_attribute(cx, &item, attr_sp, sym::test); expand_test_or_bench(cx, attr_sp, item, false) } @@ -99,7 +99,7 @@ pub(crate) fn expand_bench( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::bench); - warn_on_duplicate_attribute(cx, &item, sym::bench); + warn_on_duplicate_attribute(cx, &item, attr_path_sp, sym::bench); expand_test_or_bench(cx, attr_path_sp, item, true) } diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 7b990c5af080f..903f08e2b7ebd 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -1,6 +1,6 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{self as ast, AttrStyle, Attribute, MetaItem, attr, token}; -use rustc_attr_parsing::{AttributeTemplate, validate_attr}; +use rustc_attr_parsing::{AttributeTemplate, UnusedMultiple, validate_attr}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt}; use rustc_expand::expand::AstFragment; @@ -26,30 +26,33 @@ pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaI /// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when /// an attribute may have been mistakenly duplicated. -pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) { - let attrs: Option<&[Attribute]> = match item { - Annotatable::Item(item) => Some(&item.attrs), - Annotatable::AssocItem(item, _) => Some(&item.attrs), - Annotatable::ForeignItem(item) => Some(&item.attrs), - Annotatable::Expr(expr) => Some(&expr.attrs), - Annotatable::Arm(arm) => Some(&arm.attrs), - Annotatable::ExprField(field) => Some(&field.attrs), - Annotatable::PatField(field) => Some(&field.attrs), - Annotatable::GenericParam(param) => Some(¶m.attrs), - Annotatable::Param(param) => Some(¶m.attrs), - Annotatable::FieldDef(def) => Some(&def.attrs), - Annotatable::Variant(variant) => Some(&variant.attrs), - _ => None, +pub(crate) fn warn_on_duplicate_attribute( + ecx: &ExtCtxt<'_>, + item: &Annotatable, + span: Span, + name: Symbol, +) { + let attrs: &[Attribute] = match item { + Annotatable::Item(item) => &item.attrs, + Annotatable::AssocItem(item, _) => &item.attrs, + Annotatable::ForeignItem(item) => &item.attrs, + Annotatable::Expr(expr) => &expr.attrs, + Annotatable::Arm(arm) => &arm.attrs, + Annotatable::ExprField(field) => &field.attrs, + Annotatable::PatField(field) => &field.attrs, + Annotatable::GenericParam(param) => ¶m.attrs, + Annotatable::Param(param) => ¶m.attrs, + Annotatable::FieldDef(def) => &def.attrs, + Annotatable::Variant(variant) => &variant.attrs, + _ => return, }; - if let Some(attrs) = attrs { - if let Some(attr) = attr::find_by_name(attrs, name) { - ecx.psess().buffer_lint( - DUPLICATE_MACRO_ATTRIBUTES, - attr.span, - ecx.current_expansion.lint_node_id, - diagnostics::DuplicateMacroAttribute, - ); - } + if let Some(attr) = attr::find_by_name(attrs, name) { + ecx.psess().buffer_lint( + DUPLICATE_MACRO_ATTRIBUTES, + attr.span, + ecx.current_expansion.lint_node_id, + UnusedMultiple { this: attr.span, other: span, name }, + ); } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index ed2bf64263c67..5de5d0a9a0b7e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -390,6 +390,8 @@ declare_features! ( (unstable, asm_goto_with_outputs, "1.85.0", Some(119364)), /// Allows the `may_unwind` option in inline assembly. (unstable, asm_unwind, "1.58.0", Some(93334)), + /// Allows `_` for the name of associated constants. + (unstable, associated_const_underscore, "CURRENT_RUSTC_VERSION", Some(158944)), /// Allows associated type defaults. (unstable, associated_type_defaults, "1.2.0", Some(29661)), /// Allows implementing `AsyncDrop`. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4ce8f5e793bc9..779b049063b8f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3144,6 +3144,13 @@ impl<'hir> ImplItem<'hir> { ImplItemId { owner_id: self.owner_id } } + /// Returns whether this is an anonymous associated constant in an inherent impl. + pub fn is_anon_const(&self) -> bool { + matches!(self.impl_kind, ImplItemImplKind::Inherent { .. }) + && matches!(self.kind, ImplItemKind::Const(..)) + && self.ident.name == kw::Underscore + } + pub fn vis_span(&self) -> Option { match self.impl_kind { ImplItemImplKind::Trait { .. } => None, diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 02acd8dc58918..b063a8e68422d 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -614,7 +614,10 @@ fn suggestion_signature<'tcx>( ); format!("type {}{generics} = /* Type */{where_clauses};", assoc.name()) } - ty::AssocKind::Const { name, .. } => { + ty::AssocKind::Const { data: ty::AssocConstData::Anonymous } => { + panic!("anonymous associated consts shouldn't end up here") + } + ty::AssocKind::Const { data: ty::AssocConstData::Named(name) } => { let ty = tcx.type_of(assoc.def_id).instantiate_identity().skip_norm_wip(); let val = tcx .infer_ctxt() diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 05ceb049e0dba..576300b5eaf1f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -49,7 +49,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { std::mem::swap(&mut impl_items1, &mut impl_items2); } - for &item1 in impl_items1.in_definition_order() { + for &item1 in impl_items1.named_items_in_definition_order() { let collision = impl_items2 .filter_by_name_unhygienic(item1.name()) .any(|&item2| self.compare_hygienically(item1, item2)); @@ -74,7 +74,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { let mut seen_items = FxIndexMap::default(); let mut res = Ok(()); - for impl_item in impl_items.in_definition_order() { + for &impl_item in impl_items.named_items_in_definition_order() { let span = self.tcx.def_span(impl_item.def_id); let ident = impl_item.ident(self.tcx); @@ -111,7 +111,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { let impl_items2 = self.tcx.associated_items(impl2); let mut res = Ok(()); - for &item1 in impl_items1.in_definition_order() { + for &item1 in impl_items1.named_items_in_definition_order() { let collision = impl_items2 .filter_by_name_unhygienic(item1.name()) .find(|&&item2| self.compare_hygienically(item1, item2)); @@ -228,7 +228,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // First obtain a list of existing connected region ids let mut idents_to_add = SmallVec::<[Symbol; 8]>::new(); let mut ids = impl_items - .in_definition_order() + .named_items_in_definition_order() .filter_map(|item| { let entry = connected_region_ids.entry(item.name()); if let IndexEntry::Occupied(e) = &entry { 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 83f924b9e374c..0488c378b934c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -205,10 +205,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let wider_candidate_names: Vec<_> = visible_traits .iter() - .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order()) - .filter_map(|item| { - (!item.is_impl_trait_in_trait() && item.tag() == assoc_tag).then(|| item.name()) + .flat_map(|trait_def_id| { + tcx.associated_items(*trait_def_id).named_items_in_definition_order() }) + .filter_map(|item| (item.tag() == assoc_tag).then(|| item.name())) .collect(); if let Some(suggested_name) = diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 40f48898ec658..67a692b07a2ca 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -283,7 +283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(iterator_item_id) = tcx .associated_items(iterator_trait_id) - .in_definition_order() + .named_items_in_definition_order() .find(|item| item.name() == sym::Item) .map(|item| item.def_id) else { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index b20115a6df556..f6cfe6faf7a79 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1894,7 +1894,10 @@ impl<'tcx> Pick<'tcx> { tcx.def_path_str(this.item.def_id), )); } - (ty::AssocKind::Const { name, .. }, ty::AssocContainer::Trait) => { + ( + ty::AssocKind::Const { data: ty::AssocConstData::Named(name) }, + ty::AssocContainer::Trait, + ) => { let def_id = this.item.container_id(tcx); lint.span_suggestion( span, @@ -2662,7 +2665,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { { return true; } - false } @@ -2676,7 +2678,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let max_dist = max(name.as_str().len(), 3) / 3; self.tcx .associated_items(def_id) - .in_definition_order() + .named_items_in_definition_order() .filter(|x| { if !self.is_relevant_kind_for_mode(x.kind) { return false; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 14f5f4683e970..cec1c7c092186 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1444,7 +1444,14 @@ impl CrateMetadata { fn get_associated_item(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ty::AssocItem { let kind = match self.def_kind(id) { - DefKind::AssocConst => ty::AssocKind::Const { name: self.item_name(id) }, + DefKind::AssocConst => { + let data = if let Some(item_name) = self.root.tables.opt_item_name.get(self, id) { + ty::AssocConstData::Named(item_name.decode((self, tcx))) + } else { + ty::AssocConstData::Anonymous + }; + ty::AssocKind::Const { data } + } DefKind::AssocFn => ty::AssocKind::Fn { name: self.item_name(id), has_self: self.get_fn_has_self_parameter(tcx, id), diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 24fecc6014c80..3385f33b64989 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1898,6 +1898,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.table_writer().assoc_container(def_id, item.container); + if let Some(item_name) = item.opt_name() { + self.table_writer().opt_item_name(def_id, Some(item_name)); + } + if let AssocContainer::Trait = item.container && item.is_type() { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 62999889515cb..3706d78613619 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -641,6 +641,7 @@ define_tables! { explicit_implied_clauses_of: Table, Span)>>, explicit_implied_const_bounds: Table, Span)>>, inherent_impls: Table>, + opt_item_name: Table>>, // Reexported names are not associated with individual `DefId`s, // e.g. a glob import can introduce a lot of names, all with the same `DefId`. // That's why the encoded list needs to contain `ModChild` structures describing all the names diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index e52d74f4c23fe..05635c9e2ce26 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -31,15 +31,16 @@ impl AssocItem { match self.kind { ty::AssocKind::Type { data: AssocTypeData::Normal(name) } => Some(name), ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None, - ty::AssocKind::Const { name, .. } => Some(name), + ty::AssocKind::Const { data: AssocConstData::Named(name), .. } => Some(name), + ty::AssocKind::Const { data: AssocConstData::Anonymous, .. } => None, ty::AssocKind::Fn { name, .. } => Some(name), } } - // Gets the identifier name. Aborts if it lacks one, i.e. is an RPITIT - // associated type. + // Gets the identifier name. Aborts if it lacks one, e.g. for an RPITIT + // associated type or an anonymous associated const. pub fn name(&self) -> Symbol { - self.opt_name().expect("name of non-Rpitit assoc item") + self.opt_name().expect("name of anonymous associated item") } pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { @@ -120,7 +121,11 @@ impl AssocItem { tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string() } ty::AssocKind::Type { .. } => format!("type {};", self.name()), - ty::AssocKind::Const { name, .. } => { + ty::AssocKind::Const { data, .. } => { + let name = match data { + AssocConstData::Named(name) => name, + AssocConstData::Anonymous => rustc_span::symbol::kw::Underscore, + }; format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity()) } } @@ -149,6 +154,10 @@ impl AssocItem { } } + pub fn is_anon_const(&self) -> bool { + matches!(self.kind, ty::AssocKind::Const { data: AssocConstData::Anonymous, .. }) + } + pub fn is_fn(&self) -> bool { matches!(self.kind, ty::AssocKind::Fn { .. }) } @@ -179,9 +188,16 @@ pub enum AssocTypeData { Rpitit(ty::ImplTraitInTraitData), } +#[derive(Copy, Clone, PartialEq, Debug, StableHash, Eq, Hash, Encodable, Decodable)] +pub enum AssocConstData { + Named(Symbol), + /// An associated constant named `_`, which *semantically* has no name. + Anonymous, +} + #[derive(Copy, Clone, PartialEq, Debug, StableHash, Eq, Hash, Encodable, Decodable)] pub enum AssocKind { - Const { name: Symbol }, + Const { data: AssocConstData }, Fn { name: Symbol, has_self: bool }, Type { data: AssocTypeData }, } @@ -268,6 +284,14 @@ impl AssocItems { self.items.iter().map(|(_, v)| v) } + /// Returns named associated items in definition order. + /// + /// New code should avoid relying on definition order. If you need a particular associated item + /// for a known trait, make that trait a lang item instead of indexing this array. + pub fn named_items_in_definition_order(&self) -> impl '_ + Iterator { + self.items.iter().filter_map(|(name, v)| name.is_some().then(|| v)) + } + pub fn len(&self) -> usize { self.items.len() } diff --git a/compiler/rustc_mir_build/src/builder/cfg.rs b/compiler/rustc_mir_build/src/builder/cfg.rs index 76bb5009a6ec1..b540f0d8cb718 100644 --- a/compiler/rustc_mir_build/src/builder/cfg.rs +++ b/compiler/rustc_mir_build/src/builder/cfg.rs @@ -1,38 +1,66 @@ //! Routines for manipulating the control-flow graph. +use itertools::Either; use rustc_attr_ir::UnrollAttr; use rustc_data_structures::thin_vec::ThinVec; +use rustc_index::IndexVec; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::debug; -use crate::builder::CFG; +use crate::builder::{CFG, CFGBlock, UnterminatedBlockData}; impl<'tcx> CFG<'tcx> { - pub(crate) fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { + fn block_data(&self, blk: BasicBlock) -> &CFGBlock<'tcx> { &self.basic_blocks[blk] } - pub(crate) fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> { + fn block_data_mut(&mut self, blk: BasicBlock) -> &mut CFGBlock<'tcx> { &mut self.basic_blocks[blk] } + pub(crate) fn assert_terminator(&self, bb: BasicBlock) -> &Terminator<'tcx> { + self.block_data(bb).as_ref().left().unwrap().terminator() + } + + pub(crate) fn assert_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { + self.block_data_mut(bb).as_mut().left().unwrap().terminator_mut() + } + + pub(crate) fn statements(&self, blk: BasicBlock) -> &[Statement<'tcx>] { + match &self.basic_blocks[blk] { + CFGBlock::Left(bb) => &bb.statements, + CFGBlock::Right(bb) => &bb.statements, + } + } + + pub(crate) fn statements_mut(&mut self, blk: BasicBlock) -> &mut Vec> { + match &mut self.basic_blocks[blk] { + CFGBlock::Left(bb) => &mut bb.statements, + CFGBlock::Right(bb) => &mut bb.statements, + } + } + + pub(crate) fn into_basic_blocks(self) -> IndexVec> { + // CFGBlock has the same layout as BasicBlockData, so this call should be + // almost no-op (we have a specialization for reusing the allocation in this case). + self.basic_blocks.into_iter().map(|bb| bb.left().unwrap()).collect() + } + // llvm.org/PR32488 makes this function use an excess of stack space. Mark // it as #[inline(never)] to keep rustc's stack use in check. #[inline(never)] pub(crate) fn start_new_block(&mut self) -> BasicBlock { - self.basic_blocks.push(BasicBlockData::maybe_unterminated(None, false)) + self.basic_blocks.push(Either::Right(UnterminatedBlockData::new(Vec::new(), false))) } pub(crate) fn start_new_cleanup_block(&mut self) -> BasicBlock { - let bb = self.start_new_block(); - self.block_data_mut(bb).is_cleanup = true; - bb + self.basic_blocks.push(Either::Right(UnterminatedBlockData::new(Vec::new(), true))) } pub(crate) fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) { debug!("push({:?}, {:?})", block, statement); - self.block_data_mut(block).statements.push(statement); + self.statements_mut(block).push(statement); } pub(crate) fn push_assign( @@ -112,13 +140,20 @@ impl<'tcx> CFG<'tcx> { ) -> &mut Terminator<'tcx> { debug!("terminating block {:?} <- {:?}", block, kind); debug_assert!( - self.block_data(block).terminator.is_none(), + self.block_data(block).is_right(), "terminate: block {:?}={:?} already has a terminator set", block, self.block_data(block) ); - self.block_data_mut(block).terminator = Some(Terminator { source_info, kind }); - self.block_data_mut(block).terminator.as_mut().unwrap() + let UnterminatedBlockData { statements, is_cleanup } = + self.block_data_mut(block).as_mut().right().unwrap(); + + *self.block_data_mut(block) = Either::Left(BasicBlockData::new_stmts( + std::mem::take(statements), + Terminator { source_info, kind }, + *is_cleanup, + )); + self.block_data_mut(block).as_mut().left().unwrap().terminator_mut() } /// In the `origin` block, push a `goto -> target` terminator. diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 64a1fea013ace..05efc2f4e7138 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -470,8 +470,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { outer_source_info.span.with_lo(outer_source_info.span.hi() - BytePos::from_usize(1)), ); for arm_block in arm_end_blocks { - let block = &self.cfg.basic_blocks[arm_block]; - let last_location = block.statements.last().map(|s| s.source_info); + let statements = self.cfg.statements(arm_block); + let last_location = statements.last().map(|s| s.source_info); self.cfg.goto(arm_block, last_location.unwrap_or(end_brace), end_block); } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 6e8df5e0809ba..21899a0a03a7f 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -20,7 +20,7 @@ //! `let this = self;` or similar, allowing subsequent code to uniformly refer //! to the builder as `this` (and never `self`), even when not nested. -use itertools::Itertools; +use itertools::{Either, Itertools}; use rustc_abi::{ExternAbi, FieldIdx}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; @@ -392,8 +392,35 @@ impl LocalsForNode { } } +#[derive(Debug, Clone)] +pub(crate) struct UnterminatedBlockData<'tcx> { + statements: Vec>, + is_cleanup: bool, +} +impl<'tcx> UnterminatedBlockData<'tcx> { + fn new(statements: Vec>, is_cleanup: bool) -> Self { + UnterminatedBlockData { statements, is_cleanup } + } +} + +pub(crate) type CFGBlock<'tcx> = Either, UnterminatedBlockData<'tcx>>; + +#[cfg(target_pointer_width = "64")] +mod size_asserts { + use rustc_data_structures::static_assert_size; + + use super::*; + // Note: It's important that `CFGBlock` has the same layout as `BasicBlockData`. + // because it makes the final transition to `IndexVec>` + // cheaper. If those type layouts differ, we get a perf regression. + // See benchmarks in https://github.com/rust-lang/rust/pull/165611 for more info. + static_assert_size!(BasicBlockData<'_>, 136); + static_assert_size!(CFGBlock<'_>, 136); +} + +#[derive(Debug, Clone)] struct CFG<'tcx> { - basic_blocks: IndexVec>, + basic_blocks: IndexVec>, } #[derive(Debug)] @@ -756,7 +783,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - Body::new( MirSource::item(def_id.to_def_id()), - cfg.basic_blocks, + cfg.into_basic_blocks(), source_scopes, local_decls, IndexVec::new(), @@ -919,7 +946,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn dump_for_debugging(&self) { let mut body = Body::new( MirSource::item(self.def_id.to_def_id()), - self.cfg.basic_blocks.clone(), + self.cfg.clone().into_basic_blocks(), self.source_scopes.clone(), self.local_decls.clone(), self.canonical_user_type_annotations.clone(), @@ -938,7 +965,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn finish(self) -> Body<'tcx> { let mut body = Body::new( MirSource::item(self.def_id.to_def_id()), - self.cfg.basic_blocks, + self.cfg.into_basic_blocks(), self.source_scopes, self.local_decls, self.canonical_user_type_annotations, diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index fd1215cfdad9b..28b2a98b6120d 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1621,7 +1621,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn diverge_from(&mut self, start: BasicBlock) { debug_assert!( matches!( - self.cfg.block_data(start).terminator().kind, + self.cfg.assert_terminator(start).kind, TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } @@ -1680,10 +1680,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// This path terminates in CoroutineDrop. pub(crate) fn coroutine_drop_cleanup(&mut self, yield_block: BasicBlock) { debug_assert!( - matches!( - self.cfg.block_data(yield_block).terminator().kind, - TerminatorKind::Yield { .. } - ), + matches!(self.cfg.assert_terminator(yield_block).kind, TerminatorKind::Yield { .. }), "coroutine_drop_cleanup called on block with non-yield terminator." ); let cached_drop = self.diverge_dropline(); @@ -2108,7 +2105,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for ExitScopes { // There should be an existing terminator with real source info and a // dummy TerminatorKind. Replace it with a proper goto. // (The dummy is added by `break_scope` and `break_from_if_then_scope`.) - let term = cfg.block_data_mut(from).terminator_mut(); + let term = cfg.assert_terminator_mut(from); if let TerminatorKind::UnwindResume = term.kind { term.kind = TerminatorKind::goto(to); } else { @@ -2124,7 +2121,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for CoroutineDrop { cfg.start_new_block() } fn link_entry_point(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) { - let term = cfg.block_data_mut(from).terminator_mut(); + let term = cfg.assert_terminator_mut(from); if let TerminatorKind::Yield { ref mut drop, .. } = term.kind { *drop = Some(to); } else if let TerminatorKind::Drop { ref mut drop, .. } = term.kind { @@ -2146,7 +2143,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { cfg.start_new_cleanup_block() } fn link_entry_point(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) { - let term = &mut cfg.block_data_mut(from).terminator_mut(); + let term = &mut cfg.assert_terminator_mut(from); match &mut term.kind { TerminatorKind::Drop { unwind, .. } => { if let UnwindAction::Cleanup(unwind) = *unwind { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ffa3a7443ecc4..8513d3631248b 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -954,6 +954,17 @@ fn maybe_record_as_seed<'tcx>( } } DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy => { + // As with free constants named `_`, associated constants named `_` are always live. + if let hir::Node::ImplItem(impl_item) = tcx.hir_node_by_def_id(owner_id.def_id) + && impl_item.is_anon_const() + { + push_into_worklist(WorkItem { + id: owner_id.def_id, + propagated: ComesFromAllowExpect::No, + own: ComesFromAllowExpect::No, + }); + } + if allow_dead_code.is_none() { let parent = tcx.local_parent(owner_id.def_id); match tcx.def_kind(parent) { diff --git a/compiler/rustc_public/src/ty/tys.rs b/compiler/rustc_public/src/ty/tys.rs index 179d969a53675..6a41392d1c3e4 100644 --- a/compiler/rustc_public/src/ty/tys.rs +++ b/compiler/rustc_public/src/ty/tys.rs @@ -1374,9 +1374,15 @@ pub enum AssocTypeData { Rpitit(ImplTraitInTraitData), } +#[derive(Clone, PartialEq, Debug, Eq, Serialize)] +pub enum AssocConstData { + Named(Symbol), + Anonymous, +} + #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AssocKind { - Const { name: Symbol }, + Const { data: AssocConstData }, Fn { name: Symbol, has_self: bool }, Type { data: AssocTypeData }, } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 51dd03a252693..f4f461980023e 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -1075,9 +1075,14 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - use crate::ty::{AssocKind, AssocTypeData}; + use crate::ty::{AssocConstData, AssocKind, AssocTypeData}; match *self { - ty::AssocKind::Const { name, .. } => AssocKind::Const { name: name.to_string() }, + ty::AssocKind::Const { data, .. } => AssocKind::Const { + data: match data { + ty::AssocConstData::Named(name) => AssocConstData::Named(name.to_string()), + ty::AssocConstData::Anonymous => AssocConstData::Anonymous, + }, + }, ty::AssocKind::Fn { name, has_self } => { AssocKind::Fn { name: name.to_string(), has_self } } diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 7df6549a07a70..4d74cc543b8b8 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -269,6 +269,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { sess.dcx().emit_fatal(err); }); let mut has_atomic = false; + let (min_atomic_width, max_atomic_width) = { + let cpu = sess.opts.cg.target_cpu.as_deref().unwrap_or(sess.target.cpu.as_ref()); + sess.target.atomic_widths(cpu) + }; for (i, align) in [ (8, layout.i8_align), (16, layout.i16_align), @@ -276,7 +280,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { (64, layout.i64_align), (128, layout.i128_align), ] { - if i >= sess.target.min_atomic_width() && i <= sess.target.max_atomic_width() { + if i >= min_atomic_width && i <= max_atomic_width { if !has_atomic { has_atomic = true; if sess.is_nightly_build() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2170f610f0939..a96e8b597d77a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -479,6 +479,7 @@ symbols! { assert_zero_valid, asserting, associated_const_equality, + associated_const_underscore, associated_consts, associated_type_bounds, associated_type_defaults, diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index 896609bdbe3a7..d99d14bee7055 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -58,6 +58,12 @@ impl ToJson for [A] { } } +impl ToJson for (T, U) { + fn to_json(&self) -> Json { + Json::Array(vec![self.0.to_json(), self.1.to_json()]) + } +} + impl ToJson for Vec { fn to_json(&self) -> Json { Json::Array(self.iter().map(|elt| elt.to_json()).collect()) diff --git a/compiler/rustc_target/src/spec/base/bpf.rs b/compiler/rustc_target/src/spec/base/bpf.rs index 8d541cb78deac..46cbe65b667fd 100644 --- a/compiler/rustc_target/src/spec/base/bpf.rs +++ b/compiler/rustc_target/src/spec/base/bpf.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use rustc_abi::Endian; use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions}; @@ -19,11 +21,27 @@ pub(crate) fn opts(endian: Endian) -> TargetOptions { merge_functions: MergeFunctions::Disabled, obj_is_bitcode: true, singlethread: true, - // When targeting the `v3` cpu in llvm, 32-bit atomics are also supported. - // But making this value change based on the target cpu can be mostly confusing - // and would require a bit of a refactor. - min_atomic_width: Some(64), + // Atomic loads and stores up to 64 bits are supported from CPU v4. + min_atomic_width: Some(8), max_atomic_width: Some(64), + per_cpu_atomic_widths: BTreeMap::from([ + // CPU versions from v1 to v3 support only read-modify-write atomic + // operations (atomicrmw, cmpxchg), they do not support atomic + // loads and stores. Proof: + // - src/llvm-project/llvm/test/CodeGen/BPF/atomic-load-store.ll + // works only on v4. + // - All other atomic*.ll tests enabled on lower CPU versions don't + // perform loads and stores. + // `Atomic*` types from `core::sync::atomic` require availability + // of both kinds of operations, so they need to be disabled for + // CPU versions lower than v4. BPF developers wanting to use r-m-w + // operations on older kernels/CPUs can call intrinsics directly + // instead of using `core::sync::atomic`. + ("v1".into(), (8, 0)), + ("v2".into(), (8, 0)), + ("v3".into(), (8, 0)), + ("generic".into(), (8, 0)), // generic == v3 + ]), ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index 03dbbcb5b481d..87d878a86944e 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -168,6 +168,7 @@ impl Target { forward!(obj_is_bitcode); forward_opt!(max_atomic_width); forward_opt!(min_atomic_width); + forward!(per_cpu_atomic_widths); forward!(atomic_cas); forward!(panic_strategy); forward!(crt_static_allows_dylibs); @@ -368,6 +369,7 @@ impl ToJson for Target { target_option_val!(obj_is_bitcode); target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); + target_option_val!(per_cpu_atomic_widths); target_option_val!(atomic_cas); target_option_val!(panic_strategy); target_option_val!(crt_static_allows_dylibs); @@ -590,6 +592,7 @@ struct TargetSpecJson { obj_is_bitcode: Option, max_atomic_width: Option, min_atomic_width: Option, + per_cpu_atomic_widths: Option, (u64, u64)>>, atomic_cas: Option, panic_strategy: Option, crt_static_allows_dylibs: Option, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ae17e37e29f86..b3839b23d9a10 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2433,6 +2433,10 @@ pub struct TargetOptions { /// Don't use this field; instead use the `.max_atomic_width()` method. pub max_atomic_width: Option, + /// Don't use this field; instead use the `.min_atomic_width()` and + /// `max_atomic_width()` methods. + pub per_cpu_atomic_widths: BTreeMap, (u64, u64)>, + /// Whether the target supports atomic CAS operations natively pub atomic_cas: bool, @@ -2807,6 +2811,7 @@ impl Default for TargetOptions { obj_is_bitcode: false, min_atomic_width: None, max_atomic_width: None, + per_cpu_atomic_widths: BTreeMap::new(), atomic_cas: true, panic_strategy: PanicStrategy::Unwind, crt_static_allows_dylibs: false, @@ -2881,16 +2886,13 @@ impl Target { abi_map.canonize_abi(abi, false).is_mapped() } - /// Minimum integer size in bits that this target can perform atomic - /// operations on. - pub fn min_atomic_width(&self) -> u64 { - self.min_atomic_width.unwrap_or(8) - } - - /// Maximum integer size in bits that this target can perform atomic - /// operations on. - pub fn max_atomic_width(&self) -> u64 { - self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()) + /// Minimum and maximum integer size in bits that this target can perform + /// atomic operations on. + pub fn atomic_widths(&self, cpu: &str) -> (u64, u64) { + self.per_cpu_atomic_widths.get(cpu).copied().unwrap_or(( + self.min_atomic_width.unwrap_or(8), + self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()), + )) } /// Test target self-consistency and JSON encoding/decoding roundtrip. diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 38bfeb04fbce4..c171b9894151c 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -361,7 +361,10 @@ pub fn dyn_compatibility_violations_for_assoc_item( let span = || item.ident(tcx).span; match item.kind { - ty::AssocKind::Const { name } => { + ty::AssocKind::Const { data: ty::AssocConstData::Anonymous } => { + panic!("anonymous associated consts shouldn't end up here") + } + ty::AssocKind::Const { data: ty::AssocConstData::Named(name) } => { // We will permit type associated consts if they are explicitly mentioned in the // trait object type. We can't check this here, as here we only check if it is // guaranteed to not be possible. diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 6b30019127f27..526419215334b 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -93,7 +93,9 @@ fn associated_item_from_trait_item( let owner_id = trait_item.owner_id; let name = trait_item.ident.name; let kind = match trait_item.kind { - hir::TraitItemKind::Const(_, _) => ty::AssocKind::Const { name }, + hir::TraitItemKind::Const(_, _) => { + ty::AssocKind::Const { data: ty::AssocConstData::Named(name) } + } hir::TraitItemKind::Fn { .. } => ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id, trait_item.generics), @@ -110,7 +112,14 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_> let owner_id = impl_item.owner_id; let name = impl_item.ident.name; let kind = match impl_item.kind { - hir::ImplItemKind::Const(..) => ty::AssocKind::Const { name }, + hir::ImplItemKind::Const(..) => { + let data = if impl_item.is_anon_const() { + ty::AssocConstData::Anonymous + } else { + ty::AssocConstData::Named(name) + }; + ty::AssocKind::Const { data } + } hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id, impl_item.generics), diff --git a/library/std/src/sys/sync/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs index 98ca2288f74a2..ff2046b0edcdf 100644 --- a/library/std/src/sys/sync/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -8,6 +8,9 @@ use crate::time::Duration; // the main thread, but they are forbidden from accessing sync primitives (the same as UNIX // signal handlers). not(target_os = "vexos"), + // Trusty is "target_has_threads" because it needs atomics for shared-memory IPC, but processes + // can't spawn threads. + not(target_os = "trusty"), ))] compile_error!("Using no_threads implementation on a target with threads"); diff --git a/library/std/src/sys/sync/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs index d031c0e7e1dcf..6fcbb29cfaaeb 100644 --- a/library/std/src/sys/sync/mutex/no_threads.rs +++ b/library/std/src/sys/sync/mutex/no_threads.rs @@ -6,6 +6,9 @@ use crate::cell::Cell; // the main thread, but they are forbidden from accessing sync primitives (the same as UNIX // signal handlers). not(target_os = "vexos"), + // Trusty is "target_has_threads" because it needs atomics for shared-memory IPC, but processes + // can't spawn threads. + not(target_os = "trusty"), ))] compile_error!("Using no_threads implementation on a target with threads"); diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index 725ec28f7cd4f..c4eb8a775ef6e 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -8,6 +8,9 @@ use crate::sync::once::OnceExclusiveState; // the main thread, but they are forbidden from accessing sync primitives (the same as UNIX // signal handlers). not(target_os = "vexos"), + // Trusty is "target_has_threads" because it needs atomics for shared-memory IPC, but processes + // can't spawn threads. + not(target_os = "trusty"), ))] compile_error!("Using no_threads implementation on a target with threads"); diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index e7e845cc785c7..62c893dd56e0e 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -6,6 +6,9 @@ use crate::cell::Cell; // the main thread, but they are forbidden from accessing sync primitives (the same as UNIX // signal handlers). not(target_os = "vexos"), + // Trusty is "target_has_threads" because it needs atomics for shared-memory IPC, but processes + // can't spawn threads. + not(target_os = "trusty"), ))] compile_error!("Using no_threads implementation on a target with threads"); diff --git a/library/std/src/sys/thread_local/no_threads.rs b/library/std/src/sys/thread_local/no_threads.rs index c8d40a5f4e5d7..fe77ca61b6f6a 100644 --- a/library/std/src/sys/thread_local/no_threads.rs +++ b/library/std/src/sys/thread_local/no_threads.rs @@ -12,6 +12,9 @@ use crate::ptr; // Since there is only one context that's allowed to access thread locals, it's sound to use the // no_threads implementation. not(target_os = "vexos"), + // Trusty is "target_has_threads" because it needs atomics for shared-memory IPC, but processes + // can't spawn threads. + not(target_os = "trusty"), ))] compile_error!("Using no_threads implementation on a target with threads"); diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 27de3ec60b96b..5928860bad0a9 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1505,18 +1505,14 @@ impl Builder<'_> { .unwrap_or(&self.config.rust_rustflags) .clone(); - let profile = - if matches!(cmd_kind, Kind::Bench | Kind::Miri | Kind::MiriSetup | Kind::MiriTest) { - // Use the default profile for bench/miri - None - } else { - match (mode, self.config.rust_optimize.is_release()) { - // Some std configuration exists in its own profile - (Mode::Std, _) => Some("dist"), - (_, true) => Some("release"), - (_, false) => Some("dev"), - } - }; + let profile = match (cmd_kind, mode) { + // Use the default profile for miri + (Kind::Miri | Kind::MiriSetup | Kind::MiriTest, _) => None, + // Some std configuration exists in its own profile + (_, Mode::Std) => Some("dist"), + _ if self.config.rust_optimize.is_release() => Some("release"), + _ => Some("dev"), + }; Cargo { command: cargo, diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index df8adab351e65..21957694d85dc 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -105,7 +105,7 @@ transformations, the passes are run on the _cleaned_ crate. Here is the list of passes as of March 2023: -- `calculate-doc-coverage` calculates information used for the `--show-coverage` +- `calculate-doc-coverage` calculates information used for the `--coverage` flag. - `check-doc-test-visibility` runs `doctest` visibility–related `lint`s. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 9bd795b759ec4..a699013ca1bc5 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -485,14 +485,14 @@ This flag allows you to keep doctest executables around after they're compiled o Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but with this option, you can keep those binaries around for farther testing. -## `--show-coverage`: calculate the percentage of items with documentation +## `--coverage`: calculate the percentage of items with documentation * Tracking issue: [#58154](https://github.com/rust-lang/rust/issues/58154) Using this flag looks like this: ```bash -$ rustdoc src/lib.rs -Z unstable-options --show-coverage +$ rustdoc src/lib.rs -Z unstable-options --coverage ``` It generates something like this: @@ -539,7 +539,7 @@ Calculating code examples follows these rules: If you use the `-o` option with it, it will generate the file into the given older name. For example: ```shell -rustdoc foo.rs --show-coverage -o doc +rustdoc foo.rs --coverage -o doc ``` Will generate a `foo.txt` into the `doc` folder. If the `-o` option isn't passed, it will display @@ -586,8 +586,8 @@ rustup component add --toolchain nightly rust-docs-json Then the json files will be present in the `share/doc/rust/json/` directory of the rustup toolchain directory. -It can also be used with `--show-coverage`. Take a look at its -[documentation](#--show-coverage-calculate-the-percentage-of-items-with-documentation) for more +It can also be used with `--coverage`. Take a look at its +[documentation](#--coverage-calculate-the-percentage-of-items-with-documentation) for more information. ### doctest diff --git a/src/librustdoc/calculate_doc_coverage.rs b/src/librustdoc/calculate_doc_coverage.rs index 45e1c18051444..dc00a689d7bc9 100644 --- a/src/librustdoc/calculate_doc_coverage.rs +++ b/src/librustdoc/calculate_doc_coverage.rs @@ -1,4 +1,4 @@ -//! Calculates information used for the `--show-coverage` flag. +//! Calculates information used for the `--coverage` flag. //! //! More specifically, it counts the number of items with documentation, ones with //! "examples" (i.e., non-ignored Rust code blocks) and various totals. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d3d3cef8d7860..f89d4d7d0ad78 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -539,6 +539,7 @@ pub(crate) fn build_impl( .items .iter() .map(|&item| tcx.hir_impl_item(item)) + .filter(|item| !item.is_anon_const()) .filter(|item| { // Filter out impl items whose corresponding trait item has `doc(hidden)` // not to document such impl items. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 79840366fc74c..47e46bc35f922 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3059,7 +3059,9 @@ fn clean_impl<'tcx>( let items = impl_ .items .iter() - .map(|&ii| clean_impl_item(tcx.hir_impl_item(ii), cx)) + .map(|&ii| tcx.hir_impl_item(ii)) + .filter(|item| !item.is_anon_const()) + .map(|item| clean_impl_item(item, cx)) .collect::>(); // If this impl block is a positive implementation of the Deref trait, then we diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9acf150b3b354..4c8793c2cd4a6 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -32,11 +32,11 @@ use crate::{html, opts, theme}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub(crate) enum OutputFormat { - /// `--output-format=json` without `--show-coverage`. + /// `--output-format=json` without `--coverage`. /// /// JSON description of crate API. IrJson, - /// `--output-format=json` with `--show-coverage`. + /// `--output-format=json` with `--coverage`. CoverageJson, Html, Doctest, @@ -151,7 +151,7 @@ pub(crate) struct Options { pub(crate) crate_version: Option, /// The format that we output when rendering. /// - /// Currently used only for the `--show-coverage` option. + /// Currently used only for the `--coverage` option. pub(crate) output_format: OutputFormat, /// If this option is set to `true`, rustdoc will only run checks and not generate /// documentation. @@ -437,7 +437,7 @@ impl Options { check_deprecated_options(matches, dcx); let should_test = matches.opt_present("test"); - let show_coverage = matches.opt_present("show-coverage"); + let show_coverage = matches.opt_present("coverage"); let output_format_s = matches.opt_str("output-format"); let output_format = match output_format_s.as_deref() { None | Some("html") => OutputFormat::Html, @@ -452,7 +452,7 @@ impl Options { Some(other) => dcx.fatal(format!("unknown output format `{other}`")), }; - // check for `--output-format` stability, and compatibility with `--show-coverage` + // check for `--output-format` stability, and compatibility with `--coverage` match ( output_format_s.as_ref().map(|_| output_format), show_coverage, @@ -461,7 +461,7 @@ impl Options { (None | Some(OutputFormat::CoverageJson), true, _) => {} (_, true, _) => { dcx.fatal(format!( - "`--output-format={}` is not supported for the `--show-coverage` option", + "`--output-format={}` is not supported for the `--coverage` option", output_format_s.expect("checked for none above"), )); } @@ -715,7 +715,7 @@ impl Options { } (None, None) => { if show_coverage { - // If no `-o` option is given and we're in the `--show-coverage` mode, by + // If no `-o` option is given and we're in the `--coverage` mode, by // default we print on the stdout. output_to_stdout = true; } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0c3995f1d3620..ff60e7dd5b00f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -144,7 +144,7 @@ impl<'tcx> DocContext<'tcx> { /// Returns `true` if the JSON output format is enabled for generating the crate content. /// - /// If another option like `--show-coverage` is enabled, it will return `false`. + /// If another option like `--coverage` is enabled, it will return `false`. pub(crate) fn is_json_output(&self) -> bool { self.output_format == OutputFormat::IrJson } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 11bf38b1e4084..a7d0b0251310b 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -546,13 +546,8 @@ function preLoadCss(cssUrl) { if (ev !== null && window.searchState.isDisplayed() && ev.newURL) { // This block occurs when clicking on an element in the navbar while // in a search. - switchDisplayedElement(null); + window.searchState.hideResults(); const hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); - if (browserSupportsHistoryApi()) { - // `window.location.search`` contains all the query parameters, not just `search`. - history.replaceState(null, "", - getNakedUrl() + window.location.search + "#" + hash); - } const elem = document.getElementById(hash); if (elem) { elem.scrollIntoView(); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4f974b35cf0ba..9a16942a2e5bc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -499,7 +499,7 @@ fn opts() -> Vec { Unstable, FlagMulti, "", - "show-coverage", + "coverage", "calculate percentage of public items with documentation", "", ), diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 290738514b69d..f9e00d999137b 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { }) && let resolved_assoc_items = cx.tcx.associated_items(resolved_impl) // Only suggest if `clone_from`/`clone_into` is explicitly implemented - && resolved_assoc_items.in_definition_order().any(|assoc| + && resolved_assoc_items.named_items_in_definition_order().any(|assoc| match which_trait { CloneTrait::Clone => assoc.name() == sym::clone_from, CloneTrait::ToOwned => assoc.name() == sym::clone_into, diff --git a/tests/assembly-llvm/bpf-v4-atomics.rs b/tests/assembly-llvm/bpf-v4-atomics.rs new file mode 100644 index 0000000000000..ef8060302eb69 --- /dev/null +++ b/tests/assembly-llvm/bpf-v4-atomics.rs @@ -0,0 +1,148 @@ +//@ add-minicore +//@ assembly-output: emit-asm +//@ compile-flags: --target bpfel-unknown-none -Ctarget-cpu=v4 +//@ needs-llvm-components: bpf + +// Regression test for 64-bit atomic load/store on BPF. The BPF ISA *does* have +// atomic instructions and LLVM can lower them, but it only selects the 64-bit +// atomic load/store patterns (relaxed included, which lower to plain loads and +// stores) when the subtarget is the `v4` CPU. The target spec pins `cpu = "v4"`, +// so `core::io::Error`'s 64-bit `AtomicPtr` relaxed load/store (the path that +// used to fail at ISel with `Cannot select: ... AtomicLoad`) must lower here. +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +// Relaxed load/store lower to plain loads/stores (no acquire/release fence). +// CHECK-LABEL: atomic_load_relaxed: +// CHECK: r0 = *(u64 *)(r1 + 0) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_relaxed(p: *const u64) -> u64 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_store_relaxed: +// CHECK: *(u64 *)(r1 + 0) = r2 +// CHECK: exit +#[no_mangle] +pub fn atomic_store_relaxed(p: *mut u64, v: u64) { + unsafe { atomic::atomic_store::(p, v) } +} + +// Acquire load lowers to the `load_acquire` BPF instruction. +// CHECK-LABEL: atomic_load_acquire: +// CHECK: r0 = load_acquire((u64 *)(r1 + 0)) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_acquire(p: *const u64) -> u64 { + unsafe { atomic::atomic_load::(p) } +} + +// Release store lowers to the `store_release` BPF instruction. +// CHECK-LABEL: atomic_store_release: +// CHECK: store_release((u64 *)(r1 + 0), r2) +// CHECK: exit +#[no_mangle] +pub fn atomic_store_release(p: *mut u64, v: u64) { + unsafe { atomic::atomic_store::(p, v) } +} + +// CHECK-LABEL: atomic_load_relaxed8: +// CHECK: w0 = *(u8 *)(r1 + 0) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_relaxed8(p: *const u8) -> u8 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_load_acquire8: +// CHECK: w0 = load_acquire((u8 *)(r1 + 0)) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_acquire8(p: *const u8) -> u8 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_store_relaxed8: +// CHECK: *(u8 *)(r1 + 0) = w2 +// CHECK: exit +#[no_mangle] +pub fn atomic_store_relaxed8(p: *mut u8, v: u8) { + unsafe { atomic::atomic_store::(p, v) } +} + +// CHECK-LABEL: atomic_store_release8: +// CHECK: store_release((u8 *)(r1 + 0), w2) +// CHECK: exit +#[no_mangle] +pub fn atomic_store_release8(p: *mut u8, v: u8) { + unsafe { atomic::atomic_store::(p, v) } +} + +// CHECK-LABEL: atomic_load_relaxed16: +// CHECK: w0 = *(u16 *)(r1 + 0) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_relaxed16(p: *const u16) -> u16 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_load_acquire16: +// CHECK: w0 = load_acquire((u16 *)(r1 + 0)) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_acquire16(p: *const u16) -> u16 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_store_relaxed16: +// CHECK: *(u16 *)(r1 + 0) = w2 +// CHECK: exit +#[no_mangle] +pub fn atomic_store_relaxed16(p: *mut u16, v: u16) { + unsafe { atomic::atomic_store::(p, v) } +} + +// CHECK-LABEL: atomic_store_release16: +// CHECK: store_release((u16 *)(r1 + 0), w2) +// CHECK: exit +#[no_mangle] +pub fn atomic_store_release16(p: *mut u16, v: u16) { + unsafe { atomic::atomic_store::(p, v) } +} + +// CHECK-LABEL: atomic_load_relaxed32: +// CHECK: w0 = *(u32 *)(r1 + 0) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_relaxed32(p: *const u32) -> u32 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_load_acquire32: +// CHECK: w0 = load_acquire((u32 *)(r1 + 0)) +// CHECK: exit +#[no_mangle] +pub fn atomic_load_acquire32(p: *const u32) -> u32 { + unsafe { atomic::atomic_load::(p) } +} + +// CHECK-LABEL: atomic_store_relaxed32: +// CHECK: *(u32 *)(r1 + 0) = w2 +// CHECK: exit +#[no_mangle] +pub fn atomic_store_relaxed32(p: *mut u32, v: u32) { + unsafe { atomic::atomic_store::(p, v) } +} + +// CHECK-LABEL: atomic_store_release32: +// CHECK: store_release((u32 *)(r1 + 0), w2) +// CHECK: exit +#[no_mangle] +pub fn atomic_store_release32(p: *mut u32, v: u32) { + unsafe { atomic::atomic_store::(p, v) } +} diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index e7e924f9ebc08..f4a6929063c33 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -22,6 +22,7 @@ no_core, intrinsics, lang_items, + adt_const_params, auto_traits, freeze_impls, negative_impls, @@ -381,6 +382,33 @@ trait Drop { #[rustc_intrinsic] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); +pub enum AtomicOrdering { + Relaxed = 0, + Release = 1, + Acquire = 2, + AcqRel = 3, + SeqCst = 4, +} + +impl ConstParamTy_ for AtomicOrdering {} + +pub mod atomic { + use super::{AtomicOrdering, Copy}; + + #[rustc_nounwind] + #[rustc_intrinsic] + pub const unsafe fn atomic_load( + src: *const T, + ) -> T; + + #[rustc_nounwind] + #[rustc_intrinsic] + pub const unsafe fn atomic_store( + dst: *mut T, + val: T, + ); +} + pub mod mem { #[rustc_nounwind] #[rustc_intrinsic] @@ -490,6 +518,21 @@ impl Copy for Ordering {} #[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] pub trait ConstParamTy_ {} +impl ConstParamTy_ for usize {} +impl ConstParamTy_ for u8 {} +impl ConstParamTy_ for u16 {} +impl ConstParamTy_ for u32 {} +impl ConstParamTy_ for u64 {} +impl ConstParamTy_ for u128 {} +impl ConstParamTy_ for isize {} +impl ConstParamTy_ for i8 {} +impl ConstParamTy_ for i16 {} +impl ConstParamTy_ for i32 {} +impl ConstParamTy_ for i64 {} +impl ConstParamTy_ for i128 {} +impl ConstParamTy_ for bool {} +impl ConstParamTy_ for char {} + pub enum SimdAlign { // These values must match the compiler's `SimdAlign` defined in // `rustc_middle/src/ty/consts/int.rs`! diff --git a/tests/run-make/rustdoc-show-coverage/rmake.rs b/tests/run-make/rustdoc-show-coverage/rmake.rs index 90ad50267b8ad..43cfdcb26976a 100644 --- a/tests/run-make/rustdoc-show-coverage/rmake.rs +++ b/tests/run-make/rustdoc-show-coverage/rmake.rs @@ -1,4 +1,4 @@ -// This test ensures that `-o` option works as expected with `--show-coverage`. +// This test ensures that `-o` option works as expected with `--coverage`. // Regression test for . //@ needs-target-std @@ -12,7 +12,7 @@ fn run_rustdoc(extra_args: &[&str]) -> String { rustdoc() .input("foo.rs") .arg("-Zunstable-options") - .arg("--show-coverage") + .arg("--coverage") .args(extra_args) .run() .stdout_utf8() diff --git a/tests/run-make/rustdoc/default-output/output-default.stdout b/tests/run-make/rustdoc/default-output/output-default.stdout index 346140b2d921c..7178f53cb2120 100644 --- a/tests/run-make/rustdoc/default-output/output-default.stdout +++ b/tests/run-make/rustdoc/default-output/output-default.stdout @@ -140,8 +140,7 @@ Options: to reach the documentation root. --persist-doctests PATH Directory to persist doctest executables into - --show-coverage - calculate percentage of public items with + --coverage calculate percentage of public items with documentation --test-runtool The tool to run tests with when building for a different target than host diff --git a/tests/rustdoc-gui/search-button-sidebar-anchor.goml b/tests/rustdoc-gui/search-button-sidebar-anchor.goml new file mode 100644 index 0000000000000..7cad070fe6086 --- /dev/null +++ b/tests/rustdoc-gui/search-button-sidebar-anchor.goml @@ -0,0 +1,15 @@ +// This test ensures that clicking on a sidebar anchor while the search is open closes the +// search, resets the search button and removes the search query from the URL. +include: "utils.goml" + +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" + +call-function: ("open-search", {}) +assert-text: ("#search-button a span.label", "Exit") +assert-document-property: ({"URL": "struct.Foo.html?search="}, CONTAINS) + +click: "//*[@class='sidebar']//a[@href='#method.must_use']" +wait-for: "#not-displayed #search" +assert-attribute: ("#main-content", {"class": "content"}) +assert-text: ("#search-button a span.label", "Search") +assert-document-property: ({"URL": "struct.Foo.html#method.must_use"}, ENDS_WITH) diff --git a/tests/rustdoc-html/associated-const-underscore.rs b/tests/rustdoc-html/associated-const-underscore.rs new file mode 100644 index 0000000000000..ab2b3bc6cf1d3 --- /dev/null +++ b/tests/rustdoc-html/associated-const-underscore.rs @@ -0,0 +1,11 @@ +#![feature(associated_const_underscore)] + +pub struct Struct; + +impl Struct { + //@ has associated_const_underscore/struct.Struct.html '//*[@id="associatedconstant.NAMED"]' '' + pub const NAMED: () = (); + + //@ !has associated_const_underscore/struct.Struct.html '//*[@id="associatedconstant._"]' '' + pub const _: () = (); +} diff --git a/tests/rustdoc-json/associated-const-underscore.rs b/tests/rustdoc-json/associated-const-underscore.rs new file mode 100644 index 0000000000000..8626dabaacfdd --- /dev/null +++ b/tests/rustdoc-json/associated-const-underscore.rs @@ -0,0 +1,11 @@ +#![feature(associated_const_underscore)] + +pub struct Struct; + +impl Struct { + //@ has "$..index[?(@.name=='NAMED')].inner.assoc_const" + pub const NAMED: () = (); + + //@ !has "$..index[?(@.name=='_')]" + pub const _: () = (); +} diff --git a/tests/rustdoc-ui/coverage/allow_missing_docs.rs b/tests/rustdoc-ui/coverage/allow_missing_docs.rs index feca5a1bfe3e9..86a4f211fb6b9 100644 --- a/tests/rustdoc-ui/coverage/allow_missing_docs.rs +++ b/tests/rustdoc-ui/coverage/allow_missing_docs.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass //! Make sure to have some docs on your crate root diff --git a/tests/rustdoc-ui/coverage/basic.rs b/tests/rustdoc-ui/coverage/basic.rs index fc44f6826cb9c..99c2305baf95c 100644 --- a/tests/rustdoc-ui/coverage/basic.rs +++ b/tests/rustdoc-ui/coverage/basic.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass #![feature(extern_types)] diff --git a/tests/rustdoc-ui/coverage/doc-examples-json.rs b/tests/rustdoc-ui/coverage/doc-examples-json.rs index bfec2600cb875..8aa5c5c4c1267 100644 --- a/tests/rustdoc-ui/coverage/doc-examples-json.rs +++ b/tests/rustdoc-ui/coverage/doc-examples-json.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:-Z unstable-options --output-format json --show-coverage -o - +//@ compile-flags:-Z unstable-options --output-format json --coverage -o - // This check ensures that only one doc example is counted since they're "optional" on // certain items. diff --git a/tests/rustdoc-ui/coverage/doc-examples.rs b/tests/rustdoc-ui/coverage/doc-examples.rs index dd8969f934ee2..b0ce9bd5e50b9 100644 --- a/tests/rustdoc-ui/coverage/doc-examples.rs +++ b/tests/rustdoc-ui/coverage/doc-examples.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass //! This test ensure that only rust code examples are counted. diff --git a/tests/rustdoc-ui/coverage/doctest-output.rs b/tests/rustdoc-ui/coverage/doctest-output.rs index 28364c3a3ea5e..2fcbf5ed408a1 100644 --- a/tests/rustdoc-ui/coverage/doctest-output.rs +++ b/tests/rustdoc-ui/coverage/doctest-output.rs @@ -1,3 +1,3 @@ -//@ compile-flags:-Z unstable-options --show-coverage --output-format=doctest +//@ compile-flags:-Z unstable-options --coverage --output-format=doctest -//~? ERROR `--output-format=doctest` is not supported for the `--show-coverage` option +//~? ERROR `--output-format=doctest` is not supported for the `--coverage` option diff --git a/tests/rustdoc-ui/coverage/doctest-output.stderr b/tests/rustdoc-ui/coverage/doctest-output.stderr index 20c618dc61b16..8f6deeb9fa213 100644 --- a/tests/rustdoc-ui/coverage/doctest-output.stderr +++ b/tests/rustdoc-ui/coverage/doctest-output.stderr @@ -1,2 +1,2 @@ -error: `--output-format=doctest` is not supported for the `--show-coverage` option +error: `--output-format=doctest` is not supported for the `--coverage` option diff --git a/tests/rustdoc-ui/coverage/empty.rs b/tests/rustdoc-ui/coverage/empty.rs index fd9f1e617fbec..f2c6ceca8edcb 100644 --- a/tests/rustdoc-ui/coverage/empty.rs +++ b/tests/rustdoc-ui/coverage/empty.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass // an empty crate still has one item to document: the crate root diff --git a/tests/rustdoc-ui/coverage/enum-tuple-documented.rs b/tests/rustdoc-ui/coverage/enum-tuple-documented.rs index 9e88e896f8da7..0972610b09e32 100644 --- a/tests/rustdoc-ui/coverage/enum-tuple-documented.rs +++ b/tests/rustdoc-ui/coverage/enum-tuple-documented.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass // The point of this test is to ensure that the number of "documented" items diff --git a/tests/rustdoc-ui/coverage/enum-tuple.rs b/tests/rustdoc-ui/coverage/enum-tuple.rs index 25d3c9f57bafe..6a4b2bdbf6db1 100644 --- a/tests/rustdoc-ui/coverage/enum-tuple.rs +++ b/tests/rustdoc-ui/coverage/enum-tuple.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass //! (remember the crate root is still a module) diff --git a/tests/rustdoc-ui/coverage/enums.rs b/tests/rustdoc-ui/coverage/enums.rs index bdb213c2a53b7..5db9e97c8fe52 100644 --- a/tests/rustdoc-ui/coverage/enums.rs +++ b/tests/rustdoc-ui/coverage/enums.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass //! (remember the crate root is still a module) diff --git a/tests/rustdoc-ui/coverage/exotic.rs b/tests/rustdoc-ui/coverage/exotic.rs index 947ff43713b44..b84a52df921d9 100644 --- a/tests/rustdoc-ui/coverage/exotic.rs +++ b/tests/rustdoc-ui/coverage/exotic.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass #![feature(rustdoc_internals)] diff --git a/tests/rustdoc-ui/coverage/html.rs b/tests/rustdoc-ui/coverage/html.rs index 7fd080f075824..402d5b3836fa4 100644 --- a/tests/rustdoc-ui/coverage/html.rs +++ b/tests/rustdoc-ui/coverage/html.rs @@ -1,6 +1,6 @@ -//@ compile-flags:-Z unstable-options --output-format html --show-coverage +//@ compile-flags:-Z unstable-options --output-format html --coverage /// Foo pub struct Xo; -//~? ERROR `--output-format=html` is not supported for the `--show-coverage` option +//~? ERROR `--output-format=html` is not supported for the `--coverage` option diff --git a/tests/rustdoc-ui/coverage/html.stderr b/tests/rustdoc-ui/coverage/html.stderr index 764179820c5ba..457163ea2e4a0 100644 --- a/tests/rustdoc-ui/coverage/html.stderr +++ b/tests/rustdoc-ui/coverage/html.stderr @@ -1,2 +1,2 @@ -error: `--output-format=html` is not supported for the `--show-coverage` option +error: `--output-format=html` is not supported for the `--coverage` option diff --git a/tests/rustdoc-ui/coverage/json.rs b/tests/rustdoc-ui/coverage/json.rs index dcab7df252249..cbedebe308389 100644 --- a/tests/rustdoc-ui/coverage/json.rs +++ b/tests/rustdoc-ui/coverage/json.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:-Z unstable-options --output-format json --show-coverage -o - +//@ compile-flags:-Z unstable-options --output-format json --coverage -o - pub mod foo { /// Hello! diff --git a/tests/rustdoc-ui/coverage/output-format-coveragejson-emit-depinfo.rs b/tests/rustdoc-ui/coverage/output-format-coveragejson-emit-depinfo.rs index 97cdedecb0aaf..4c1c36b93b82a 100644 --- a/tests/rustdoc-ui/coverage/output-format-coveragejson-emit-depinfo.rs +++ b/tests/rustdoc-ui/coverage/output-format-coveragejson-emit-depinfo.rs @@ -1,2 +1,2 @@ -//@ compile-flags: --show-coverage --output-format=json --emit=dep-info -Zunstable-options -o - +//@ compile-flags: --coverage --output-format=json --emit=dep-info -Zunstable-options -o - //@ build-pass diff --git a/tests/rustdoc-ui/coverage/output-format-json-emit-html.rs b/tests/rustdoc-ui/coverage/output-format-json-emit-html.rs index f97392bab5b68..9bf47d11c8008 100644 --- a/tests/rustdoc-ui/coverage/output-format-json-emit-html.rs +++ b/tests/rustdoc-ui/coverage/output-format-json-emit-html.rs @@ -1,9 +1,9 @@ //@ revisions: html_static html_non_static html_static_coverage html_non_static_coverage //@ compile-flags: -Zunstable-options --output-format json //@[html_static] compile-flags: --emit html-static-files -//@[html_static_coverage] compile-flags: --emit html-static-files --show-coverage +//@[html_static_coverage] compile-flags: --emit html-static-files --coverage //@[html_non_static] compile-flags: --emit html-non-static-files -//@[html_non_static_coverage] compile-flags: --emit html-non-static-files --show-coverage +//@[html_non_static_coverage] compile-flags: --emit html-non-static-files --coverage //[html_static]~? ERROR the `--emit=html-static-files` flag is not supported with `--output-format=json` //[html_static_coverage]~? ERROR the `--emit=html-static-files` flag is not supported with `--output-format=json` diff --git a/tests/rustdoc-ui/coverage/private.rs b/tests/rustdoc-ui/coverage/private.rs index 3b78c5d761dbc..8cb59d962b2be 100644 --- a/tests/rustdoc-ui/coverage/private.rs +++ b/tests/rustdoc-ui/coverage/private.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage --document-private-items -o - +//@ compile-flags:-Z unstable-options --coverage --document-private-items -o - //@ check-pass #![allow(unused)] diff --git a/tests/rustdoc-ui/coverage/show-coverage-json-emit-html-non-static.rs b/tests/rustdoc-ui/coverage/show-coverage-json-emit-html-non-static.rs index b0f67a3b4195e..225eba039f30f 100644 --- a/tests/rustdoc-ui/coverage/show-coverage-json-emit-html-non-static.rs +++ b/tests/rustdoc-ui/coverage/show-coverage-json-emit-html-non-static.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z unstable-options --show-coverage --output-format=json --emit=html-non-static-files +//@ compile-flags: -Z unstable-options --coverage --output-format=json --emit=html-non-static-files //@ check-fail //~? ERROR the `--emit=html-non-static-files` flag is not supported with `--output-format=json` diff --git a/tests/rustdoc-ui/coverage/show-coverage-json.rs b/tests/rustdoc-ui/coverage/show-coverage-json.rs index e7ddc69d79f8a..5929d6fa105c0 100644 --- a/tests/rustdoc-ui/coverage/show-coverage-json.rs +++ b/tests/rustdoc-ui/coverage/show-coverage-json.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z unstable-options --show-coverage --output-format=json -o - +//@ compile-flags: -Z unstable-options --coverage --output-format=json -o - //@ check-pass mod bar { diff --git a/tests/rustdoc-ui/coverage/show-coverage.rs b/tests/rustdoc-ui/coverage/show-coverage.rs index 1f9c3a8f805b7..8995974566c4b 100644 --- a/tests/rustdoc-ui/coverage/show-coverage.rs +++ b/tests/rustdoc-ui/coverage/show-coverage.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z unstable-options --show-coverage -o - +//@ compile-flags: -Z unstable-options --coverage -o - //@ check-pass mod bar { diff --git a/tests/rustdoc-ui/coverage/statics-consts.rs b/tests/rustdoc-ui/coverage/statics-consts.rs index 5177673f7958a..75e88cc64bcbd 100644 --- a/tests/rustdoc-ui/coverage/statics-consts.rs +++ b/tests/rustdoc-ui/coverage/statics-consts.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass //! gotta make sure we can count statics and consts correctly, too diff --git a/tests/rustdoc-ui/coverage/traits.rs b/tests/rustdoc-ui/coverage/traits.rs index 37e147004d714..fd57fc8ff3b43 100644 --- a/tests/rustdoc-ui/coverage/traits.rs +++ b/tests/rustdoc-ui/coverage/traits.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Z unstable-options --show-coverage -o - +//@ compile-flags:-Z unstable-options --coverage -o - //@ check-pass #![feature(trait_alias)] diff --git a/tests/ui/associated-consts/associated-const-underscore-dead-code.rs b/tests/ui/associated-consts/associated-const-underscore-dead-code.rs new file mode 100644 index 0000000000000..866d67eee6f3b --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore-dead-code.rs @@ -0,0 +1,13 @@ +#![feature(associated_const_underscore)] +#![deny(dead_code)] + +fn main() {} + +struct Struct {} + +impl Struct { + const _: () = { + struct Unused; + //~^ ERROR: struct `Unused` is never constructed [dead_code] + }; +} diff --git a/tests/ui/associated-consts/associated-const-underscore-dead-code.stderr b/tests/ui/associated-consts/associated-const-underscore-dead-code.stderr new file mode 100644 index 0000000000000..246b145076f13 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore-dead-code.stderr @@ -0,0 +1,14 @@ +error: struct `Unused` is never constructed + --> $DIR/associated-const-underscore-dead-code.rs:10:16 + | +LL | struct Unused; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/associated-const-underscore-dead-code.rs:2:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/associated-consts/associated-const-underscore-fail.rs b/tests/ui/associated-consts/associated-const-underscore-fail.rs new file mode 100644 index 0000000000000..f1fcdab96b137 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore-fail.rs @@ -0,0 +1,41 @@ +#![feature(associated_const_underscore)] + +fn main() {} + +pub struct Struct; + +impl Struct { + const _: () = { + let _ = Struct; + }; + // typeck + const _: u32 = "not a number"; + //~^ ERROR mismatched types +} + +trait InvalidTrait { + const _: (); + //~^ ERROR `const` items in this context need a name +} + +trait Trait {} + +struct Type; + +impl Trait for Type { + const _: () = (); + //~^ ERROR `const` items in this context need a name + //~| ERROR const `_` is not a member of trait `Trait` +} + +struct Local; + +impl std::thread::Thread { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined + const _: () = (); +} + +impl &Local { + //~^ ERROR cannot define inherent `impl` for primitive types + const _: () = (); +} diff --git a/tests/ui/associated-consts/associated-const-underscore-fail.stderr b/tests/ui/associated-consts/associated-const-underscore-fail.stderr new file mode 100644 index 0000000000000..a56b3415bd7be --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore-fail.stderr @@ -0,0 +1,48 @@ +error: `const` items in this context need a name + --> $DIR/associated-const-underscore-fail.rs:17:11 + | +LL | const _: (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/associated-const-underscore-fail.rs:26:11 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error[E0438]: const `_` is not a member of trait `Trait` + --> $DIR/associated-const-underscore-fail.rs:26:5 + | +LL | const _: () = (); + | ^^^^^^^^^^^^^^^^^ not a member of trait `Trait` + +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/associated-const-underscore-fail.rs:33:1 + | +LL | impl std::thread::Thread { + | ^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate + | + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/associated-const-underscore-fail.rs:38:1 + | +LL | impl &Local { + | ^^^^^^^^^^^ + | + = help: consider using an extension trait instead + = note: you could also try moving the reference to uses of `Local` (such as `self`) within the implementation + +error[E0308]: mismatched types + --> $DIR/associated-const-underscore-fail.rs:12:20 + | +LL | const _: u32 = "not a number"; + | --- ^^^^^^^^^^^^^^ expected `u32`, found `&str` + | | + | expected because of the type of the associated constant + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0116, E0308, E0390, E0438. +For more information about an error, try `rustc --explain E0116`. diff --git a/tests/ui/associated-consts/associated-const-underscore-visibility.rs b/tests/ui/associated-consts/associated-const-underscore-visibility.rs new file mode 100644 index 0000000000000..52fefed006e27 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore-visibility.rs @@ -0,0 +1,20 @@ +#![feature(associated_const_underscore)] +#![deny(private_interfaces)] +fn main() {} + +pub struct Public; +struct Private; + +impl Public { + pub const _: Private = Private; + //~^ ERROR: type `Private` is more private than the item `Public::_` [private_interfaces] +} + +impl Public { + const _: Private = Private; +} + +impl Private { + pub const _: Private = Private; + pub const _: () = {}; +} diff --git a/tests/ui/associated-consts/associated-const-underscore-visibility.stderr b/tests/ui/associated-consts/associated-const-underscore-visibility.stderr new file mode 100644 index 0000000000000..9a055038ad52c --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore-visibility.stderr @@ -0,0 +1,19 @@ +error: type `Private` is more private than the item `Public::_` + --> $DIR/associated-const-underscore-visibility.rs:9:5 + | +LL | pub const _: Private = Private; + | ^^^^^^^^^^^^^^^^^^^^ associated constant `Public::_` is reachable at visibility `pub` + | +note: but type `Private` is only usable at visibility `pub(crate)` + --> $DIR/associated-const-underscore-visibility.rs:6:1 + | +LL | struct Private; + | ^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/associated-const-underscore-visibility.rs:2:9 + | +LL | #![deny(private_interfaces)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/associated-consts/associated-const-underscore.rs b/tests/ui/associated-consts/associated-const-underscore.rs new file mode 100644 index 0000000000000..d1a79c5636663 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-underscore.rs @@ -0,0 +1,75 @@ +//@ check-pass + +#![feature(associated_const_underscore)] + +use std::mem; + +struct Struct(T); + +impl Struct { + const _: () = { + let _: Option; + }; + + const _: i16 = 0; +} + +impl Struct { + const _: () = (); +} + +type Field<'a, T> = &'a mut T; + +struct Thing<'a, T> { + field: Field<'a, T>, +} + +impl<'a, T: Eq> Thing<'a, T> { + const _: () = { + fn require_outlives<'a, T: 'a>() {} + let _ = require_outlives::<'a, T>; + let _: Option; + }; +} + +struct Unit; + +impl Unit { + // An associated const named `_` is not evaluated unless it is accessed. + // However, associated consts named `_` cannot be accessed, so this should pass. + const _: () = panic!(); + const _: () = assert!(false); + const _: [(); { + { + assert!(std::mem::size_of::() == 0) + }; + 0 + }] = []; + const _: [(); { + { + assert!(true) + }; + 0 + }] = []; +} + +struct Generic(T); + +impl Generic { + const _: () = assert!(mem::size_of::() % 2 == 0); +} + +fn main() { + let _ = Unit; + let _ = Generic([0u8; 3]); +} + +trait CfgTrait { + #[cfg(any())] + const _: () = (); +} + +impl CfgTrait for Unit { + #[cfg(any())] + const _: () = (); +} diff --git a/tests/ui/attributes/duplicated-attributes.rs b/tests/ui/attributes/duplicated-attributes.rs index 65cab297af715..31a54fb45a99a 100644 --- a/tests/ui/attributes/duplicated-attributes.rs +++ b/tests/ui/attributes/duplicated-attributes.rs @@ -7,10 +7,11 @@ #![feature(test)] #![feature(cfg_eval)] +#![feature(custom_test_frameworks)] #[test] #[test] -//~^ WARNING duplicated attribute +//~^ WARNING multiple `test` attributes fn f() {} // The following shouldn't trigger an error. The attribute is not duplicated. @@ -27,12 +28,24 @@ use test::Bencher; #[bench] #[bench] -//~^ WARNING duplicated attribute +//~^ WARNING multiple `bench` attributes fn f4(_: &mut Bencher) {} +#[test] +#[test] +//~^ WARNING multiple `test` attributes +#[test] +//~^ WARNING multiple `test` attributes +fn f5() {} + +#[test_case] +#[test_case] +//~^ WARNING multiple `test_case` attributes +struct T; + #[cfg_eval] #[cfg_eval] -//~^ WARNING duplicated attribute +//~^ WARNING multiple `cfg_eval` attributes struct S; #[cfg_eval] diff --git a/tests/ui/attributes/duplicated-attributes.stderr b/tests/ui/attributes/duplicated-attributes.stderr index 735d950b27c22..1230b90127a90 100644 --- a/tests/ui/attributes/duplicated-attributes.stderr +++ b/tests/ui/attributes/duplicated-attributes.stderr @@ -1,22 +1,75 @@ -warning: duplicated attribute +warning: multiple `test` attributes + --> $DIR/duplicated-attributes.rs:13:1 + | +LL | #[test] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here --> $DIR/duplicated-attributes.rs:12:1 | LL | #[test] | ^^^^^^^ - | = note: `#[warn(duplicate_macro_attributes)]` on by default -warning: duplicated attribute +warning: multiple `bench` attributes + --> $DIR/duplicated-attributes.rs:30:1 + | +LL | #[bench] + | ^^^^^^^^ help: remove this attribute + | +note: attribute also specified here --> $DIR/duplicated-attributes.rs:29:1 | LL | #[bench] | ^^^^^^^^ -warning: duplicated attribute +warning: multiple `test` attributes + --> $DIR/duplicated-attributes.rs:35:1 + | +LL | #[test] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here --> $DIR/duplicated-attributes.rs:34:1 | +LL | #[test] + | ^^^^^^^ + +warning: multiple `test` attributes + --> $DIR/duplicated-attributes.rs:37:1 + | +LL | #[test] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/duplicated-attributes.rs:35:1 + | +LL | #[test] + | ^^^^^^^ + +warning: multiple `test_case` attributes + --> $DIR/duplicated-attributes.rs:42:1 + | +LL | #[test_case] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/duplicated-attributes.rs:41:1 + | +LL | #[test_case] + | ^^^^^^^^^^^^ + +warning: multiple `cfg_eval` attributes + --> $DIR/duplicated-attributes.rs:47:1 + | +LL | #[cfg_eval] + | ^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/duplicated-attributes.rs:46:1 + | LL | #[cfg_eval] | ^^^^^^^^^^^ -warning: 3 warnings emitted +warning: 6 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-associated-const-underscore.rs b/tests/ui/feature-gates/feature-gate-associated-const-underscore.rs new file mode 100644 index 0000000000000..f3a8cc7179c2d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-associated-const-underscore.rs @@ -0,0 +1,10 @@ +struct Thing {} + +impl Thing { + const _: () = {}; + //~^ ERROR: naming associated constants with `_` is unstable [E0658] +} + +fn main() { + let _ = Thing {}; +} diff --git a/tests/ui/feature-gates/feature-gate-associated-const-underscore.stderr b/tests/ui/feature-gates/feature-gate-associated-const-underscore.stderr new file mode 100644 index 0000000000000..665ba9cb9dbcd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-associated-const-underscore.stderr @@ -0,0 +1,13 @@ +error[E0658]: naming associated constants with `_` is unstable + --> $DIR/feature-gate-associated-const-underscore.rs:4:11 + | +LL | const _: () = {}; + | ^ + | + = note: see issue #158944 for more information + = help: add `#![feature(associated_const_underscore)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs index d37ce06c555bf..f266e3a7cd837 100644 --- a/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs +++ b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.rs @@ -1,5 +1,4 @@ -// Semantically, an associated constant cannot use `_` as a name. - +// Semantically, a trait/trait impl associated constant cannot use _ as a name. fn main() {} const _: () = { @@ -10,8 +9,4 @@ const _: () = { const _: () = (); //~ ERROR `const` items in this context need a name //~^ ERROR const `_` is not a member of trait `A` } - struct B; - impl B { - const _: () = (); //~ ERROR `const` items in this context need a name - } }; diff --git a/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr index 538bf0ec100dc..6d7043abff802 100644 --- a/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr +++ b/tests/ui/parser/assoc/assoc-const-underscore-semantic-fail.stderr @@ -1,27 +1,21 @@ error: `const` items in this context need a name - --> $DIR/assoc-const-underscore-semantic-fail.rs:7:15 + --> $DIR/assoc-const-underscore-semantic-fail.rs:6:15 | LL | const _: () = (); | ^ `_` is not a valid name for this `const` item error: `const` items in this context need a name - --> $DIR/assoc-const-underscore-semantic-fail.rs:10:15 - | -LL | const _: () = (); - | ^ `_` is not a valid name for this `const` item - -error: `const` items in this context need a name - --> $DIR/assoc-const-underscore-semantic-fail.rs:15:15 + --> $DIR/assoc-const-underscore-semantic-fail.rs:9:15 | LL | const _: () = (); | ^ `_` is not a valid name for this `const` item error[E0438]: const `_` is not a member of trait `A` - --> $DIR/assoc-const-underscore-semantic-fail.rs:10:9 + --> $DIR/assoc-const-underscore-semantic-fail.rs:9:9 | LL | const _: () = (); | ^^^^^^^^^^^^^^^^^ not a member of trait `A` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0438`.