about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs4
-rw-r--r--compiler/rustc_borrowck/src/lib.rs15
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs102
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs21
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs32
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs87
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs9
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs9
-rw-r--r--compiler/rustc_typeck/src/check/check.rs84
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_typeck/src/check/op.rs17
-rw-r--r--library/panic_unwind/src/gcc.rs2
-rw-r--r--library/std/build.rs1
-rw-r--r--library/std/src/os/mod.rs1
-rw-r--r--library/std/src/os/unix/mod.rs1
-rw-r--r--library/std/src/os/unix/net/stream.rs3
-rw-r--r--library/std/src/os/unix/ucred.rs4
-rw-r--r--library/std/src/os/unix/ucred/tests.rs3
-rw-r--r--library/std/src/sys/unix/args.rs4
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs4
-rw-r--r--library/std/src/sys/unix/fs.rs25
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs4
-rw-r--r--library/std/src/sys/unix/mod.rs3
-rw-r--r--library/std/src/sys/unix/os.rs6
-rw-r--r--library/std/src/sys/unix/rand.rs3
-rw-r--r--library/std/src/sys/unix/thread.rs2
-rw-r--r--library/std/src/sys/unix/thread_parker.rs15
-rw-r--r--library/std/src/sys/unix/time.rs4
-rw-r--r--library/std/src/sys_common/net.rs2
-rw-r--r--library/unwind/src/libunwind.rs6
-rw-r--r--src/test/codegen/noalias-box-off.rs8
-rw-r--r--src/test/codegen/noalias-box.rs8
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/ui/argument-suggestions/issue-99482.rs5
-rw-r--r--src/test/ui/argument-suggestions/issue-99482.stderr19
-rw-r--r--src/test/ui/deriving/deriving-all-codegen.stdout99
-rw-r--r--src/test/ui/impl-trait/issue-99073-2.rs17
-rw-r--r--src/test/ui/impl-trait/issue-99073-2.stderr15
-rw-r--r--src/test/ui/impl-trait/issue-99073.rs8
-rw-r--r--src/test/ui/impl-trait/issue-99073.stderr14
-rw-r--r--src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr22
-rw-r--r--src/test/ui/lint/auxiliary/add-impl.rs22
-rw-r--r--src/test/ui/lint/unused-qualification-in-derive-expansion.rs16
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.rs4
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.stderr46
-rw-r--r--src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs2
-rw-r--r--src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr23
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57961.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57961.stderr20
57 files changed, 544 insertions, 332 deletions
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 97daad201d9..efc17a173f4 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -2,7 +2,7 @@
 
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::vec::IndexVec;
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
 use rustc_middle::mir::Body;
 use rustc_middle::ty::{self, TyCtxt};
 
@@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>(
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> BodyWithBorrowckFacts<'tcx> {
     let (input_body, promoted) = tcx.mir_promoted(def);
-    tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
+    tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| {
         let input_body: &Body<'_> = &input_body.borrow();
         let promoted: &IndexVec<_, _> = &promoted.borrow();
         *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 29f47200b80..9dfefe4d236 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -24,7 +24,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::ChunkedBitSet;
 use rustc_index::vec::IndexVec;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
 use rustc_middle::mir::{
     traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
     PlaceRef, VarDebugInfoContents,
@@ -130,11 +130,14 @@ fn mir_borrowck<'tcx>(
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
     let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
 
-    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
-        let input_body: &Body<'_> = &input_body.borrow();
-        let promoted: &IndexVec<_, _> = &promoted.borrow();
-        do_mir_borrowck(&infcx, input_body, promoted, false).0
-    });
+    let opt_closure_req = tcx
+        .infer_ctxt()
+        .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
+        .enter(|infcx| {
+            let input_body: &Body<'_> = &input_body.borrow();
+            let promoted: &IndexVec<_, _> = &promoted.borrow();
+            do_mir_borrowck(&infcx, input_body, promoted, false).0
+        });
     debug!("mir_borrowck done");
 
     tcx.arena.alloc(opt_closure_req)
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index de9da845729..407bbf48813 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -3,8 +3,8 @@ use rustc_data_structures::vec_map::VecMap;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::OpaqueTyOrigin;
 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::TyCtxtInferExt as _;
+use rustc_infer::infer::{DefiningAnchor, InferCtxt};
 use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
@@ -269,59 +269,65 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
             let param_env = self.tcx.param_env(def_id);
             let body_id = self.tcx.local_def_id_to_hir_id(def_id);
-            self.tcx.infer_ctxt().enter(move |infcx| {
-                // Require the hidden type to be well-formed with only the generics of the opaque type.
-                // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
-                // hidden type is well formed even without those bounds.
-                let predicate =
-                    ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
-                        .to_predicate(infcx.tcx);
-                let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
-
-                // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
-                // the bounds that the function supplies.
-                match infcx.register_hidden_type(
-                    OpaqueTypeKey { def_id, substs: id_substs },
-                    ObligationCause::misc(instantiated_ty.span, body_id),
-                    param_env,
-                    definition_ty,
-                    origin,
-                ) {
-                    Ok(infer_ok) => {
-                        for obligation in infer_ok.obligations {
-                            fulfillment_cx.register_predicate_obligation(&infcx, obligation);
+            // HACK This bubble is required for this tests to pass:
+            // type-alias-impl-trait/issue-67844-nested-opaque.rs
+            self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(
+                move |infcx| {
+                    // Require the hidden type to be well-formed with only the generics of the opaque type.
+                    // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+                    // hidden type is well formed even without those bounds.
+                    let predicate =
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
+                            .to_predicate(infcx.tcx);
+                    let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
+
+                    // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
+                    // the bounds that the function supplies.
+                    match infcx.register_hidden_type(
+                        OpaqueTypeKey { def_id, substs: id_substs },
+                        ObligationCause::misc(instantiated_ty.span, body_id),
+                        param_env,
+                        definition_ty,
+                        origin,
+                    ) {
+                        Ok(infer_ok) => {
+                            for obligation in infer_ok.obligations {
+                                fulfillment_cx.register_predicate_obligation(&infcx, obligation);
+                            }
+                        }
+                        Err(err) => {
+                            infcx
+                                .report_mismatched_types(
+                                    &ObligationCause::misc(instantiated_ty.span, body_id),
+                                    self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
+                                    definition_ty,
+                                    err,
+                                )
+                                .emit();
                         }
                     }
-                    Err(err) => {
-                        infcx
-                            .report_mismatched_types(
-                                &ObligationCause::misc(instantiated_ty.span, body_id),
-                                self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
-                                definition_ty,
-                                err,
-                            )
-                            .emit();
-                    }
-                }
 
-                fulfillment_cx.register_predicate_obligation(
-                    &infcx,
-                    Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
-                );
+                    fulfillment_cx.register_predicate_obligation(
+                        &infcx,
+                        Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
+                    );
 
-                // Check that all obligations are satisfied by the implementation's
-                // version.
-                let errors = fulfillment_cx.select_all_or_error(&infcx);
+                    // Check that all obligations are satisfied by the implementation's
+                    // version.
+                    let errors = fulfillment_cx.select_all_or_error(&infcx);
 
-                let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+                    // This is still required for many(half of the tests in ui/type-alias-impl-trait)
+                    // tests to pass
+                    let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 
-                if errors.is_empty() {
-                    definition_ty
-                } else {
-                    infcx.report_fulfillment_errors(&errors, None, false);
-                    self.tcx.ty_error()
-                }
-            })
+                    if errors.is_empty() {
+                        definition_ty
+                    } else {
+                        infcx.report_fulfillment_errors(&errors, None, false);
+                        self.tcx.ty_error()
+                    }
+                },
+            )
         } else {
             definition_ty
         }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index cf2140097e6..eb9df281e7d 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -21,6 +21,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{
     InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
 };
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::AssertKind;
@@ -224,6 +225,26 @@ pub(crate) fn type_check<'mir, 'tcx>(
                     )
                     .unwrap();
                     let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
+                    // Check that RPITs are only constrained in their outermost
+                    // function, otherwise report a mismatched types error.
+                    if let OpaqueTyOrigin::FnReturn(parent) | OpaqueTyOrigin::AsyncFn(parent)
+                            = infcx.opaque_ty_origin_unchecked(opaque_type_key.def_id, hidden_type.span)
+                        && parent.to_def_id() != body.source.def_id()
+                    {
+                        infcx
+                            .report_mismatched_types(
+                                &ObligationCause::misc(
+                                    hidden_type.span,
+                                    infcx.tcx.hir().local_def_id_to_hir_id(
+                                        body.source.def_id().expect_local(),
+                                    ),
+                                ),
+                                infcx.tcx.mk_opaque(opaque_type_key.def_id.to_def_id(), opaque_type_key.substs),
+                                hidden_type.ty,
+                                ty::error::TypeError::Mismatch,
+                            )
+                            .emit();
+                    }
                     trace!(
                         "finalized opaque type {:?} to {:#?}",
                         opaque_type_key,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 076b627ca79..735017aa5a8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -727,16 +727,8 @@ impl<'a> TraitDef<'a> {
 
         let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
         let opt_trait_ref = Some(trait_ref);
-        let unused_qual = {
-            let word = rustc_ast::attr::mk_nested_word_item(Ident::new(
-                sym::unused_qualifications,
-                self.span,
-            ));
-            let list = rustc_ast::attr::mk_list_item(Ident::new(sym::allow, self.span), vec![word]);
-            cx.attribute(list)
-        };
 
-        let mut a = vec![attr, unused_qual];
+        let mut a = vec![attr];
         a.extend(self.attributes.iter().cloned());
 
         cx.item(
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index b3dc2e586d2..0e44d4e7c97 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -239,17 +239,31 @@ impl<'tcx> InferCtxtInner<'tcx> {
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum DefiningAnchor {
+    /// `DefId` of the item.
+    Bind(LocalDefId),
+    /// When opaque types are not resolved, we `Bubble` up, meaning
+    /// return the opaque/hidden type pair from query, for caller of query to handle it.
+    Bubble,
+    /// Used to catch type mismatch errors when handling opaque types.
+    Error,
+}
+
 pub struct InferCtxt<'a, 'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
     /// The `DefId` of the item in whose context we are performing inference or typeck.
     /// It is used to check whether an opaque type use is a defining use.
     ///
-    /// If it is `None`, we can't resolve opaque types here and need to bubble up
+    /// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up
     /// the obligation. This frequently happens for
     /// short lived InferCtxt within queries. The opaque type obligations are forwarded
     /// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
-    pub defining_use_anchor: Option<LocalDefId>,
+    ///
+    /// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
+    /// might come up during inference or typeck.
+    pub defining_use_anchor: DefiningAnchor,
 
     /// During type-checking/inference of a body, `in_progress_typeck_results`
     /// contains a reference to the typeck results being built up, which are
@@ -526,7 +540,7 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
 pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
     fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
-    defining_use_anchor: Option<LocalDefId>,
+    defining_use_anchor: DefiningAnchor,
 }
 
 pub trait TyCtxtInferExt<'tcx> {
@@ -535,7 +549,11 @@ pub trait TyCtxtInferExt<'tcx> {
 
 impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
     fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
-        InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None }
+        InferCtxtBuilder {
+            tcx: self,
+            defining_use_anchor: DefiningAnchor::Error,
+            fresh_typeck_results: None,
+        }
     }
 }
 
@@ -545,7 +563,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     /// Will also change the scope for opaque type defining use checks to the given owner.
     pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self {
         self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner)));
-        self.with_opaque_type_inference(table_owner)
+        self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner))
     }
 
     /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
@@ -554,8 +572,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     /// It is only meant to be called in two places, for typeck
     /// (via `with_fresh_in_progress_typeck_results`) and for the inference context used
     /// in mir borrowck.
-    pub fn with_opaque_type_inference(mut self, defining_use_anchor: LocalDefId) -> Self {
-        self.defining_use_anchor = Some(defining_use_anchor);
+    pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
+        self.defining_use_anchor = defining_use_anchor;
         self
     }
 
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 4ee9c4eeda4..7b0ff9552a3 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -1,4 +1,4 @@
-use crate::infer::{InferCtxt, InferOk};
+use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
 use crate::traits;
 use hir::def_id::{DefId, LocalDefId};
 use hir::{HirId, OpaqueTyOrigin};
@@ -101,44 +101,46 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
             ty::Opaque(def_id, substs) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
-                let origin = if self.defining_use_anchor.is_some() {
-                    // Check that this is `impl Trait` type is
-                    // declared by `parent_def_id` -- i.e., one whose
-                    // value we are inferring.  At present, this is
-                    // always true during the first phase of
-                    // type-check, but not always true later on during
-                    // NLL. Once we support named opaque types more fully,
-                    // this same scenario will be able to arise during all phases.
-                    //
-                    // Here is an example using type alias `impl Trait`
-                    // that indicates the distinction we are checking for:
-                    //
-                    // ```rust
-                    // mod a {
-                    //   pub type Foo = impl Iterator;
-                    //   pub fn make_foo() -> Foo { .. }
-                    // }
-                    //
-                    // mod b {
-                    //   fn foo() -> a::Foo { a::make_foo() }
-                    // }
-                    // ```
-                    //
-                    // Here, the return type of `foo` references an
-                    // `Opaque` indeed, but not one whose value is
-                    // presently being inferred. You can get into a
-                    // similar situation with closure return types
-                    // today:
-                    //
-                    // ```rust
-                    // fn foo() -> impl Iterator { .. }
-                    // fn bar() {
-                    //     let x = || foo(); // returns the Opaque assoc with `foo`
-                    // }
-                    // ```
-                    self.opaque_type_origin(def_id, cause.span)?
-                } else {
-                    self.opaque_ty_origin_unchecked(def_id, cause.span)
+                let origin = match self.defining_use_anchor {
+                    DefiningAnchor::Bind(_) => {
+                        // Check that this is `impl Trait` type is
+                        // declared by `parent_def_id` -- i.e., one whose
+                        // value we are inferring.  At present, this is
+                        // always true during the first phase of
+                        // type-check, but not always true later on during
+                        // NLL. Once we support named opaque types more fully,
+                        // this same scenario will be able to arise during all phases.
+                        //
+                        // Here is an example using type alias `impl Trait`
+                        // that indicates the distinction we are checking for:
+                        //
+                        // ```rust
+                        // mod a {
+                        //   pub type Foo = impl Iterator;
+                        //   pub fn make_foo() -> Foo { .. }
+                        // }
+                        //
+                        // mod b {
+                        //   fn foo() -> a::Foo { a::make_foo() }
+                        // }
+                        // ```
+                        //
+                        // Here, the return type of `foo` references an
+                        // `Opaque` indeed, but not one whose value is
+                        // presently being inferred. You can get into a
+                        // similar situation with closure return types
+                        // today:
+                        //
+                        // ```rust
+                        // fn foo() -> impl Iterator { .. }
+                        // fn bar() {
+                        //     let x = || foo(); // returns the Opaque assoc with `foo`
+                        // }
+                        // ```
+                        self.opaque_type_origin(def_id, cause.span)?
+                    }
+                    DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
+                    DefiningAnchor::Error => return None,
                 };
                 if let ty::Opaque(did2, _) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
@@ -407,7 +409,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     #[instrument(skip(self), level = "trace")]
     pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<OpaqueTyOrigin> {
         let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
-        let parent_def_id = self.defining_use_anchor?;
+        let parent_def_id = match self.defining_use_anchor {
+            DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
+            DefiningAnchor::Bind(bind) => bind,
+        };
         let item_kind = &self.tcx.hir().expect_item(def_id).kind;
 
         let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, ..  }) = item_kind else {
@@ -433,7 +438,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     #[instrument(skip(self), level = "trace")]
-    fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
+    pub fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
         let origin = match self.tcx.hir().expect_item(def_id).kind {
             hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
             ref itemkind => {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 9c0b534798e..3eef3308770 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -718,6 +718,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(asm_comments, true);
     tracked!(assume_incomplete_release, true);
     tracked!(binary_dep_depinfo, true);
+    tracked!(box_noalias, Some(false));
     tracked!(
         branch_protection,
         Some(BranchProtection {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index c41a8318ec5..4491965347b 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -3266,7 +3266,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     // this attribute doesn't make it UB for the pointed-to data to be undef.
                     attrs.set(ArgAttribute::NoUndef);
 
-                    // `Box` pointer parameters never alias because ownership is transferred
+                    // The aliasing rules for `Box<T>` are still not decided, but currently we emit
+                    // `noalias` for it. This can be turned off using an unstable flag.
+                    // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
+                    let noalias_for_box =
+                        self.tcx().sess.opts.unstable_opts.box_noalias.unwrap_or(true);
+
                     // `&mut` pointer parameters never alias other parameters,
                     // or mutable global data
                     //
@@ -3281,7 +3286,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     // `-Zmutable-noalias` debugging option.
                     let no_alias = match kind {
                         PointerKind::Shared | PointerKind::UniqueBorrowed => false,
-                        PointerKind::UniqueOwned => true,
+                        PointerKind::UniqueOwned => noalias_for_box,
                         PointerKind::Frozen => !is_return,
                     };
                     if no_alias {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 01ff9e254f7..5d365fc5246 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1209,6 +1209,8 @@ options! {
     binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
         "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \
         (default: no)"),
+    box_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
+        "emit noalias metadata for box (default: yes)"),
     branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED],
         "set options for branch target identification and pointer authentication on AArch64"),
     cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 6ca630b74cc..c2b2e319951 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -3,7 +3,7 @@
 // seems likely that they should eventually be merged into more
 // general routines.
 
-use crate::infer::TyCtxtInferExt;
+use crate::infer::{DefiningAnchor, TyCtxtInferExt};
 use crate::traits::{
     FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
     Unimplemented,
@@ -30,7 +30,9 @@ pub fn codegen_fulfill_obligation<'tcx>(
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    tcx.infer_ctxt().enter(|infcx| {
+    tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(|infcx| {
+        //~^ HACK `Bubble` is required for
+        // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
         let mut selcx = SelectionContext::new(&infcx);
 
         let obligation_cause = ObligationCause::dummy();
@@ -69,7 +71,8 @@ pub fn codegen_fulfill_obligation<'tcx>(
 
         // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
         // as they will get constrained elsewhere, too.
-        let _opaque_types = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+        // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
+        let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 
         debug!("Cache miss: {trait_ref:?} => {impl_source:?}");
         Ok(&*tcx.arena.alloc(impl_source))
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 69f3f03cfa9..9497d5c4528 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ItemKind, Node, PathSegment};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
+use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::hir::nested_filter;
@@ -731,52 +731,52 @@ fn check_opaque_meets_bounds<'tcx>(
     };
     let param_env = tcx.param_env(defining_use_anchor);
 
-    tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| {
-        let ocx = ObligationCtxt::new(&infcx);
-        let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
+    tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)).enter(
+        move |infcx| {
+            let ocx = ObligationCtxt::new(&infcx);
+            let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
 
-        let misc_cause = traits::ObligationCause::misc(span, hir_id);
+            let misc_cause = traits::ObligationCause::misc(span, hir_id);
 
-        match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
-            Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
-            Err(ty_err) => {
-                tcx.sess.delay_span_bug(
-                    span,
-                    &format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
-                );
+            match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
+                Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
+                Err(ty_err) => {
+                    tcx.sess.delay_span_bug(
+                        span,
+                        &format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
+                    );
+                }
             }
-        }
 
-        // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
-        // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
-        // hidden type is well formed even without those bounds.
-        let predicate =
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into())).to_predicate(tcx);
-        ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
-
-        // Check that all obligations are satisfied by the implementation's
-        // version.
-        let errors = ocx.select_all_or_error();
-        if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-        }
-
-        match origin {
-            // Checked when type checking the function containing them.
-            hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
-            // Can have different predicates to their defining use
-            hir::OpaqueTyOrigin::TyAlias => {
-                let outlives_environment = OutlivesEnvironment::new(param_env);
-                infcx.check_region_obligations_and_report_errors(
-                    defining_use_anchor,
-                    &outlives_environment,
-                );
+            // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
+            // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+            // hidden type is well formed even without those bounds.
+            let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into()))
+                .to_predicate(tcx);
+            ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
+
+            // Check that all obligations are satisfied by the implementation's
+            // version.
+            let errors = ocx.select_all_or_error();
+            if !errors.is_empty() {
+                infcx.report_fulfillment_errors(&errors, None, false);
             }
-        }
-
-        // Clean up after ourselves
-        let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
-    });
+            match origin {
+                // Checked when type checking the function containing them.
+                hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
+                // Can have different predicates to their defining use
+                hir::OpaqueTyOrigin::TyAlias => {
+                    let outlives_environment = OutlivesEnvironment::new(param_env);
+                    infcx.check_region_obligations_and_report_errors(
+                        defining_use_anchor,
+                        &outlives_environment,
+                    );
+                }
+            }
+            // Clean up after ourselves
+            let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+        },
+    );
 }
 
 fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 3fb8e5080f3..020aa95d0be 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -1460,6 +1460,7 @@ pub fn check_type_bounds<'tcx>(
             .map(|e| e.map_bound(|e| *e).transpose_tuple2())
             .map(|(bound, span)| {
                 debug!(?bound);
+                // this is where opaque type is found
                 let concrete_ty_bound = bound.subst(tcx, rebased_substs);
                 debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
 
@@ -1481,7 +1482,6 @@ pub fn check_type_bounds<'tcx>(
             ocx.register_obligations(obligations);
             ocx.register_obligation(obligation);
         }
-
         // Check that all obligations are satisfied by the implementation's
         // version.
         let errors = ocx.select_all_or_error();
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index e6fa95b91e9..e3db70845dd 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -573,6 +573,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If so, we might have just forgotten to wrap some args in a tuple.
             if let Some(ty::Tuple(tys)) =
                 formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
+                // If the tuple is unit, we're not actually wrapping any arguments.
+                && !tys.is_empty()
                 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
             {
                 // Wrap up the N provided arguments starting at this position in a tuple.
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index a2daf6886f1..9858cd8fa19 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -630,18 +630,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let rm_borrow_msg = "remove the borrow to obtain an owned `String`";
         let to_owned_msg = "create an owned `String` from a string reference";
 
-        let string_type = self.tcx.get_diagnostic_item(sym::String);
-        let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() {
-            Some(ty_def) => Some(ty_def.did()) == string_type,
-            None => false,
+        let is_std_string = |ty: Ty<'tcx>| {
+            ty.ty_adt_def()
+                .map_or(false, |ty_def| self.tcx.is_diagnostic_item(sym::String, ty_def.did()))
         };
 
         match (lhs_ty.kind(), rhs_ty.kind()) {
             (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str
-                if (*l_ty.kind() == Str || is_std_string(l_ty)) && (
-                        *r_ty.kind() == Str || is_std_string(r_ty) ||
-                        &format!("{:?}", rhs_ty) == "&&str"
-                    ) =>
+                if (*l_ty.kind() == Str || is_std_string(l_ty))
+                    && (*r_ty.kind() == Str
+                        || is_std_string(r_ty)
+                        || matches!(
+                            r_ty.kind(), Ref(_, inner_ty, _) if *inner_ty.kind() == Str
+                        )) =>
             {
                 if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str`
                     err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings");
diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index a0297b4b2f5..057e47bfdd1 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -131,7 +131,7 @@ const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
 
 cfg_if::cfg_if! {
-    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))] {
+    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
         // ARM EHABI personality routine.
         // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
         //
diff --git a/library/std/build.rs b/library/std/build.rs
index bffbe802fd0..8b1a06ee750 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -15,6 +15,7 @@ fn main() {
         || target.contains("illumos")
         || target.contains("apple-darwin")
         || target.contains("apple-ios")
+        || target.contains("apple-watchos")
         || target.contains("uwp")
         || target.contains("windows")
         || target.contains("fuchsia")
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index a1df72a8a04..6fbaa42c768 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -141,7 +141,6 @@ pub mod openbsd;
 pub mod redox;
 #[cfg(target_os = "solaris")]
 pub mod solaris;
-
 #[cfg(target_os = "solid_asp3")]
 pub mod solid;
 #[cfg(target_os = "vxworks")]
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index cef546487f3..411cc0925c4 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -90,6 +90,7 @@ pub mod thread;
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "watchos",
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd"
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index 1d6083e66e1..cc3a8858793 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -12,6 +12,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "watchos",
     target_os = "netbsd",
     target_os = "openbsd"
 ))]
@@ -30,6 +31,7 @@ use crate::time::Duration;
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "watchos",
     target_os = "netbsd",
     target_os = "openbsd"
 ))]
@@ -238,6 +240,7 @@ impl UnixStream {
         target_os = "freebsd",
         target_os = "ios",
         target_os = "macos",
+        target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd"
     ))]
diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs
index 32e6430d3f6..ae4faf27b4d 100644
--- a/library/std/src/os/unix/ucred.rs
+++ b/library/std/src/os/unix/ucred.rs
@@ -36,7 +36,7 @@ pub use self::impl_linux::peer_cred;
 ))]
 pub use self::impl_bsd::peer_cred;
 
-#[cfg(any(target_os = "macos", target_os = "ios",))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 pub use self::impl_mac::peer_cred;
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -97,7 +97,7 @@ pub mod impl_bsd {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios",))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 pub mod impl_mac {
     use super::UCred;
     use crate::os::unix::io::AsRawFd;
diff --git a/library/std/src/os/unix/ucred/tests.rs b/library/std/src/os/unix/ucred/tests.rs
index 42d79418cf7..e63a2fc248e 100644
--- a/library/std/src/os/unix/ucred/tests.rs
+++ b/library/std/src/os/unix/ucred/tests.rs
@@ -9,6 +9,7 @@ use libc::{getegid, geteuid, getpid};
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "watchos",
     target_os = "openbsd"
 ))]
 fn test_socket_pair() {
@@ -25,7 +26,7 @@ fn test_socket_pair() {
 }
 
 #[test]
-#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos",))]
+#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos", target_os = "watchos"))]
 fn test_socket_pair_pids(arg: Type) -> RetType {
     // Create two connected sockets and get their peer credentials.
     let (sock_a, sock_b) = UnixStream::pair().unwrap();
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 79964e2b238..a342f0f5e85 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -151,7 +151,7 @@ mod imp {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 mod imp {
     use super::Args;
     use crate::ffi::CStr;
@@ -192,7 +192,7 @@ mod imp {
     // for i in (0..[args count])
     //      res.push([args objectAtIndex:i])
     // res
-    #[cfg(target_os = "ios")]
+    #[cfg(any(target_os = "ios", target_os = "watchos"))]
     pub fn args() -> Args {
         use crate::ffi::OsString;
         use crate::mem;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 4d8391656a4..c9ba661c829 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -31,6 +31,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
+#[cfg(target_os = "watchos")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "watchos";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".dylib";
+    pub const DLL_EXTENSION: &str = "dylib";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
+
 #[cfg(target_os = "freebsd")]
 pub mod os {
     pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index 137ca3a7633..30812dabb4e 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -47,6 +47,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
+    target_os = "watchos",
 ))]
 const fn max_iov() -> usize {
     libc::IOV_MAX as usize
@@ -67,7 +68,8 @@ const fn max_iov() -> usize {
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
-    target_os = "horizon"
+    target_os = "horizon",
+    target_os = "watchos",
 )))]
 const fn max_iov() -> usize {
     16 // The minimum value required by POSIX.
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 8b0bbd6a55c..7c882469440 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -17,6 +17,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
     all(target_os = "linux", target_env = "gnu"),
     target_os = "macos",
     target_os = "ios",
+    target_os = "watchos",
 ))]
 use crate::sys::weak::syscall;
 #[cfg(target_os = "macos")]
@@ -27,6 +28,7 @@ use libc::{c_int, mode_t};
 #[cfg(any(
     target_os = "macos",
     target_os = "ios",
+    target_os = "watchos",
     all(target_os = "linux", target_env = "gnu")
 ))]
 use libc::c_char;
@@ -443,7 +445,8 @@ impl FileAttr {
         target_os = "freebsd",
         target_os = "openbsd",
         target_os = "macos",
-        target_os = "ios"
+        target_os = "ios",
+        target_os = "watchos",
     ))]
     pub fn created(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64))
@@ -453,7 +456,8 @@ impl FileAttr {
         target_os = "freebsd",
         target_os = "openbsd",
         target_os = "macos",
-        target_os = "ios"
+        target_os = "ios",
+        target_os = "watchos",
     )))]
     pub fn created(&self) -> io::Result<SystemTime> {
         cfg_has_statx! {
@@ -707,6 +711,7 @@ impl DirEntry {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "linux",
         target_os = "emscripten",
         target_os = "android",
@@ -737,6 +742,7 @@ impl DirEntry {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd",
         target_os = "freebsd",
@@ -754,6 +760,7 @@ impl DirEntry {
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd",
         target_os = "freebsd",
@@ -911,11 +918,11 @@ impl File {
         cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?;
         return Ok(());
 
-        #[cfg(any(target_os = "macos", target_os = "ios"))]
+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
         unsafe fn os_fsync(fd: c_int) -> c_int {
             libc::fcntl(fd, libc::F_FULLFSYNC)
         }
-        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+        #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
         unsafe fn os_fsync(fd: c_int) -> c_int {
             libc::fsync(fd)
         }
@@ -925,7 +932,7 @@ impl File {
         cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?;
         return Ok(());
 
-        #[cfg(any(target_os = "macos", target_os = "ios"))]
+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
         unsafe fn os_datasync(fd: c_int) -> c_int {
             libc::fcntl(fd, libc::F_FULLFSYNC)
         }
@@ -946,7 +953,8 @@ impl File {
             target_os = "linux",
             target_os = "macos",
             target_os = "netbsd",
-            target_os = "openbsd"
+            target_os = "openbsd",
+            target_os = "watchos",
         )))]
         unsafe fn os_datasync(fd: c_int) -> c_int {
             libc::fsync(fd)
@@ -1396,7 +1404,8 @@ fn open_to_and_set_permissions(
     target_os = "linux",
     target_os = "android",
     target_os = "macos",
-    target_os = "ios"
+    target_os = "ios",
+    target_os = "watchos",
 )))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     let (mut reader, reader_metadata) = open_from(from)?;
@@ -1423,7 +1432,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use crate::sync::atomic::{AtomicBool, Ordering};
 
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 78f10f0534c..abf27e7db78 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -37,6 +37,7 @@ impl Condvar {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "l4re",
         target_os = "android",
         target_os = "redox"
@@ -58,6 +59,7 @@ impl Condvar {
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "l4re",
         target_os = "android",
         target_os = "redox",
@@ -102,6 +104,7 @@ impl Condvar {
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "android",
         target_os = "espidf",
         target_os = "horizon"
@@ -135,6 +138,7 @@ impl Condvar {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "android",
         target_os = "espidf",
         target_os = "horizon"
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 34a023b02c4..3d0d91460f7 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -86,6 +86,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
             // The poll on Darwin doesn't set POLLNVAL for closed fds.
             target_os = "macos",
             target_os = "ios",
+            target_os = "watchos",
             target_os = "redox",
             target_os = "l4re",
             target_os = "horizon",
@@ -329,7 +330,7 @@ cfg_if::cfg_if! {
         // See #41582 and https://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
         #[link(name = "resolv")]
         extern "C" {}
-    } else if #[cfg(target_os = "ios")] {
+    } else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
         #[link(name = "System")]
         #[link(name = "objc")]
         #[link(name = "Security", kind = "framework")]
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 7252ad32184..46545a0839f 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -61,7 +61,7 @@ extern "C" {
     )]
     #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
     #[cfg_attr(
-        any(target_os = "macos", target_os = "ios", target_os = "freebsd"),
+        any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
         link_name = "__error"
     )]
     #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
@@ -361,7 +361,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         let mut sz: u32 = 0;
@@ -598,6 +598,7 @@ pub fn home_dir() -> Option<PathBuf> {
     #[cfg(any(
         target_os = "android",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
@@ -610,6 +611,7 @@ pub fn home_dir() -> Option<PathBuf> {
     #[cfg(not(any(
         target_os = "android",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index 56d01074c20..bf49204881d 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -14,6 +14,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     unix,
     not(target_os = "macos"),
     not(target_os = "ios"),
+    not(target_os = "watchos"),
     not(target_os = "openbsd"),
     not(target_os = "freebsd"),
     not(target_os = "netbsd"),
@@ -195,7 +196,7 @@ mod imp {
 // once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
 // only used on iOS where direct access to `/dev/urandom` is blocked by the
 // sandbox.
-#[cfg(target_os = "ios")]
+#[cfg(any(target_os = "ios", target_os = "watchos"))]
 mod imp {
     use crate::io;
     use crate::ptr;
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index d191e1fe7a6..6533625876f 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -139,7 +139,7 @@ impl Thread {
         }
     }
 
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
     pub fn set_name(name: &CStr) {
         unsafe {
             libc::pthread_setname_np(name.as_ptr());
diff --git a/library/std/src/sys/unix/thread_parker.rs b/library/std/src/sys/unix/thread_parker.rs
index 9f4d4f7e736..ca1a7138fde 100644
--- a/library/std/src/sys/unix/thread_parker.rs
+++ b/library/std/src/sys/unix/thread_parker.rs
@@ -52,7 +52,12 @@ unsafe fn wait_timeout(
 ) {
     // Use the system clock on systems that do not support pthread_condattr_setclock.
     // This unfortunately results in problems when the system time changes.
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "espidf"))]
+    #[cfg(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "espidf"
+    ))]
     let (now, dur) = {
         use super::time::SystemTime;
         use crate::cmp::min;
@@ -73,7 +78,12 @@ unsafe fn wait_timeout(
         (now, dur)
     };
     // Use the monotonic clock on other systems.
-    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "espidf")))]
+    #[cfg(not(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "espidf"
+    )))]
     let (now, dur) = {
         use super::time::Timespec;
 
@@ -111,6 +121,7 @@ impl Parker {
             if #[cfg(any(
                 target_os = "macos",
                 target_os = "ios",
+                target_os = "watchos",
                 target_os = "l4re",
                 target_os = "android",
                 target_os = "redox"
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index d114af49d26..dff973f59d1 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -141,7 +141,7 @@ impl From<libc::timespec> for Timespec {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 mod inner {
     use crate::sync::atomic::{AtomicU64, Ordering};
     use crate::sys::cvt;
@@ -257,7 +257,7 @@ mod inner {
     }
 }
 
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
 mod inner {
     use crate::fmt;
     use crate::mem::MaybeUninit;
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index f5730a2cea5..c13bda32823 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -18,7 +18,7 @@ use libc::{c_int, c_void};
 cfg_if::cfg_if! {
     if #[cfg(any(
         target_os = "dragonfly", target_os = "freebsd",
-        target_os = "ios", target_os = "macos",
+        target_os = "ios", target_os = "macos", target_os = "watchos",
         target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
         target_os = "solaris", target_os = "haiku", target_os = "l4re"))] {
         use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 7b78bda424b..a5b6193b086 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -30,10 +30,10 @@ pub const unwinder_private_data_size: usize = 5;
 #[cfg(target_arch = "x86_64")]
 pub const unwinder_private_data_size: usize = 6;
 
-#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
+#[cfg(all(target_arch = "arm", not(any(target_os = "ios", target_os = "watchos"))))]
 pub const unwinder_private_data_size: usize = 20;
 
-#[cfg(all(target_arch = "arm", target_os = "ios"))]
+#[cfg(all(target_arch = "arm", any(target_os = "ios", target_os = "watchos")))]
 pub const unwinder_private_data_size: usize = 5;
 
 #[cfg(all(target_arch = "aarch64", target_pointer_width = "64"))]
@@ -105,7 +105,7 @@ extern "C" {
 }
 
 cfg_if::cfg_if! {
-if #[cfg(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm")))] {
+if #[cfg(any(target_os = "ios", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] {
     // Not ARM EHABI
     #[repr(C)]
     #[derive(Copy, Clone, PartialEq)]
diff --git a/src/test/codegen/noalias-box-off.rs b/src/test/codegen/noalias-box-off.rs
new file mode 100644
index 00000000000..afd17c7c160
--- /dev/null
+++ b/src/test/codegen/noalias-box-off.rs
@@ -0,0 +1,8 @@
+// compile-flags: -O -Z box-noalias=no
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @box_should_not_have_noalias_if_disabled(
+// CHECK-NOT: noalias
+#[no_mangle]
+pub fn box_should_not_have_noalias_if_disabled(_b: Box<u8>) {}
diff --git a/src/test/codegen/noalias-box.rs b/src/test/codegen/noalias-box.rs
new file mode 100644
index 00000000000..a3d1f093d8b
--- /dev/null
+++ b/src/test/codegen/noalias-box.rs
@@ -0,0 +1,8 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @box_should_have_noalias_by_default(
+// CHECK: noalias
+#[no_mangle]
+pub fn box_should_have_noalias_by_default(_b: Box<u8>) {}
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 7296b35788a..6f5248f5b18 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -4,6 +4,7 @@
     -Z                            asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
     -Z                       assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
     -Z                      binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
+    -Z                             box-noalias=val -- emit noalias metadata for box (default: yes)
     -Z                       branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
     -Z                           cf-protection=val -- instrument control-flow architecture protection
     -Z               cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
diff --git a/src/test/ui/argument-suggestions/issue-99482.rs b/src/test/ui/argument-suggestions/issue-99482.rs
new file mode 100644
index 00000000000..731b863069b
--- /dev/null
+++ b/src/test/ui/argument-suggestions/issue-99482.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let f = |_: (), f: fn()| f;
+    let _f = f(main);
+    //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+}
diff --git a/src/test/ui/argument-suggestions/issue-99482.stderr b/src/test/ui/argument-suggestions/issue-99482.stderr
new file mode 100644
index 00000000000..bc005e82a2c
--- /dev/null
+++ b/src/test/ui/argument-suggestions/issue-99482.stderr
@@ -0,0 +1,19 @@
+error[E0057]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/issue-99482.rs:3:14
+   |
+LL |     let _f = f(main);
+   |              ^ ---- an argument of type `()` is missing
+   |
+note: closure defined here
+  --> $DIR/issue-99482.rs:2:13
+   |
+LL |     let f = |_: (), f: fn()| f;
+   |             ^^^^^^^^^^^^^^^^
+help: provide the argument
+   |
+LL |     let _f = f((), main);
+   |              ~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout
index 542911537be..21fe663f067 100644
--- a/src/test/ui/deriving/deriving-all-codegen.stdout
+++ b/src/test/ui/deriving/deriving-all-codegen.stdout
@@ -25,42 +25,35 @@ extern crate std;
 // Empty struct.
 struct Empty;
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Empty {
     #[inline]
     fn clone(&self) -> Empty { *self }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for Empty { }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Empty {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         ::core::fmt::Formatter::write_str(f, "Empty")
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for Empty {
     #[inline]
     fn default() -> Empty { Empty {} }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Empty {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
 }
 impl ::core::marker::StructuralPartialEq for Empty {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Empty {
     #[inline]
     fn eq(&self, other: &Empty) -> bool { true }
 }
 impl ::core::marker::StructuralEq for Empty {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Empty {
     #[inline]
     #[doc(hidden)]
@@ -68,7 +61,6 @@ impl ::core::cmp::Eq for Empty {
     fn assert_receiver_is_total_eq(&self) -> () {}
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Empty {
     #[inline]
     fn partial_cmp(&self, other: &Empty)
@@ -77,7 +69,6 @@ impl ::core::cmp::PartialOrd for Empty {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Empty {
     #[inline]
     fn cmp(&self, other: &Empty) -> ::core::cmp::Ordering {
@@ -91,7 +82,6 @@ struct Point {
     y: u32,
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Point {
     #[inline]
     fn clone(&self) -> Point {
@@ -100,10 +90,8 @@ impl ::core::clone::Clone for Point {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for Point { }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Point {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x",
@@ -111,7 +99,6 @@ impl ::core::fmt::Debug for Point {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for Point {
     #[inline]
     fn default() -> Point {
@@ -122,7 +109,6 @@ impl ::core::default::Default for Point {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Point {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.x, state);
@@ -131,7 +117,6 @@ impl ::core::hash::Hash for Point {
 }
 impl ::core::marker::StructuralPartialEq for Point {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Point {
     #[inline]
     fn eq(&self, other: &Point) -> bool {
@@ -144,7 +129,6 @@ impl ::core::cmp::PartialEq for Point {
 }
 impl ::core::marker::StructuralEq for Point {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Point {
     #[inline]
     #[doc(hidden)]
@@ -154,7 +138,6 @@ impl ::core::cmp::Eq for Point {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Point {
     #[inline]
     fn partial_cmp(&self, other: &Point)
@@ -167,7 +150,6 @@ impl ::core::cmp::PartialOrd for Point {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Point {
     #[inline]
     fn cmp(&self, other: &Point) -> ::core::cmp::Ordering {
@@ -191,7 +173,6 @@ struct Big {
     b8: u32,
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Big {
     #[inline]
     fn clone(&self) -> Big {
@@ -208,7 +189,6 @@ impl ::core::clone::Clone for Big {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Big {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         let names: &'static _ =
@@ -221,7 +201,6 @@ impl ::core::fmt::Debug for Big {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for Big {
     #[inline]
     fn default() -> Big {
@@ -238,7 +217,6 @@ impl ::core::default::Default for Big {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Big {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.b1, state);
@@ -253,7 +231,6 @@ impl ::core::hash::Hash for Big {
 }
 impl ::core::marker::StructuralPartialEq for Big {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Big {
     #[inline]
     fn eq(&self, other: &Big) -> bool {
@@ -272,7 +249,6 @@ impl ::core::cmp::PartialEq for Big {
 }
 impl ::core::marker::StructuralEq for Big {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Big {
     #[inline]
     #[doc(hidden)]
@@ -282,7 +258,6 @@ impl ::core::cmp::Eq for Big {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Big {
     #[inline]
     fn partial_cmp(&self, other: &Big)
@@ -331,7 +306,6 @@ impl ::core::cmp::PartialOrd for Big {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Big {
     #[inline]
     fn cmp(&self, other: &Big) -> ::core::cmp::Ordering {
@@ -370,7 +344,6 @@ impl ::core::cmp::Ord for Big {
 // A struct with an unsized field. Some derives are not usable in this case.
 struct Unsized([u32]);
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Unsized {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized",
@@ -378,7 +351,6 @@ impl ::core::fmt::Debug for Unsized {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Unsized {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&self.0, state)
@@ -386,7 +358,6 @@ impl ::core::hash::Hash for Unsized {
 }
 impl ::core::marker::StructuralPartialEq for Unsized {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Unsized {
     #[inline]
     fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 }
@@ -395,7 +366,6 @@ impl ::core::cmp::PartialEq for Unsized {
 }
 impl ::core::marker::StructuralEq for Unsized {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Unsized {
     #[inline]
     #[doc(hidden)]
@@ -405,7 +375,6 @@ impl ::core::cmp::Eq for Unsized {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Unsized {
     #[inline]
     fn partial_cmp(&self, other: &Unsized)
@@ -414,7 +383,6 @@ impl ::core::cmp::PartialOrd for Unsized {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Unsized {
     #[inline]
     fn cmp(&self, other: &Unsized) -> ::core::cmp::Ordering {
@@ -426,7 +394,6 @@ impl ::core::cmp::Ord for Unsized {
 #[repr(packed)]
 struct PackedCopy(u32);
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for PackedCopy {
     #[inline]
     fn clone(&self) -> PackedCopy {
@@ -435,10 +402,8 @@ impl ::core::clone::Clone for PackedCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for PackedCopy { }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for PackedCopy {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedCopy",
@@ -446,7 +411,6 @@ impl ::core::fmt::Debug for PackedCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for PackedCopy {
     #[inline]
     fn default() -> PackedCopy {
@@ -454,7 +418,6 @@ impl ::core::default::Default for PackedCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for PackedCopy {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         ::core::hash::Hash::hash(&{ self.0 }, state)
@@ -462,7 +425,6 @@ impl ::core::hash::Hash for PackedCopy {
 }
 impl ::core::marker::StructuralPartialEq for PackedCopy {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for PackedCopy {
     #[inline]
     fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } }
@@ -471,7 +433,6 @@ impl ::core::cmp::PartialEq for PackedCopy {
 }
 impl ::core::marker::StructuralEq for PackedCopy {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for PackedCopy {
     #[inline]
     #[doc(hidden)]
@@ -481,7 +442,6 @@ impl ::core::cmp::Eq for PackedCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for PackedCopy {
     #[inline]
     fn partial_cmp(&self, other: &PackedCopy)
@@ -490,7 +450,6 @@ impl ::core::cmp::PartialOrd for PackedCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for PackedCopy {
     #[inline]
     fn cmp(&self, other: &PackedCopy) -> ::core::cmp::Ordering {
@@ -506,7 +465,6 @@ impl ::core::cmp::Ord for PackedCopy {
 #[repr(packed)]
 struct PackedNonCopy(u8);
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for PackedNonCopy {
     #[inline]
     fn clone(&self) -> PackedNonCopy {
@@ -515,7 +473,6 @@ impl ::core::clone::Clone for PackedNonCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for PackedNonCopy {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         let Self(ref __self_0_0) = *self;
@@ -524,7 +481,6 @@ impl ::core::fmt::Debug for PackedNonCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for PackedNonCopy {
     #[inline]
     fn default() -> PackedNonCopy {
@@ -532,7 +488,6 @@ impl ::core::default::Default for PackedNonCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for PackedNonCopy {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let Self(ref __self_0_0) = *self;
@@ -541,7 +496,6 @@ impl ::core::hash::Hash for PackedNonCopy {
 }
 impl ::core::marker::StructuralPartialEq for PackedNonCopy {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for PackedNonCopy {
     #[inline]
     fn eq(&self, other: &PackedNonCopy) -> bool {
@@ -558,7 +512,6 @@ impl ::core::cmp::PartialEq for PackedNonCopy {
 }
 impl ::core::marker::StructuralEq for PackedNonCopy {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for PackedNonCopy {
     #[inline]
     #[doc(hidden)]
@@ -568,7 +521,6 @@ impl ::core::cmp::Eq for PackedNonCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for PackedNonCopy {
     #[inline]
     fn partial_cmp(&self, other: &PackedNonCopy)
@@ -579,7 +531,6 @@ impl ::core::cmp::PartialOrd for PackedNonCopy {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for PackedNonCopy {
     #[inline]
     fn cmp(&self, other: &PackedNonCopy) -> ::core::cmp::Ordering {
@@ -592,23 +543,19 @@ impl ::core::cmp::Ord for PackedNonCopy {
 // An empty enum.
 enum Enum0 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Enum0 {
     #[inline]
     fn clone(&self) -> Enum0 { *self }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for Enum0 { }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Enum0 {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         unsafe { ::core::intrinsics::unreachable() }
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Enum0 {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         unsafe { ::core::intrinsics::unreachable() }
@@ -616,7 +563,6 @@ impl ::core::hash::Hash for Enum0 {
 }
 impl ::core::marker::StructuralPartialEq for Enum0 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Enum0 {
     #[inline]
     fn eq(&self, other: &Enum0) -> bool {
@@ -625,7 +571,6 @@ impl ::core::cmp::PartialEq for Enum0 {
 }
 impl ::core::marker::StructuralEq for Enum0 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Enum0 {
     #[inline]
     #[doc(hidden)]
@@ -633,7 +578,6 @@ impl ::core::cmp::Eq for Enum0 {
     fn assert_receiver_is_total_eq(&self) -> () {}
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Enum0 {
     #[inline]
     fn partial_cmp(&self, other: &Enum0)
@@ -642,7 +586,6 @@ impl ::core::cmp::PartialOrd for Enum0 {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Enum0 {
     #[inline]
     fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering {
@@ -657,7 +600,6 @@ enum Enum1 {
     },
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Enum1 {
     #[inline]
     fn clone(&self) -> Enum1 {
@@ -668,7 +610,6 @@ impl ::core::clone::Clone for Enum1 {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Enum1 {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         match self {
@@ -679,7 +620,6 @@ impl ::core::fmt::Debug for Enum1 {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Enum1 {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         match self {
@@ -690,7 +630,6 @@ impl ::core::hash::Hash for Enum1 {
 }
 impl ::core::marker::StructuralPartialEq for Enum1 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Enum1 {
     #[inline]
     fn eq(&self, other: &Enum1) -> bool {
@@ -709,7 +648,6 @@ impl ::core::cmp::PartialEq for Enum1 {
 }
 impl ::core::marker::StructuralEq for Enum1 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Enum1 {
     #[inline]
     #[doc(hidden)]
@@ -719,7 +657,6 @@ impl ::core::cmp::Eq for Enum1 {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Enum1 {
     #[inline]
     fn partial_cmp(&self, other: &Enum1)
@@ -731,7 +668,6 @@ impl ::core::cmp::PartialOrd for Enum1 {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Enum1 {
     #[inline]
     fn cmp(&self, other: &Enum1) -> ::core::cmp::Ordering {
@@ -749,39 +685,33 @@ enum Fieldless1 {
     A,
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Fieldless1 {
     #[inline]
     fn clone(&self) -> Fieldless1 { Fieldless1::A }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Fieldless1 {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         ::core::fmt::Formatter::write_str(f, "A")
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for Fieldless1 {
     #[inline]
     fn default() -> Fieldless1 { Self::A }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Fieldless1 {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
 }
 impl ::core::marker::StructuralPartialEq for Fieldless1 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Fieldless1 {
     #[inline]
     fn eq(&self, other: &Fieldless1) -> bool { true }
 }
 impl ::core::marker::StructuralEq for Fieldless1 {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Fieldless1 {
     #[inline]
     #[doc(hidden)]
@@ -789,7 +719,6 @@ impl ::core::cmp::Eq for Fieldless1 {
     fn assert_receiver_is_total_eq(&self) -> () {}
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Fieldless1 {
     #[inline]
     fn partial_cmp(&self, other: &Fieldless1)
@@ -798,7 +727,6 @@ impl ::core::cmp::PartialOrd for Fieldless1 {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Fieldless1 {
     #[inline]
     fn cmp(&self, other: &Fieldless1) -> ::core::cmp::Ordering {
@@ -815,16 +743,13 @@ enum Fieldless {
     C,
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Fieldless {
     #[inline]
     fn clone(&self) -> Fieldless { *self }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for Fieldless { }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Fieldless {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         match self {
@@ -835,13 +760,11 @@ impl ::core::fmt::Debug for Fieldless {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for Fieldless {
     #[inline]
     fn default() -> Fieldless { Self::A }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Fieldless {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
@@ -850,7 +773,6 @@ impl ::core::hash::Hash for Fieldless {
 }
 impl ::core::marker::StructuralPartialEq for Fieldless {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Fieldless {
     #[inline]
     fn eq(&self, other: &Fieldless) -> bool {
@@ -861,7 +783,6 @@ impl ::core::cmp::PartialEq for Fieldless {
 }
 impl ::core::marker::StructuralEq for Fieldless {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Fieldless {
     #[inline]
     #[doc(hidden)]
@@ -869,7 +790,6 @@ impl ::core::cmp::Eq for Fieldless {
     fn assert_receiver_is_total_eq(&self) -> () {}
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Fieldless {
     #[inline]
     fn partial_cmp(&self, other: &Fieldless)
@@ -880,7 +800,6 @@ impl ::core::cmp::PartialOrd for Fieldless {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Fieldless {
     #[inline]
     fn cmp(&self, other: &Fieldless) -> ::core::cmp::Ordering {
@@ -903,7 +822,6 @@ enum Mixed {
     },
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Mixed {
     #[inline]
     fn clone(&self) -> Mixed {
@@ -912,10 +830,8 @@ impl ::core::clone::Clone for Mixed {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for Mixed { }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Mixed {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         match self {
@@ -931,13 +847,11 @@ impl ::core::fmt::Debug for Mixed {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::default::Default for Mixed {
     #[inline]
     fn default() -> Mixed { Self::P }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Mixed {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
@@ -954,7 +868,6 @@ impl ::core::hash::Hash for Mixed {
 }
 impl ::core::marker::StructuralPartialEq for Mixed {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Mixed {
     #[inline]
     fn eq(&self, other: &Mixed) -> bool {
@@ -987,7 +900,6 @@ impl ::core::cmp::PartialEq for Mixed {
 }
 impl ::core::marker::StructuralEq for Mixed {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Mixed {
     #[inline]
     #[doc(hidden)]
@@ -997,7 +909,6 @@ impl ::core::cmp::Eq for Mixed {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Mixed {
     #[inline]
     fn partial_cmp(&self, other: &Mixed)
@@ -1025,7 +936,6 @@ impl ::core::cmp::PartialOrd for Mixed {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Mixed {
     #[inline]
     fn cmp(&self, other: &Mixed) -> ::core::cmp::Ordering {
@@ -1054,7 +964,6 @@ impl ::core::cmp::Ord for Mixed {
 // for this enum.
 enum Fielded { X(u32), Y(bool), Z(Option<i32>), }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Fielded {
     #[inline]
     fn clone(&self) -> Fielded {
@@ -1069,7 +978,6 @@ impl ::core::clone::Clone for Fielded {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::fmt::Debug for Fielded {
     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
         match self {
@@ -1086,7 +994,6 @@ impl ::core::fmt::Debug for Fielded {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::hash::Hash for Fielded {
     fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
         let __self_tag = ::core::intrinsics::discriminant_value(self);
@@ -1100,7 +1007,6 @@ impl ::core::hash::Hash for Fielded {
 }
 impl ::core::marker::StructuralPartialEq for Fielded {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialEq for Fielded {
     #[inline]
     fn eq(&self, other: &Fielded) -> bool {
@@ -1135,7 +1041,6 @@ impl ::core::cmp::PartialEq for Fielded {
 }
 impl ::core::marker::StructuralEq for Fielded {}
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Eq for Fielded {
     #[inline]
     #[doc(hidden)]
@@ -1147,7 +1052,6 @@ impl ::core::cmp::Eq for Fielded {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::PartialOrd for Fielded {
     #[inline]
     fn partial_cmp(&self, other: &Fielded)
@@ -1170,7 +1074,6 @@ impl ::core::cmp::PartialOrd for Fielded {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::cmp::Ord for Fielded {
     #[inline]
     fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering {
@@ -1199,7 +1102,6 @@ pub union Union {
     pub i: i32,
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::clone::Clone for Union {
     #[inline]
     fn clone(&self) -> Union {
@@ -1208,5 +1110,4 @@ impl ::core::clone::Clone for Union {
     }
 }
 #[automatically_derived]
-#[allow(unused_qualifications)]
 impl ::core::marker::Copy for Union { }
diff --git a/src/test/ui/impl-trait/issue-99073-2.rs b/src/test/ui/impl-trait/issue-99073-2.rs
new file mode 100644
index 00000000000..bebd8286de9
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073-2.rs
@@ -0,0 +1,17 @@
+use std::fmt::Display;
+
+fn main() {
+    test("hi", true);
+}
+
+fn test<T: Display>(t: T, recurse: bool) -> impl Display {
+    let f = || {
+        let i: u32 = test::<i32>(-1, false);
+        //~^ ERROR mismatched types
+        println!("{i}");
+    };
+    if recurse {
+        f();
+    }
+    t
+}
diff --git a/src/test/ui/impl-trait/issue-99073-2.stderr b/src/test/ui/impl-trait/issue-99073-2.stderr
new file mode 100644
index 00000000000..c1e4b823c08
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073-2.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-99073-2.rs:9:22
+   |
+LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
+   |                                             ------------ the expected opaque type
+LL |     let f = || {
+LL |         let i: u32 = test::<i32>(-1, false);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ types differ
+   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issue-99073.rs b/src/test/ui/impl-trait/issue-99073.rs
new file mode 100644
index 00000000000..1d75f608666
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let _ = fix(|_: &dyn Fn()| {});
+}
+
+fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
+    move || f(fix(&f))
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/impl-trait/issue-99073.stderr b/src/test/ui/impl-trait/issue-99073.stderr
new file mode 100644
index 00000000000..b35d58093d5
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-99073.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-99073.rs:6:13
+   |
+LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
+   |                                    --------- the expected opaque type
+LL |     move || f(fix(&f))
+   |             ^^^^^^^^^^ types differ
+   |
+   = note: expected opaque type `impl Fn()`
+           found type parameter `G`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
index d29a82f76a7..b05579f2166 100644
--- a/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
+++ b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
@@ -6,7 +6,7 @@ type Tait = impl Sized;
 
 impl Foo for Concrete {
     type Item = Concrete;
-    //~^ mismatched types
+    //~^ type mismatch resolving
 }
 
 impl Bar for Concrete {
diff --git a/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr
index a25f0cd8761..f0dceb1b11a 100644
--- a/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr
+++ b/src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr
@@ -1,15 +1,25 @@
-error[E0308]: mismatched types
+error[E0271]: type mismatch resolving `<Concrete as Bar>::Other == Concrete`
   --> $DIR/issue-99348-impl-compatibility.rs:8:17
    |
 LL | type Tait = impl Sized;
-   |             ---------- the expected opaque type
+   |             ---------- the found opaque type
 ...
 LL |     type Item = Concrete;
-   |                 ^^^^^^^^ types differ
+   |                 ^^^^^^^^ type mismatch resolving `<Concrete as Bar>::Other == Concrete`
    |
-   = note: expected opaque type `Tait`
-                   found struct `Concrete`
+note: expected this to be `Concrete`
+  --> $DIR/issue-99348-impl-compatibility.rs:13:18
+   |
+LL |     type Other = Tait;
+   |                  ^^^^
+   = note:   expected struct `Concrete`
+           found opaque type `Tait`
+note: required by a bound in `Foo::Item`
+  --> $DIR/issue-99348-impl-compatibility.rs:17:20
+   |
+LL |     type Item: Bar<Other = Self>;
+   |                    ^^^^^^^^^^^^ required by this bound in `Foo::Item`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/lint/auxiliary/add-impl.rs b/src/test/ui/lint/auxiliary/add-impl.rs
new file mode 100644
index 00000000000..9d0e3068aed
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/add-impl.rs
@@ -0,0 +1,22 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(AddImpl)]
+// Unnecessary qualification `bar::foo`
+// https://github.com/rust-lang/rust/issues/71898
+pub fn derive(input: TokenStream) -> TokenStream {
+    "impl B {
+            fn foo(&self) { use bar::foo; bar::foo() }
+        }
+
+        fn foo() {}
+
+        mod bar { pub fn foo() {} }
+    ".parse().unwrap()
+}
diff --git a/src/test/ui/lint/unused-qualification-in-derive-expansion.rs b/src/test/ui/lint/unused-qualification-in-derive-expansion.rs
new file mode 100644
index 00000000000..c2efbf507fe
--- /dev/null
+++ b/src/test/ui/lint/unused-qualification-in-derive-expansion.rs
@@ -0,0 +1,16 @@
+// run-pass
+// aux-build:add-impl.rs
+
+#![forbid(unused_qualifications)]
+
+#[macro_use]
+extern crate add_impl;
+
+#[derive(AddImpl)]
+struct B;
+
+fn main() {
+    B.foo();
+    foo();
+    bar::foo();
+}
diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs
index c2954868f78..8ff14fb1f30 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.rs
+++ b/src/test/ui/parser/fn-header-semantic-fail.rs
@@ -27,7 +27,7 @@ fn main() {
     struct Y;
     impl X for Y {
         async fn ft1() {} //~ ERROR functions in traits cannot be declared `async`
-        //~^ ERROR impl has stricter requirements than trait
+        //~^ ERROR has an incompatible type for trait
         unsafe fn ft2() {} // OK.
         const fn ft3() {} //~ ERROR functions in traits cannot be declared const
         extern "C" fn ft4() {}
@@ -36,7 +36,7 @@ fn main() {
         //~| ERROR functions in traits cannot be declared const
         //~| ERROR functions cannot be both `const` and `async`
         //~| ERROR cycle detected
-        //~| ERROR impl has stricter requirements than trait
+        //~| ERROR has an incompatible type for trait
     }
 
     impl Y {
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
index 75d27c614e2..bc51ba8b8c5 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -216,23 +216,41 @@ LL | |     }
 LL | | }
    | |_^
 
-error[E0276]: impl has stricter requirements than trait
-  --> $DIR/fn-header-semantic-fail.rs:29:9
+error[E0053]: method `ft1` has an incompatible type for trait
+  --> $DIR/fn-header-semantic-fail.rs:29:24
    |
-LL |         async fn ft1();
-   |         --------------- definition of `ft1` from trait
-...
 LL |         async fn ft1() {}
-   |         ^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
+   |                        ^
+   |                        |
+   |                        checked the `Output` of this `async fn`, found opaque type
+   |                        expected `()`, found opaque type
+   |
+   = note: while checking the return type of the `async fn`
+note: type in trait
+  --> $DIR/fn-header-semantic-fail.rs:17:23
+   |
+LL |         async fn ft1();
+   |                       ^
+   = note: expected fn pointer `fn()`
+              found fn pointer `fn() -> impl Future<Output = ()>`
 
-error[E0276]: impl has stricter requirements than trait
-  --> $DIR/fn-header-semantic-fail.rs:34:9
+error[E0053]: method `ft5` has an incompatible type for trait
+  --> $DIR/fn-header-semantic-fail.rs:34:48
    |
-LL |         const async unsafe extern "C" fn ft5();
-   |         --------------------------------------- definition of `ft5` from trait
-...
 LL |         const async unsafe extern "C" fn ft5() {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
+   |                                                ^
+   |                                                |
+   |                                                checked the `Output` of this `async fn`, found opaque type
+   |                                                expected `()`, found opaque type
+   |
+   = note: while checking the return type of the `async fn`
+note: type in trait
+  --> $DIR/fn-header-semantic-fail.rs:21:47
+   |
+LL |         const async unsafe extern "C" fn ft5();
+   |                                               ^
+   = note: expected fn pointer `unsafe extern "C" fn()`
+              found fn pointer `unsafe extern "C" fn() -> impl Future<Output = ()>`
 
 error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`
   --> $DIR/fn-header-semantic-fail.rs:34:48
@@ -308,5 +326,5 @@ LL | | }
 
 error: aborting due to 23 previous errors
 
-Some errors have detailed explanations: E0276, E0379, E0391, E0706.
-For more information about an error, try `rustc --explain E0276`.
+Some errors have detailed explanations: E0053, E0379, E0391, E0706.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
index 6facc467f7a..aaf0f7eaef0 100644
--- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
@@ -14,7 +14,7 @@ trait B {
 impl B for A {
     async fn associated(); //~ ERROR without body
     //~^ ERROR cannot be declared `async`
-    //~| ERROR impl has stricter requirements than trait
+    //~| ERROR has an incompatible type for trait
 }
 
 fn main() {}
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
index c144060a859..d3214458eac 100644
--- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
@@ -44,16 +44,25 @@ LL |     async fn associated();
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
-error[E0276]: impl has stricter requirements than trait
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
+error[E0053]: method `associated` has an incompatible type for trait
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
    |
 LL |     async fn associated();
-   |     ---------------------- definition of `associated` from trait
-...
+   |                          ^
+   |                          |
+   |                          checked the `Output` of this `async fn`, found opaque type
+   |                          expected `()`, found opaque type
+   |
+   = note: while checking the return type of the `async fn`
+note: type in trait
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26
+   |
 LL |     async fn associated();
-   |     ^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
+   |                          ^
+   = note: expected fn pointer `fn()`
+              found fn pointer `fn() -> impl Future<Output = ()>`
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0276, E0706.
-For more information about an error, try `rustc --explain E0276`.
+Some errors have detailed explanations: E0053, E0706.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
index 377ce85e8b2..4a11bb5020e 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
@@ -3,7 +3,7 @@
 type Foo = impl Fn() -> Foo;
 
 fn foo() -> Foo {
-//~^ ERROR: overflow evaluating the requirement `fn() -> Foo {foo}: Sized`
+//~^ ERROR: overflow evaluating the requirement
     foo
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
index d20b1cc6d85..00c682b2193 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
@@ -1,10 +1,8 @@
-error[E0275]: overflow evaluating the requirement `fn() -> Foo {foo}: Sized`
+error[E0275]: overflow evaluating the requirement `<fn() -> Foo {foo} as FnOnce<()>>::Output == fn() -> Foo {foo}`
   --> $DIR/issue-53398-cyclic-types.rs:5:13
    |
 LL | fn foo() -> Foo {
    |             ^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.rs b/src/test/ui/type-alias-impl-trait/issue-57961.rs
new file mode 100644
index 00000000000..472886c9caa
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57961.rs
@@ -0,0 +1,18 @@
+#![feature(type_alias_impl_trait)]
+
+type X = impl Sized;
+
+trait Foo {
+    type Bar: Iterator<Item = X>;
+}
+
+impl Foo for () {
+    type Bar = std::vec::IntoIter<u32>;
+    //~^ ERROR type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X
+}
+
+fn incoherent() {
+    let f: X = 22_i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.stderr b/src/test/ui/type-alias-impl-trait/issue-57961.stderr
new file mode 100644
index 00000000000..ed4caf6ce68
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57961.stderr
@@ -0,0 +1,20 @@
+error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as Iterator>::Item == X`
+  --> $DIR/issue-57961.rs:10:16
+   |
+LL | type X = impl Sized;
+   |          ---------- the expected opaque type
+...
+LL |     type Bar = std::vec::IntoIter<u32>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `u32`
+   |
+   = note: expected opaque type `X`
+                     found type `u32`
+note: required by a bound in `Foo::Bar`
+  --> $DIR/issue-57961.rs:6:24
+   |
+LL |     type Bar: Iterator<Item = X>;
+   |                        ^^^^^^^^ required by this bound in `Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.