From 5e7610378f5dce4f3cfdaf05fbafc962d000ffcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 16 Mar 2022 00:00:00 +0000 Subject: [PATCH 01/12] Reject `#[thread_local]` attribute on non-static items --- compiler/rustc_passes/src/check_attr.rs | 16 +++++++++ src/test/ui/thread-local/non-static.rs | 30 +++++++++++++++++ src/test/ui/thread-local/non-static.stderr | 38 ++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 src/test/ui/thread-local/non-static.rs create mode 100644 src/test/ui/thread-local/non-static.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 06184b4797255..8c1d6188e7c82 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -80,6 +80,7 @@ impl CheckAttrVisitor<'_> { self.check_rustc_must_implement_one_of(attr, span, target) } sym::target_feature => self.check_target_feature(hir_id, attr, span, target), + sym::thread_local => self.check_thread_local(attr, span, target), sym::track_caller => { self.check_track_caller(hir_id, attr.span, attrs, span, target) } @@ -521,6 +522,21 @@ impl CheckAttrVisitor<'_> { } } + /// Checks if the `#[thread_local]` attribute on `item` is valid. Returns `true` if valid. + fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) -> bool { + match target { + Target::ForeignStatic | Target::Static => true, + _ => { + self.tcx + .sess + .struct_span_err(attr.span, "attribute should be applied to a static") + .span_label(span, "not a static") + .emit(); + false + } + } + } + fn doc_attr_str_error(&self, meta: &NestedMetaItem, attr_name: &str) { self.tcx .sess diff --git a/src/test/ui/thread-local/non-static.rs b/src/test/ui/thread-local/non-static.rs new file mode 100644 index 0000000000000..f1c4273870bff --- /dev/null +++ b/src/test/ui/thread-local/non-static.rs @@ -0,0 +1,30 @@ +// Check that #[thread_local] attribute is rejected on non-static items. +#![feature(thread_local)] + +#[thread_local] +//~^ ERROR attribute should be applied to a static +const A: u32 = 0; + +#[thread_local] +//~^ ERROR attribute should be applied to a static +fn main() { + #[thread_local] || {}; + //~^ ERROR attribute should be applied to a static +} + +struct S { + #[thread_local] + //~^ ERROR attribute should be applied to a static + a: String, + b: String, +} + +#[thread_local] +// Static. OK. +static B: u32 = 0; + +extern "C" { + #[thread_local] + // Foreign static. OK. + static C: u32; +} diff --git a/src/test/ui/thread-local/non-static.stderr b/src/test/ui/thread-local/non-static.stderr new file mode 100644 index 0000000000000..09a1618d6e710 --- /dev/null +++ b/src/test/ui/thread-local/non-static.stderr @@ -0,0 +1,38 @@ +error: attribute should be applied to a static + --> $DIR/non-static.rs:4:1 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ +LL | +LL | const A: u32 = 0; + | ----------------- not a static + +error: attribute should be applied to a static + --> $DIR/non-static.rs:8:1 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ +LL | +LL | / fn main() { +LL | | #[thread_local] || {}; +LL | | +LL | | } + | |_- not a static + +error: attribute should be applied to a static + --> $DIR/non-static.rs:11:5 + | +LL | #[thread_local] || {}; + | ^^^^^^^^^^^^^^^ ----- not a static + +error: attribute should be applied to a static + --> $DIR/non-static.rs:16:5 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ +LL | +LL | a: String, + | --------- not a static + +error: aborting due to 4 previous errors + From 8c2353b6c142d5665006cf79cbec511f666dbed2 Mon Sep 17 00:00:00 2001 From: Fausto Date: Fri, 18 Mar 2022 17:13:38 -0400 Subject: [PATCH 02/12] remove find_use_placement A more robust solution to finding where to place use suggestions was added. The algorithm uses the AST to find the span for the suggestion so we pass this span down to the HIR during lowering and use it. Signed-off-by: Miguel Guarniz --- compiler/rustc_ast_lowering/src/index.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 13 +- compiler/rustc_hir/src/hir.rs | 14 +- compiler/rustc_middle/src/hir/map/mod.rs | 4 +- .../rustc_save_analysis/src/dump_visitor.rs | 4 +- compiler/rustc_save_analysis/src/lib.rs | 2 +- .../rustc_typeck/src/check/method/suggest.rs | 146 +++--------------- src/librustdoc/html/render/span_map.rs | 7 +- src/librustdoc/visit_ast.rs | 2 +- src/test/ui/imports/overlapping_pub_trait.rs | 4 +- src/test/ui/imports/unnamed_pub_trait.rs | 4 +- .../ui/suggestions/use-placement-typeck.fixed | 1 - 12 files changed, 57 insertions(+), 148 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 62935a2b1f718..5eab21bf79a90 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -52,7 +52,9 @@ pub(super) fn index_hir<'hir>( }; match item { - OwnerNode::Crate(citem) => collector.visit_mod(&citem, citem.inner, hir::CRATE_HIR_ID), + OwnerNode::Crate(citem) => { + collector.visit_mod(&citem, citem.spans.inner_span, hir::CRATE_HIR_ID) + } OwnerNode::Item(item) => collector.visit_item(item), OwnerNode::TraitItem(item) => collector.visit_trait_item(item), OwnerNode::ImplItem(item) => collector.visit_impl_item(item), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c8fd96309a6cd..a8bd8c92a41c4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -124,7 +124,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); self.with_lctx(CRATE_NODE_ID, |lctx| { - let module = lctx.lower_mod(&c.items, c.spans.inner_span); + let module = lctx.lower_mod(&c.items, &c.spans); lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); hir::OwnerNode::Crate(lctx.arena.alloc(module)) }) @@ -186,9 +186,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } impl<'hir> LoweringContext<'_, 'hir> { - pub(super) fn lower_mod(&mut self, items: &[P], inner: Span) -> hir::Mod<'hir> { + pub(super) fn lower_mod(&mut self, items: &[P], spans: &ModSpans) -> hir::Mod<'hir> { hir::Mod { - inner: self.lower_span(inner), + spans: hir::ModSpans { + inner_span: self.lower_span(spans.inner_span), + inject_use_span: self.lower_span(spans.inject_use_span), + }, item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), } } @@ -308,8 +311,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } ItemKind::Mod(_, ref mod_kind) => match mod_kind { - ModKind::Loaded(items, _, ModSpans { inner_span, inject_use_span: _ }) => { - hir::ItemKind::Mod(self.lower_mod(items, *inner_span)) + ModKind::Loaded(items, _, spans) => { + hir::ItemKind::Mod(self.lower_mod(items, spans)) } ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), }, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 10871df3ab9d0..5e55ca7790180 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2522,11 +2522,17 @@ impl FnRetTy<'_> { #[derive(Encodable, Debug, HashStable_Generic)] pub struct Mod<'hir> { + pub spans: ModSpans, + pub item_ids: &'hir [ItemId], +} + +#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable)] +pub struct ModSpans { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. - pub inner: Span, - pub item_ids: &'hir [ItemId], + pub inner_span: Span, + pub inject_use_span: Span, } #[derive(Debug, HashStable_Generic)] @@ -3024,8 +3030,8 @@ impl<'hir> OwnerNode<'hir> { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) - | OwnerNode::Crate(Mod { inner: span, .. }) => *span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 561653f3bebf7..8c3b1730b1341 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -586,7 +586,7 @@ impl<'hir> Map<'hir> { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { (m, span, hir_id) } - Some(OwnerNode::Crate(item)) => (item, item.inner, hir_id), + Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {:?}", node), } } @@ -1014,7 +1014,7 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::Visibility(v) => bug!("unexpected Visibility {:?}", v), Node::Local(local) => local.span, - Node::Crate(item) => item.inner, + Node::Crate(item) => item.spans.inner_span, }; Some(span) } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 1eb575e0db2a6..22d0a20395ec7 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1095,11 +1095,11 @@ impl<'tcx> DumpVisitor<'tcx> { let sm = self.tcx.sess.source_map(); let krate_mod = self.tcx.hir().root_module(); - let filename = sm.span_to_filename(krate_mod.inner); + let filename = sm.span_to_filename(krate_mod.spans.inner_span); let data_id = id_from_hir_id(id, &self.save_ctxt); let children = krate_mod.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect(); - let span = self.span_from_span(krate_mod.inner); + let span = self.span_from_span(krate_mod.spans.inner_span); let attrs = self.tcx.hir().attrs(id); self.dumper.dump_def( diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 08a990c65fff7..102268c6ca352 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -282,7 +282,7 @@ impl<'tcx> SaveContext<'tcx> { let qualname = format!("::{}", self.tcx.def_path_str(def_id)); let sm = self.tcx.sess.source_map(); - let filename = sm.span_to_filename(m.inner); + let filename = sm.span_to_filename(m.spans.inner_span); filter!(self.span_utils, item.ident.span); diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b05f0e4d3c389..83c6b6362fece 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -7,7 +7,7 @@ use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, }; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1473,12 +1473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn suggest_use_candidates( - &self, - err: &mut Diagnostic, - mut msg: String, - candidates: Vec, - ) { + fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec) { let parent_map = self.tcx.visible_parent_map(()); // Separate out candidates that must be imported with a glob, because they are named `_` @@ -1502,80 +1497,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let module_did = self.tcx.parent_module(self.body_id); - let (span, found_use) = find_use_placement(self.tcx, module_did); - if let Some(span) = span { - let path_strings = candidates.iter().map(|trait_did| { - // Produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { "" } else { "\n" }; - format!( - "use {};\n{}", - with_crate_prefix!(self.tcx.def_path_str(*trait_did)), - additional_newline - ) - }); + let (module, _, _) = self.tcx.hir().get_module(module_did); + let span = module.spans.inject_use_span; - let glob_path_strings = globs.iter().map(|trait_did| { - let parent_did = parent_map.get(trait_did).unwrap(); + let path_strings = candidates.iter().map(|trait_did| { + format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),) + }); - // Produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { "" } else { "\n" }; - format!( - "use {}::*; // trait {}\n{}", - with_crate_prefix!(self.tcx.def_path_str(*parent_did)), - self.tcx.item_name(*trait_did), - additional_newline - ) - }); + let glob_path_strings = globs.iter().map(|trait_did| { + let parent_did = parent_map.get(trait_did).unwrap(); + format!( + "use {}::*; // trait {}\n", + with_crate_prefix!(self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + ) + }); - err.span_suggestions( - span, - &msg, - path_strings.chain(glob_path_strings), - Applicability::MaybeIncorrect, - ); - } else { - let limit = if candidates.len() + globs.len() == 5 { 5 } else { 4 }; - for (i, trait_did) in candidates.iter().take(limit).enumerate() { - if candidates.len() + globs.len() > 1 { - msg.push_str(&format!( - "\ncandidate #{}: `use {};`", - i + 1, - with_crate_prefix!(self.tcx.def_path_str(*trait_did)) - )); - } else { - msg.push_str(&format!( - "\n`use {};`", - with_crate_prefix!(self.tcx.def_path_str(*trait_did)) - )); - } - } - for (i, trait_did) in - globs.iter().take(limit.saturating_sub(candidates.len())).enumerate() - { - let parent_did = parent_map.get(trait_did).unwrap(); - - if candidates.len() + globs.len() > 1 { - msg.push_str(&format!( - "\ncandidate #{}: `use {}::*; // trait {}`", - candidates.len() + i + 1, - with_crate_prefix!(self.tcx.def_path_str(*parent_did)), - self.tcx.item_name(*trait_did), - )); - } else { - msg.push_str(&format!( - "\n`use {}::*; // trait {}`", - with_crate_prefix!(self.tcx.def_path_str(*parent_did)), - self.tcx.item_name(*trait_did), - )); - } - } - if candidates.len() > limit { - msg.push_str(&format!("\nand {} others", candidates.len() + globs.len() - limit)); - } - err.note(&msg); - } + err.span_suggestions( + span, + &msg, + path_strings.chain(glob_path_strings), + Applicability::MaybeIncorrect, + ); } fn suggest_valid_traits( @@ -2100,53 +2043,6 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() } -fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option, bool) { - // FIXME(#94854): this code uses an out-of-date method for inferring a span - // to suggest. It would be better to thread the ModSpans from the AST into - // the HIR, and then use that to drive the suggestion here. - - let mut span = None; - let mut found_use = false; - let (module, _, _) = tcx.hir().get_module(target_module); - - // Find a `use` statement. - for &item_id in module.item_ids { - let item = tcx.hir().item(item_id); - match item.kind { - hir::ItemKind::Use(..) => { - // Don't suggest placing a `use` before the prelude - // import or other generated ones. - if !item.span.from_expansion() { - span = Some(item.span.shrink_to_lo()); - found_use = true; - break; - } - } - // Don't place `use` before `extern crate`... - hir::ItemKind::ExternCrate(_) => {} - // ...but do place them before the first other item. - _ => { - if span.map_or(true, |span| item.span < span) { - if !item.span.from_expansion() { - span = Some(item.span.shrink_to_lo()); - // Don't insert between attributes and an item. - let attrs = tcx.hir().attrs(item.hir_id()); - // Find the first attribute on the item. - // FIXME: This is broken for active attributes. - for attr in attrs { - if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) { - span = Some(attr.span.shrink_to_lo()); - } - } - } - } - } - } - } - - (span, found_use) -} - fn print_disambiguation_help<'tcx>( item_name: Ident, args: Option<&'tcx [hir::Expr<'tcx>]>, diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 731e18b1eec2c..06c63ec97d7f2 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -119,11 +119,14 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) { // To make the difference between "mod foo {}" and "mod foo;". In case we "import" another // file, we want to link to it. Otherwise no need to create a link. - if !span.overlaps(m.inner) { + if !span.overlaps(m.spans.inner_span) { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". if let Some(Node::Item(item)) = self.tcx.hir().find(id) { - self.matches.insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner))); + self.matches.insert( + item.ident.span, + LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), + ); } } intravisit::walk_mod(self, m, id); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e793ee75fd2e0..75276d18fe5e9 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { m: &'tcx hir::Mod<'tcx>, name: Symbol, ) -> Module<'tcx> { - let mut om = Module::new(name, id, m.inner); + let mut om = Module::new(name, id, m.spans.inner_span); let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id(); // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; diff --git a/src/test/ui/imports/overlapping_pub_trait.rs b/src/test/ui/imports/overlapping_pub_trait.rs index f5f5d4ed3804f..69aba3ae9b4e7 100644 --- a/src/test/ui/imports/overlapping_pub_trait.rs +++ b/src/test/ui/imports/overlapping_pub_trait.rs @@ -4,10 +4,10 @@ * This crate declares two public paths, `m::Tr` and `prelude::_`. Make sure we prefer the former. */ extern crate overlapping_pub_trait_source; +//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: +//~| SUGGESTION overlapping_pub_trait_source::m::Tr fn main() { - //~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: - //~| SUGGESTION overlapping_pub_trait_source::m::Tr use overlapping_pub_trait_source::S; S.method(); //~^ ERROR no method named `method` found for struct `S` in the current scope [E0599] diff --git a/src/test/ui/imports/unnamed_pub_trait.rs b/src/test/ui/imports/unnamed_pub_trait.rs index b06b1e1d07dce..c38fb17b97649 100644 --- a/src/test/ui/imports/unnamed_pub_trait.rs +++ b/src/test/ui/imports/unnamed_pub_trait.rs @@ -5,10 +5,10 @@ * importing it by name, and instead we suggest importing it by glob. */ extern crate unnamed_pub_trait_source; +//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: +//~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr fn main() { - //~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: - //~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr use unnamed_pub_trait_source::S; S.method(); //~^ ERROR no method named `method` found for struct `S` in the current scope [E0599] diff --git a/src/test/ui/suggestions/use-placement-typeck.fixed b/src/test/ui/suggestions/use-placement-typeck.fixed index 40c55d1dd06bc..37335da060e42 100644 --- a/src/test/ui/suggestions/use-placement-typeck.fixed +++ b/src/test/ui/suggestions/use-placement-typeck.fixed @@ -7,7 +7,6 @@ #![allow(unused)] use m::Foo; - fn main() { let s = m::S; s.abc(); //~ ERROR no method named `abc` From abf2b4c04d4d6a0a2c49562fde33ae1d46e6ead7 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 28 Feb 2022 15:33:50 -0500 Subject: [PATCH 03/12] Stabilize `derive_default_enum` --- .../src/deriving/default.rs | 13 +---- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 - compiler/rustc_feature/src/lib.rs | 2 +- compiler/rustc_infer/src/lib.rs | 2 +- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_session/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 2 +- library/core/src/lib.rs | 2 +- src/test/ui/deriving/deriving-default-enum.rs | 2 - src/test/ui/deriving/deriving-with-helper.rs | 1 - .../feature-gate-derive_default_enum.rs | 7 --- .../feature-gate-derive_default_enum.stderr | 13 ----- src/test/ui/macros/macros-nonfatal-errors.rs | 1 - .../ui/macros/macros-nonfatal-errors.stderr | 58 +++++++++---------- 15 files changed, 38 insertions(+), 73 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-derive_default_enum.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index ca83941f600ca..2c5260616c7da 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -46,18 +46,7 @@ pub fn expand_deriving_default( StaticStruct(_, fields) => { default_struct_substructure(cx, trait_span, substr, fields) } - StaticEnum(enum_def, _) => { - if !cx.sess.features_untracked().derive_default_enum { - rustc_session::parse::feature_err( - cx.parse_sess(), - sym::derive_default_enum, - span, - "deriving `Default` on enums is experimental", - ) - .emit(); - } - default_enum_substructure(cx, trait_span, enum_def) - } + StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def), _ => cx.span_bug(trait_span, "method in `derive(Default)`"), } })), diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e37251c9c2439..048039343a7a2 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -126,6 +126,8 @@ declare_features! ( (accepted, default_type_params, "1.0.0", None, None), /// Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows `#[derive(Default)]` and `#[default]` on enums. + (accepted, derive_default_enum, "1.62.0", Some(86985), None), /// Allows the use of destructuring assignments. (accepted, destructuring_assignment, "1.59.0", Some(71126), None), /// Allows `#[doc(alias = "...")]`. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 28466315c8687..81863162df318 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -368,8 +368,6 @@ declare_features! ( (active, deprecated_safe, "1.61.0", Some(94978), None), /// Allows having using `suggestion` in the `#[deprecated]` attribute. (active, deprecated_suggestion, "1.61.0", Some(94785), None), - /// Allows `#[derive(Default)]` and `#[default]` on enums. - (active, derive_default_enum, "1.56.0", Some(86985), None), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. (active, doc_auto_cfg, "1.58.0", Some(43781), None), /// Allows `#[doc(cfg(...))]`. diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index bfc537cfae2cb..940c4ecdcc23a 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -11,7 +11,7 @@ //! even if it is stabilized or removed, *do not remove it*. Instead, move the //! symbol to the `accepted` or `removed` modules respectively. -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(once_cell)] mod accepted; diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 08e005364ce64..e859bcaec1206 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -17,7 +17,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(control_flow_enum)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(extend_one)] #![feature(label_break_value)] #![feature(let_chains)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index fa2dad5ce25f0..cffcd6699b6e4 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,7 +30,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(core_intrinsics)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(get_mut_unchecked)] diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 3151b025ffff7..054b18b6b633a 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,7 +1,7 @@ #![feature(crate_visibility_modifier)] -#![feature(derive_default_enum)] #![feature(if_let_guard)] #![feature(let_chains)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 7523b8441013a..2ae7f34a91e00 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -16,7 +16,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(drain_filter)] #![feature(hash_drain_filter)] #![feature(label_break_value)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 660f6d92fe184..dc6bec246b9fe 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -167,7 +167,7 @@ #![feature(const_precise_live_drops)] #![feature(const_refs_to_cell)] #![feature(decl_macro)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] diff --git a/src/test/ui/deriving/deriving-default-enum.rs b/src/test/ui/deriving/deriving-default-enum.rs index 931ff1a5847d4..d1a81c72c2fdc 100644 --- a/src/test/ui/deriving/deriving-default-enum.rs +++ b/src/test/ui/deriving/deriving-default-enum.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(derive_default_enum)] - // nb: does not impl Default #[derive(Debug, PartialEq)] struct NotDefault; diff --git a/src/test/ui/deriving/deriving-with-helper.rs b/src/test/ui/deriving/deriving-with-helper.rs index d8f0b27a2e5f6..1c30b0b6fba75 100644 --- a/src/test/ui/deriving/deriving-with-helper.rs +++ b/src/test/ui/deriving/deriving-with-helper.rs @@ -5,7 +5,6 @@ #![feature(lang_items)] #![feature(no_core)] #![feature(rustc_attrs)] -#![feature(derive_default_enum)] #![no_core] diff --git a/src/test/ui/feature-gates/feature-gate-derive_default_enum.rs b/src/test/ui/feature-gates/feature-gate-derive_default_enum.rs deleted file mode 100644 index 05a5d4e14223a..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-derive_default_enum.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[derive(Default)] //~ ERROR deriving `Default` on enums is experimental -enum Foo { - #[default] - Alpha, -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr b/src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr deleted file mode 100644 index 58dd4d508a709..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: deriving `Default` on enums is experimental - --> $DIR/feature-gate-derive_default_enum.rs:1:10 - | -LL | #[derive(Default)] - | ^^^^^^^ - | - = note: see issue #86985 for more information - = help: add `#![feature(derive_default_enum)]` to the crate attributes to enable - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs index 98f64aa6f8025..e7a01f105de0b 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.rs +++ b/src/test/ui/macros/macros-nonfatal-errors.rs @@ -5,7 +5,6 @@ #![feature(trace_macros, concat_idents)] #![feature(stmt_expr_attributes, arbitrary_enum_discriminant)] -#![feature(derive_default_enum)] use std::arch::asm; diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr index 79e8db9c1d429..b3c6d07f96763 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.stderr +++ b/src/test/ui/macros/macros-nonfatal-errors.stderr @@ -1,41 +1,41 @@ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:14:5 + --> $DIR/macros-nonfatal-errors.rs:13:5 | LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:19:36 + --> $DIR/macros-nonfatal-errors.rs:18:36 | LL | struct DefaultInnerAttrTupleStruct(#[default] ()); | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:23:1 + --> $DIR/macros-nonfatal-errors.rs:22:1 | LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:27:1 + --> $DIR/macros-nonfatal-errors.rs:26:1 | LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:37:11 + --> $DIR/macros-nonfatal-errors.rs:36:11 | LL | Foo = #[default] 0, | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:38:14 + --> $DIR/macros-nonfatal-errors.rs:37:14 | LL | Bar([u8; #[default] 1]), | ^^^^^^^^^^ error: no default declared - --> $DIR/macros-nonfatal-errors.rs:43:10 + --> $DIR/macros-nonfatal-errors.rs:42:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -44,7 +44,7 @@ LL | #[derive(Default)] = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: multiple declared defaults - --> $DIR/macros-nonfatal-errors.rs:49:10 + --> $DIR/macros-nonfatal-errors.rs:48:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -62,7 +62,7 @@ LL | Baz, = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[default]` attribute does not accept a value - --> $DIR/macros-nonfatal-errors.rs:61:5 + --> $DIR/macros-nonfatal-errors.rs:60:5 | LL | #[default = 1] | ^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | #[default = 1] = help: try using `#[default]` error: multiple `#[default]` attributes - --> $DIR/macros-nonfatal-errors.rs:69:5 + --> $DIR/macros-nonfatal-errors.rs:68:5 | LL | #[default] | ---------- `#[default]` used here @@ -81,13 +81,13 @@ LL | Foo, | = note: only one `#[default]` attribute is needed help: try removing this - --> $DIR/macros-nonfatal-errors.rs:68:5 + --> $DIR/macros-nonfatal-errors.rs:67:5 | LL | #[default] | ^^^^^^^^^^ error: multiple `#[default]` attributes - --> $DIR/macros-nonfatal-errors.rs:79:5 + --> $DIR/macros-nonfatal-errors.rs:78:5 | LL | #[default] | ---------- `#[default]` used here @@ -99,7 +99,7 @@ LL | Foo, | = note: only one `#[default]` attribute is needed help: try removing these - --> $DIR/macros-nonfatal-errors.rs:76:5 + --> $DIR/macros-nonfatal-errors.rs:75:5 | LL | #[default] | ^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:86:5 + --> $DIR/macros-nonfatal-errors.rs:85:5 | LL | Foo {}, | ^^^ @@ -117,7 +117,7 @@ LL | Foo {}, = help: consider a manual implementation of `Default` error: default variant must be exhaustive - --> $DIR/macros-nonfatal-errors.rs:94:5 + --> $DIR/macros-nonfatal-errors.rs:93:5 | LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here @@ -127,37 +127,37 @@ LL | Foo, = help: consider a manual implementation of `Default` error: asm template must be a string literal - --> $DIR/macros-nonfatal-errors.rs:99:10 + --> $DIR/macros-nonfatal-errors.rs:98:10 | LL | asm!(invalid); | ^^^^^^^ error: concat_idents! requires ident args - --> $DIR/macros-nonfatal-errors.rs:102:5 + --> $DIR/macros-nonfatal-errors.rs:101:5 | LL | concat_idents!("not", "idents"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:104:17 + --> $DIR/macros-nonfatal-errors.rs:103:17 | LL | option_env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:105:10 + --> $DIR/macros-nonfatal-errors.rs:104:10 | LL | env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:106:10 + --> $DIR/macros-nonfatal-errors.rs:105:10 | LL | env!(foo, abr, baz); | ^^^ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined - --> $DIR/macros-nonfatal-errors.rs:107:5 + --> $DIR/macros-nonfatal-errors.rs:106:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:109:13 + --> $DIR/macros-nonfatal-errors.rs:108:13 | LL | format!(invalid); | ^^^^^^^ @@ -176,19 +176,19 @@ LL | format!("{}", invalid); | +++++ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:111:14 + --> $DIR/macros-nonfatal-errors.rs:110:14 | LL | include!(invalid); | ^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:113:18 + --> $DIR/macros-nonfatal-errors.rs:112:18 | LL | include_str!(invalid); | ^^^^^^^ error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/macros-nonfatal-errors.rs:114:5 + --> $DIR/macros-nonfatal-errors.rs:113:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,13 +196,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed") = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:115:20 + --> $DIR/macros-nonfatal-errors.rs:114:20 | LL | include_bytes!(invalid); | ^^^^^^^ error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/macros-nonfatal-errors.rs:116:5 + --> $DIR/macros-nonfatal-errors.rs:115:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -210,13 +210,13 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: trace_macros! accepts only `true` or `false` - --> $DIR/macros-nonfatal-errors.rs:118:5 + --> $DIR/macros-nonfatal-errors.rs:117:5 | LL | trace_macros!(invalid); | ^^^^^^^^^^^^^^^^^^^^^^ error: cannot find macro `llvm_asm` in this scope - --> $DIR/macros-nonfatal-errors.rs:100:5 + --> $DIR/macros-nonfatal-errors.rs:99:5 | LL | llvm_asm!(invalid); | ^^^^^^^^ From a3dd654ae9f9002d3ff47e45a9a9b6afcb484d2f Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Tue, 8 Mar 2022 15:44:52 -0500 Subject: [PATCH 04/12] Add documentation --- library/core/src/default.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/core/src/default.rs b/library/core/src/default.rs index fb862f7df947b..1ce00828bf344 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -52,6 +52,23 @@ /// This trait can be used with `#[derive]` if all of the type's fields implement /// `Default`. When `derive`d, it will use the default value for each field's type. /// +/// ### `enum`s +/// +/// When using `#[derive(Default)]` on an `enum`, you need to choose which unit variant will be +/// default. You do this by placing the `#[default]` attribute on the variant. +/// +/// ``` +/// #[derive(Default)] +/// enum Kind { +/// #[default] +/// A, +/// B, +/// C, +/// } +/// ``` +/// +/// You cannot use the `#[default]` attribute on non-unit or non-exhaustive variants. +/// /// ## How can I implement `Default`? /// /// Provide an implementation for the `default()` method that returns the value of From d5f3863204b655ad4498f08c3a02dc320b7b6ea1 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Wed, 13 Apr 2022 05:42:28 -0400 Subject: [PATCH 05/12] Consider lifetimes when comparing types for equality in MIR validator --- compiler/rustc_const_eval/src/transform/validate.rs | 7 +++---- compiler/rustc_middle/src/mir/mod.rs | 3 ++- .../mir/issue-95978-validator-lifetime-comparison.rs | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 01af95851357e..79d427ccc4469 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -315,9 +315,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | ty::FnPtr(..) ) } - // None of the possible types have lifetimes, so we can just compare - // directly - if a != b { + // The function pointer types can have lifetimes + if !self.mir_assign_valid_types(a, b) { self.fail( location, format!("Cannot compare unequal types {:?} and {:?}", a, b), @@ -464,7 +463,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; // since CopyNonOverlapping is parametrized by 1 type, // we only need to check that they are equal and not keep an extra parameter. - if op_src_ty != op_dst_ty { + if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) { self.fail(location, format!("bad arg ({:?} != {:?})", op_src_ty, op_dst_ty)); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9f7832c8a64a2..bceacc2e374f2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2518,7 +2518,8 @@ pub enum Rvalue<'tcx> { /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second /// parameter may be a `usize` as well. /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, - /// raw pointers, or function pointers of matching types and return a `bool`. + /// raw pointers, or function pointers and return a `bool`. The types of the operands must be + /// matching, up to the usual caveat of the lifetimes in function pointers. /// * Left and right shift operations accept signed or unsigned integers not necessarily of the /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is /// truncated as needed. diff --git a/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs b/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs new file mode 100644 index 0000000000000..cd6c5bf271935 --- /dev/null +++ b/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Zvalidate-mir + +fn foo(_a: &str) {} + +fn main() { + let x = foo as fn(&'static str); + + let _ = x == foo; +} From 4a0f8d517529cdaca6750966536052b5104b05be Mon Sep 17 00:00:00 2001 From: rainy-me Date: Thu, 14 Apr 2022 03:22:02 +0900 Subject: [PATCH 06/12] improve diagnostics for unterminated nested block comment --- compiler/rustc_parse/src/lexer/mod.rs | 63 ++++++++++++++++--- src/test/ui/unterminated-nested-comment.rs | 4 ++ .../ui/unterminated-nested-comment.stderr | 21 +++++++ 3 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/unterminated-nested-comment.rs create mode 100644 src/test/ui/unterminated-nested-comment.stderr diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 5ab412dc777de..96513958eb06b 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -182,16 +182,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => { if !terminated { - let msg = match doc_style { - Some(_) => "unterminated block doc-comment", - None => "unterminated block comment", - }; - let last_bpos = self.pos; - self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start, last_bpos), - msg, - error_code!(E0758), - ); + self.report_unterminated_block_comment(start, doc_style); } // Skip non-doc comments @@ -553,6 +544,58 @@ impl<'a> StringReader<'a> { err.emit() } + fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option) { + let msg = match doc_style { + Some(_) => "unterminated block doc-comment", + None => "unterminated block comment", + }; + let last_bpos = self.pos; + let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code( + self.mk_sp(start, last_bpos), + msg, + error_code!(E0758), + ); + let mut nested_block_comment_open_idxs = vec![]; + let mut last_nested_block_comment_idxs = None; + let mut content_chars = self.str_from(start).char_indices(); + + if let Some((_, mut last_char)) = content_chars.next() { + while let Some((idx, c)) = content_chars.next() { + match c { + '*' if last_char == '/' => { + nested_block_comment_open_idxs.push(idx); + } + '/' if last_char == '*' => { + last_nested_block_comment_idxs = + nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx)); + } + _ => {} + }; + last_char = c; + } + } + + if let Some((nested_open_idx, nested_close_idx)) = last_nested_block_comment_idxs { + err.span_label(self.mk_sp(start, start + BytePos(2)), msg) + .span_label( + self.mk_sp( + start + BytePos(nested_open_idx as u32 - 1), + start + BytePos(nested_open_idx as u32 + 1), + ), + "...as last nested comment starts here, maybe you want to close this instead?", + ) + .span_label( + self.mk_sp( + start + BytePos(nested_close_idx as u32 - 1), + start + BytePos(nested_close_idx as u32 + 1), + ), + "...and last nested comment terminates here", + ); + } + + err.emit(); + } + // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021, // using a (unknown) prefix is an error. In earlier editions, however, they // only result in a (allowed by default) lint, and are treated as regular diff --git a/src/test/ui/unterminated-nested-comment.rs b/src/test/ui/unterminated-nested-comment.rs new file mode 100644 index 0000000000000..db5f2f3ba1358 --- /dev/null +++ b/src/test/ui/unterminated-nested-comment.rs @@ -0,0 +1,4 @@ +/* //~ ERROR E0758 +/* */ +/* +*/ diff --git a/src/test/ui/unterminated-nested-comment.stderr b/src/test/ui/unterminated-nested-comment.stderr new file mode 100644 index 0000000000000..eda8f2dcd2469 --- /dev/null +++ b/src/test/ui/unterminated-nested-comment.stderr @@ -0,0 +1,21 @@ +error[E0758]: unterminated block comment + --> $DIR/unterminated-nested-comment.rs:1:1 + | +LL | /* + | ^- + | | + | _unterminated block comment + | | +LL | | /* */ +LL | | /* + | | -- + | | | + | | ...as last nested comment starts here, maybe you want to close this instead? +LL | | */ + | |_--^ + | | + | ...and last nested comment terminates here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0758`. From 849ede1cee9cca22683f9061f466cee82b738a36 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 13 Apr 2022 18:28:57 -0700 Subject: [PATCH 07/12] Update books --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book b/src/doc/book index ea90bbaf53ba6..765318b844569 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit ea90bbaf53ba64ef4e2da9ac2352b298aec6bec8 +Subproject commit 765318b844569a642ceef7bf1adab9639cbf6af3 diff --git a/src/doc/nomicon b/src/doc/nomicon index 11f1165e8a2f5..c7d8467ca9158 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 11f1165e8a2f5840467e748c8108dc53c948ee9a +Subproject commit c7d8467ca9158da58ef295ae65dbf00a308752d9 diff --git a/src/doc/reference b/src/doc/reference index c97d14fa6fed0..b5f6c2362baf9 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit c97d14fa6fed0baa9255432b8a93cb70614f80e3 +Subproject commit b5f6c2362baf932db9440fbfcb509b309237ee85 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ec954f35eedf5..c2a98d9fc5d29 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ec954f35eedf592cd173b21c05a7f80a65b61d8a +Subproject commit c2a98d9fc5d29c481d42052fbeccfde15ed03116 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 155126b1d2e2c..eeb5a83c15b6a 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 155126b1d2e2cb01ddb1d7ba9489b90d7cd173ad +Subproject commit eeb5a83c15b6ae60df3e4f19207376b22c6fbc4c From f6d957701f8113d8c05e6a2397b93ad6fc450400 Mon Sep 17 00:00:00 2001 From: Boyd Kane <33420535+beyarkay@users.noreply.github.com> Date: Thu, 14 Apr 2022 09:51:47 +0200 Subject: [PATCH 08/12] docs: add link from zip to unzip The docs for `Iterator::unzip` explain that it is kind of an inverse operation to `Iterator::zip` and guide the reader to the `zip` docs, but the `zip` docs don't let the user know that they can undo the `zip` operation with `unzip`. This change modifies the docs to help the user find `unzip`. --- library/core/src/iter/traits/iterator.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 53fbe4cbc42f5..eae29278f5572 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -469,6 +469,10 @@ pub trait Iterator { /// If the zipped iterator has no more elements to return then each further attempt to advance /// it will first try to advance the first iterator at most one time and if it still yielded an item /// try to advance the second iterator at most one time. + /// + /// To 'undo' the result of zipping up two iterators, see [`unzip`]. + /// + /// [`unzip`]: Iterator::unzip /// /// # Examples /// From d73e32867f45690720c17422b83c8abc8ceff645 Mon Sep 17 00:00:00 2001 From: Boyd Kane <33420535+beyarkay@users.noreply.github.com> Date: Thu, 14 Apr 2022 11:19:49 +0200 Subject: [PATCH 09/12] Remove trailing whitespace Co-authored-by: Mara Bos --- library/core/src/iter/traits/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index eae29278f5572..69f06fb06ef5d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -469,7 +469,7 @@ pub trait Iterator { /// If the zipped iterator has no more elements to return then each further attempt to advance /// it will first try to advance the first iterator at most one time and if it still yielded an item /// try to advance the second iterator at most one time. - /// + /// /// To 'undo' the result of zipping up two iterators, see [`unzip`]. /// /// [`unzip`]: Iterator::unzip From 7a35c0f52d2a37d3ce10772b07d7a45a445ebbf0 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 14 Apr 2022 09:51:25 +0200 Subject: [PATCH 10/12] Use u32 instead of i32 for futexes. --- library/std/src/sys/unix/futex.rs | 30 +++++++------- library/std/src/sys/unix/locks/futex.rs | 12 +++--- .../std/src/sys/unix/locks/futex_rwlock.rs | 40 +++++++++---------- library/std/src/sys/wasm/atomics/futex.rs | 14 ++++--- .../std/src/sys_common/thread_parker/futex.rs | 12 +++--- 5 files changed, 55 insertions(+), 53 deletions(-) diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index b45d1c0149cb4..62760373a6aff 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs @@ -4,7 +4,7 @@ all(target_os = "emscripten", target_feature = "atomics") ))] -use crate::sync::atomic::AtomicI32; +use crate::sync::atomic::AtomicU32; use crate::time::Duration; /// Wait for a futex_wake operation to wake us. @@ -13,7 +13,7 @@ use crate::time::Duration; /// /// Returns false on timeout, and true in all other cases. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) -> bool { +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) -> bool { use super::time::Timespec; use crate::ptr::null; use crate::sync::atomic::Ordering::Relaxed; @@ -35,7 +35,7 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) - let r = unsafe { libc::syscall( libc::SYS_futex, - futex as *const AtomicI32, + futex as *const AtomicU32, libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, expected, timespec.as_ref().map_or(null(), |t| &t.t as *const libc::timespec), @@ -53,10 +53,10 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) - } #[cfg(target_os = "emscripten")] -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) { extern "C" { fn emscripten_futex_wait( - addr: *const AtomicI32, + addr: *const AtomicU32, val: libc::c_uint, max_wait_ms: libc::c_double, ) -> libc::c_int; @@ -64,10 +64,8 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { unsafe { emscripten_futex_wait( - futex as *const AtomicI32, - // `val` is declared unsigned to match the Emscripten headers, but since it's used as - // an opaque value, we can ignore the meaning of signed vs. unsigned and cast here. - expected as libc::c_uint, + futex, + expected, timeout.map_or(crate::f64::INFINITY, |d| d.as_secs_f64() * 1000.0), ); } @@ -78,11 +76,11 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { /// Returns true if this actually woke up such a thread, /// or false if no thread was waiting on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wake(futex: &AtomicI32) -> bool { +pub fn futex_wake(futex: &AtomicU32) -> bool { unsafe { libc::syscall( libc::SYS_futex, - futex as *const AtomicI32, + futex as *const AtomicU32, libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG, 1, ) > 0 @@ -91,11 +89,11 @@ pub fn futex_wake(futex: &AtomicI32) -> bool { /// Wake up all threads that are waiting on futex_wait on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wake_all(futex: &AtomicI32) { +pub fn futex_wake_all(futex: &AtomicU32) { unsafe { libc::syscall( libc::SYS_futex, - futex as *const AtomicI32, + futex as *const AtomicU32, libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG, i32::MAX, ); @@ -103,10 +101,10 @@ pub fn futex_wake_all(futex: &AtomicI32) { } #[cfg(target_os = "emscripten")] -pub fn futex_wake(futex: &AtomicI32) -> bool { +pub fn futex_wake(futex: &AtomicU32) -> bool { extern "C" { - fn emscripten_futex_wake(addr: *const AtomicI32, count: libc::c_int) -> libc::c_int; + fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int; } - unsafe { emscripten_futex_wake(futex as *const AtomicI32, 1) > 0 } + unsafe { emscripten_futex_wake(futex, 1) > 0 } } diff --git a/library/std/src/sys/unix/locks/futex.rs b/library/std/src/sys/unix/locks/futex.rs index d97777e4da29d..b166e7c453cad 100644 --- a/library/std/src/sys/unix/locks/futex.rs +++ b/library/std/src/sys/unix/locks/futex.rs @@ -1,6 +1,6 @@ use crate::cell::UnsafeCell; use crate::sync::atomic::{ - AtomicI32, AtomicUsize, + AtomicU32, AtomicUsize, Ordering::{Acquire, Relaxed, Release}, }; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; @@ -13,13 +13,13 @@ pub struct Mutex { /// 0: unlocked /// 1: locked, no other threads waiting /// 2: locked, and other threads waiting (contended) - futex: AtomicI32, + futex: AtomicU32, } impl Mutex { #[inline] pub const fn new() -> Self { - Self { futex: AtomicI32::new(0) } + Self { futex: AtomicU32::new(0) } } #[inline] @@ -71,7 +71,7 @@ impl Mutex { } } - fn spin(&self) -> i32 { + fn spin(&self) -> u32 { let mut spin = 100; loop { // We only use `load` (and not `swap` or `compare_exchange`) @@ -110,13 +110,13 @@ pub struct Condvar { // The value of this atomic is simply incremented on every notification. // This is used by `.wait()` to not miss any notifications after // unlocking the mutex and before waiting for notifications. - futex: AtomicI32, + futex: AtomicU32, } impl Condvar { #[inline] pub const fn new() -> Self { - Self { futex: AtomicI32::new(0) } + Self { futex: AtomicU32::new(0) } } #[inline] diff --git a/library/std/src/sys/unix/locks/futex_rwlock.rs b/library/std/src/sys/unix/locks/futex_rwlock.rs index aa16da97e4c19..e42edb2585834 100644 --- a/library/std/src/sys/unix/locks/futex_rwlock.rs +++ b/library/std/src/sys/unix/locks/futex_rwlock.rs @@ -1,5 +1,5 @@ use crate::sync::atomic::{ - AtomicI32, + AtomicU32, Ordering::{Acquire, Relaxed, Release}, }; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; @@ -14,36 +14,36 @@ pub struct RwLock { // 0x3FFF_FFFF: Write locked // Bit 30: Readers are waiting on this futex. // Bit 31: Writers are waiting on the writer_notify futex. - state: AtomicI32, + state: AtomicU32, // The 'condition variable' to notify writers through. // Incremented on every signal. - writer_notify: AtomicI32, + writer_notify: AtomicU32, } -const READ_LOCKED: i32 = 1; -const MASK: i32 = (1 << 30) - 1; -const WRITE_LOCKED: i32 = MASK; -const MAX_READERS: i32 = MASK - 1; -const READERS_WAITING: i32 = 1 << 30; -const WRITERS_WAITING: i32 = 1 << 31; +const READ_LOCKED: u32 = 1; +const MASK: u32 = (1 << 30) - 1; +const WRITE_LOCKED: u32 = MASK; +const MAX_READERS: u32 = MASK - 1; +const READERS_WAITING: u32 = 1 << 30; +const WRITERS_WAITING: u32 = 1 << 31; -fn is_unlocked(state: i32) -> bool { +fn is_unlocked(state: u32) -> bool { state & MASK == 0 } -fn is_write_locked(state: i32) -> bool { +fn is_write_locked(state: u32) -> bool { state & MASK == WRITE_LOCKED } -fn has_readers_waiting(state: i32) -> bool { +fn has_readers_waiting(state: u32) -> bool { state & READERS_WAITING != 0 } -fn has_writers_waiting(state: i32) -> bool { +fn has_writers_waiting(state: u32) -> bool { state & WRITERS_WAITING != 0 } -fn is_read_lockable(state: i32) -> bool { +fn is_read_lockable(state: u32) -> bool { // This also returns false if the counter could overflow if we tried to read lock it. // // We don't allow read-locking if there's readers waiting, even if the lock is unlocked @@ -53,14 +53,14 @@ fn is_read_lockable(state: i32) -> bool { state & MASK < MAX_READERS && !has_readers_waiting(state) && !has_writers_waiting(state) } -fn has_reached_max_readers(state: i32) -> bool { +fn has_reached_max_readers(state: u32) -> bool { state & MASK == MAX_READERS } impl RwLock { #[inline] pub const fn new() -> Self { - Self { state: AtomicI32::new(0), writer_notify: AtomicI32::new(0) } + Self { state: AtomicU32::new(0), writer_notify: AtomicU32::new(0) } } #[inline] @@ -227,7 +227,7 @@ impl RwLock { /// If both are waiting, this will wake up only one writer, but will fall /// back to waking up readers if there was no writer to wake up. #[cold] - fn wake_writer_or_readers(&self, mut state: i32) { + fn wake_writer_or_readers(&self, mut state: u32) { assert!(is_unlocked(state)); // The readers waiting bit might be turned on at any point now, @@ -287,7 +287,7 @@ impl RwLock { } /// Spin for a while, but stop directly at the given condition. - fn spin_until(&self, f: impl Fn(i32) -> bool) -> i32 { + fn spin_until(&self, f: impl Fn(u32) -> bool) -> u32 { let mut spin = 100; // Chosen by fair dice roll. loop { let state = self.state.load(Relaxed); @@ -299,12 +299,12 @@ impl RwLock { } } - fn spin_write(&self) -> i32 { + fn spin_write(&self) -> u32 { // Stop spinning when it's unlocked or when there's waiting writers, to keep things somewhat fair. self.spin_until(|state| is_unlocked(state) || has_writers_waiting(state)) } - fn spin_read(&self) -> i32 { + fn spin_read(&self) -> u32 { // Stop spinning when it's unlocked or read locked, or when there's waiting threads. self.spin_until(|state| { !is_write_locked(state) || has_readers_waiting(state) || has_writers_waiting(state) diff --git a/library/std/src/sys/wasm/atomics/futex.rs b/library/std/src/sys/wasm/atomics/futex.rs index 3d8bf42f7255e..bbe9bd6951af9 100644 --- a/library/std/src/sys/wasm/atomics/futex.rs +++ b/library/std/src/sys/wasm/atomics/futex.rs @@ -1,17 +1,21 @@ use crate::arch::wasm32; use crate::convert::TryInto; -use crate::sync::atomic::AtomicI32; +use crate::sync::atomic::AtomicU32; use crate::time::Duration; -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) { let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1); unsafe { - wasm32::memory_atomic_wait32(futex as *const AtomicI32 as *mut i32, expected, timeout); + wasm32::memory_atomic_wait32( + futex as *const AtomicU32 as *mut i32, + expected as i32, + timeout, + ); } } -pub fn futex_wake(futex: &AtomicI32) { +pub fn futex_wake(futex: &AtomicU32) { unsafe { - wasm32::memory_atomic_notify(futex as *const AtomicI32 as *mut i32, 1); + wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1); } } diff --git a/library/std/src/sys_common/thread_parker/futex.rs b/library/std/src/sys_common/thread_parker/futex.rs index 0132743b24404..fbf6231ff4ab3 100644 --- a/library/std/src/sys_common/thread_parker/futex.rs +++ b/library/std/src/sys_common/thread_parker/futex.rs @@ -1,14 +1,14 @@ -use crate::sync::atomic::AtomicI32; +use crate::sync::atomic::AtomicU32; use crate::sync::atomic::Ordering::{Acquire, Release}; use crate::sys::futex::{futex_wait, futex_wake}; use crate::time::Duration; -const PARKED: i32 = -1; -const EMPTY: i32 = 0; -const NOTIFIED: i32 = 1; +const PARKED: u32 = u32::MAX; +const EMPTY: u32 = 0; +const NOTIFIED: u32 = 1; pub struct Parker { - state: AtomicI32, + state: AtomicU32, } // Notes about memory ordering: @@ -34,7 +34,7 @@ pub struct Parker { impl Parker { #[inline] pub const fn new() -> Self { - Parker { state: AtomicI32::new(EMPTY) } + Parker { state: AtomicU32::new(EMPTY) } } // Assumes this is only called by the thread that owns the Parker, From 1b7008dc77e25049b04e5c3e31aecf4de00803e7 Mon Sep 17 00:00:00 2001 From: rainy-me Date: Thu, 14 Apr 2022 21:18:27 +0900 Subject: [PATCH 11/12] refactor: change to use peekable --- compiler/rustc_parse/src/lexer/mod.rs | 37 +++++++++---------- .../ui/unterminated-nested-comment.stderr | 2 +- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 96513958eb06b..e5ee1d5dab92e 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -557,39 +557,36 @@ impl<'a> StringReader<'a> { ); let mut nested_block_comment_open_idxs = vec![]; let mut last_nested_block_comment_idxs = None; - let mut content_chars = self.str_from(start).char_indices(); + let mut content_chars = self.str_from(start).char_indices().peekable(); - if let Some((_, mut last_char)) = content_chars.next() { - while let Some((idx, c)) = content_chars.next() { - match c { - '*' if last_char == '/' => { - nested_block_comment_open_idxs.push(idx); - } - '/' if last_char == '*' => { - last_nested_block_comment_idxs = - nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx)); - } - _ => {} - }; - last_char = c; - } + while let Some((idx, current_char)) = content_chars.next() { + match content_chars.peek() { + Some((_, '*')) if current_char == '/' => { + nested_block_comment_open_idxs.push(idx); + } + Some((_, '/')) if current_char == '*' => { + last_nested_block_comment_idxs = + nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx)); + } + _ => {} + }; } if let Some((nested_open_idx, nested_close_idx)) = last_nested_block_comment_idxs { err.span_label(self.mk_sp(start, start + BytePos(2)), msg) .span_label( self.mk_sp( - start + BytePos(nested_open_idx as u32 - 1), - start + BytePos(nested_open_idx as u32 + 1), + start + BytePos(nested_open_idx as u32), + start + BytePos(nested_open_idx as u32 + 2), ), "...as last nested comment starts here, maybe you want to close this instead?", ) .span_label( self.mk_sp( - start + BytePos(nested_close_idx as u32 - 1), - start + BytePos(nested_close_idx as u32 + 1), + start + BytePos(nested_close_idx as u32), + start + BytePos(nested_close_idx as u32 + 2), ), - "...and last nested comment terminates here", + "...and last nested comment terminates here.", ); } diff --git a/src/test/ui/unterminated-nested-comment.stderr b/src/test/ui/unterminated-nested-comment.stderr index eda8f2dcd2469..3653e76c9cbda 100644 --- a/src/test/ui/unterminated-nested-comment.stderr +++ b/src/test/ui/unterminated-nested-comment.stderr @@ -14,7 +14,7 @@ LL | | /* LL | | */ | |_--^ | | - | ...and last nested comment terminates here + | ...and last nested comment terminates here. error: aborting due to previous error From 48029aba2c4a902fae9c6f028bceae5105979114 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Apr 2022 13:31:21 +0000 Subject: [PATCH 12/12] Remove some now-dead code that was only relevant before deaggregation. The code was broken anyway, if the deaggregator is disabled, it would have ICE on any non-enum Adt --- .../rustc_const_eval/src/interpret/step.rs | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index eb1a184bf9b21..e6dfdf54a32d1 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -196,27 +196,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(*val, &dest)?; } - Aggregate(ref kind, ref operands) => { - // active_field_index is for union initialization. - let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { - self.write_discriminant(variant_index, &dest)?; - if self.tcx.adt_def(adt_did).is_enum() { - assert!(active_field_index.is_none()); - (self.place_downcast(&dest, variant_index)?, None) - } else { - if active_field_index.is_some() { - assert_eq!(operands.len(), 1); - } - (dest, active_field_index) - } - } - _ => (dest, None), - }; + Aggregate(box ref kind, ref operands) => { + assert!(matches!(kind, mir::AggregateKind::Array(..))); - for (i, operand) in operands.iter().enumerate() { + for (field_index, operand) in operands.iter().enumerate() { let op = self.eval_operand(operand, None)?; - let field_index = active_field_index.unwrap_or(i); let field_dest = self.place_field(&dest, field_index)?; self.copy_op(&op, &field_dest)?; }