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<Item>], inner: Span) -> hir::Mod<'hir> {
+ pub(super) fn lower_mod(&mut self, items: &[P<Item>], 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_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_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)?;
}
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_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 8340a0b360ef7..f3d4c8ab43843 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_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index ff8b13d31122e..68ae2441af797 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2557,11 +2557,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)]
@@ -3059,8 +3065,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_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/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 65796fbc698d8..08cd40f38efce 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -584,7 +584,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),
}
}
@@ -1012,7 +1012,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_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index fd2b5f5335f69..199b5fa0314b3 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_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index db7e973fb6223..49769b7ae3d89 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/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 5ab412dc777de..e5ee1d5dab92e 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,55 @@ impl<'a> StringReader<'a> {
err.emit()
}
+ fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option<DocStyle>) {
+ 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().peekable();
+
+ 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),
+ 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),
+ start + BytePos(nested_close_idx as u32 + 2),
+ ),
+ "...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/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c45326e1e6e6c..a9444972130a8 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)
}
@@ -523,6 +524,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/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_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/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index e6560ca4d9b90..2921176ca4b38 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -8,7 +8,7 @@ use rustc_errors::{
MultiSpan,
};
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<DefId>,
- ) {
+ fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec<DefId>) {
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(
@@ -2106,53 +2049,6 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect()
}
-fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, 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/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
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 53fbe4cbc42f5..69f06fb06ef5d 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -470,6 +470,10 @@ pub trait Iterator {
/// 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
///
/// Basic usage:
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 6546a5244fd03..2b613a71bc13b 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/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<Duration>) -> bool {
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> 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<Duration>) -
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<Duration>) -
}
#[cfg(target_os = "emscripten")]
-pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
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<Duration>) {
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<Duration>) {
/// 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<Duration>) {
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
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,
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
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/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 <https://github.com/rust-lang/rust/issues/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/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/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);
| ^^^^^^^^
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;
+}
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`
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
+
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..3653e76c9cbda
--- /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`.