about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-03 04:28:08 +0000
committerbors <bors@rust-lang.org>2022-03-03 04:28:08 +0000
commit2f8d1a835b4e7feaf625f74d0d5cb9b84dbc845a (patch)
tree58c9e240fbbb366d99880f74d49ab390c79285fb
parent8769f4ef2fe1efddd1f072485f97f568e7328f79 (diff)
parent878a4ff90e5987027f8ce3d350faaad02e0c83c9 (diff)
downloadrust-2f8d1a835b4e7feaf625f74d0d5cb9b84dbc845a.tar.gz
rust-2f8d1a835b4e7feaf625f74d0d5cb9b84dbc845a.zip
Auto merge of #94541 - Dylan-DPC:rollup-564wbq3, r=Dylan-DPC
Rollup of 9 pull requests

Successful merges:

 - #92061 (update char signess for openbsd)
 - #93072 (Compatible variants suggestion with desugaring)
 - #93354 (Add documentation about `BorrowedFd::to_owned`.)
 - #93663 (Rename `BorrowedFd::borrow_raw_fd` to `BorrowedFd::borrow_raw`.)
 - #94375 (Adt copy suggestions)
 - #94433 (Improve allowness of the unexpected_cfgs lint)
 - #94499 (Documentation was missed when demoting Windows XP to no_std only)
 - #94505 (Restore the local filter on mono item sorting)
 - #94529 (Unused doc comments blocks)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_attr/src/builtin.rs14
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs63
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs3
-rw-r--r--compiler/rustc_expand/src/config.rs20
-rw-r--r--compiler/rustc_expand/src/expand.rs23
-rw-r--r--compiler/rustc_interface/src/passes.rs3
-rw-r--r--compiler/rustc_lint/src/builtin.rs10
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs3
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs9
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs398
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs21
-rw-r--r--library/core/src/ffi/mod.rs3
-rw-r--r--library/portable-simd/crates/core_simd/src/intrinsics.rs7
-rw-r--r--library/std/src/os/fd/mod.rs3
-rw-r--r--library/std/src/os/fd/owned.rs8
-rw-r--r--library/std/src/os/fd/tests.rs34
-rw-r--r--library/std/src/os/windows/io/handle.rs28
-rw-r--r--library/std/src/os/windows/io/socket.rs14
-rw-r--r--library/std/src/sys/unix/stdio.rs12
m---------library/stdarch0
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/test/codegen/debuginfo-generic-closure-env-names.rs18
-rw-r--r--src/test/ui/async-await/proper-span-for-type-error.fixed3
-rw-r--r--src/test/ui/async-await/proper-span-for-type-error.stderr7
-rw-r--r--src/test/ui/check-cfg/allow-macro-cfg.rs14
-rw-r--r--src/test/ui/check-cfg/allow-same-level.rs11
-rw-r--r--src/test/ui/check-cfg/allow-same-level.stderr10
-rw-r--r--src/test/ui/check-cfg/allow-top-level.rs15
-rw-r--r--src/test/ui/check-cfg/allow-upper-level.rs12
-rw-r--r--src/test/ui/did_you_mean/compatible-variants.rs15
-rw-r--r--src/test/ui/did_you_mean/compatible-variants.stderr61
-rw-r--r--src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs14
-rw-r--r--src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr28
-rw-r--r--src/test/ui/moves/use_of_moved_value_clone_suggestions.rs6
-rw-r--r--src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr13
-rw-r--r--src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed72
-rw-r--r--src/test/ui/moves/use_of_moved_value_copy_suggestions.rs72
-rw-r--r--src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr147
43 files changed, 971 insertions, 254 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 68b536da9f7..846abce9d6a 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -1,8 +1,7 @@
 //! Parsing and validation of builtin attributes
 
 use rustc_ast as ast;
-use rustc_ast::node_id::CRATE_NODE_ID;
-use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem};
+use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
@@ -436,7 +435,12 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
 }
 
 /// Tests if a cfg-pattern matches the cfg set
-pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
+pub fn cfg_matches(
+    cfg: &ast::MetaItem,
+    sess: &ParseSess,
+    lint_node_id: NodeId,
+    features: Option<&Features>,
+) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
         try_gate_cfg(cfg, sess, features);
         let error = |span, msg| {
@@ -470,7 +474,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                         sess.buffer_lint_with_diagnostic(
                             UNEXPECTED_CFGS,
                             cfg.span,
-                            CRATE_NODE_ID,
+                            lint_node_id,
                             "unexpected `cfg` condition name",
                             BuiltinLintDiagnostics::UnexpectedCfg(ident.span, name, None),
                         );
@@ -482,7 +486,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                             sess.buffer_lint_with_diagnostic(
                                 UNEXPECTED_CFGS,
                                 cfg.span,
-                                CRATE_NODE_ID,
+                                lint_node_id,
                                 "unexpected `cfg` condition value",
                                 BuiltinLintDiagnostics::UnexpectedCfg(
                                     cfg.name_value_literal_span().unwrap(),
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 4502d15f36f..684a3ced5a0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -5,16 +5,21 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
     FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
     ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
 };
-use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
+use rustc_middle::ty::{
+    self, suggest_constraining_type_param, suggest_constraining_type_params, PredicateKind, Ty,
+};
 use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::TraitEngineExt as _;
 
 use crate::borrow_set::TwoPhaseActivation;
 use crate::borrowck_errors;
@@ -423,7 +428,63 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             None,
                         );
                     }
+                } else {
+                    // Try to find predicates on *generic params* that would allow copying `ty`
+
+                    let tcx = self.infcx.tcx;
+                    let generics = tcx.generics_of(self.mir_def_id());
+                    if let Some(hir_generics) = tcx
+                        .typeck_root_def_id(self.mir_def_id().to_def_id())
+                        .as_local()
+                        .and_then(|def_id| tcx.hir().get_generics(def_id))
+                    {
+                        let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
+                            let mut fulfill_cx =
+                                <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
+
+                            let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
+                            let cause = ObligationCause::new(
+                                span,
+                                self.mir_hir_id(),
+                                rustc_infer::traits::ObligationCauseCode::MiscObligation,
+                            );
+                            fulfill_cx.register_bound(&infcx, self.param_env, ty, copy_did, cause);
+                            let errors = fulfill_cx.select_where_possible(&infcx);
+
+                            // Only emit suggestion if all required predicates are on generic
+                            errors
+                                .into_iter()
+                                .map(|err| match err.obligation.predicate.kind().skip_binder() {
+                                    PredicateKind::Trait(predicate) => {
+                                        match predicate.self_ty().kind() {
+                                            ty::Param(param_ty) => Ok((
+                                                generics.type_param(param_ty, tcx),
+                                                predicate
+                                                    .trait_ref
+                                                    .print_only_trait_path()
+                                                    .to_string(),
+                                            )),
+                                            _ => Err(()),
+                                        }
+                                    }
+                                    _ => Err(()),
+                                })
+                                .collect()
+                        });
+
+                        if let Ok(predicates) = predicates {
+                            suggest_constraining_type_params(
+                                tcx,
+                                hir_generics,
+                                &mut err,
+                                predicates.iter().map(|(param, constraint)| {
+                                    (param.name.as_str(), &**constraint, None)
+                                }),
+                            );
+                        }
+                    }
                 }
+
                 let span = if let Some(local) = place.as_local() {
                     let decl = &self.body.local_decls[local];
                     Some(decl.source_info.span)
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 1e1cf917c60..f5ef4765df6 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -19,7 +19,12 @@ pub fn expand_cfg(
 
     match parse_cfg(cx, sp, tts) {
         Ok(cfg) => {
-            let matches_cfg = attr::cfg_matches(&cfg, &cx.sess.parse_sess, cx.ecfg.features);
+            let matches_cfg = attr::cfg_matches(
+                &cfg,
+                &cx.sess.parse_sess,
+                cx.current_expansion.lint_node_id,
+                cx.ecfg.features,
+            );
             MacEager::expr(cx.expr_bool(sp, matches_cfg))
         }
         Err(mut err) => {
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 8574cfae860..3c8f8f1854b 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -5,6 +5,7 @@ use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
 use rustc_ast::visit::Visitor;
+use rustc_ast::NodeId;
 use rustc_ast::{mut_visit, visit};
 use rustc_ast::{AstLike, Attribute};
 use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -26,15 +27,16 @@ crate fn expand(
 ) -> Vec<Annotatable> {
     check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
     warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval);
-    vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
+    vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable, ecx.current_expansion.lint_node_id)]
 }
 
 crate fn cfg_eval(
     sess: &Session,
     features: Option<&Features>,
     annotatable: Annotatable,
+    lint_node_id: NodeId,
 ) -> Annotatable {
-    CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true } }
+    CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true, lint_node_id } }
         .configure_annotatable(annotatable)
         // Since the item itself has already been configured by the `InvocationCollector`,
         // we know that fold result vector will contain exactly one element.
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 47d7b6c259e..61681ec66a4 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -64,7 +64,12 @@ impl MultiItemModifier for Expander {
                 match &mut resolutions[..] {
                     [] => {}
                     [(_, first_item, _), others @ ..] => {
-                        *first_item = cfg_eval(sess, features, item.clone());
+                        *first_item = cfg_eval(
+                            sess,
+                            features,
+                            item.clone(),
+                            ecx.current_expansion.lint_node_id,
+                        );
                         for (_, item, _) in others {
                             *item = first_item.clone();
                         }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 4a8894983b9..6e9e0332faf 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -576,12 +576,12 @@ pub enum PassKind {
     Module,
 }
 
-/// LLVMRustThinLTOData
+// LLVMRustThinLTOData
 extern "C" {
     pub type ThinLTOData;
 }
 
-/// LLVMRustThinLTOBuffer
+// LLVMRustThinLTOBuffer
 extern "C" {
     pub type ThinLTOBuffer;
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 9e252c0d9b7..9cc06ac0319 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,4 +1,5 @@
 use rustc_arena::TypedArena;
+use rustc_ast::CRATE_NODE_ID;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::temp_dir::MaybeTempDir;
@@ -2434,7 +2435,7 @@ fn add_upstream_native_libraries(
 
 fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None),
+        Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
         None => true,
     }
 }
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index c0d7bc359bf..d43c6fec7d5 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -5,6 +5,7 @@ use rustc_ast::token::{DelimToken, Token, TokenKind};
 use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
 use rustc_ast::tokenstream::{DelimSpan, Spacing};
 use rustc_ast::tokenstream::{LazyTokenStream, TokenTree};
+use rustc_ast::NodeId;
 use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
@@ -29,6 +30,7 @@ pub struct StripUnconfigured<'a> {
     /// This is only used for the input to derive macros,
     /// which needs eager expansion of `cfg` and `cfg_attr`
     pub config_tokens: bool,
+    pub lint_node_id: NodeId,
 }
 
 fn get_features(
@@ -196,8 +198,13 @@ fn get_features(
 }
 
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) {
-    let mut strip_unconfigured = StripUnconfigured { sess, features: None, config_tokens: false };
+pub fn features(
+    sess: &Session,
+    mut krate: ast::Crate,
+    lint_node_id: NodeId,
+) -> (ast::Crate, Features) {
+    let mut strip_unconfigured =
+        StripUnconfigured { sess, features: None, config_tokens: false, lint_node_id };
 
     let unconfigured_attrs = krate.attrs.clone();
     let diag = &sess.parse_sess.span_diagnostic;
@@ -353,7 +360,12 @@ impl<'a> StripUnconfigured<'a> {
             );
         }
 
-        if !attr::cfg_matches(&cfg_predicate, &self.sess.parse_sess, self.features) {
+        if !attr::cfg_matches(
+            &cfg_predicate,
+            &self.sess.parse_sess,
+            self.lint_node_id,
+            self.features,
+        ) {
             return vec![];
         }
 
@@ -445,7 +457,7 @@ impl<'a> StripUnconfigured<'a> {
             }
         };
         parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
-            attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.features)
+            attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.lint_node_id, self.features)
         })
     }
 
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index ab3951d7683..1b976180509 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -551,11 +551,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 // attribute is expanded. Therefore, we don't need to configure the tokens
                 // Derive macros *can* see the results of cfg-expansion - they are handled
                 // specially in `fully_expand_fragment`
-                cfg: StripUnconfigured {
-                    sess: &self.cx.sess,
-                    features: self.cx.ecfg.features,
-                    config_tokens: false,
-                },
                 cx: self.cx,
                 invocations: Vec::new(),
                 monotonic: self.monotonic,
@@ -1538,12 +1533,20 @@ impl InvocationCollectorNode for AstLikeWrapper<P<ast::Expr>, OptExprTag> {
 
 struct InvocationCollector<'a, 'b> {
     cx: &'a mut ExtCtxt<'b>,
-    cfg: StripUnconfigured<'a>,
     invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
     monotonic: bool,
 }
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
+    fn cfg(&self) -> StripUnconfigured<'_> {
+        StripUnconfigured {
+            sess: &self.cx.sess,
+            features: self.cx.ecfg.features,
+            config_tokens: false,
+            lint_node_id: self.cx.current_expansion.lint_node_id,
+        }
+    }
+
     fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
         let expn_id = LocalExpnId::fresh_empty();
         let vis = kind.placeholder_visibility();
@@ -1683,7 +1686,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         attr: ast::Attribute,
         pos: usize,
     ) -> bool {
-        let res = self.cfg.cfg_true(&attr);
+        let res = self.cfg().cfg_true(&attr);
         if res {
             // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
             // and some tools like rustdoc and clippy rely on that. Find a way to remove them
@@ -1696,7 +1699,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
     fn expand_cfg_attr(&self, node: &mut impl AstLike, attr: ast::Attribute, pos: usize) {
         node.visit_attrs(|attrs| {
-            attrs.splice(pos..pos, self.cfg.expand_cfg_attr(attr, false));
+            attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
         });
     }
 
@@ -1718,7 +1721,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         continue;
                     }
                     _ => {
-                        Node::pre_flat_map_node_collect_attr(&self.cfg, &attr);
+                        Node::pre_flat_map_node_collect_attr(&self.cfg(), &attr);
                         self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
                             .make_ast::<Node>()
                     }
@@ -1882,7 +1885,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
     fn visit_expr(&mut self, node: &mut P<ast::Expr>) {
         // FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
         if let Some(attr) = node.attrs.first() {
-            self.cfg.maybe_emit_expr_attr_err(attr);
+            self.cfg().maybe_emit_expr_attr_err(attr);
         }
         self.visit_node(node)
     }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 2cdcf0b11d1..3b51f8eb61c 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -2,6 +2,7 @@ use crate::interface::{Compiler, Result};
 use crate::proc_macro_decls;
 use crate::util;
 
+use ast::CRATE_NODE_ID;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self as ast, visit};
 use rustc_borrowck as mir_borrowck;
@@ -188,7 +189,7 @@ pub fn register_plugins<'a>(
         )
     });
 
-    let (krate, features) = rustc_expand::config::features(sess, krate);
+    let (krate, features) = rustc_expand::config::features(sess, krate, CRATE_NODE_ID);
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 46b90baa585..72b8d8bb297 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1086,6 +1086,16 @@ impl EarlyLintPass for UnusedDocComment {
     fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
         warn_if_doc(cx, param.ident.span, "generic parameters", &param.attrs);
     }
+
+    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
+        warn_if_doc(cx, block.span, "block", &block.attrs());
+    }
+
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        if let ast::ItemKind::ForeignMod(_) = item.kind {
+            warn_if_doc(cx, item.span, "extern block", &item.attrs);
+        }
+    }
 }
 
 declare_lint! {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index dce1b35c6b8..7cdcb6a4ab3 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -1,3 +1,4 @@
+use rustc_ast::CRATE_NODE_ID;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
@@ -21,7 +22,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
 
 crate fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
+        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
         None => true,
     }
 }
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 7ca564f29e6..f977b0fffeb 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -56,6 +56,7 @@
 #![feature(nonzero_ops)]
 #![feature(unwrap_infallible)]
 #![feature(decl_macro)]
+#![feature(drain_filter)]
 #![recursion_limit = "512"]
 #![allow(rustc::potential_query_instability)]
 
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 892808386de..13c325a14e4 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::ItemId;
+use rustc_index::vec::Idx;
 use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
 use rustc_session::config::OptLevel;
 use rustc_span::source_map::Span;
@@ -380,7 +381,7 @@ impl<'tcx> CodegenUnit<'tcx> {
                             // instances into account. The others don't matter for
                             // the codegen tests and can even make item order
                             // unstable.
-                            InstanceDef::Item(def) => Some(def.did.index.as_usize()),
+                            InstanceDef::Item(def) => def.did.as_local().map(Idx::index),
                             InstanceDef::VtableShim(..)
                             | InstanceDef::ReifyShim(..)
                             | InstanceDef::Intrinsic(..)
@@ -391,10 +392,8 @@ impl<'tcx> CodegenUnit<'tcx> {
                             | InstanceDef::CloneShim(..) => None,
                         }
                     }
-                    MonoItem::Static(def_id) => Some(def_id.index.as_usize()),
-                    MonoItem::GlobalAsm(item_id) => {
-                        Some(item_id.def_id.to_def_id().index.as_usize())
-                    }
+                    MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),
+                    MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.index()),
                 },
                 item.symbol_name(tcx),
             )
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 58cf9fa7a89..99a3d4c7fe4 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -7,6 +7,7 @@ use crate::ty::{
     ProjectionTy, Term, Ty, TyCtxt, TypeAndMut,
 };
 
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -157,9 +158,17 @@ pub fn suggest_arbitrary_trait_bound(
     true
 }
 
+#[derive(Debug)]
+enum SuggestChangingConstraintsMessage<'a> {
+    RestrictBoundFurther,
+    RestrictType { ty: &'a str },
+    RestrictTypeFurther { ty: &'a str },
+    RemovingQSized,
+}
+
 fn suggest_removing_unsized_bound(
     generics: &hir::Generics<'_>,
-    err: &mut Diagnostic,
+    suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
     param_name: &str,
     param: &hir::GenericParam<'_>,
     def_id: Option<DefId>,
@@ -221,13 +230,12 @@ fn suggest_removing_unsized_bound(
                         //             ^^^^^^^^^
                         (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
                     };
-                    err.span_suggestion_verbose(
+
+                    suggestions.push((
                         sp,
-                        "consider removing the `?Sized` bound to make the \
-                            type parameter `Sized`",
                         String::new(),
-                        Applicability::MaybeIncorrect,
-                    );
+                        SuggestChangingConstraintsMessage::RemovingQSized,
+                    ));
                 }
             }
             _ => {}
@@ -249,13 +257,12 @@ fn suggest_removing_unsized_bound(
                     //       ^^^^^^^^^
                     (_, pos) => param.bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
                 };
-                err.span_suggestion_verbose(
+
+                suggestions.push((
                     sp,
-                    "consider removing the `?Sized` bound to make the type parameter \
-                        `Sized`",
                     String::new(),
-                    Applicability::MaybeIncorrect,
-                );
+                    SuggestChangingConstraintsMessage::RemovingQSized,
+                ));
             }
             _ => {}
         }
@@ -271,184 +278,249 @@ pub fn suggest_constraining_type_param(
     constraint: &str,
     def_id: Option<DefId>,
 ) -> bool {
-    let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
+    suggest_constraining_type_params(
+        tcx,
+        generics,
+        err,
+        [(param_name, constraint, def_id)].into_iter(),
+    )
+}
 
-    let Some(param) = param else {
-        return false;
-    };
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_params<'a>(
+    tcx: TyCtxt<'_>,
+    generics: &hir::Generics<'_>,
+    err: &mut Diagnostic,
+    param_names_and_constraints: impl Iterator<Item = (&'a str, &'a str, Option<DefId>)>,
+) -> bool {
+    let mut grouped = FxHashMap::default();
+    param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
+        grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id))
+    });
 
-    const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound";
-    let msg_restrict_type = format!("consider restricting type parameter `{}`", param_name);
-    let msg_restrict_type_further =
-        format!("consider further restricting type parameter `{}`", param_name);
+    let mut applicability = Applicability::MachineApplicable;
+    let mut suggestions = Vec::new();
 
-    if def_id == tcx.lang_items().sized_trait() {
-        // Type parameters are already `Sized` by default.
-        err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
-        suggest_removing_unsized_bound(generics, err, param_name, param, def_id);
-        return true;
-    }
-    let mut suggest_restrict = |span| {
-        err.span_suggestion_verbose(
-            span,
-            MSG_RESTRICT_BOUND_FURTHER,
-            format!(" + {}", constraint),
-            Applicability::MachineApplicable,
-        );
-    };
+    for (param_name, mut constraints) in grouped {
+        let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
+        let Some(param) = param else { return false };
 
-    if param_name.starts_with("impl ") {
-        // If there's an `impl Trait` used in argument position, suggest
-        // restricting it:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             help: consider further restricting this bound with `+ Bar`
-        //
-        // Suggestion for tools in this case is:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             replace with: `impl Foo + Bar`
-
-        suggest_restrict(param.span.shrink_to_hi());
-        return true;
-    }
+        {
+            let mut sized_constraints =
+                constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
+            if let Some((constraint, def_id)) = sized_constraints.next() {
+                applicability = Applicability::MaybeIncorrect;
 
-    if generics.where_clause.predicates.is_empty()
-        // Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
-        // `where` clause instead of `trait Base<T: Copy = String>: Super<T>`.
-        && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
-    {
-        if let Some(span) = param.bounds_span_for_suggestions() {
-            // If user has provided some bounds, suggest restricting them:
+                err.span_label(
+                    param.span,
+                    &format!("this type parameter needs to be `{}`", constraint),
+                );
+                suggest_removing_unsized_bound(
+                    generics,
+                    &mut suggestions,
+                    param_name,
+                    param,
+                    def_id,
+                );
+            }
+        }
+
+        if constraints.is_empty() {
+            continue;
+        }
+
+        let constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>().join(" + ");
+        let mut suggest_restrict = |span| {
+            suggestions.push((
+                span,
+                format!(" + {}", constraint),
+                SuggestChangingConstraintsMessage::RestrictBoundFurther,
+            ))
+        };
+
+        if param_name.starts_with("impl ") {
+            // If there's an `impl Trait` used in argument position, suggest
+            // restricting it:
             //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //             ---
+            //   fn foo(t: impl Foo) { ... }
+            //             --------
             //             |
             //             help: consider further restricting this bound with `+ Bar`
             //
             // Suggestion for tools in this case is:
             //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //          --
-            //          |
-            //          replace with: `T: Bar +`
-            suggest_restrict(span);
-        } else {
-            // If user hasn't provided any bounds, suggest adding a new one:
-            //
-            //   fn foo<T>(t: T) { ... }
-            //          - help: consider restricting this type parameter with `T: Foo`
-            err.span_suggestion_verbose(
-                param.span.shrink_to_hi(),
-                &msg_restrict_type,
-                format!(": {}", constraint),
-                Applicability::MachineApplicable,
-            );
+            //   fn foo(t: impl Foo) { ... }
+            //             --------
+            //             |
+            //             replace with: `impl Foo + Bar`
+
+            suggest_restrict(param.span.shrink_to_hi());
+            continue;
         }
 
-        true
-    } else {
-        // This part is a bit tricky, because using the `where` clause user can
-        // provide zero, one or many bounds for the same type parameter, so we
-        // have following cases to consider:
-        //
-        // 1) When the type parameter has been provided zero bounds
-        //
-        //    Message:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //             - help: consider restricting this type parameter with `where X: Bar`
-        //
-        //    Suggestion:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //                                           - insert: `, X: Bar`
-        //
-        //
-        // 2) When the type parameter has been provided one bound
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^^^^^
-        //                            |
-        //                            help: consider further restricting this bound with `+ Bar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^
-        //                            |
-        //                            replace with: `T: Bar +`
-        //
-        //
-        // 3) When the type parameter has been provided many bounds
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //             - help: consider further restricting this type parameter with `where T: Zar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //                                          - insert: `, T: Zar`
-        //
-        // Additionally, there may be no `where` clause whatsoever in the case that this was
-        // reached because the generic parameter has a default:
-        //
-        //    Message:
-        //      trait Foo<T=()> {... }
-        //             - help: consider further restricting this type parameter with `where T: Zar`
-        //
-        //    Suggestion:
-        //      trait Foo<T=()> where T: Zar {... }
-        //                     - insert: `where T: Zar`
-
-        if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
-            && generics.where_clause.predicates.len() == 0
+        if generics.where_clause.predicates.is_empty()
+        // Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
+        // `where` clause instead of `trait Base<T: Copy = String>: Super<T>`.
+        && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
         {
-            // Suggest a bound, but there is no existing `where` clause *and* the type param has a
-            // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
-            err.span_suggestion_verbose(
-                generics.where_clause.tail_span_for_suggestion(),
-                &msg_restrict_type_further,
-                format!(" where {}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
+            if let Some(span) = param.bounds_span_for_suggestions() {
+                // If user has provided some bounds, suggest restricting them:
+                //
+                //   fn foo<T: Foo>(t: T) { ... }
+                //             ---
+                //             |
+                //             help: consider further restricting this bound with `+ Bar`
+                //
+                // Suggestion for tools in this case is:
+                //
+                //   fn foo<T: Foo>(t: T) { ... }
+                //          --
+                //          |
+                //          replace with: `T: Bar +`
+                suggest_restrict(span);
+            } else {
+                // If user hasn't provided any bounds, suggest adding a new one:
+                //
+                //   fn foo<T>(t: T) { ... }
+                //          - help: consider restricting this type parameter with `T: Foo`
+                suggestions.push((
+                    param.span.shrink_to_hi(),
+                    format!(": {}", constraint),
+                    SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
+                ));
+            }
         } else {
-            let mut param_spans = Vec::new();
+            // This part is a bit tricky, because using the `where` clause user can
+            // provide zero, one or many bounds for the same type parameter, so we
+            // have following cases to consider:
+            //
+            // 1) When the type parameter has been provided zero bounds
+            //
+            //    Message:
+            //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
+            //             - help: consider restricting this type parameter with `where X: Bar`
+            //
+            //    Suggestion:
+            //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
+            //                                           - insert: `, X: Bar`
+            //
+            //
+            // 2) When the type parameter has been provided one bound
+            //
+            //    Message:
+            //      fn foo<T>(t: T) where T: Foo { ... }
+            //                            ^^^^^^
+            //                            |
+            //                            help: consider further restricting this bound with `+ Bar`
+            //
+            //    Suggestion:
+            //      fn foo<T>(t: T) where T: Foo { ... }
+            //                            ^^
+            //                            |
+            //                            replace with: `T: Bar +`
+            //
+            //
+            // 3) When the type parameter has been provided many bounds
+            //
+            //    Message:
+            //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
+            //             - help: consider further restricting this type parameter with `where T: Zar`
+            //
+            //    Suggestion:
+            //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
+            //                                          - insert: `, T: Zar`
+            //
+            // Additionally, there may be no `where` clause whatsoever in the case that this was
+            // reached because the generic parameter has a default:
+            //
+            //    Message:
+            //      trait Foo<T=()> {... }
+            //             - help: consider further restricting this type parameter with `where T: Zar`
+            //
+            //    Suggestion:
+            //      trait Foo<T=()> where T: Zar {... }
+            //                     - insert: `where T: Zar`
 
-            for predicate in generics.where_clause.predicates {
-                if let WherePredicate::BoundPredicate(WhereBoundPredicate {
-                    span,
-                    bounded_ty,
-                    ..
-                }) = predicate
-                {
-                    if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
-                        if let Some(segment) = path.segments.first() {
-                            if segment.ident.to_string() == param_name {
-                                param_spans.push(span);
+            if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
+                && generics.where_clause.predicates.len() == 0
+            {
+                // Suggest a bound, but there is no existing `where` clause *and* the type param has a
+                // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
+                suggestions.push((
+                    generics.where_clause.tail_span_for_suggestion(),
+                    format!(" where {}: {}", param_name, constraint),
+                    SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
+                ));
+            } else {
+                let mut param_spans = Vec::new();
+
+                for predicate in generics.where_clause.predicates {
+                    if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                        span,
+                        bounded_ty,
+                        ..
+                    }) = predicate
+                    {
+                        if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
+                            if let Some(segment) = path.segments.first() {
+                                if segment.ident.to_string() == param_name {
+                                    param_spans.push(span);
+                                }
                             }
                         }
                     }
                 }
-            }
 
-            match param_spans[..] {
-                [&param_span] => suggest_restrict(param_span.shrink_to_hi()),
-                _ => {
-                    err.span_suggestion_verbose(
-                        generics.where_clause.tail_span_for_suggestion(),
-                        &msg_restrict_type_further,
-                        format!(", {}: {}", param_name, constraint),
-                        Applicability::MachineApplicable,
-                    );
+                match param_spans[..] {
+                    [&param_span] => suggest_restrict(param_span.shrink_to_hi()),
+                    _ => {
+                        suggestions.push((
+                            generics.where_clause.tail_span_for_suggestion(),
+                            constraints
+                                .iter()
+                                .map(|&(constraint, _)| format!(", {}: {}", param_name, constraint))
+                                .collect::<String>(),
+                            SuggestChangingConstraintsMessage::RestrictTypeFurther {
+                                ty: param_name,
+                            },
+                        ));
+                    }
                 }
             }
         }
+    }
 
-        true
+    if suggestions.len() == 1 {
+        let (span, suggestion, msg) = suggestions.pop().unwrap();
+
+        let s;
+        let msg = match msg {
+            SuggestChangingConstraintsMessage::RestrictBoundFurther => {
+                "consider further restricting this bound"
+            }
+            SuggestChangingConstraintsMessage::RestrictType { ty } => {
+                s = format!("consider restricting type parameter `{}`", ty);
+                &s
+            }
+            SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
+                s = format!("consider further restricting type parameter `{}`", ty);
+                &s
+            }
+            SuggestChangingConstraintsMessage::RemovingQSized => {
+                "consider removing the `?Sized` bound to make the type parameter `Sized`"
+            }
+        };
+
+        err.span_suggestion_verbose(span, msg, suggestion, applicability);
+    } else {
+        err.multipart_suggestion_verbose(
+            "consider restricting type parameters",
+            suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(),
+            applicability,
+        );
     }
+
+    true
 }
 
 /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 040a087b235..f01843ebaba 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -276,11 +276,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // we suggest adding a separate return expression instead.
             // (To avoid things like suggesting `Ok(while .. { .. })`.)
             if expr_ty.is_unit() {
+                let mut id = expr.hir_id;
+                let mut parent;
+
+                // Unroll desugaring, to make sure this works for `for` loops etc.
+                loop {
+                    parent = self.tcx.hir().get_parent_node(id);
+                    if let Some(parent_span) = self.tcx.hir().opt_span(parent) {
+                        if parent_span.find_ancestor_inside(expr.span).is_some() {
+                            // The parent node is part of the same span, so is the result of the
+                            // same expansion/desugaring and not the 'real' parent node.
+                            id = parent;
+                            continue;
+                        }
+                    }
+                    break;
+                }
+
                 if let Some(hir::Node::Block(&hir::Block {
                     span: block_span, expr: Some(e), ..
-                })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
+                })) = self.tcx.hir().find(parent)
                 {
-                    if e.hir_id == expr.hir_id {
+                    if e.hir_id == id {
                         if let Some(span) = expr.span.find_ancestor_inside(block_span) {
                             let return_suggestions =
                                 if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) {
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index e5255686ff9..2b611e5aae2 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -117,7 +117,7 @@ mod c_char_definition {
             all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
             all(target_os = "l4re", target_arch = "x86_64"),
             all(
-                target_os = "freebsd",
+                any(target_os = "freebsd", target_os = "openbsd"),
                 any(
                     target_arch = "aarch64",
                     target_arch = "arm",
@@ -130,7 +130,6 @@ mod c_char_definition {
                 target_os = "netbsd",
                 any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
             ),
-            all(target_os = "openbsd", target_arch = "aarch64"),
             all(
                 target_os = "vxworks",
                 any(
diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs
index 4c68d11e893..cf2c0a02351 100644
--- a/library/portable-simd/crates/core_simd/src/intrinsics.rs
+++ b/library/portable-simd/crates/core_simd/src/intrinsics.rs
@@ -18,9 +18,10 @@
 //!
 //! Unless stated otherwise, all intrinsics for binary operations require SIMD vectors of equal types and lengths.
 
-/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
-/// mostly lowered to the matching LLVM instructions by the compiler in a fairly straightforward manner.
-/// The associated LLVM instruction or intrinsic is documented alongside each Rust intrinsic function.
+
+// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
+// mostly lowered to the matching LLVM instructions by the compiler in a fairly straightforward manner.
+// The associated LLVM instruction or intrinsic is documented alongside each Rust intrinsic function.
 extern "platform-intrinsic" {
     /// add/fadd
     pub(crate) fn simd_add<T>(x: T, y: T) -> T;
diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs
index df11dc21aa7..13bb079194f 100644
--- a/library/std/src/os/fd/mod.rs
+++ b/library/std/src/os/fd/mod.rs
@@ -11,3 +11,6 @@ pub mod owned;
 
 // Implementations for `AsRawFd` etc. for network types.
 mod net;
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index d72f9a2ff9c..807b057234a 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -21,6 +21,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// descriptor, so it can be used in FFI in places where a file descriptor is
 /// passed as an argument, it is not captured or consumed, and it never has the
 /// value `-1`.
+///
+/// This type's `.to_owned()` implementation returns another `BorrowedFd`
+/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
+/// descriptor, which is then borrowed under the same lifetime.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
@@ -62,7 +66,7 @@ impl BorrowedFd<'_> {
     /// the returned `BorrowedFd`, and it must not have the value `-1`.
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_fd(fd: RawFd) -> Self {
+    pub unsafe fn borrow_raw(fd: RawFd) -> Self {
         assert_ne!(fd, u32::MAX as RawFd);
         // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
         unsafe { Self { fd, _phantom: PhantomData } }
@@ -231,7 +235,7 @@ impl AsFd for OwnedFd {
         // Safety: `OwnedFd` and `BorrowedFd` have the same validity
         // invariants, and the `BorrowdFd` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) }
+        unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
     }
 }
 
diff --git a/library/std/src/os/fd/tests.rs b/library/std/src/os/fd/tests.rs
new file mode 100644
index 00000000000..26ef93e3d71
--- /dev/null
+++ b/library/std/src/os/fd/tests.rs
@@ -0,0 +1,34 @@
+#[cfg(any(unix, target_os = "wasi"))]
+#[test]
+fn test_raw_fd() {
+    #[cfg(unix)]
+    use crate::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
+    #[cfg(target_os = "wasi")]
+    use crate::os::wasi::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
+
+    let raw_fd: RawFd = crate::io::stdin().as_raw_fd();
+
+    let stdin_as_file = unsafe { crate::fs::File::from_raw_fd(raw_fd) };
+    assert_eq!(stdin_as_file.as_raw_fd(), raw_fd);
+    assert_eq!(unsafe { BorrowedFd::borrow_raw(raw_fd).as_raw_fd() }, raw_fd);
+    assert_eq!(stdin_as_file.into_raw_fd(), 0);
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+#[test]
+fn test_fd() {
+    #[cfg(unix)]
+    use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+    #[cfg(target_os = "wasi")]
+    use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+
+    let stdin = crate::io::stdin();
+    let fd: BorrowedFd<'_> = stdin.as_fd();
+    let raw_fd: RawFd = fd.as_raw_fd();
+    let owned_fd: OwnedFd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
+
+    let stdin_as_file = crate::fs::File::from(owned_fd);
+
+    assert_eq!(stdin_as_file.as_fd().as_raw_fd(), raw_fd);
+    assert_eq!(Into::<OwnedFd>::into(stdin_as_file).into_raw_fd(), raw_fd);
+}
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 8df6c54a414..842a15ae1bf 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -28,6 +28,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// And, it *may* have the value `NULL` (0), which can occur when consoles are
 /// detached from processes, or when `windows_subsystem` is used.
 ///
+/// This type's `.to_owned()` implementation returns another `BorrowedHandle`
+/// rather than an `OwnedHandle`. It just makes a trivial copy of the raw
+/// handle, which is then borrowed under the same lifetime.
+///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
 #[derive(Copy, Clone)]
 #[repr(transparent)]
@@ -131,7 +135,7 @@ impl BorrowedHandle<'_> {
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn borrow_raw(handle: RawHandle) -> Self {
         Self { handle, _phantom: PhantomData }
     }
 }
@@ -345,7 +349,7 @@ impl AsHandle for OwnedHandle {
         // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
         // invariants, and the `BorrowdHandle` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -373,49 +377,49 @@ impl From<OwnedHandle> for fs::File {
 impl AsHandle for crate::io::Stdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StdinLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::io::Stdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StdoutLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::io::Stderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StderrLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::process::ChildStdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -429,7 +433,7 @@ impl From<crate::process::ChildStdin> for OwnedHandle {
 impl AsHandle for crate::process::ChildStdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -443,7 +447,7 @@ impl From<crate::process::ChildStdout> for OwnedHandle {
 impl AsHandle for crate::process::ChildStderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -457,7 +461,7 @@ impl From<crate::process::ChildStderr> for OwnedHandle {
 impl<T> AsHandle for crate::thread::JoinHandle<T> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 2f13eb77a1b..a695a4106e8 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -21,6 +21,10 @@ use crate::sys::cvt;
 /// so it can be used in FFI in places where a socket is passed as an argument,
 /// it is not captured or consumed, and it never has the value
 /// `INVALID_SOCKET`.
+///
+/// This type's `.to_owned()` implementation returns another `BorrowedSocket`
+/// rather than an `OwnedSocket`. It just makes a trivial copy of the raw
+/// socket, which is then borrowed under the same lifetime.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
@@ -67,7 +71,7 @@ impl BorrowedSocket<'_> {
     /// `INVALID_SOCKET`.
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_socket(socket: RawSocket) -> Self {
+    pub unsafe fn borrow_raw(socket: RawSocket) -> Self {
         debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
         Self { socket, _phantom: PhantomData }
     }
@@ -239,14 +243,14 @@ impl AsSocket for OwnedSocket {
         // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
         // invariants, and the `BorrowdSocket` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
 impl AsSocket for crate::net::TcpStream {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
@@ -267,7 +271,7 @@ impl From<OwnedSocket> for crate::net::TcpStream {
 impl AsSocket for crate::net::TcpListener {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
@@ -288,7 +292,7 @@ impl From<OwnedSocket> for crate::net::TcpListener {
 impl AsSocket for crate::net::UdpSocket {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
-        unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
+        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
     }
 }
 
diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs
index b359987595d..e4d83ba0ffd 100644
--- a/library/std/src/sys/unix/stdio.rs
+++ b/library/std/src/sys/unix/stdio.rs
@@ -96,7 +96,7 @@ pub fn panic_output() -> Option<impl io::Write> {
 impl AsFd for io::Stdin {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) }
     }
 }
 
@@ -104,7 +104,7 @@ impl AsFd for io::Stdin {
 impl<'a> AsFd for io::StdinLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) }
     }
 }
 
@@ -112,7 +112,7 @@ impl<'a> AsFd for io::StdinLock<'a> {
 impl AsFd for io::Stdout {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }
     }
 }
 
@@ -120,7 +120,7 @@ impl AsFd for io::Stdout {
 impl<'a> AsFd for io::StdoutLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }
     }
 }
 
@@ -128,7 +128,7 @@ impl<'a> AsFd for io::StdoutLock<'a> {
 impl AsFd for io::Stderr {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) }
     }
 }
 
@@ -136,6 +136,6 @@ impl AsFd for io::Stderr {
 impl<'a> AsFd for io::StderrLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
-        unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) }
+        unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) }
     }
 }
diff --git a/library/stdarch b/library/stdarch
-Subproject b4a0e07552cf90ef8f1a5b775bf70e4db94b3d6
+Subproject bcbe010614f398ec86f3a9274d22e33e5f2ee60
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index d7e0b9d50f0..4c05818440b 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -139,7 +139,7 @@ target | std | notes
 `armv7r-none-eabi` | * | Bare ARMv7-R
 `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat
 `asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten
-`i586-pc-windows-msvc` | ✓ | 32-bit Windows w/o SSE
+`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE
 `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23)
 `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL
 `i686-linux-android` | ✓ | 32-bit x86 Android
@@ -236,7 +236,7 @@ target | std | host | notes
 `hexagon-unknown-linux-musl` | ? |  |
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS
 `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+)
-`i686-pc-windows-msvc` | ✓ |  | 32-bit Windows XP support
+`i686-pc-windows-msvc` | * |  | 32-bit Windows XP support
 `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
 `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2
 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
@@ -283,7 +283,7 @@ target | std | host | notes
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
-`x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support
+`x86_64-pc-windows-msvc` | * |  | 64-bit Windows XP support
 `x86_64-sun-solaris` | ? |  | Deprecated target for 64-bit Solaris 10/11, illumos
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
diff --git a/src/test/codegen/debuginfo-generic-closure-env-names.rs b/src/test/codegen/debuginfo-generic-closure-env-names.rs
index ad59f740b56..b29f8b4a029 100644
--- a/src/test/codegen/debuginfo-generic-closure-env-names.rs
+++ b/src/test/codegen/debuginfo-generic-closure-env-names.rs
@@ -3,7 +3,7 @@
 // of the enclosing functions don't get lost.
 //
 // Unfortunately, the order that debuginfo gets emitted into LLVM IR becomes a bit hard
-// to predict once async fns are involved.
+// to predict once async fns are involved, so DAG allows any order.
 //
 // Note that the test does not check async-fns when targeting MSVC because debuginfo for
 // those does not follow the enum-fallback encoding yet and thus is incomplete.
@@ -27,24 +27,24 @@
 // CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block"
 
 // function_containing_closure<u32>()
-// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: ![[function_containing_closure_NAMESPACE]]
-// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: ![[function_containing_closure_NAMESPACE]]
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: ![[function_containing_closure_NAMESPACE]]
+// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: ![[function_containing_closure_NAMESPACE]]
 
 // generic_async_function<Foo>()
-// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_function_NAMESPACE]]
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_function_NAMESPACE]]
 
 // generic_async_function<u32>()
-// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: ![[generic_async_function_NAMESPACE]]
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: ![[generic_async_function_NAMESPACE]]
 
 // generic_async_block<Foo>()
-// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_block_NAMESPACE]]
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_block_NAMESPACE]]
 
 // generic_async_block<u32>()
-// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: ![[generic_async_block_NAMESPACE]]
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: ![[generic_async_block_NAMESPACE]]
 
 // function_containing_closure<Foo>()
-// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
-// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
+// NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
+// MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
 
 
 #![crate_type = "lib"]
diff --git a/src/test/ui/async-await/proper-span-for-type-error.fixed b/src/test/ui/async-await/proper-span-for-type-error.fixed
index 1f1e1184dcc..7d43b575d2f 100644
--- a/src/test/ui/async-await/proper-span-for-type-error.fixed
+++ b/src/test/ui/async-await/proper-span-for-type-error.fixed
@@ -5,7 +5,8 @@
 async fn a() {}
 
 async fn foo() -> Result<(), i32> {
-    Ok(a().await) //~ ERROR mismatched types
+    a().await;
+    Ok(()) //~ ERROR mismatched types
 }
 
 fn main() {}
diff --git a/src/test/ui/async-await/proper-span-for-type-error.stderr b/src/test/ui/async-await/proper-span-for-type-error.stderr
index 611dc0407bf..25f05156ce2 100644
--- a/src/test/ui/async-await/proper-span-for-type-error.stderr
+++ b/src/test/ui/async-await/proper-span-for-type-error.stderr
@@ -6,10 +6,11 @@ LL |     a().await
    |
    = note:   expected enum `Result<(), i32>`
            found unit type `()`
-help: try wrapping the expression in `Ok`
+help: try adding an expression at the end of the block
+   |
+LL ~     a().await;
+LL ~     Ok(())
    |
-LL |     Ok(a().await)
-   |     +++         +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/check-cfg/allow-macro-cfg.rs b/src/test/ui/check-cfg/allow-macro-cfg.rs
new file mode 100644
index 00000000000..8016a4d190c
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-macro-cfg.rs
@@ -0,0 +1,14 @@
+// This test check that local #[allow(unexpected_cfgs)] works
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#[allow(unexpected_cfgs)]
+fn foo() {
+    if cfg!(FALSE) {}
+}
+
+fn main() {
+    #[allow(unexpected_cfgs)]
+    if cfg!(FALSE) {}
+}
diff --git a/src/test/ui/check-cfg/allow-same-level.rs b/src/test/ui/check-cfg/allow-same-level.rs
new file mode 100644
index 00000000000..6c869dc4202
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-same-level.rs
@@ -0,0 +1,11 @@
+// This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#[allow(unexpected_cfgs)]
+#[cfg(FALSE)]
+//~^ WARNING unexpected `cfg` condition name
+fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/allow-same-level.stderr b/src/test/ui/check-cfg/allow-same-level.stderr
new file mode 100644
index 00000000000..7797de584b9
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-same-level.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/allow-same-level.rs:7:7
+   |
+LL | #[cfg(FALSE)]
+   |       ^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/check-cfg/allow-top-level.rs b/src/test/ui/check-cfg/allow-top-level.rs
new file mode 100644
index 00000000000..d14b0eae5cc
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-top-level.rs
@@ -0,0 +1,15 @@
+// This test check that a top-level #![allow(unexpected_cfgs)] works
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#![allow(unexpected_cfgs)]
+
+#[cfg(FALSE)]
+fn bar() {}
+
+fn foo() {
+    if cfg!(FALSE) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/allow-upper-level.rs b/src/test/ui/check-cfg/allow-upper-level.rs
new file mode 100644
index 00000000000..04340694d9c
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-upper-level.rs
@@ -0,0 +1,12 @@
+// This test check that #[allow(unexpected_cfgs)] work if put on an upper level
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#[allow(unexpected_cfgs)]
+mod aa {
+    #[cfg(FALSE)]
+    fn bar() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs
index a70dda8386f..b078064b267 100644
--- a/src/test/ui/did_you_mean/compatible-variants.rs
+++ b/src/test/ui/did_you_mean/compatible-variants.rs
@@ -23,6 +23,21 @@ fn b() -> Result<(), ()> {
     //~| HELP try adding an expression
 }
 
+fn c() -> Option<()> {
+    for _ in [1, 2] {
+        //~^ ERROR mismatched types
+        f();
+    }
+    //~^ HELP try adding an expression
+}
+
+fn d() -> Option<()> {
+    c()?
+    //~^ ERROR incompatible types
+    //~| HELP try removing this `?`
+    //~| HELP try adding an expression
+}
+
 fn main() {
     let _: Option<()> = while false {};
     //~^ ERROR mismatched types
diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr
index 0dfd8f5c128..51c1bf97c4e 100644
--- a/src/test/ui/did_you_mean/compatible-variants.stderr
+++ b/src/test/ui/did_you_mean/compatible-variants.stderr
@@ -37,7 +37,52 @@ LL +     Ok(())
    |
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:27:25
+  --> $DIR/compatible-variants.rs:27:5
+   |
+LL |   fn c() -> Option<()> {
+   |             ---------- expected `Option<()>` because of return type
+LL | /     for _ in [1, 2] {
+LL | |
+LL | |         f();
+LL | |     }
+   | |_____^ expected enum `Option`, found `()`
+   |
+   = note:   expected enum `Option<()>`
+           found unit type `()`
+help: try adding an expression at the end of the block
+   |
+LL ~     }
+LL +     None
+   |
+LL ~     }
+LL +     Some(())
+   |
+
+error[E0308]: `?` operator has incompatible types
+  --> $DIR/compatible-variants.rs:35:5
+   |
+LL |     c()?
+   |     ^^^^ expected enum `Option`, found `()`
+   |
+   = note: `?` operator cannot convert from `()` to `Option<()>`
+   = note:   expected enum `Option<()>`
+           found unit type `()`
+help: try removing this `?`
+   |
+LL -     c()?
+LL +     c()
+   | 
+help: try adding an expression at the end of the block
+   |
+LL ~     c()?;
+LL +     None
+   |
+LL ~     c()?;
+LL +     Some(())
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/compatible-variants.rs:42:25
    |
 LL |     let _: Option<()> = while false {};
    |            ----------   ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
@@ -52,7 +97,7 @@ LL |     let _: Option<()> = Some(while false {});
    |                         +++++              +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:31:9
+  --> $DIR/compatible-variants.rs:46:9
    |
 LL |         while false {}
    |         ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
@@ -69,7 +114,7 @@ LL +         Some(())
    |
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:35:31
+  --> $DIR/compatible-variants.rs:50:31
    |
 LL |     let _: Result<i32, i32> = 1;
    |            ----------------   ^ expected enum `Result`, found integer
@@ -86,7 +131,7 @@ LL |     let _: Result<i32, i32> = Err(1);
    |                               ++++ +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:38:26
+  --> $DIR/compatible-variants.rs:53:26
    |
 LL |     let _: Option<i32> = 1;
    |            -----------   ^ expected enum `Option`, found integer
@@ -101,7 +146,7 @@ LL |     let _: Option<i32> = Some(1);
    |                          +++++ +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:41:28
+  --> $DIR/compatible-variants.rs:56:28
    |
 LL |     let _: Hey<i32, i32> = 1;
    |            -------------   ^ expected enum `Hey`, found integer
@@ -118,7 +163,7 @@ LL |     let _: Hey<i32, i32> = Hey::B(1);
    |                            +++++++ +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:44:29
+  --> $DIR/compatible-variants.rs:59:29
    |
 LL |     let _: Hey<i32, bool> = false;
    |            --------------   ^^^^^ expected enum `Hey`, found `bool`
@@ -133,7 +178,7 @@ LL |     let _: Hey<i32, bool> = Hey::B(false);
    |                             +++++++     +
 
 error[E0308]: mismatched types
-  --> $DIR/compatible-variants.rs:48:19
+  --> $DIR/compatible-variants.rs:63:19
    |
 LL |     let _ = Foo { bar };
    |                   ^^^ expected enum `Option`, found `i32`
@@ -145,6 +190,6 @@ help: try wrapping the expression in `Some`
 LL |     let _ = Foo { bar: Some(bar) };
    |                   ++++++++++   +
 
-error: aborting due to 9 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs
index 258f9e4831f..54d86c31fb4 100644
--- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs
+++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs
@@ -29,4 +29,18 @@ fn doc_comment_on_expr(num: u8) -> bool {
 fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
 //~^ ERROR: unused doc comment
 
+fn doc_comment_on_block() {
+    /// unused doc comment
+    //~^ ERROR: unused doc comment
+    {
+        let x = 12;
+    }
+}
+
+/// unused doc comment
+//~^ ERROR: unused doc comment
+extern "C" {
+    fn foo();
+}
+
 fn main() {}
diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
index 3ce1df71a2e..30a96af583a 100644
--- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
+++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
@@ -49,6 +49,32 @@ LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
    |
    = help: use `//` for a plain comment
 
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:33:5
+   |
+LL |       /// unused doc comment
+   |       ^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | /     {
+LL | |         let x = 12;
+LL | |     }
+   | |_____- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:40:1
+   |
+LL |   /// unused doc comment
+   |   ^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | / extern "C" {
+LL | |     fn foo();
+LL | | }
+   | |_- rustdoc does not generate documentation for extern block
+   |
+   = help: use `//` for a plain comment
+
 error[E0308]: mismatched types
   --> $DIR/unused-doc-comments-edge-cases.rs:14:9
    |
@@ -63,7 +89,7 @@ help: you might have meant to return this value
 LL |         return true;
    |         ++++++     +
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/moves/use_of_moved_value_clone_suggestions.rs b/src/test/ui/moves/use_of_moved_value_clone_suggestions.rs
new file mode 100644
index 00000000000..d5c8d4e6bdf
--- /dev/null
+++ b/src/test/ui/moves/use_of_moved_value_clone_suggestions.rs
@@ -0,0 +1,6 @@
+// `Rc` is not ever `Copy`, we should not suggest adding `T: Copy` constraint
+fn duplicate_rc<T>(t: std::rc::Rc<T>) -> (std::rc::Rc<T>, std::rc::Rc<T>) {
+    (t, t) //~ use of moved value: `t`
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr
new file mode 100644
index 00000000000..c25981e6f80
--- /dev/null
+++ b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_clone_suggestions.rs:3:9
+   |
+LL | fn duplicate_rc<T>(t: std::rc::Rc<T>) -> (std::rc::Rc<T>, std::rc::Rc<T>) {
+   |                    - move occurs because `t` has type `Rc<T>`, which does not implement the `Copy` trait
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed
new file mode 100644
index 00000000000..d31046c7700
--- /dev/null
+++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed
@@ -0,0 +1,72 @@
+// run-rustfix
+#![allow(dead_code)]
+
+fn duplicate_t<T: Copy>(t: T) -> (T, T) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_opt<T: Copy>(t: Option<T>) -> (Option<T>, Option<T>) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_tup1<T: Copy>(t: (T,)) -> ((T,), (T,)) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_tup2<A: Copy, B: Copy>(t: (A, B)) -> ((A, B), (A, B)) {
+    //~^ HELP consider restricting type parameters
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+struct S<T>(T);
+trait Trait {}
+impl<T: Trait + Clone> Clone for S<T> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+impl<T: Trait + Copy> Copy for S<T> {}
+
+trait A {}
+trait B {}
+
+// Test where bounds are added with different bound placements
+fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
+where
+    T: A + Trait + Copy,
+    //~^ HELP consider further restricting this bound
+{
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
+where
+    T: A,
+    T: B, T: Trait, T: Copy
+    //~^ HELP consider further restricting type parameter `T`
+{
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
+where
+    T: B + Trait + Copy,
+    //~^ HELP consider further restricting this bound
+{
+    (t, t) //~ use of moved value: `t`
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.rs b/src/test/ui/moves/use_of_moved_value_copy_suggestions.rs
new file mode 100644
index 00000000000..7cc5189fac0
--- /dev/null
+++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.rs
@@ -0,0 +1,72 @@
+// run-rustfix
+#![allow(dead_code)]
+
+fn duplicate_t<T>(t: T) -> (T, T) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_opt<T>(t: Option<T>) -> (Option<T>, Option<T>) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_tup1<T>(t: (T,)) -> ((T,), (T,)) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_tup2<A, B>(t: (A, B)) -> ((A, B), (A, B)) {
+    //~^ HELP consider restricting type parameters
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom<T>(t: S<T>) -> (S<T>, S<T>) {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+struct S<T>(T);
+trait Trait {}
+impl<T: Trait + Clone> Clone for S<T> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+impl<T: Trait + Copy> Copy for S<T> {}
+
+trait A {}
+trait B {}
+
+// Test where bounds are added with different bound placements
+fn duplicate_custom_1<T>(t: S<T>) -> (S<T>, S<T>) where {
+    //~^ HELP consider restricting type parameter `T`
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
+where
+    T: A,
+    //~^ HELP consider further restricting this bound
+{
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
+where
+    T: A,
+    T: B,
+    //~^ HELP consider further restricting type parameter `T`
+{
+    (t, t) //~ use of moved value: `t`
+}
+
+fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
+where
+    T: B,
+    //~^ HELP consider further restricting this bound
+{
+    (t, t) //~ use of moved value: `t`
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr
new file mode 100644
index 00000000000..8e72697ca30
--- /dev/null
+++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr
@@ -0,0 +1,147 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:6:9
+   |
+LL | fn duplicate_t<T>(t: T) -> (T, T) {
+   |                   - move occurs because `t` has type `T`, which does not implement the `Copy` trait
+LL |
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) {
+   |                 ++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:11:9
+   |
+LL | fn duplicate_opt<T>(t: Option<T>) -> (Option<T>, Option<T>) {
+   |                     - move occurs because `t` has type `Option<T>`, which does not implement the `Copy` trait
+LL |
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn duplicate_opt<T: Copy>(t: Option<T>) -> (Option<T>, Option<T>) {
+   |                   ++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:16:9
+   |
+LL | fn duplicate_tup1<T>(t: (T,)) -> ((T,), (T,)) {
+   |                      - move occurs because `t` has type `(T,)`, which does not implement the `Copy` trait
+LL |
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn duplicate_tup1<T: Copy>(t: (T,)) -> ((T,), (T,)) {
+   |                    ++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:21:9
+   |
+LL | fn duplicate_tup2<A, B>(t: (A, B)) -> ((A, B), (A, B)) {
+   |                         - move occurs because `t` has type `(A, B)`, which does not implement the `Copy` trait
+LL |
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider restricting type parameters
+   |
+LL | fn duplicate_tup2<A: Copy, B: Copy>(t: (A, B)) -> ((A, B), (A, B)) {
+   |                    ++++++   ++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:26:9
+   |
+LL | fn duplicate_custom<T>(t: S<T>) -> (S<T>, S<T>) {
+   |                        - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
+LL |
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
+   |                      ++++++++++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:44:9
+   |
+LL | fn duplicate_custom_1<T>(t: S<T>) -> (S<T>, S<T>) where {
+   |                          - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
+LL |
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
+   |                        ++++++++++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:52:9
+   |
+LL | fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
+   |                          - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
+...
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider further restricting this bound
+   |
+LL |     T: A + Trait + Copy,
+   |          ++++++++++++++
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:61:9
+   |
+LL | fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
+   |                          - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
+...
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider further restricting type parameter `T`
+   |
+LL |     T: B, T: Trait, T: Copy
+   |         ~~~~~~~~~~~~~~~~~~~
+
+error[E0382]: use of moved value: `t`
+  --> $DIR/use_of_moved_value_copy_suggestions.rs:69:9
+   |
+LL | fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>)
+   |                             - move occurs because `t` has type `S<T>`, which does not implement the `Copy` trait
+...
+LL |     (t, t)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+   |
+help: consider further restricting this bound
+   |
+LL |     T: B + Trait + Copy,
+   |          ++++++++++++++
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0382`.