]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #99480 - miam-miam100:arg-format, r=oli-obk
authorMatthias Krüger <matthias.krueger@famsik.de>
Wed, 20 Jul 2022 16:58:17 +0000 (18:58 +0200)
committerGitHub <noreply@github.com>
Wed, 20 Jul 2022 16:58:17 +0000 (18:58 +0200)
Diagnostic width span is not added when '0$' is used as width in format strings

When the following code is run rustc does not add diagnostic spans for the width argument. Such spans are necessary for a clippy lint that I am currently writing.

```rust
println!("Hello {1:0$}!", 5, "x");
//                 ^^
// Should have a span here
```

186 files changed:
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_borrowck/src/consumers.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/mod.rs
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/places_conflict.rs
compiler/rustc_borrowck/src/prefixes.rs
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/value_and_place.rs
compiler/rustc_codegen_ssa/src/mir/place.rs
compiler/rustc_const_eval/src/interpret/projection.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_error_codes/src/error_codes/E0118.md
compiler/rustc_error_messages/locales/en-US/passes.ftl
compiler/rustc_expand/src/mbe/transcribe.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_llvm/build.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_middle/src/middle/mod.rs
compiler/rustc_middle/src/middle/stability.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/syntax.rs
compiler/rustc_middle/src/mir/tcx.rs
compiler/rustc_middle/src/mir/type_foldable.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_mir_build/src/build/expr/as_place.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/as_temp.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/matches/mod.rs
compiler/rustc_mir_build/src/build/matches/simplify.rs
compiler/rustc_mir_build/src/build/matches/test.rs
compiler/rustc_mir_build/src/build/matches/util.rs
compiler/rustc_mir_build/src/build/scope.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
compiler/rustc_mir_transform/src/add_retag.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/errors.rs
compiler/rustc_passes/src/lib_features.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_session/src/options.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_trait_selection/src/traits/codegen.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/coherence/inherent_impls.rs
library/core/src/fmt/mod.rs
library/core/src/hash/mod.rs
library/core/src/num/int_macros.rs
library/core/src/primitive_docs.rs
library/core/src/ptr/mod.rs
library/core/src/tuple.rs
library/panic_unwind/src/gcc.rs
library/std/build.rs
library/std/src/fs/tests.rs
library/std/src/os/mod.rs
library/std/src/os/unix/mod.rs
library/std/src/os/unix/net/stream.rs
library/std/src/os/unix/ucred.rs
library/std/src/os/unix/ucred/tests.rs
library/std/src/primitive_docs.rs
library/std/src/sys/unix/args.rs
library/std/src/sys/unix/env.rs
library/std/src/sys/unix/fd.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/locks/pthread_condvar.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/rand.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unix/thread_parker.rs
library/std/src/sys/unix/time.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys_common/net.rs
library/unwind/src/libunwind.rs
src/bootstrap/builder.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/html/format.rs
src/librustdoc/json/conversions.rs
src/test/codegen/noalias-box-off.rs [new file with mode: 0644]
src/test/codegen/noalias-box.rs [new file with mode: 0644]
src/test/rustdoc-ui/tuple-variadic-check.rs
src/test/rustdoc-ui/tuple-variadic-check.stderr
src/test/rustdoc-ui/z-help.stdout
src/test/rustdoc/primitive-tuple-auto-trait.rs
src/test/rustdoc/primitive-tuple-variadic.rs
src/test/ui/argument-suggestions/issue-99482.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/issue-99482.stderr [new file with mode: 0644]
src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
src/test/ui/const-generics/issues/issue-71547.rs [new file with mode: 0644]
src/test/ui/deriving/deriving-all-codegen.stdout
src/test/ui/error-codes/E0118.rs
src/test/ui/error-codes/E0118.stderr
src/test/ui/error-codes/E0390.rs
src/test/ui/error-codes/E0390.stderr
src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs
src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr
src/test/ui/foreign/issue-99276-same-type-lifetimes.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073-2.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073-2.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
src/test/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr
src/test/ui/issues/issue-59488.stderr
src/test/ui/kindck/kindck-copy.stderr
src/test/ui/lint/auxiliary/add-impl.rs [new file with mode: 0644]
src/test/ui/lint/unused-qualification-in-derive-expansion.rs [new file with mode: 0644]
src/test/ui/liveness/liveness-forgot-ret.stderr
src/test/ui/macros/meta-variable-depth-outside-repeat.rs [new file with mode: 0644]
src/test/ui/macros/meta-variable-depth-outside-repeat.stderr [new file with mode: 0644]
src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs
src/test/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr
src/test/ui/not-panic/not-panic-safe.stderr
src/test/ui/parser/fn-header-semantic-fail.rs
src/test/ui/parser/fn-header-semantic-fail.stderr
src/test/ui/parser/issues/issue-33413.stderr
src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
src/test/ui/stability-attribute/auxiliary/stability-attribute-implies.rs [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-missing.rs [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-missing.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-no-feature.rs [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-no-feature.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-using-stable.rs [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-using-stable.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-using-unstable.rs [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-sanity-2.stderr
src/test/ui/stability-attribute/stability-attribute-sanity.stderr
src/test/ui/suggestions/return-bindings-multi.rs [new file with mode: 0644]
src/test/ui/suggestions/return-bindings-multi.stderr [new file with mode: 0644]
src/test/ui/suggestions/return-bindings.fixed [new file with mode: 0644]
src/test/ui/suggestions/return-bindings.rs [new file with mode: 0644]
src/test/ui/suggestions/return-bindings.stderr [new file with mode: 0644]
src/test/ui/traits/issue-32963.rs
src/test/ui/traits/issue-32963.stderr
src/test/ui/traits/suggest-where-clause.stderr
src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
src/test/ui/type-alias-impl-trait/issue-57961.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-57961.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-only-pattern-rpit.rs [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-only-pattern.rs [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-struct.rs [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-upvar-enum.rs [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-upvar.rs [deleted file]
src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs [deleted file]
src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs
src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
src/tools/cargo
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs

index 22cb27af4fbc51afed2d1782a7fce9f7cfb70687..ad9ed798e558bde002fc058adade9b854c903bf5 100644 (file)
@@ -404,8 +404,8 @@ macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
                     gate_feature_post!(self, rustdoc_internals, attr.span, msg);
                 }
 
-                if nested_meta.has_name(sym::tuple_variadic) {
-                    let msg = "`#[doc(tuple_variadic)]` is meant for internal use only";
+                if nested_meta.has_name(sym::fake_variadic) {
+                    let msg = "`#[doc(fake_variadic)]` is meant for internal use only";
                     gate_feature_post!(self, rustdoc_internals, attr.span, msg);
                 }
             }
index dcfbecedfe8ffd5d9a77bb85d804956566a14383..64a6f91f02206f6472f00a6ada3ef730d94c5045 100644 (file)
@@ -135,9 +135,42 @@ pub fn is_const_stable(&self) -> bool {
 #[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub enum StabilityLevel {
-    // Reason for the current stability level and the relevant rust-lang issue
-    Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
-    Stable { since: Symbol, allowed_through_unstable_modules: bool },
+    /// `#[unstable]`
+    Unstable {
+        /// Reason for the current stability level.
+        reason: Option<Symbol>,
+        /// Relevant `rust-lang/rust` issue.
+        issue: Option<NonZeroU32>,
+        is_soft: bool,
+        /// If part of a feature is stabilized and a new feature is added for the remaining parts,
+        /// then the `implied_by` attribute is used to indicate which now-stable feature previously
+        /// contained a item.
+        ///
+        /// ```pseudo-Rust
+        /// #[unstable(feature = "foo", issue = "...")]
+        /// fn foo() {}
+        /// #[unstable(feature = "foo", issue = "...")]
+        /// fn foobar() {}
+        /// ```
+        ///
+        /// ...becomes...
+        ///
+        /// ```pseudo-Rust
+        /// #[stable(feature = "foo", since = "1.XX.X")]
+        /// fn foo() {}
+        /// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]
+        /// fn foobar() {}
+        /// ```
+        implied_by: Option<Symbol>,
+    },
+    /// `#[stable]`
+    Stable {
+        /// Rust release which stabilized this feature.
+        since: Symbol,
+        /// Is this item allowed to be referred to on stable, despite being contained in unstable
+        /// modules?
+        allowed_through_unstable_modules: bool,
+    },
 }
 
 impl StabilityLevel {
@@ -243,6 +276,7 @@ fn find_stability_generic<'a, I>(
                     let mut issue = None;
                     let mut issue_num = None;
                     let mut is_soft = false;
+                    let mut implied_by = None;
                     for meta in metas {
                         let Some(mi) = meta.meta_item() else {
                             handle_errors(
@@ -308,6 +342,11 @@ fn find_stability_generic<'a, I>(
                                 }
                                 is_soft = true;
                             }
+                            sym::implied_by => {
+                                if !get(mi, &mut implied_by) {
+                                    continue 'outer;
+                                }
+                            }
                             _ => {
                                 handle_errors(
                                     &sess.parse_sess,
@@ -332,7 +371,7 @@ fn find_stability_generic<'a, I>(
                                 );
                                 continue;
                             }
-                            let level = Unstable { reason, issue: issue_num, is_soft };
+                            let level = Unstable { reason, issue: issue_num, is_soft, implied_by };
                             if sym::unstable == meta_name {
                                 stab = Some((Stability { level, feature }, attr.span));
                             } else {
@@ -391,7 +430,7 @@ fn find_stability_generic<'a, I>(
                                         meta.span(),
                                         AttrError::UnknownMetaItem(
                                             pprust::path_to_string(&mi.path),
-                                            &["since", "note"],
+                                            &["feature", "since"],
                                         ),
                                     );
                                     continue 'outer;
index 97daad201d95941be78f57725f8468592430ffed..efc17a173f4d308f539c7c19d59b9f457b6f3f3e 100644 (file)
@@ -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()
index ee96dbc2f60b480228082662b1ed0ec160266d0e..1b3c6cac9c42f82dc915aa65a4406d4af8427086 100644 (file)
@@ -2155,9 +2155,7 @@ fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<
                             }
                             StorageDeadOrDrop::Destructor(_) => kind,
                         },
-                        ProjectionElem::OpaqueCast { .. }
-                        | ProjectionElem::Field(..)
-                        | ProjectionElem::Downcast(..) => {
+                        ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
                             match place_ty.ty.kind() {
                                 ty::Adt(def, _) if def.has_dtor(tcx) => {
                                     // Report the outermost adt with a destructor
index fada3d45fbed856cb088632a1526a193f431c79b..53c07a3d481e0912d509944ba441de351c47906c 100644 (file)
@@ -226,7 +226,6 @@ pub(super) fn describe_place_with_options(
                 }
                 ProjectionElem::Downcast(..) if including_downcast.0 => return None,
                 ProjectionElem::Downcast(..) => (),
-                ProjectionElem::OpaqueCast(..) => (),
                 ProjectionElem::Field(field, _ty) => {
                     // FIXME(project-rfc_2229#36): print capture precisely here.
                     if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -287,7 +286,6 @@ fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
                     PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
                 }
                 ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
-                ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
                 ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
             },
         };
index cb7077fe621715e0ecb7133b3ca70607a03ac913..8134e1226628fa2aef91e132497f0b4599ce6d98 100644 (file)
@@ -169,7 +169,6 @@ pub(crate) fn report_mutability_error(
                         ..,
                         ProjectionElem::Index(_)
                         | ProjectionElem::ConstantIndex { .. }
-                        | ProjectionElem::OpaqueCast { .. }
                         | ProjectionElem::Subslice { .. }
                         | ProjectionElem::Downcast(..),
                     ],
index 15c2a9f7aefa00e6b21cbf9951056d27aebf1977..9dfefe4d236f66fe28eab3c0d9662a927d6a923b 100644 (file)
@@ -24,7 +24,7 @@
 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)
@@ -1788,7 +1791,6 @@ fn check_if_assigned_path_is_moved(
         for (place_base, elem) in place.iter_projections().rev() {
             match elem {
                 ProjectionElem::Index(_/*operand*/) |
-                ProjectionElem::OpaqueCast(_) |
                 ProjectionElem::ConstantIndex { .. } |
                 // assigning to P[i] requires P to be valid.
                 ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
@@ -2180,7 +2182,6 @@ fn is_mutable(
                     | ProjectionElem::Index(..)
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. }
-                    | ProjectionElem::OpaqueCast { .. }
                     | ProjectionElem::Downcast(..) => {
                         let upvar_field_projection = self.is_upvar_field_projection(place);
                         if let Some(field) = upvar_field_projection {
index 5b67e6aa1cffa9c2e8339dd07c6ff1e25f877cca..97335fd0dffaeb4d28205c7adfd76654f4e4706e 100644 (file)
@@ -255,7 +255,6 @@ fn place_components_conflict<'tcx>(
                 | (ProjectionElem::Index { .. }, _, _)
                 | (ProjectionElem::ConstantIndex { .. }, _, _)
                 | (ProjectionElem::Subslice { .. }, _, _)
-                | (ProjectionElem::OpaqueCast { .. }, _, _)
                 | (ProjectionElem::Downcast { .. }, _, _) => {
                     // Recursive case. This can still be disjoint on a
                     // further iteration if this a shallow access and
@@ -323,17 +322,6 @@ fn place_projection_conflict<'tcx>(
             debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
             Overlap::EqualOrDisjoint
         }
-        (ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
-            if v1 == v2 {
-                // same type - recur.
-                debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
-                Overlap::EqualOrDisjoint
-            } else {
-                // Different types. Disjoint!
-                debug!("place_element_conflict: DISJOINT-OPAQUE");
-                Overlap::Disjoint
-            }
-        }
         (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
             if f1 == f2 {
                 // same field (e.g., `a.y` vs. `a.y`) - recur.
@@ -537,7 +525,6 @@ fn place_projection_conflict<'tcx>(
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
-            | ProjectionElem::OpaqueCast { .. }
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Downcast(..),
             _,
index 2b50cbac9a02da128786fa86e3ed5d80dcfa8b44..bdf2becb711264eff522a8cbe962ea5db3888cc1 100644 (file)
@@ -81,7 +81,6 @@ fn next(&mut self) -> Option<Self::Item> {
                         }
                         ProjectionElem::Downcast(..)
                         | ProjectionElem::Subslice { .. }
-                        | ProjectionElem::OpaqueCast { .. }
                         | ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::Index(_) => {
                             cursor = cursor_base;
index de9da845729835c28e33a9a7880db49ba0a6f07e..407bbf48813c35fb0e3d55d13a901174be38cea4 100644 (file)
@@ -3,8 +3,8 @@
 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 @@ fn infer_opaque_definition_from_instantiation(
             // 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
         }
index 8e763a02af33f11b13726a65a77a0b014d0440eb..eb9df281e7d24ab26a755ed2e6b28f199c6b916d 100644 (file)
@@ -21,6 +21,7 @@
 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,
@@ -790,19 +811,6 @@ fn sanitize_projection(
                 }
                 PlaceTy::from_ty(fty)
             }
-            ProjectionElem::OpaqueCast(ty) => {
-                let ty = self.sanitize_type(place, ty);
-                let ty = self.cx.normalize(ty, location);
-                self.cx
-                    .eq_types(
-                        base.ty,
-                        ty,
-                        location.to_locations(),
-                        ConstraintCategory::TypeAnnotation,
-                    )
-                    .unwrap();
-                PlaceTy::from_ty(ty)
-            }
         }
     }
 
@@ -1208,11 +1216,10 @@ fn relate_type_and_user_type(
                 tcx,
                 self.param_env,
                 proj,
-                |this, field, _| {
+                |this, field, ()| {
                     let ty = this.field_ty(tcx, field);
                     self.normalize(ty, locations)
                 },
-                |_, _| unreachable!(),
             );
             curr_projected_ty = projected_ty;
         }
@@ -2507,7 +2514,6 @@ fn add_reborrow_constraint(
                 }
                 ProjectionElem::Field(..)
                 | ProjectionElem::Downcast(..)
-                | ProjectionElem::OpaqueCast(..)
                 | ProjectionElem::Index(..)
                 | ProjectionElem::ConstantIndex { .. }
                 | ProjectionElem::Subslice { .. } => {
index 076b627ca79f6bb6bcf68b052be82282de1c06ef..735017aa5a850f9d3ec9690aab3e029b7bfba649 100644 (file)
@@ -727,16 +727,8 @@ fn create_derived_impl(
 
         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(
index 54652623d940187536a7bea565b00615805e1ee2..63cd4d6de4c3e12fab188e78f1c323e019e8915e 100644 (file)
@@ -825,7 +825,6 @@ pub(crate) fn codegen_place<'tcx>(
                     cplace = cplace.place_deref(fx);
                 }
             }
-            PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty),
             PlaceElem::Field(field, _ty) => {
                 cplace = cplace.place_field(fx, field);
             }
index 8ff35d2f76dbfb62c4c79b5ff9f1dbc3234343a1..a68225de58b32d160dd2302ed54eaf352b3d8831 100644 (file)
@@ -615,14 +615,6 @@ fn transmute_value<'tcx>(
         }
     }
 
-    pub(crate) fn place_opaque_cast(
-        self,
-        fx: &mut FunctionCx<'_, '_, 'tcx>,
-        ty: Ty<'tcx>,
-    ) -> CPlace<'tcx> {
-        CPlace { inner: self.inner, layout: fx.layout_of(ty) }
-    }
-
     pub(crate) fn place_field(
         self,
         fx: &mut FunctionCx<'_, '_, 'tcx>,
index 421d6f807ae8e128f855a18a676da5a41dd24c02..58cee0c8bb0dbf166d9d7fbb827e44d319607e1a 100644 (file)
@@ -411,21 +411,6 @@ pub fn project_downcast<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         downcast
     }
 
-    pub fn project_type<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        &self,
-        bx: &mut Bx,
-        ty: Ty<'tcx>,
-    ) -> Self {
-        let mut downcast = *self;
-        downcast.layout = bx.cx().layout_of(ty);
-
-        // Cast to the appropriate type.
-        let variant_ty = bx.cx().backend_type(downcast.layout);
-        downcast.llval = bx.pointercast(downcast.llval, bx.cx().type_ptr_to(variant_ty));
-
-        downcast
-    }
-
     pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
         bx.lifetime_start(self.llval, self.layout.size);
     }
@@ -474,7 +459,6 @@ pub fn codegen_place(
                 mir::ProjectionElem::Field(ref field, _) => {
                     cg_base.project_field(bx, field.index())
                 }
-                mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty),
                 mir::ProjectionElem::Index(index) => {
                     let index = &mir::Operand::Copy(mir::Place::from(index));
                     let index = self.codegen_operand(bx, index);
index 4e69d71dc00ec6c1370c9426e867540074c65bc0..61d58232dc29c5bccabcf418093443242900b8b9 100644 (file)
@@ -349,11 +349,6 @@ pub fn place_projection(
     ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc_middle::mir::ProjectionElem::*;
         Ok(match proj_elem {
-            OpaqueCast(ty) => {
-                let mut place = base.clone();
-                place.layout = self.layout_of(ty)?;
-                place
-            }
             Field(field, _) => self.place_field(base, field.index())?,
             Downcast(_, variant) => self.place_downcast(base, variant)?,
             Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
@@ -378,11 +373,6 @@ pub fn operand_projection(
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc_middle::mir::ProjectionElem::*;
         Ok(match proj_elem {
-            OpaqueCast(ty) => {
-                let mut op = base.clone();
-                op.layout = self.layout_of(ty)?;
-                op
-            }
             Field(field, _) => self.operand_field(base, field.index())?,
             Downcast(_, variant) => self.operand_downcast(base, variant)?,
             Deref => self.deref_operand(base)?.into(),
index 0581f4919782de87b05b7fa66071a8986b031eb9..628298df4738560af218809c0cba1f6770768344 100644 (file)
@@ -652,7 +652,6 @@ fn visit_projection_elem(
 
             ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Downcast(..)
-            | ProjectionElem::OpaqueCast(..)
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {}
index c2b4f6eca5cedae20f51eccce1af89d3f04df078..29464cf8c4e4fa1856269a66e30828b8c5d5076f 100644 (file)
@@ -316,7 +316,6 @@ pub fn in_place<'tcx, Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: Pla
 
             ProjectionElem::Deref
             | ProjectionElem::Field(_, _)
-            | ProjectionElem::OpaqueCast(_)
             | ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Downcast(_, _)
index daa154576ae4b99acd3e0f88d89bb0aeefba05bb..ed4d8c95d1e6178d882bcaef5a3c9b5bad620a39 100644 (file)
@@ -361,7 +361,7 @@ fn validate_place(&mut self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable>
                             return Err(Unpromotable);
                         }
                     }
-                    ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
+                    ProjectionElem::Downcast(..) => {
                         return Err(Unpromotable);
                     }
 
index 8033aa8384c2e1276f742b8dd37070774da23ef8..cfabae1a6346d6a2d0217d4622efb5706d06ed2f 100644 (file)
@@ -4,7 +4,7 @@ enum, union, or trait object.
 Erroneous code example:
 
 ```compile_fail,E0118
-impl fn(u8) { // error: no nominal type found for inherent implementation
+impl<T> T { // error: no nominal type found for inherent implementation
     fn get_state(&self) -> String {
         // ...
     }
@@ -20,8 +20,8 @@ trait LiveLongAndProsper {
     fn get_state(&self) -> String;
 }
 
-// and now you can implement it on fn(u8)
-impl LiveLongAndProsper for fn(u8) {
+// and now you can implement it on T
+impl<T> LiveLongAndProsper for T {
     fn get_state(&self) -> String {
         "He's dead, Jim!".to_owned()
     }
@@ -33,9 +33,9 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
 Example:
 
 ```
-struct TypeWrapper(fn(u8));
+struct TypeWrapper<T>(T);
 
-impl TypeWrapper {
+impl<T> TypeWrapper<T> {
     fn get_state(&self) -> String {
         "Fascinating!".to_owned()
     }
index e4c9a4dad7b4815cf164781bcab0d7cc870d30b0..04c67cf8ff73ae3542c4ee5676c0876d9f5a555c 100644 (file)
@@ -81,8 +81,8 @@ passes-doc-keyword-not-mod = `#[doc(keyword = "...")]` should be used on modules
 
 passes-doc-keyword-invalid-ident = `{$doc_keyword}` is not a valid identifier
 
-passes-doc-tuple-variadic-not-first =
-    `#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity
+passes-doc-fake-variadic-not-valid =
+    `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
 
 passes-doc-keyword-only-impl = `#[doc(keyword = "...")]` should be used on impl blocks
 
index fdd8dc93fc1a58a8c99b9d75a1b398c2584c08e8..3037855ae28a6b6c7ea6d742bf9678a07b387c4b 100644 (file)
@@ -512,7 +512,18 @@ fn out_of_bounds_err<'a>(
     span: Span,
     ty: &str,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-    cx.struct_span_err(span, &format!("{ty} depth must be less than {max}"))
+    let msg = if max == 0 {
+        format!(
+            "meta-variable expression `{ty}` with depth parameter \
+             must be called inside of a macro repetition"
+        )
+    } else {
+        format!(
+            "depth parameter on meta-variable expression `{ty}` \
+             must be less than {max}"
+        )
+    };
+    cx.struct_span_err(span, &msg)
 }
 
 fn transcribe_metavar_expr<'a>(
index b3dc2e586d251849b2fa63eb211241e68e53496d..0e44d4e7c972b392eccd9228cc0e40a2b71a581c 100644 (file)
@@ -239,17 +239,31 @@ pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tc
     }
 }
 
+#[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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 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 @@ pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId)
     /// 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
     }
 
index 4ee9c4eeda40a0ffda176fe394679cc255de1736..7b0ff9552a3a407ff852fa97c15758dc3da9bfa8 100644 (file)
@@ -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 @@ pub fn handle_opaque_type(
         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 @@ pub fn register_member_constraints(
     #[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 @@ pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<Opaqu
     }
 
     #[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 => {
index 9c0b534798e395074eb605be8210f504c63fba84..3eef3308770bee04c512e47296a0d401938f008b 100644 (file)
@@ -718,6 +718,7 @@ macro_rules! tracked {
     tracked!(asm_comments, true);
     tracked!(assume_incomplete_release, true);
     tracked!(binary_dep_depinfo, true);
+    tracked!(box_noalias, Some(false));
     tracked!(
         branch_protection,
         Some(BranchProtection {
index a0472f98d7204e1dab2d618c2c9c45418dfd32e9..9e4dc702f0737bec6c37c2ead5936972c20f6a7a 100644 (file)
@@ -2858,9 +2858,10 @@ fn structurally_same_type_impl<'tcx>(
                             let a_poly_sig = a.fn_sig(tcx);
                             let b_poly_sig = b.fn_sig(tcx);
 
-                            // As we don't compare regions, skip_binder is fine.
-                            let a_sig = a_poly_sig.skip_binder();
-                            let b_sig = b_poly_sig.skip_binder();
+                            // We don't compare regions, but leaving bound regions around ICEs, so
+                            // we erase them.
+                            let a_sig = tcx.erase_late_bound_regions(a_poly_sig);
+                            let b_sig = tcx.erase_late_bound_regions(b_poly_sig);
 
                             (a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
                                 == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
index 7729ec6bef4a7409eff955dc96b90e90524fcf4a..62ef5804dce6d7491f1a8c79620d4986114ed745 100644 (file)
@@ -4,6 +4,29 @@
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 
+const OPTIONAL_COMPONENTS: &[&str] = &[
+    "x86",
+    "arm",
+    "aarch64",
+    "amdgpu",
+    "avr",
+    "m68k",
+    "mips",
+    "powerpc",
+    "systemz",
+    "jsbackend",
+    "webassembly",
+    "msp430",
+    "sparc",
+    "nvptx",
+    "hexagon",
+    "riscv",
+    "bpf",
+];
+
+const REQUIRED_COMPONENTS: &[&str] =
+    &["ipo", "bitreader", "bitwriter", "linker", "asmparser", "lto", "coverage", "instrumentation"];
+
 fn detect_llvm_link() -> (&'static str, &'static str) {
     // Force the link mode we want, preferring static by default, but
     // possibly overridden by `configure --enable-llvm-link-shared`.
@@ -76,6 +99,10 @@ fn output(cmd: &mut Command) -> String {
 }
 
 fn main() {
+    for component in REQUIRED_COMPONENTS.iter().chain(OPTIONAL_COMPONENTS.iter()) {
+        println!("cargo:rustc-check-cfg=values(llvm_component,\"{}\")", component);
+    }
+
     if tracked_env_var_os("RUST_CHECK").is_some() {
         // If we're just running `check`, there's no need for LLVM to be built.
         return;
@@ -131,42 +158,11 @@ fn main() {
     let host = env::var("HOST").expect("HOST was not set");
     let is_crossed = target != host;
 
-    let optional_components = &[
-        "x86",
-        "arm",
-        "aarch64",
-        "amdgpu",
-        "avr",
-        "m68k",
-        "mips",
-        "powerpc",
-        "systemz",
-        "jsbackend",
-        "webassembly",
-        "msp430",
-        "sparc",
-        "nvptx",
-        "hexagon",
-        "riscv",
-        "bpf",
-    ];
-
-    let required_components = &[
-        "ipo",
-        "bitreader",
-        "bitwriter",
-        "linker",
-        "asmparser",
-        "lto",
-        "coverage",
-        "instrumentation",
-    ];
-
     let components = output(Command::new(&llvm_config).arg("--components"));
     let mut components = components.split_whitespace().collect::<Vec<_>>();
-    components.retain(|c| optional_components.contains(c) || required_components.contains(c));
+    components.retain(|c| OPTIONAL_COMPONENTS.contains(c) || REQUIRED_COMPONENTS.contains(c));
 
-    for component in required_components {
+    for component in REQUIRED_COMPONENTS {
         if !components.contains(component) {
             panic!("require llvm component {} but wasn't found", component);
         }
index f0874f8f2da00374f8f7fb773fbfa308329b822d..aa5705d3fcdc3c368820455749c6d6906e893ee5 100644 (file)
@@ -951,6 +951,13 @@ fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)]
         tcx.arena.alloc_from_iter(self.root.lib_features.decode(self))
     }
 
+    /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute
+    /// has an `implied_by` meta item, then the mapping from the implied feature to the actual
+    /// feature is a stability implication).
+    fn get_stability_implications(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] {
+        tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self))
+    }
+
     /// Iterates over the language items in the given crate.
     fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
         tcx.arena.alloc_from_iter(
index 565eec18ea9b8d39818c16f14f533fc413b82989..65cae29c58dcbdd21accf3086843208d21f3f1de 100644 (file)
@@ -291,6 +291,9 @@ fn into_args(self) -> (DefId, SimplifiedType) {
         tcx.arena.alloc_slice(&result)
     }
     defined_lib_features => { cdata.get_lib_features(tcx) }
+    stability_implications => {
+        cdata.get_stability_implications(tcx).iter().copied().collect()
+    }
     is_intrinsic => { cdata.get_is_intrinsic(def_id.index) }
     defined_lang_items => { cdata.get_lang_items(tcx) }
     diagnostic_items => { cdata.get_diagnostic_items() }
index 8e97300977723abd722fbd6ef3701218da2ec69f..50d983754e89c6204e1dbdc3905da4bda237b821 100644 (file)
@@ -538,6 +538,11 @@ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
         let lib_features = self.encode_lib_features();
         let lib_feature_bytes = self.position() - i;
 
+        // Encode the stability implications.
+        i = self.position();
+        let stability_implications = self.encode_stability_implications();
+        let stability_implications_bytes = self.position() - i;
+
         // Encode the language items.
         i = self.position();
         let lang_items = self.encode_lang_items();
@@ -686,6 +691,7 @@ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
             crate_deps,
             dylib_dependency_formats,
             lib_features,
+            stability_implications,
             lang_items,
             diagnostic_items,
             lang_items_missing,
@@ -710,6 +716,7 @@ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
         let computed_total_bytes = preamble_bytes
             + dep_bytes
             + lib_feature_bytes
+            + stability_implications_bytes
             + lang_item_bytes
             + diagnostic_item_bytes
             + native_lib_bytes
@@ -761,6 +768,7 @@ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
             p("preamble", preamble_bytes);
             p("dep", dep_bytes);
             p("lib feature", lib_feature_bytes);
+            p("stability_implications", stability_implications_bytes);
             p("lang item", lang_item_bytes);
             p("diagnostic item", diagnostic_item_bytes);
             p("native lib", native_lib_bytes);
@@ -1777,6 +1785,13 @@ fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
         self.lazy_array(lib_features.to_vec())
     }
 
+    fn encode_stability_implications(&mut self) -> LazyArray<(Symbol, Symbol)> {
+        empty_proc_macro!(self);
+        let tcx = self.tcx;
+        let implications = tcx.stability_implications(LOCAL_CRATE);
+        self.lazy_array(implications.iter().map(|(k, v)| (*k, *v)))
+    }
+
     fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
index af1c09f4ae87adb86111644348fd2c5689c6ba29..0f291f926477702c9924e57f7dff06361f085aa2 100644 (file)
@@ -226,6 +226,7 @@ pub(crate) struct CrateRoot {
     crate_deps: LazyArray<CrateDep>,
     dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
     lib_features: LazyArray<(Symbol, Option<Symbol>)>,
+    stability_implications: LazyArray<(Symbol, Symbol)>,
     lang_items: LazyArray<(DefIndex, usize)>,
     lang_items_missing: LazyArray<lang_items::LangItem>,
     diagnostic_items: LazyArray<(Symbol, DefIndex)>,
index fc35cafcc77a16bc30e1080404ddb121a3b435dc..8dc68b1f5a820d415d0e21d696eeaedf3c780000 100644 (file)
@@ -3,14 +3,14 @@
 pub mod exported_symbols;
 pub mod lang_items;
 pub mod lib_features {
-    use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-    use rustc_span::symbol::Symbol;
+    use rustc_data_structures::fx::FxHashMap;
+    use rustc_span::{symbol::Symbol, Span};
 
     #[derive(HashStable, Debug)]
     pub struct LibFeatures {
-        // A map from feature to stabilisation version.
-        pub stable: FxHashMap<Symbol, Symbol>,
-        pub unstable: FxHashSet<Symbol>,
+        /// A map from feature to stabilisation version.
+        pub stable: FxHashMap<Symbol, (Symbol, Span)>,
+        pub unstable: FxHashMap<Symbol, Span>,
     }
 
     impl LibFeatures {
@@ -18,8 +18,8 @@ pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
             let mut all_features: Vec<_> = self
                 .stable
                 .iter()
-                .map(|(f, s)| (*f, Some(*s)))
-                .chain(self.unstable.iter().map(|f| (*f, None)))
+                .map(|(f, (s, _))| (*f, Some(*s)))
+                .chain(self.unstable.iter().map(|(f, _)| (*f, None)))
                 .collect();
             all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
             all_features
index 96e068a36012adb923f356d9c905298f1d434fda..0fbad3f0f0f06761c56b77ce6740cfdc936eb1ba 100644 (file)
@@ -62,6 +62,19 @@ pub struct Index {
     pub stab_map: FxHashMap<LocalDefId, Stability>,
     pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
     pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
+    /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
+    /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
+    /// exists, then this map will have a `impliee -> implier` entry.
+    ///
+    /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should
+    /// specify their implications (both `implies` and `implied_by`). If only one of the two
+    /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this
+    /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is
+    /// reported, only the `#[stable]` attribute information is available, so the map is necessary
+    /// to know that the feature implies another feature. If it were reversed, and the `#[stable]`
+    /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of
+    /// unstable feature" error for a feature that was implied.
+    pub implications: FxHashMap<Symbol, Symbol>,
 }
 
 impl Index {
@@ -423,7 +436,9 @@ pub fn eval_stability_allow_unstable(
 
         match stability {
             Some(Stability {
-                level: attr::Unstable { reason, issue, is_soft }, feature, ..
+                level: attr::Unstable { reason, issue, is_soft, implied_by },
+                feature,
+                ..
             }) => {
                 if span.allows_unstable(feature) {
                     debug!("stability: skipping span={:?} since it is internal", span);
@@ -433,6 +448,13 @@ pub fn eval_stability_allow_unstable(
                     return EvalResult::Allow;
                 }
 
+                // If this item was previously part of a now-stabilized feature which is still
+                // active (i.e. the user hasn't removed the attribute for the stabilized feature
+                // yet) then allow use of this item.
+                if let Some(implied_by) = implied_by && self.features().active(implied_by) {
+                    return EvalResult::Allow;
+                }
+
                 // When we're compiling the compiler itself we may pull in
                 // crates from crates.io, but those crates may depend on other
                 // crates also pulled in from crates.io. We want to ideally be
index 0b5d23be58d85e2c44c499e2e75209729af441b9..f61cb7e8c472e68a55674e853d2c168f262e0a95 100644 (file)
@@ -1397,7 +1397,6 @@ fn is_indirect(&self) -> bool {
 
             Self::Field(_, _)
             | Self::Index(_)
-            | Self::OpaqueCast(_)
             | Self::ConstantIndex { .. }
             | Self::Subslice { .. }
             | Self::Downcast(_, _) => false,
@@ -1575,9 +1574,7 @@ impl Debug for Place<'_> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         for elem in self.projection.iter().rev() {
             match elem {
-                ProjectionElem::OpaqueCast(_)
-                | ProjectionElem::Downcast(_, _)
-                | ProjectionElem::Field(_, _) => {
+                ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
                     write!(fmt, "(").unwrap();
                 }
                 ProjectionElem::Deref => {
@@ -1593,9 +1590,6 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
         for elem in self.projection.iter() {
             match elem {
-                ProjectionElem::OpaqueCast(ty) => {
-                    write!(fmt, " as {})", ty)?;
-                }
                 ProjectionElem::Downcast(Some(name), _index) => {
                     write!(fmt, " as {})", name)?;
                 }
index 263c2ca3c700ec2a1d594d120f9faed459c78e79..510316c778bc7678a0ebd40ec4a8549cebbec164 100644 (file)
@@ -754,9 +754,6 @@ pub enum InlineAsmOperand<'tcx> {
 ///    generator has more than one variant, the parent place's variant index must be set, indicating
 ///    which variant is being used. If it has just one variant, the variant index may or may not be
 ///    included - the single possible variant is inferred if it is not included.
-///  - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
-///    given one, and makes no other changes. A `OpaqueCast` projection on any type other than an
-///    opaque type from the current crate is not well-formed.
 ///  - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
 ///    place as described in the documentation for the `ProjectionElem`. The resulting address is
 ///    the parent's address plus that offset, and the type is `T`. This is only legal if the parent
@@ -859,10 +856,6 @@ pub enum ProjectionElem<V, T> {
     ///
     /// The included Symbol is the name of the variant, used for printing MIR.
     Downcast(Option<Symbol>, VariantIdx),
-
-    /// Like an explicit cast from an opaque type to a concrete type, but without
-    /// requiring an intermediate variable.
-    OpaqueCast(T),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
index c6975df45efc2a8247012dba1f74deecb2b534da..fd3359ea80fe50e6d6776d25d861db65cd1a4df9 100644 (file)
@@ -57,7 +57,7 @@ pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
     /// `PlaceElem`, where we can just use the `Ty` that is already
     /// stored inline on field projection elems.
     pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
-        self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
+        self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty)
     }
 
     /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -71,7 +71,6 @@ pub fn projection_ty_core<V, T>(
         param_env: ty::ParamEnv<'tcx>,
         elem: &ProjectionElem<V, T>,
         mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
-        mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
     ) -> PlaceTy<'tcx>
     where
         V: ::std::fmt::Debug,
@@ -110,7 +109,6 @@ pub fn projection_ty_core<V, T>(
                 PlaceTy { ty: self.ty, variant_index: Some(index) }
             }
             ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
-            ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)),
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
         answer
index a73ef23e28132db30842800b65d731571a14ad73..82a6b0c506f58c0087ce9dff2713ae2c6314dee1 100644 (file)
@@ -182,7 +182,6 @@ fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Se
         Ok(match self {
             Deref => Deref,
             Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
-            OpaqueCast(ty) => OpaqueCast(ty.try_fold_with(folder)?),
             Index(v) => Index(v.try_fold_with(folder)?),
             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
             ConstantIndex { offset, min_length, from_end } => {
index e5599fb15ad312ff3c60c8b6ba135b8a4c1e4807..d285728ec0783002073eaf556b9aefd8bbc832cd 100644 (file)
@@ -1064,11 +1064,6 @@ fn process_projection_elem(
                     self.visit_ty(&mut new_ty, TyContext::Location(location));
                     if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
                 }
-                PlaceElem::OpaqueCast(ty) => {
-                    let mut new_ty = ty;
-                    self.visit_ty(&mut new_ty, TyContext::Location(location));
-                    if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
-                }
                 PlaceElem::Deref
                 | PlaceElem::ConstantIndex { .. }
                 | PlaceElem::Subslice { .. }
@@ -1138,7 +1133,7 @@ fn super_projection_elem(
             location: Location,
         ) {
             match elem {
-                ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
+                ProjectionElem::Field(_field, ty) => {
                     self.visit_ty(ty, TyContext::Location(location));
                 }
                 ProjectionElem::Index(local) => {
index 0581ef41f66c2c4c6f0f33b096146267645b5316..466a0fc25f7d11ca3563cdd7a377aa4f55586d02 100644 (file)
         storage(ArenaCacheSelector<'tcx>)
         desc { "calculating the lib features map" }
     }
-    query defined_lib_features(_: CrateNum)
-        -> &'tcx [(Symbol, Option<Symbol>)] {
+    query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
         desc { "calculating the lib features defined in a crate" }
         separate_provide_extern
     }
+    query stability_implications(_: CrateNum) -> FxHashMap<Symbol, Symbol> {
+        storage(ArenaCacheSelector<'tcx>)
+        desc { "calculating the implications between `#[unstable]` features defined in a crate" }
+        separate_provide_extern
+    }
     /// Whether the function is an intrinsic
     query is_intrinsic(def_id: DefId) -> bool {
         desc { |tcx| "is_intrinsic({})", tcx.def_path_str(def_id) }
index c41a8318ec57f3c6867981e2f6fe1d2b86b45266..4491965347bd66473b2791a9c752b81e09e5653b 100644 (file)
@@ -3266,7 +3266,12 @@ fn fn_abi_new_uncached(
                     // 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 @@ fn fn_abi_new_uncached(
                     // `-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 {
index 6abf419dd4991bfb8347499e00e3d96e350cca26..e88f9dc1f08f5bf81c1218c051399adcc561be3b 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_middle::hir::place::Projection as HirProjection;
 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
 use rustc_middle::middle::region;
-use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::AssertKind::BoundsCheck;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
@@ -72,7 +71,7 @@ pub(crate) enum PlaceBase {
 /// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
 /// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
 #[derive(Clone, Debug, PartialEq)]
-pub(in crate::build) struct PlaceBuilder<'tcx> {
+pub(crate) struct PlaceBuilder<'tcx> {
     base: PlaceBase,
     projection: Vec<PlaceElem<'tcx>>,
 }
@@ -105,8 +104,6 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
                 variant = Some(*idx);
                 continue;
             }
-            // These do not affect anything, they just make sure we know the right type.
-            ProjectionElem::OpaqueCast(_) => continue,
             ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Subslice { .. } => {
@@ -204,10 +201,10 @@ fn find_capture_matching_projections<'a, 'tcx>(
 /// `PlaceBuilder` now starts from `PlaceBase::Local`.
 ///
 /// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
-#[instrument(level = "trace", skip(cx))]
-fn to_upvars_resolved_place_builder<'tcx>(
+fn to_upvars_resolved_place_builder<'a, 'tcx>(
     from_builder: PlaceBuilder<'tcx>,
-    cx: &Builder<'_, 'tcx>,
+    tcx: TyCtxt<'tcx>,
+    typeck_results: &'a ty::TypeckResults<'tcx>,
 ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
     match from_builder.base {
         PlaceBase::Local(_) => Ok(from_builder),
@@ -222,13 +219,13 @@ fn to_upvars_resolved_place_builder<'tcx>(
 
             let Some((capture_index, capture)) =
                 find_capture_matching_projections(
-                    cx.typeck_results,
+                    typeck_results,
                     var_hir_id,
                     closure_def_id,
                     &from_builder.projection,
                 ) else {
-                let closure_span = cx.tcx.def_span(closure_def_id);
-                if !enable_precise_capture(cx.tcx, closure_span) {
+                let closure_span = tcx.def_span(closure_def_id);
+                if !enable_precise_capture(tcx, closure_span) {
                     bug!(
                         "No associated capture found for {:?}[{:#?}] even though \
                             capture_disjoint_fields isn't enabled",
@@ -245,8 +242,8 @@ fn to_upvars_resolved_place_builder<'tcx>(
             };
 
             // We won't be building MIR if the closure wasn't local
-            let closure_hir_id = cx.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
-            let closure_ty = cx.typeck_results.node_type(closure_hir_id);
+            let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
+            let closure_ty = typeck_results.node_type(closure_hir_id);
 
             let substs = match closure_ty.kind() {
                 ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
@@ -273,14 +270,12 @@ fn to_upvars_resolved_place_builder<'tcx>(
 
             // We used some of the projections to build the capture itself,
             // now we apply the remaining to the upvar resolved place.
-            trace!(?capture.place, ?from_builder.projection);
             let remaining_projections = strip_prefix(
                 capture.place.base_ty,
                 from_builder.projection,
                 &capture.place.projections,
             );
             upvar_resolved_place_builder.projection.extend(remaining_projections);
-            trace!(?upvar_resolved_place_builder);
 
             Ok(upvar_resolved_place_builder)
         }
@@ -299,21 +294,16 @@ fn strip_prefix<'tcx>(
     prefix_projections: &[HirProjection<'tcx>],
 ) -> impl Iterator<Item = PlaceElem<'tcx>> {
     let mut iter = projections.into_iter();
-    let mut next = || match iter.next()? {
-        // Filter out opaque casts, they are unnecessary in the prefix.
-        ProjectionElem::OpaqueCast(..) => iter.next(),
-        other => Some(other),
-    };
     for projection in prefix_projections {
         match projection.kind {
             HirProjectionKind::Deref => {
-                assert!(matches!(next(), Some(ProjectionElem::Deref)));
+                assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
             }
             HirProjectionKind::Field(..) => {
                 if base_ty.is_enum() {
-                    assert!(matches!(next(), Some(ProjectionElem::Downcast(..))));
+                    assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
                 }
-                assert!(matches!(next(), Some(ProjectionElem::Field(..))));
+                assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
             }
             HirProjectionKind::Index | HirProjectionKind::Subslice => {
                 bug!("unexpected projection kind: {:?}", projection);
@@ -325,32 +315,24 @@ fn strip_prefix<'tcx>(
 }
 
 impl<'tcx> PlaceBuilder<'tcx> {
-    pub(crate) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
+    pub(crate) fn into_place<'a>(
+        self,
+        tcx: TyCtxt<'tcx>,
+        typeck_results: &'a ty::TypeckResults<'tcx>,
+    ) -> Place<'tcx> {
         if let PlaceBase::Local(local) = self.base {
-            let mut projections = vec![];
-            let mut ty = PlaceTy::from_ty(cx.local_decls[local].ty);
-            for projection in self.projection {
-                // Only preserve those opaque casts that actually go from an opaque type
-                // to another type.
-                if let ProjectionElem::OpaqueCast(t) = projection {
-                    if let ty::Opaque(..) = ty.ty.kind() {
-                        if t != ty.ty {
-                            projections.push(ProjectionElem::OpaqueCast(t));
-                        }
-                    }
-                } else {
-                    projections.push(projection);
-                }
-                ty = ty.projection_ty(cx.tcx, projection);
-            }
-            Place { local, projection: cx.tcx.intern_place_elems(&projections) }
+            Place { local, projection: tcx.intern_place_elems(&self.projection) }
         } else {
-            self.expect_upvars_resolved(cx).into_place(cx)
+            self.expect_upvars_resolved(tcx, typeck_results).into_place(tcx, typeck_results)
         }
     }
 
-    fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
-        to_upvars_resolved_place_builder(self, cx).unwrap()
+    fn expect_upvars_resolved<'a>(
+        self,
+        tcx: TyCtxt<'tcx>,
+        typeck_results: &'a ty::TypeckResults<'tcx>,
+    ) -> PlaceBuilder<'tcx> {
+        to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap()
     }
 
     /// Attempts to resolve the `PlaceBuilder`.
@@ -364,11 +346,12 @@ fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
     /// not captured. This can happen because the final mir that will be
     /// generated doesn't require a read for this place. Failures will only
     /// happen inside closures.
-    pub(crate) fn try_upvars_resolved(
+    pub(crate) fn try_upvars_resolved<'a>(
         self,
-        cx: &Builder<'_, 'tcx>,
+        tcx: TyCtxt<'tcx>,
+        typeck_results: &'a ty::TypeckResults<'tcx>,
     ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
-        to_upvars_resolved_place_builder(self, cx)
+        to_upvars_resolved_place_builder(self, tcx, typeck_results)
     }
 
     pub(crate) fn base(&self) -> PlaceBase {
@@ -428,7 +411,7 @@ pub(crate) fn as_place(
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_place_builder(block, expr));
-        block.and(place_builder.into_place(self))
+        block.and(place_builder.into_place(self.tcx, self.typeck_results))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -452,7 +435,7 @@ pub(crate) fn as_read_only_place(
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
-        block.and(place_builder.into_place(self))
+        block.and(place_builder.into_place(self.tcx, self.typeck_results))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -547,7 +530,7 @@ fn expr_as_place(
                             inferred_ty: expr.ty,
                         });
 
-                    let place = place_builder.clone().into_place(this);
+                    let place = place_builder.clone().into_place(this.tcx, this.typeck_results);
                     this.cfg.push(
                         block,
                         Statement {
@@ -699,7 +682,7 @@ fn lower_index_expression(
         if is_outermost_index {
             self.read_fake_borrows(block, fake_borrow_temps, source_info)
         } else {
-            base_place = base_place.expect_upvars_resolved(self);
+            base_place = base_place.expect_upvars_resolved(self.tcx, self.typeck_results);
             self.add_fake_borrows_of_base(
                 &base_place,
                 block,
@@ -727,7 +710,12 @@ fn bounds_check(
         let lt = self.temp(bool_ty, expr_span);
 
         // len = len(slice)
-        self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
+        self.cfg.push_assign(
+            block,
+            source_info,
+            len,
+            Rvalue::Len(slice.into_place(self.tcx, self.typeck_results)),
+        );
         // lt = idx < len
         self.cfg.push_assign(
             block,
@@ -807,7 +795,6 @@ fn add_fake_borrows_of_base(
                     }
                     ProjectionElem::Field(..)
                     | ProjectionElem::Downcast(..)
-                    | ProjectionElem::OpaqueCast(..)
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. } => (),
                 }
index 93f76333165a5c1bb3cc041fdaff6a36d974ce8c..15f2d17c4e08b2ddc45d181ea9f89d0a2c408cfa 100644 (file)
@@ -321,8 +321,11 @@ pub(crate) fn as_rvalue(
                     let place_builder =
                         unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
 
-                    if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
-                        let mir_place = place_builder_resolved.into_place(this);
+                    if let Ok(place_builder_resolved) =
+                        place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
+                    {
+                        let mir_place =
+                            place_builder_resolved.into_place(this.tcx, this.typeck_results);
                         this.cfg.push_fake_read(
                             block,
                             this.source_info(this.tcx.hir().span(*hir_id)),
@@ -613,7 +616,8 @@ fn limit_capture_mutability(
             // by the parent itself. The mutability of the current capture
             // is same as that of the capture in the parent closure.
             PlaceBase::Upvar { .. } => {
-                let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
+                let enclosing_upvars_resolved =
+                    arg_place_builder.clone().into_place(this.tcx, this.typeck_results);
 
                 match enclosing_upvars_resolved.as_ref() {
                     PlaceRef {
@@ -650,7 +654,7 @@ fn limit_capture_mutability(
             Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
         };
 
-        let arg_place = arg_place_builder.into_place(this);
+        let arg_place = arg_place_builder.into_place(this.tcx, this.typeck_results);
 
         this.cfg.push_assign(
             block,
index dac8862647a85c7e303f0a7946fa122926bae9d5..724b72f8769b8bc8bd460880f3a3cb90a5fc2d44 100644 (file)
@@ -23,7 +23,6 @@ pub(crate) fn as_temp(
         ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
     }
 
-    #[instrument(skip(self), level = "debug")]
     fn as_temp_inner(
         &mut self,
         mut block: BasicBlock,
@@ -31,6 +30,10 @@ fn as_temp_inner(
         expr: &Expr<'tcx>,
         mutability: Mutability,
     ) -> BlockAnd<Local> {
+        debug!(
+            "as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
+            block, temp_lifetime, expr, mutability
+        );
         let this = self;
 
         let expr_span = expr.span;
index d1ef515b3d29bda290a6f6f3a4684c24fa80a650..017d43d10a9a917a52b5db18720d92a9f20a4f8d 100644 (file)
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
-    #[instrument(level = "debug", skip(self))]
     pub(crate) fn expr_into_dest(
         &mut self,
         destination: Place<'tcx>,
         mut block: BasicBlock,
         expr: &Expr<'tcx>,
     ) -> BlockAnd<()> {
+        debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
+
         // since we frequently have to reference `self` from within a
         // closure, where `self` would be shadowed, it's easier to
         // just use the name `this` uniformly
@@ -365,7 +366,9 @@ pub(crate) fn expr_into_dest(
                             None => {
                                 let place_builder = place_builder.clone();
                                 this.consume_by_copy_or_move(
-                                    place_builder.field(n, *ty).into_place(this),
+                                    place_builder
+                                        .field(n, *ty)
+                                        .into_place(this.tcx, this.typeck_results),
                                 )
                             }
                         })
index 86ef666eac8d2c88c62d2b49e1b20a4e428a8bf9..7067a48b783ec24ad61e1c066db7c6120249c738 100644 (file)
@@ -220,8 +220,10 @@ fn lower_scrutinee(
         let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
         let source_info = self.source_info(scrutinee_span);
 
-        if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
-            let scrutinee_place = scrutinee_builder.into_place(self);
+        if let Ok(scrutinee_builder) =
+            scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, self.typeck_results)
+        {
+            let scrutinee_place = scrutinee_builder.into_place(self.tcx, self.typeck_results);
             self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
         }
 
@@ -346,10 +348,12 @@ fn lower_match_arms(
                     // ```
                     let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
                     let scrutinee_place: Place<'tcx>;
-                    if let Ok(scrutinee_builder) =
-                        scrutinee_place_builder.clone().try_upvars_resolved(this)
+                    if let Ok(scrutinee_builder) = scrutinee_place_builder
+                        .clone()
+                        .try_upvars_resolved(this.tcx, this.typeck_results)
                     {
-                        scrutinee_place = scrutinee_builder.into_place(this);
+                        scrutinee_place =
+                            scrutinee_builder.into_place(this.tcx, this.typeck_results);
                         opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
                     }
                     let scope = this.declare_bindings(
@@ -598,6 +602,12 @@ pub(crate) fn place_into_pattern(
             while let Some(next) = {
                 for binding in &candidate_ref.bindings {
                     let local = self.var_local_id(binding.var_id, OutsideGuard);
+
+                    let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                        VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
+                    )))) = self.local_decls[local].local_info else {
+                        bug!("Let binding to non-user variable.")
+                    };
                     // `try_upvars_resolved` may fail if it is unable to resolve the given
                     // `PlaceBuilder` inside a closure. In this case, we don't want to include
                     // a scrutinee place. `scrutinee_place_builder` will fail for destructured
@@ -612,15 +622,10 @@ pub(crate) fn place_into_pattern(
                     //    let (v1, v2) = foo;
                     // };
                     // ```
-                    if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
-                        let place = match_pair_resolved.into_place(self);
-
-                        let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
-                            VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
-                        )))) = self.local_decls[local].local_info else {
-                            bug!("Let binding to non-user variable.")
-                        };
-
+                    if let Ok(match_pair_resolved) =
+                        initializer.clone().try_upvars_resolved(self.tcx, self.typeck_results)
+                    {
+                        let place = match_pair_resolved.into_place(self.tcx, self.typeck_results);
                         *match_place = Some(place);
                     }
                 }
@@ -649,7 +654,6 @@ pub(crate) fn place_into_pattern(
     /// scope for the bindings in these patterns, if such a scope had to be
     /// created. NOTE: Declaring the bindings should always be done in their
     /// drop scope.
-    #[instrument(skip(self), level = "debug")]
     pub(crate) fn declare_bindings(
         &mut self,
         mut visibility_scope: Option<SourceScope>,
@@ -658,6 +662,7 @@ pub(crate) fn declare_bindings(
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
     ) -> Option<SourceScope> {
+        debug!("declare_bindings: pattern={:?}", pattern);
         self.visit_primary_bindings(
             &pattern,
             UserTypeProjections::none(),
@@ -867,7 +872,7 @@ fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) ->
         Candidate {
             span: pattern.span,
             has_guard,
-            match_pairs: smallvec![MatchPair::new(place, pattern)],
+            match_pairs: smallvec![MatchPair { place, pattern }],
             bindings: Vec::new(),
             ascriptions: Vec::new(),
             subcandidates: Vec::new(),
@@ -1043,7 +1048,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// if `x.0` matches `false` (for the third arm). In the (impossible at
     /// runtime) case when `x.0` is now `true`, we branch to
     /// `otherwise_block`.
-    #[instrument(skip(self, fake_borrows), level = "debug")]
     fn match_candidates<'pat>(
         &mut self,
         span: Span,
@@ -1053,6 +1057,11 @@ fn match_candidates<'pat>(
         candidates: &mut [&mut Candidate<'pat, 'tcx>],
         fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
     ) {
+        debug!(
+            "matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})",
+            span, candidates, start_block, otherwise_block,
+        );
+
         // Start by simplifying candidates. Once this process is complete, all
         // the match pairs which remain require some form of test, whether it
         // be a switch or pattern comparison.
@@ -1371,10 +1380,6 @@ fn test_candidates_with_or(
         )
     }
 
-    #[instrument(
-        skip(self, otherwise, or_span, place, fake_borrows, candidate, pats),
-        level = "debug"
-    )]
     fn test_or_pattern<'pat>(
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
@@ -1384,7 +1389,7 @@ fn test_or_pattern<'pat>(
         place: PlaceBuilder<'tcx>,
         fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
     ) {
-        debug!("candidate={:#?}\npats={:#?}", candidate, pats);
+        debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
         let mut or_candidates: Vec<_> = pats
             .iter()
             .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
@@ -1600,9 +1605,9 @@ fn test_candidates<'pat, 'b, 'c>(
 
         // Insert a Shallow borrow of any places that is switched on.
         if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
-            match_place.clone().try_upvars_resolved(self)
+            match_place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
         {
-            let resolved_place = match_place_resolved.into_place(self);
+            let resolved_place = match_place_resolved.into_place(self.tcx, self.typeck_results);
             fb.insert(resolved_place);
         }
 
@@ -1629,14 +1634,9 @@ fn test_candidates<'pat, 'b, 'c>(
             candidates = rest;
         }
         // at least the first candidate ought to be tested
-        assert!(
-            total_candidate_count > candidates.len(),
-            "{}, {:#?}",
-            total_candidate_count,
-            candidates
-        );
-        debug!("tested_candidates: {}", total_candidate_count - candidates.len());
-        debug!("untested_candidates: {}", candidates.len());
+        assert!(total_candidate_count > candidates.len());
+        debug!("test_candidates: tested_candidates: {}", total_candidate_count - candidates.len());
+        debug!("test_candidates: untested_candidates: {}", candidates.len());
 
         // HACK(matthewjasper) This is a closure so that we can let the test
         // create its blocks before the rest of the match. This currently
@@ -1794,8 +1794,10 @@ pub(crate) fn lower_let_expr(
         );
         let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
         let expr_place: Place<'tcx>;
-        if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
-            expr_place = expr_builder.into_place(self);
+        if let Ok(expr_builder) =
+            expr_place_builder.try_upvars_resolved(self.tcx, self.typeck_results)
+        {
+            expr_place = expr_builder.into_place(self.tcx, self.typeck_results);
             opt_expr_place = Some((Some(&expr_place), expr_span));
         }
         let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
@@ -2193,7 +2195,6 @@ fn bind_matched_candidate_for_arm_body<'b>(
     /// first local is a binding for occurrences of `var` in the guard, which
     /// will have type `&T`. The second local is a binding for occurrences of
     /// `var` in the arm body, which will have type `T`.
-    #[instrument(skip(self), level = "debug")]
     fn declare_binding(
         &mut self,
         source_info: SourceInfo,
@@ -2208,12 +2209,19 @@ fn declare_binding(
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
     ) {
+        debug!(
+            "declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
+             visibility_scope={:?}, source_info={:?})",
+            var_id, name, mode, var_ty, visibility_scope, source_info
+        );
+
         let tcx = self.tcx;
         let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
         let binding_mode = match mode {
             BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
             BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
         };
+        debug!("declare_binding: user_ty={:?}", user_ty);
         let local = LocalDecl::<'tcx> {
             mutability,
             ty: var_ty,
@@ -2263,7 +2271,7 @@ fn declare_binding(
         } else {
             LocalsForNode::One(for_arm_body)
         };
-        debug!(?locals);
+        debug!("declare_binding: vars={:?}", locals);
         self.var_indices.insert(var_id, locals);
     }
 
index 6fa817da28a3c7578b6ee1b2b17bc2bf03750f07..c6298904140c39ef9166191ac078d9b597ba18ed 100644 (file)
@@ -37,13 +37,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// only generates a single switch. If this happens this method returns
     /// `true`.
-    #[instrument(skip(self, candidate), level = "debug")]
     pub(super) fn simplify_candidate<'pat>(
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
     ) -> bool {
         // repeatedly simplify match pairs until fixed point is reached
-        debug!("{:#?}", candidate);
+        debug!(?candidate, "simplify_candidate");
 
         // existing_bindings and new_bindings exists to keep the semantics in order.
         // Reversing the binding order for bindings after `@` changes the binding order in places
@@ -156,10 +155,12 @@ fn simplify_match_pair<'pat>(
                 ascription: thir::Ascription { ref annotation, variance },
             } => {
                 // Apply the type ascription to the value at `match_pair.place`, which is the
-                if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
+                if let Ok(place_resolved) =
+                    match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
+                {
                     candidate.ascriptions.push(Ascription {
                         annotation: annotation.clone(),
-                        source: place_resolved.into_place(self),
+                        source: place_resolved.into_place(self.tcx, self.typeck_results),
                         variance,
                     });
                 }
@@ -183,10 +184,12 @@ fn simplify_match_pair<'pat>(
                 ref subpattern,
                 is_primary: _,
             } => {
-                if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
+                if let Ok(place_resolved) =
+                    match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
+                {
                     candidate.bindings.push(Binding {
                         span: match_pair.pattern.span,
-                        source: place_resolved.into_place(self),
+                        source: place_resolved.into_place(self.tcx, self.typeck_results),
                         var_id: var,
                         binding_mode: mode,
                     });
index 63acd731db7c9735c901d335dcf5d276db1f1d0c..598da80c574aff45ba7d4684fb4d307c86f16dd0 100644 (file)
@@ -144,7 +144,6 @@ pub(super) fn add_variants_to_switch<'pat>(
         }
     }
 
-    #[instrument(skip(self, make_target_blocks, place_builder), level = "debug")]
     pub(super) fn perform_test(
         &mut self,
         match_start_span: Span,
@@ -154,9 +153,21 @@ pub(super) fn perform_test(
         test: &Test<'tcx>,
         make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
     ) {
-        let place = place_builder.into_place(self);
-        let place_ty = place.ty(&self.local_decls, self.tcx);
-        debug!(?place, ?place_ty,);
+        let place: Place<'tcx>;
+        if let Ok(test_place_builder) =
+            place_builder.try_upvars_resolved(self.tcx, self.typeck_results)
+        {
+            place = test_place_builder.into_place(self.tcx, self.typeck_results);
+        } else {
+            return;
+        }
+        debug!(
+            "perform_test({:?}, {:?}: {:?}, {:?})",
+            block,
+            place,
+            place.ty(&self.local_decls, self.tcx),
+            test
+        );
 
         let source_info = self.source_info(test.span);
         match test.kind {
@@ -724,7 +735,9 @@ fn candidate_after_variant_switch<'pat>(
         // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
         // we want to create a set of derived match-patterns like
         // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
-        let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
+        let elem =
+            ProjectionElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index);
+        let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
         let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
             // e.g., `(x as Variant).0`
             let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
index 4a7edc517f4e4436a73c8e16f16709acabd8e8c3..9a1e98d3bb18ddc8d6b6e646a1de00610ae4ae33 100644 (file)
@@ -31,15 +31,21 @@ pub(crate) fn prefix_slice_suffix<'pat>(
         suffix: &'pat [Pat<'tcx>],
     ) {
         let tcx = self.tcx;
-        let (min_length, exact_size) =
-            if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
-                match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
-                    ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
-                    _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
-                }
-            } else {
-                ((prefix.len() + suffix.len()).try_into().unwrap(), false)
-            };
+        let (min_length, exact_size) = if let Ok(place_resolved) =
+            place.clone().try_upvars_resolved(tcx, self.typeck_results)
+        {
+            match place_resolved
+                .into_place(tcx, self.typeck_results)
+                .ty(&self.local_decls, tcx)
+                .ty
+                .kind()
+            {
+                ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
+                _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
+            }
+        } else {
+            ((prefix.len() + suffix.len()).try_into().unwrap(), false)
+        };
 
         match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
             let elem =
@@ -94,14 +100,10 @@ pub(crate) fn false_edges(
 }
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
-    pub(in crate::build) fn new(
+    pub(crate) fn new(
         place: PlaceBuilder<'tcx>,
         pattern: &'pat Pat<'tcx>,
     ) -> MatchPair<'pat, 'tcx> {
-        // Force the place type to the pattern's type.
-        // FIXME(oli-obk): only do this when we don't already know the place type.
-        // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
-        let place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
         MatchPair { place, pattern }
     }
 }
index ab37c4802852a85e1015038723230591167e8d75..b9fd8c50e6a047fb593411dfc8b07afa23b591e9 100644 (file)
@@ -553,7 +553,6 @@ pub(crate) fn in_opt_scope<F, R>(
 
     /// Convenience wrapper that pushes a scope and then executes `f`
     /// to build its contents, popping the scope afterwards.
-    #[instrument(skip(self, f), level = "debug")]
     pub(crate) fn in_scope<F, R>(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
@@ -563,6 +562,7 @@ pub(crate) fn in_scope<F, R>(
     where
         F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
     {
+        debug!("in_scope(region_scope={:?})", region_scope);
         let source_scope = self.source_scope;
         let tcx = self.tcx;
         if let LintLevel::Explicit(current_hir_id) = lint_level {
@@ -589,7 +589,7 @@ pub(crate) fn in_scope<F, R>(
         let rv = unpack!(block = f(self));
         unpack!(block = self.pop_scope(region_scope, block));
         self.source_scope = source_scope;
-        debug!(?block);
+        debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
         block.and(rv)
     }
 
index 05da33caa91bdefe94a338c292d4e52a33cd4f16..4eb3607e9cca0e914138c344bb39fb2e1691c469 100644 (file)
@@ -48,8 +48,6 @@ pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> E
             _ => None,
         };
 
-        trace!(?expr.ty);
-
         // Now apply adjustments, if any.
         for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
             trace!(?expr, ?adjustment);
@@ -58,8 +56,6 @@ pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> E
                 self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
         }
 
-        trace!(?expr.ty, "after adjustments");
-
         // Next, wrap this up in the expr's scope.
         expr = Expr {
             temp_lifetime,
index c0fd19cf71c3186ede0fb0d75895f1afde65b6a3..60db98073a3b91776504b854718a6f88ffb494ad 100644 (file)
@@ -1202,32 +1202,35 @@ fn list_variant_nonhidden_fields<'a>(
 
     /// Creates a new list of wildcard fields for a given constructor. The result must have a
     /// length of `constructor.arity()`.
-    #[instrument(level = "trace")]
-    pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
+    pub(super) fn wildcards(
+        cx: &MatchCheckCtxt<'p, 'tcx>,
+        ty: Ty<'tcx>,
+        constructor: &Constructor<'tcx>,
+    ) -> Self {
         let ret = match constructor {
-            Single | Variant(_) => match pcx.ty.kind() {
-                ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()),
-                ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)),
+            Single | Variant(_) => match ty.kind() {
+                ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter()),
+                ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)),
                 ty::Adt(adt, substs) => {
                     if adt.is_box() {
                         // The only legal patterns of type `Box` (outside `std`) are `_` and box
                         // patterns. If we're here we can assume this is a box pattern.
-                        Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)))
+                        Fields::wildcards_from_tys(cx, once(substs.type_at(0)))
                     } else {
                         let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
-                        let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
+                        let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant)
                             .map(|(_, ty)| ty);
-                        Fields::wildcards_from_tys(pcx.cx, tys)
+                        Fields::wildcards_from_tys(cx, tys)
                     }
                 }
-                _ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
+                _ => bug!("Unexpected type for `Single` constructor: {:?}", ty),
             },
-            Slice(slice) => match *pcx.ty.kind() {
+            Slice(slice) => match *ty.kind() {
                 ty::Slice(ty) | ty::Array(ty, _) => {
                     let arity = slice.arity();
-                    Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty))
+                    Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
                 }
-                _ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
+                _ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
             },
             Str(..)
             | FloatRange(..)
@@ -1240,7 +1243,7 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
                 bug!("called `Fields::wildcards` on an `Or` ctor")
             }
         };
-        debug!(?ret);
+        debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
         ret
     }
 
@@ -1283,7 +1286,7 @@ pub(super) fn new(
     /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
     /// `Some(_)`.
     pub(super) fn wild_from_ctor(pcx: PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
-        let fields = Fields::wildcards(pcx, &ctor);
+        let fields = Fields::wildcards(pcx.cx, pcx.ty, &ctor);
         DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP)
     }
 
@@ -1550,13 +1553,13 @@ pub(super) fn iter_fields<'a>(
     /// `other_ctor` can be different from `self.ctor`, but must be covered by it.
     pub(super) fn specialize<'a>(
         &'a self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
+        cx: &MatchCheckCtxt<'p, 'tcx>,
         other_ctor: &Constructor<'tcx>,
     ) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> {
         match (&self.ctor, other_ctor) {
             (Wildcard, _) => {
                 // We return a wildcard for each field of `other_ctor`.
-                Fields::wildcards(pcx, other_ctor).iter_patterns().collect()
+                Fields::wildcards(cx, self.ty, other_ctor).iter_patterns().collect()
             }
             (Slice(self_slice), Slice(other_slice))
                 if self_slice.arity() != other_slice.arity() =>
@@ -1575,7 +1578,7 @@ pub(super) fn specialize<'a>(
                         let prefix = &self.fields.fields[..prefix];
                         let suffix = &self.fields.fields[self_slice.arity() - suffix..];
                         let wildcard: &_ =
-                            pcx.cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
+                            cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
                         let extra_wildcards = other_slice.arity() - self_slice.arity();
                         let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
                         prefix.iter().chain(extra_wildcards).chain(suffix).collect()
index 7d22f7b69d862059da105dbe1dc55b71ab79cf15..a13748a2d474ad1b92e74f24de438222379b376b 100644 (file)
@@ -196,7 +196,6 @@ fn normalize_range_pattern_ends(
         }
     }
 
-    #[instrument(skip(self), level = "debug")]
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let mut ty = self.typeck_results.node_type(pat.hir_id);
 
index f27ec22a8dee25a8a4e0cfe6669d26856761002b..9e7a267ecbd7fc86dd9d057324d9595f21ac5b74 100644 (file)
@@ -411,12 +411,12 @@ fn expand_or_pat<'a>(&'a self) -> impl Iterator<Item = PatStack<'p, 'tcx>> + Cap
     /// This is roughly the inverse of `Constructor::apply`.
     fn pop_head_constructor(
         &self,
-        pcx: PatCtxt<'_, 'p, 'tcx>,
+        cx: &MatchCheckCtxt<'p, 'tcx>,
         ctor: &Constructor<'tcx>,
     ) -> PatStack<'p, 'tcx> {
         // We pop the head pattern and push the new fields extracted from the arguments of
         // `self.head()`.
-        let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(pcx, ctor);
+        let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor);
         new_fields.extend_from_slice(&self.pats[1..]);
         PatStack::from_vec(new_fields)
     }
@@ -475,7 +475,7 @@ fn specialize_constructor(
         let mut matrix = Matrix::empty();
         for row in &self.patterns {
             if ctor.is_covered_by(pcx, row.head().ctor()) {
-                let new_row = row.pop_head_constructor(pcx, ctor);
+                let new_row = row.pop_head_constructor(pcx.cx, ctor);
                 matrix.push(new_row);
             }
         }
@@ -786,7 +786,7 @@ fn is_useful<'p, 'tcx>(
     is_under_guard: bool,
     is_top_level: bool,
 ) -> Usefulness<'p, 'tcx> {
-    debug!(?matrix, ?v);
+    debug!("matrix,v={:?}{:?}", matrix, v);
     let Matrix { patterns: rows, .. } = matrix;
 
     // The base case. We are pattern-matching on () and the return value is
@@ -806,6 +806,11 @@ fn is_useful<'p, 'tcx>(
 
     debug_assert!(rows.iter().all(|r| r.len() == v.len()));
 
+    let ty = v.head().ty();
+    let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
+    debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
+    let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
+
     // If the first pattern is an or-pattern, expand it.
     let mut ret = Usefulness::new_not_useful(witness_preference);
     if v.head().is_or_pat() {
@@ -827,19 +832,6 @@ fn is_useful<'p, 'tcx>(
             }
         }
     } else {
-        let mut ty = v.head().ty();
-
-        // Opaque types can't get destructured/split, but the patterns can
-        // actually hint at hidden types, so we use the patterns' types instead.
-        if let ty::Opaque(..) = v.head().ty().kind() {
-            if let Some(row) = rows.first() {
-                ty = row.head().ty();
-            }
-        }
-        let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
-        debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
-        let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
-
         let v_ctor = v.head().ctor();
         debug!(?v_ctor);
         if let Constructor::IntRange(ctor_range) = &v_ctor {
@@ -861,7 +853,7 @@ fn is_useful<'p, 'tcx>(
             debug!("specialize({:?})", ctor);
             // We cache the result of `Fields::wildcards` because it is used a lot.
             let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
-            let v = v.pop_head_constructor(pcx, &ctor);
+            let v = v.pop_head_constructor(cx, &ctor);
             let usefulness = ensure_sufficient_stack(|| {
                 is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
             });
index 7806e8f45d3ade55a4f6c907a90e0d515273e88a..28936274baafa639614b7aa547c37859c8a0b8aa 100644 (file)
@@ -48,7 +48,6 @@ fn lift(&self) -> Self::Abstract {
         match *self {
             ProjectionElem::Deref => ProjectionElem::Deref,
             ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()),
-            ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty.lift()),
             ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
             ProjectionElem::Subslice { from, to, from_end } => {
                 ProjectionElem::Subslice { from, to, from_end }
index 86327ade94b8a2e6305def7f7eded40abfbdb56f..b91ae083cf594e10bec90714a67d525407592139 100644 (file)
@@ -28,7 +28,6 @@ fn is_stable(place: PlaceRef<'_>) -> bool {
             ProjectionElem::Field { .. } |
             ProjectionElem::ConstantIndex { .. } |
             ProjectionElem::Subslice { .. } |
-            ProjectionElem::OpaqueCast { .. } |
             ProjectionElem::Downcast { .. } => true,
         }
     })
index d96e7d3efe83db095dc1e2180e8b60683d7cf5b9..f88997f884a4478bf5f5618fc14ab356e7631c9e 100644 (file)
@@ -706,14 +706,20 @@ fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
         true
     }
 
-    fn check_doc_tuple_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
+    fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
         match self.tcx.hir().find(hir_id).and_then(|node| match node {
             hir::Node::Item(item) => Some(&item.kind),
             _ => None,
         }) {
             Some(ItemKind::Impl(ref i)) => {
-                if !matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) {
-                    self.tcx.sess.emit_err(errors::DocTupleVariadicNotFirst { span: meta.span() });
+                let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_]))
+                    || if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind {
+                        bare_fn_ty.decl.inputs.len() == 1
+                    } else {
+                        false
+                    };
+                if !is_valid {
+                    self.tcx.sess.emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });
                     return false;
                 }
             }
@@ -887,9 +893,9 @@ fn check_doc_attrs(
                             is_valid = false
                         }
 
-                        sym::tuple_variadic
-                            if !self.check_attr_not_crate_level(meta, hir_id, "tuple_variadic")
-                                || !self.check_doc_tuple_variadic(meta, hir_id) =>
+                        sym::fake_variadic
+                            if !self.check_attr_not_crate_level(meta, hir_id, "fake_variadic")
+                                || !self.check_doc_fake_variadic(meta, hir_id) =>
                         {
                             is_valid = false
                         }
@@ -939,7 +945,7 @@ fn check_doc_attrs(
                         | sym::notable_trait
                         | sym::passes
                         | sym::plugins
-                        | sym::tuple_variadic => {}
+                        | sym::fake_variadic => {}
 
                         sym::test => {
                             if !self.check_test_attr(meta, hir_id) {
index f8e8720ab5474231a487f2c7fd2d251e611fc62b..fcd1e9363b1bed01018495447afebf0d5e9fe647 100644 (file)
@@ -212,8 +212,8 @@ pub struct DocKeywordInvalidIdent {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_tuple_variadic_not_first)]
-pub struct DocTupleVariadicNotFirst {
+#[error(passes::doc_fake_variadic_not_valid)]
+pub struct DocFakeVariadicNotValid {
     #[primary_span]
     pub span: Span,
 }
index 26bfa4737a7524ee48581a8034eac7ff77643816..e05994f13e4d9b8ef73bc5c8b50ca878cb599636 100644 (file)
@@ -1,8 +1,8 @@
-// Detecting lib features (i.e., features that are not lang features).
-//
-// These are declared using stability attributes (e.g., `#[stable (..)]`
-// and `#[unstable (..)]`), but are not declared in one single location
-// (unlike lang features), which means we need to collect them instead.
+//! Detecting lib features (i.e., features that are not lang features).
+//!
+//! These are declared using stability attributes (e.g., `#[stable (..)]` and `#[unstable (..)]`),
+//! but are not declared in one single location (unlike lang features), which means we need to
+//! collect them instead.
 
 use rustc_ast::{Attribute, MetaItemKind};
 use rustc_errors::struct_span_err;
@@ -71,11 +71,11 @@ fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
 
     fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
         let already_in_stable = self.lib_features.stable.contains_key(&feature);
-        let already_in_unstable = self.lib_features.unstable.contains(&feature);
+        let already_in_unstable = self.lib_features.unstable.contains_key(&feature);
 
         match (since, already_in_stable, already_in_unstable) {
             (Some(since), _, false) => {
-                if let Some(prev_since) = self.lib_features.stable.get(&feature) {
+                if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
                     if *prev_since != since {
                         self.span_feature_error(
                             span,
@@ -89,10 +89,10 @@ fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span
                     }
                 }
 
-                self.lib_features.stable.insert(feature, since);
+                self.lib_features.stable.insert(feature, (since, span));
             }
             (None, false, _) => {
-                self.lib_features.unstable.insert(feature);
+                self.lib_features.unstable.insert(feature, span);
             }
             (Some(_), _, true) | (None, true, _) => {
                 self.span_feature_error(
index 4e091c5b70d5cd1ef16e3011c5f6655013b9c00c..81b04c414ed9b6c11ba48e8f078310476b359407 100644 (file)
@@ -2,9 +2,9 @@
 //! propagating default levels lexically from parent to children ast nodes.
 
 use attr::StabilityLevel;
-use rustc_attr::{self as attr, ConstStability, Stability};
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
-use rustc_errors::struct_span_err;
+use rustc_attr::{self as attr, ConstStability, Stability, Unstable};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 
 #[derive(PartialEq)]
 enum AnnotationKind {
-    // Annotation is required if not inherited from unstable parents
+    /// Annotation is required if not inherited from unstable parents.
     Required,
-    // Annotation is useless, reject it
+    /// Annotation is useless, reject it.
     Prohibited,
-    // Deprecation annotation is useless, reject it. (Stability attribute is still required.)
+    /// Deprecation annotation is useless, reject it. (Stability attribute is still required.)
     DeprecationProhibited,
-    // Annotation itself is useless, but it can be propagated to children
+    /// Annotation itself is useless, but it can be propagated to children.
     Container,
 }
 
@@ -83,7 +83,7 @@ fn yes(&self) -> bool {
     }
 }
 
-// A private tree-walker for producing an Index.
+/// A private tree-walker for producing an `Index`.
 struct Annotator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     index: &'a mut Index,
@@ -94,9 +94,9 @@ struct Annotator<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Annotator<'a, 'tcx> {
-    // Determine the stability for a node based on its attributes and inherited
-    // stability. The stability is recorded in the index and used as the parent.
-    // If the node is a function, `fn_sig` is its signature
+    /// Determine the stability for a node based on its attributes and inherited stability. The
+    /// stability is recorded in the index and used as the parent. If the node is a function,
+    /// `fn_sig` is its signature.
     fn annotate<F>(
         &mut self,
         def_id: LocalDefId,
@@ -265,6 +265,10 @@ fn annotate<F>(
                 }
             }
 
+            if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab {
+                self.index.implications.insert(implied_by, feature);
+            }
+
             self.index.stab_map.insert(def_id, stab);
             stab
         });
@@ -610,6 +614,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
         stab_map: Default::default(),
         const_stab_map: Default::default(),
         depr_map: Default::default(),
+        implications: Default::default(),
     };
 
     {
@@ -637,6 +642,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
                     reason: Some(Symbol::intern(reason)),
                     issue: NonZeroU32::new(27812),
                     is_soft: false,
+                    implied_by: None,
                 },
                 feature: sym::rustc_private,
             };
@@ -667,6 +673,7 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         check_mod_unstable_api_usage,
         stability_index,
+        stability_implications: |tcx, _| tcx.stability().implications.clone(),
         lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
         lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
         lookup_deprecation_entry: |tcx, id| {
@@ -945,32 +952,51 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     remaining_lib_features.remove(&sym::libc);
     remaining_lib_features.remove(&sym::test);
 
-    let check_features = |remaining_lib_features: &mut FxIndexMap<_, _>, defined_features: &[_]| {
-        for &(feature, since) in defined_features {
-            if let Some(since) = since {
-                if let Some(span) = remaining_lib_features.get(&feature) {
-                    // Warn if the user has enabled an already-stable lib feature.
-                    unnecessary_stable_feature_lint(tcx, *span, feature, since);
-                }
-            }
-            remaining_lib_features.remove(&feature);
-            if remaining_lib_features.is_empty() {
-                break;
-            }
-        }
-    };
-
     // We always collect the lib features declared in the current crate, even if there are
     // no unknown features, because the collection also does feature attribute validation.
-    let local_defined_features = tcx.lib_features(()).to_vec();
-    if !remaining_lib_features.is_empty() {
-        check_features(&mut remaining_lib_features, &local_defined_features);
+    let local_defined_features = tcx.lib_features(());
+    let mut all_lib_features: FxHashMap<_, _> =
+        local_defined_features.to_vec().iter().map(|el| *el).collect();
+    let mut implications = tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone();
+    for &cnum in tcx.crates(()) {
+        implications.extend(tcx.stability_implications(cnum));
+        all_lib_features.extend(tcx.defined_lib_features(cnum).iter().map(|el| *el));
+    }
 
-        for &cnum in tcx.crates(()) {
+    // Check that every feature referenced by an `implied_by` exists (for features defined in the
+    // local crate).
+    for (implied_by, feature) in tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE) {
+        // Only `implied_by` needs to be checked, `feature` is guaranteed to exist.
+        if !all_lib_features.contains_key(implied_by) {
+            let span = local_defined_features
+                .stable
+                .get(feature)
+                .map(|(_, span)| span)
+                .or_else(|| local_defined_features.unstable.get(feature))
+                .expect("feature that implied another does not exist");
+            tcx.sess
+                .struct_span_err(
+                    *span,
+                    format!("feature `{implied_by}` implying `{feature}` does not exist"),
+                )
+                .emit();
+        }
+    }
+
+    if !remaining_lib_features.is_empty() {
+        for (feature, since) in all_lib_features.iter() {
+            if let Some(since) = since && let Some(span) = remaining_lib_features.get(&feature) {
+                // Warn if the user has enabled an already-stable lib feature.
+                if let Some(implies) = implications.get(&feature) {
+                    unnecessary_partially_stable_feature_lint(tcx, *span, *feature, *implies, *since);
+                } else {
+                    unnecessary_stable_feature_lint(tcx, *span, *feature, *since);
+                }
+            }
+            remaining_lib_features.remove(&feature);
             if remaining_lib_features.is_empty() {
                 break;
             }
-            check_features(&mut remaining_lib_features, tcx.defined_lib_features(cnum));
         }
     }
 
@@ -982,12 +1008,41 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     // don't lint about unused features. We should re-enable this one day!
 }
 
+fn unnecessary_partially_stable_feature_lint(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    feature: Symbol,
+    implies: Symbol,
+    since: Symbol,
+) {
+    tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
+        lint.build(&format!(
+            "the feature `{feature}` has been partially stabilized since {since} and is succeeded \
+             by the feature `{implies}`"
+        ))
+        .span_suggestion(
+            span,
+            &format!(
+                "if you are using features which are still unstable, change to using `{implies}`"
+            ),
+            implies,
+            Applicability::MaybeIncorrect,
+        )
+        .span_suggestion(
+            tcx.sess.source_map().span_extend_to_line(span),
+            "if you are using features which are now stable, remove this line",
+            "",
+            Applicability::MaybeIncorrect,
+        )
+        .emit();
+    });
+}
+
 fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) {
     tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
         lint.build(&format!(
-            "the feature `{}` has been stable since {} and no longer requires \
-                      an attribute to enable",
-            feature, since
+            "the feature `{feature}` has been stable since {since} and no longer requires an \
+             attribute to enable",
         ))
         .emit();
     });
index 54dd15270a136cd48b1b49dc36009cf82fe19c58..2b5eb12a8a890e39a26b902b8fa790856cdeaa45 100644 (file)
@@ -796,9 +796,16 @@ fn check_stability_and_deprecation(
     ) {
         let span = path.span;
         if let Some(stability) = &ext.stability {
-            if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
+            if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by } = stability.level
+            {
                 let feature = stability.feature;
-                if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
+
+                let is_allowed = |feature| {
+                    self.active_features.contains(&feature) || span.allows_unstable(feature)
+                };
+                let allowed_by_implication =
+                    implied_by.map(|feature| is_allowed(feature)).unwrap_or(false);
+                if !is_allowed(feature) && !allowed_by_implication {
                     let lint_buffer = &mut self.lint_buffer;
                     let soft_handler =
                         |lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);
index 01ff9e254f792c02f8d6561185813b4266bf8a5b..5d365fc5246287040e780d8f7fea1badf0c5cc7e 100644 (file)
@@ -1209,6 +1209,8 @@ pub(crate) fn parse_branch_protection(
     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],
index afbb88e92336049d30357fd4b322988a2d0177e0..b4a4424e876cdeb6e5178df20f6bb19d3831be88 100644 (file)
@@ -718,6 +718,11 @@ pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool)
         sp
     }
 
+    /// Extends the given `Span` to contain the entire line it is on.
+    pub fn span_extend_to_line(&self, sp: Span) -> Span {
+        self.span_extend_to_prev_char(self.span_extend_to_next_char(sp, '\n', true), '\n', true)
+    }
+
     /// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
     /// `c`.
     pub fn span_until_char(&self, sp: Span, c: char) -> Span {
index 3ccd3fcbafa2bafb5c4db93540e3689f6176dc58..2ac1ecfe87eb5f11820b3456149ecd5fab79f9dc 100644 (file)
         fabsf32,
         fabsf64,
         fadd_fast,
+        fake_variadic,
         fdiv_fast,
         feature,
         fence,
         impl_lint_pass,
         impl_macros,
         impl_trait_in_bindings,
+        implied_by,
         import,
         import_shadowing,
         imported_main,
         tuple,
         tuple_from_req,
         tuple_indexing,
-        tuple_variadic,
         two_phase,
         ty,
         type_alias_enum_variants,
index 6ca630b74cc79efcf1429ef49690de37fd4088d4..c2b2e3199511e403b8a3c39b1532f8ce679ac492 100644 (file)
@@ -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))
index 69f3f03cfa97c5a2c98538f4b8ddc44fc1cd078d..9497d5c4528cc9e85eb4b6c842e12c4a01b8f92b 100644 (file)
@@ -14,7 +14,7 @@
 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) {
index 3fb8e5080f3469868fca9fb11cb2201c19041da7..020aa95d0be215067415e1fe6cc59be7a4f9f597 100644 (file)
@@ -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();
index 41c38f558b6efb78a83b226a300439b60fe4ecda..8aa8ac90b4c56cae649bebcdd68e436c5392c810 100644 (file)
@@ -31,9 +31,7 @@
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::{self, Span};
-use rustc_trait_selection::traits::{
-    self, ObligationCauseCode, SelectionContext, StatementAsExpression,
-};
+use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
 use std::slice;
@@ -575,6 +573,8 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
             // 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.
@@ -1410,7 +1410,9 @@ pub(in super::super) fn check_block_with_expected(
                         &self.misc(sp),
                         &mut |err| {
                             if let Some(expected_ty) = expected.only_has_type(self) {
-                                self.consider_hint_about_removing_semicolon(blk, expected_ty, err);
+                                if !self.consider_removing_semicolon(blk, expected_ty, err) {
+                                    self.consider_returning_binding(blk, expected_ty, err);
+                                }
                                 if expected_ty == self.tcx.types.bool {
                                     // If this is caused by a missing `let` in a `while let`,
                                     // silence this redundant error, as we already emit E0070.
@@ -1478,42 +1480,6 @@ pub(in super::super) fn check_block_with_expected(
         ty
     }
 
-    /// A common error is to add an extra semicolon:
-    ///
-    /// ```compile_fail,E0308
-    /// fn foo() -> usize {
-    ///     22;
-    /// }
-    /// ```
-    ///
-    /// This routine checks if the final statement in a block is an
-    /// expression with an explicit semicolon whose type is compatible
-    /// with `expected_ty`. If so, it suggests removing the semicolon.
-    fn consider_hint_about_removing_semicolon(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-        err: &mut Diagnostic,
-    ) {
-        if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
-            if let StatementAsExpression::NeedsBoxing = boxed {
-                err.span_suggestion_verbose(
-                    span_semi,
-                    "consider removing this semicolon and boxing the expression",
-                    "",
-                    Applicability::HasPlaceholders,
-                );
-            } else {
-                err.span_suggestion_short(
-                    span_semi,
-                    "remove this semicolon",
-                    "",
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-    }
-
     fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
         let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id));
         match node {
@@ -1791,19 +1757,11 @@ fn point_at_type_arg_instead_of_call_if_possible(
                             .flat_map(|a| a.args.iter())
                         {
                             if let hir::GenericArg::Type(hir_ty) = &arg {
-                                if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
-                                    &hir_ty.kind
-                                {
-                                    // Avoid ICE with associated types. As this is best
-                                    // effort only, it's ok to ignore the case. It
-                                    // would trigger in `is_send::<T::AssocType>();`
-                                    // from `typeck-default-trait-impl-assoc-type.rs`.
-                                } else {
-                                    let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
-                                    let ty = self.resolve_vars_if_possible(ty);
-                                    if ty == predicate.self_ty() {
-                                        error.obligation.cause.span = hir_ty.span;
-                                    }
+                                let ty = self.resolve_vars_if_possible(
+                                    self.typeck_results.borrow().node_type(hir_ty.hir_id),
+                                );
+                                if ty == predicate.self_ty() {
+                                    error.obligation.cause.span = hir_ty.span;
                                 }
                             }
                         }
index 80feac184125c6afe67844723a220b2f1687727a..d5ee299c0f98d1f55b70d9721244539ab64edbc4 100644 (file)
@@ -3,6 +3,7 @@
 use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
 
 use rustc_ast::util::parser::ExprPrecedence;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind};
     Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
 };
 use rustc_infer::infer::{self, TyCtxtInferExt};
-use rustc_infer::traits;
+use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
+use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty, TypeVisitable};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
@@ -864,4 +865,156 @@ pub(crate) fn note_type_is_not_clone(
             );
         }
     }
+
+    /// A common error is to add an extra semicolon:
+    ///
+    /// ```compile_fail,E0308
+    /// fn foo() -> usize {
+    ///     22;
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the final statement in a block is an
+    /// expression with an explicit semicolon whose type is compatible
+    /// with `expected_ty`. If so, it suggests removing the semicolon.
+    pub(crate) fn consider_removing_semicolon(
+        &self,
+        blk: &'tcx hir::Block<'tcx>,
+        expected_ty: Ty<'tcx>,
+        err: &mut Diagnostic,
+    ) -> bool {
+        if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
+            if let StatementAsExpression::NeedsBoxing = boxed {
+                err.span_suggestion_verbose(
+                    span_semi,
+                    "consider removing this semicolon and boxing the expression",
+                    "",
+                    Applicability::HasPlaceholders,
+                );
+            } else {
+                err.span_suggestion_short(
+                    span_semi,
+                    "remove this semicolon",
+                    "",
+                    Applicability::MachineApplicable,
+                );
+            }
+            true
+        } else {
+            false
+        }
+    }
+
+    pub(crate) fn consider_returning_binding(
+        &self,
+        blk: &'tcx hir::Block<'tcx>,
+        expected_ty: Ty<'tcx>,
+        err: &mut Diagnostic,
+    ) {
+        let mut shadowed = FxHashSet::default();
+        let mut candidate_idents = vec![];
+        let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
+            if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
+                && let Some(pat_ty) = self.typeck_results.borrow().node_type_opt(*hir_id)
+            {
+                let pat_ty = self.resolve_vars_if_possible(pat_ty);
+                if self.can_coerce(pat_ty, expected_ty)
+                    && !(pat_ty, expected_ty).references_error()
+                    && shadowed.insert(ident.name)
+                {
+                    candidate_idents.push((*ident, pat_ty));
+                }
+            }
+            true
+        };
+
+        let hir = self.tcx.hir();
+        for stmt in blk.stmts.iter().rev() {
+            let StmtKind::Local(local) = &stmt.kind else { continue; };
+            local.pat.walk(&mut find_compatible_candidates);
+        }
+        match hir.find(hir.get_parent_node(blk.hir_id)) {
+            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
+                match hir.find(hir.get_parent_node(*hir_id)) {
+                    Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
+                        pat.walk(&mut find_compatible_candidates);
+                    }
+                    Some(
+                        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
+                        | hir::Node::ImplItem(hir::ImplItem {
+                            kind: hir::ImplItemKind::Fn(_, body),
+                            ..
+                        })
+                        | hir::Node::TraitItem(hir::TraitItem {
+                            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
+                            ..
+                        })
+                        | hir::Node::Expr(hir::Expr {
+                            kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
+                            ..
+                        }),
+                    ) => {
+                        for param in hir.body(*body).params {
+                            param.pat.walk(&mut find_compatible_candidates);
+                        }
+                    }
+                    Some(hir::Node::Expr(hir::Expr {
+                        kind:
+                            hir::ExprKind::If(
+                                hir::Expr { kind: hir::ExprKind::Let(let_), .. },
+                                then_block,
+                                _,
+                            ),
+                        ..
+                    })) if then_block.hir_id == *hir_id => {
+                        let_.pat.walk(&mut find_compatible_candidates);
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        match &candidate_idents[..] {
+            [(ident, _ty)] => {
+                let sm = self.tcx.sess.source_map();
+                if let Some(stmt) = blk.stmts.last() {
+                    let stmt_span = sm.stmt_span(stmt.span, blk.span);
+                    let sugg = if sm.is_multiline(blk.span)
+                        && let Some(spacing) = sm.indentation_before(stmt_span)
+                    {
+                        format!("\n{spacing}{ident}")
+                    } else {
+                        format!(" {ident}")
+                    };
+                    err.span_suggestion_verbose(
+                        stmt_span.shrink_to_hi(),
+                        format!("consider returning the local binding `{ident}`"),
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    let sugg = if sm.is_multiline(blk.span)
+                        && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
+                    {
+                        format!("\n{spacing}    {ident}\n{spacing}")
+                    } else {
+                        format!(" {ident} ")
+                    };
+                    let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
+                    err.span_suggestion_verbose(
+                        sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
+                        format!("consider returning the local binding `{ident}`"),
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            values if (1..3).contains(&values.len()) => {
+                let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
+                err.span_note(spans, "consider returning one of these bindings");
+            }
+            _ => {}
+        }
+    }
 }
index a2daf6886f1ec796390ff764e0e60fe8ef75af3a..9858cd8fa1970c5a5128c0981799a74e884c5448 100644 (file)
@@ -630,18 +630,19 @@ fn check_str_addition(
         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");
index 7a9b874b5e45643ae4e7992929cde3eea76e4b61..52aad636fd88ac887da8d5b229c7f94ae72c6d01 100644 (file)
@@ -219,8 +219,9 @@ fn check_item(&mut self, id: hir::ItemId) {
             | ty::RawPtr(_)
             | ty::Ref(..)
             | ty::Never
+            | ty::FnPtr(_)
             | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
-            ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
+            ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
index 6c3bb7229e51f1008b84f3bbcf536dc33cbce506..372141e0933f560600fdcbe7ac79ec8400170513 100644 (file)
@@ -2562,7 +2562,7 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
 
 macro_rules! maybe_tuple_doc {
     ($a:ident @ #[$meta:meta] $item:item) => {
-        #[doc(tuple_variadic)]
+        #[cfg_attr(not(bootstrap), doc(fake_variadic))]
         #[doc = "This trait is implemented for tuples up to twelve items long."]
         #[$meta]
         $item
index cf428e0b1cf1d729e5d8b4a1f3d10b3ce23a465a..5974562aced4ebee6c2742545792598c60d2f0cb 100644 (file)
@@ -900,7 +900,7 @@ fn hash<S: Hasher>(&self, state: &mut S) {
 
     macro_rules! maybe_tuple_doc {
         ($a:ident @ #[$meta:meta] $item:item) => {
-            #[doc(tuple_variadic)]
+            #[cfg_attr(not(bootstrap), doc(fake_variadic))]
             #[doc = "This trait is implemented for tuples up to twelve items long."]
             #[$meta]
             $item
index 147f04a3f125d7910ff23a4187ea05c72263d2a7..eb458f3866e63181394b48b5444f3a794ce67180 100644 (file)
@@ -2612,7 +2612,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
         /// Create an integer value from its representation as a byte array in
         /// big endian.
         ///
-        #[doc = $to_xe_bytes_doc]
+        #[doc = $from_xe_bytes_doc]
         ///
         /// # Examples
         ///
@@ -2641,7 +2641,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
         /// Create an integer value from its representation as a byte array in
         /// little endian.
         ///
-        #[doc = $to_xe_bytes_doc]
+        #[doc = $from_xe_bytes_doc]
         ///
         /// # Examples
         ///
@@ -2677,7 +2677,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
         /// [`from_be_bytes`]: Self::from_be_bytes
         /// [`from_le_bytes`]: Self::from_le_bytes
         ///
-        #[doc = $to_xe_bytes_doc]
+        #[doc = $from_xe_bytes_doc]
         ///
         /// # Examples
         ///
index 401c8159988bb7697c798106ea44f434ff5bb6d4..b8e5461640c0581ea4a242fb7724aea2140c01da 100644 (file)
@@ -996,7 +996,7 @@ impl<T> (T,) {}
 // Fake impl that's only really used for docs.
 #[cfg(doc)]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(tuple_variadic)]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
 /// This trait is implemented on arbitrary-length tuples.
 impl<T: Clone> Clone for (T,) {
     fn clone(&self) -> Self {
@@ -1007,7 +1007,7 @@ fn clone(&self) -> Self {
 // Fake impl that's only really used for docs.
 #[cfg(doc)]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(tuple_variadic)]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
 /// This trait is implemented on arbitrary-length tuples.
 impl<T: Copy> Copy for (T,) {
     // empty
@@ -1441,11 +1441,16 @@ mod prim_ref {}
 /// Note that all of this is not portable to platforms where function pointers and data pointers
 /// have different sizes.
 ///
-/// ### Traits
+/// ### Trait implementations
 ///
-/// Function pointers implement the following traits:
+/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
+/// function pointers of varying length. Note that this is a convenience notation to avoid
+/// repetitive documentation, not valid Rust syntax.
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
+/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
+/// may change:
 ///
-/// * [`Clone`]
 /// * [`PartialEq`]
 /// * [`Eq`]
 /// * [`PartialOrd`]
@@ -1454,15 +1459,50 @@ mod prim_ref {}
 /// * [`Pointer`]
 /// * [`Debug`]
 ///
+/// The following traits are implemented for function pointers with any number of arguments and
+/// any ABI. These traits have implementations that are automatically generated by the compiler,
+/// so are not limited by missing language features:
+///
+/// * [`Clone`]
+/// * [`Copy`]
+/// * [`Send`]
+/// * [`Sync`]
+/// * [`Unpin`]
+/// * [`UnwindSafe`]
+/// * [`RefUnwindSafe`]
+///
 /// [`Hash`]: hash::Hash
 /// [`Pointer`]: fmt::Pointer
+/// [`UnwindSafe`]: panic::UnwindSafe
+/// [`RefUnwindSafe`]: panic::RefUnwindSafe
 ///
-/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
-/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
-/// may change.
-///
-/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
-/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
-/// are specially known to the compiler.
+/// In addition, all *safe* function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`], because
+/// these traits are specially known to the compiler.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_fn {}
+
+// Required to make auto trait impls render.
+// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
+#[doc(hidden)]
+#[cfg(not(bootstrap))]
+impl<Ret, T> fn(T) -> Ret {}
+
+// Fake impl that's only really used for docs.
+#[cfg(doc)]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
+/// This trait is implemented on function pointers with any number of arguments.
+impl<Ret, T> Clone for fn(T) -> Ret {
+    fn clone(&self) -> Self {
+        loop {}
+    }
+}
+
+// Fake impl that's only really used for docs.
+#[cfg(doc)]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
+/// This trait is implemented on function pointers with any number of arguments.
+impl<Ret, T> Copy for fn(T) -> Ret {
+    // empty
+}
index 509854225c4f3e5be294702a5ebe6dcf75821478..62548b5fadd2eab0813622d1e03799765890e349 100644 (file)
@@ -1819,6 +1819,27 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
     hashee.hash(into);
 }
 
+// If this is a unary fn pointer, it adds a doc comment.
+// Otherwise, it hides the docs entirely.
+macro_rules! maybe_fnptr_doc {
+    (@ #[$meta:meta] $item:item) => {
+        #[doc(hidden)]
+        #[$meta]
+        $item
+    };
+    ($a:ident @ #[$meta:meta] $item:item) => {
+        #[cfg_attr(not(bootstrap), doc(fake_variadic))]
+        #[doc = "This trait is implemented for function pointers with up to twelve arguments."]
+        #[$meta]
+        $item
+    };
+    ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
+        #[doc(hidden)]
+        #[$meta]
+        $item
+    };
+}
+
 // FIXME(strict_provenance_magic): function pointers have buggy codegen that
 // necessitates casting to a usize to get the backend to do the right thing.
 // for now I will break AVR to silence *a billion* lints. We should probably
@@ -1827,51 +1848,72 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
 // Impls for function pointers
 macro_rules! fnptr_impls_safety_abi {
     ($FnTy: ty, $($Arg: ident),*) => {
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> PartialEq for $FnTy {
-            #[inline]
-            fn eq(&self, other: &Self) -> bool {
-                *self as usize == *other as usize
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> PartialEq for $FnTy {
+                #[inline]
+                fn eq(&self, other: &Self) -> bool {
+                    *self as usize == *other as usize
+                }
             }
         }
 
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> Eq for $FnTy {}
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> Eq for $FnTy {}
+        }
 
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> PartialOrd for $FnTy {
-            #[inline]
-            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-                (*self as usize).partial_cmp(&(*other as usize))
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> PartialOrd for $FnTy {
+                #[inline]
+                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+                    (*self as usize).partial_cmp(&(*other as usize))
+                }
             }
         }
 
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> Ord for $FnTy {
-            #[inline]
-            fn cmp(&self, other: &Self) -> Ordering {
-                (*self as usize).cmp(&(*other as usize))
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> Ord for $FnTy {
+                #[inline]
+                fn cmp(&self, other: &Self) -> Ordering {
+                    (*self as usize).cmp(&(*other as usize))
+                }
             }
         }
 
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> hash::Hash for $FnTy {
-            fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
-                state.write_usize(*self as usize)
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> hash::Hash for $FnTy {
+                fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
+                    state.write_usize(*self as usize)
+                }
             }
         }
 
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::pointer_fmt_inner(*self as usize, f)
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
+                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    fmt::pointer_fmt_inner(*self as usize, f)
+                }
             }
         }
 
-        #[stable(feature = "fnptr_impls", since = "1.4.0")]
-        impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::pointer_fmt_inner(*self as usize, f)
+        maybe_fnptr_doc! {
+            $($Arg)* @
+            #[stable(feature = "fnptr_impls", since = "1.4.0")]
+            impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
+                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    fmt::pointer_fmt_inner(*self as usize, f)
+                }
             }
         }
     }
@@ -1896,7 +1938,7 @@ macro_rules! fnptr_impls_args {
 }
 
 fnptr_impls_args! {}
-fnptr_impls_args! { A }
+fnptr_impls_args! { T }
 fnptr_impls_args! { A, B }
 fnptr_impls_args! { A, B, C }
 fnptr_impls_args! { A, B, C, D }
index b664b0bb866dbf0f4b1faa19681b8c470097aa56..d189e6400f1e87951c5ca8eb9166f192af9be3b1 100644 (file)
@@ -107,7 +107,7 @@ fn default() -> ($($T,)+) {
 // Otherwise, it hides the docs entirely.
 macro_rules! maybe_tuple_doc {
     ($a:ident @ #[$meta:meta] $item:item) => {
-        #[doc(tuple_variadic)]
+        #[cfg_attr(not(bootstrap), doc(fake_variadic))]
         #[doc = "This trait is implemented for tuples up to twelve items long."]
         #[$meta]
         $item
index a0297b4b2f524f783a535b16254730bb633aba59..057e47bfdd18aaa35b6f16841600595a89e36071 100644 (file)
@@ -131,7 +131,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
 // 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
         //
index bffbe802fd01e864ca2e3c476c85f04abc6a1421..8b1a06ee750fb0e84316d1452e682cdafb5c90f6 100644 (file)
@@ -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")
index e8d0132f4b98c57c954c0a67eb9ad6b69b83755b..b8959316de170e568de3fc7a366ed478158855dc 100644 (file)
@@ -1534,3 +1534,20 @@ fn read_large_dir() {
         entry.unwrap();
     }
 }
+
+/// Test the fallback for getting the metadata of files like hiberfil.sys that
+/// Windows holds a special lock on, preventing normal means of querying
+/// metadata. See #96980.
+///
+/// Note this fails in CI because `hiberfil.sys` does not actually exist there.
+/// Therefore it's marked as ignored.
+#[test]
+#[ignore]
+#[cfg(windows)]
+fn hiberfil_sys() {
+    let hiberfil = Path::new(r"C:\hiberfil.sys");
+    assert_eq!(true, hiberfil.try_exists().unwrap());
+    fs::symlink_metadata(hiberfil).unwrap();
+    fs::metadata(hiberfil).unwrap();
+    assert_eq!(true, hiberfil.exists());
+}
index a1df72a8a0480e7094e70ae7a9b0f7d94e320a6f..6fbaa42c76846b4576d323a9fff8c5552cbf47f7 100644 (file)
@@ -141,7 +141,6 @@ pub mod windows {}
 pub mod redox;
 #[cfg(target_os = "solaris")]
 pub mod solaris;
-
 #[cfg(target_os = "solid_asp3")]
 pub mod solid;
 #[cfg(target_os = "vxworks")]
index cef546487f327e8edb18653a1a1634ea075d34de..411cc0925c4b0869d0a303c95a7876cad872d8ac 100644 (file)
@@ -90,6 +90,7 @@ mod platform {
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "ios",
+    target_os = "watchos",
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd"
index 1d6083e66e172e2b5d712c1627525f9e583d2dce..cc3a8858793450a1bd0bc8ec58a359d220e7c80c 100644 (file)
@@ -12,6 +12,7 @@
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "watchos",
     target_os = "netbsd",
     target_os = "openbsd"
 ))]
@@ -30,6 +31,7 @@
     target_os = "freebsd",
     target_os = "ios",
     target_os = "macos",
+    target_os = "watchos",
     target_os = "netbsd",
     target_os = "openbsd"
 ))]
@@ -238,6 +240,7 @@ pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         target_os = "freebsd",
         target_os = "ios",
         target_os = "macos",
+        target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd"
     ))]
index 32e6430d3f62795d2d4ef0164c069cedf24f9394..ae4faf27b4d39b5b2a8336e80c5fc28ef9fef853 100644 (file)
@@ -36,7 +36,7 @@ pub struct UCred {
 ))]
 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 fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
     }
 }
 
-#[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;
index 42d79418cf78f81bbd204accfe10ed97e06ebb59..e63a2fc248eb0b0785c069fc4665fa3492afb9fe 100644 (file)
@@ -9,6 +9,7 @@
     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();
index 401c8159988bb7697c798106ea44f434ff5bb6d4..b8e5461640c0581ea4a242fb7724aea2140c01da 100644 (file)
@@ -996,7 +996,7 @@ impl<T> (T,) {}
 // Fake impl that's only really used for docs.
 #[cfg(doc)]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(tuple_variadic)]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
 /// This trait is implemented on arbitrary-length tuples.
 impl<T: Clone> Clone for (T,) {
     fn clone(&self) -> Self {
@@ -1007,7 +1007,7 @@ fn clone(&self) -> Self {
 // Fake impl that's only really used for docs.
 #[cfg(doc)]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(tuple_variadic)]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
 /// This trait is implemented on arbitrary-length tuples.
 impl<T: Copy> Copy for (T,) {
     // empty
@@ -1441,11 +1441,16 @@ mod prim_ref {}
 /// Note that all of this is not portable to platforms where function pointers and data pointers
 /// have different sizes.
 ///
-/// ### Traits
+/// ### Trait implementations
 ///
-/// Function pointers implement the following traits:
+/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
+/// function pointers of varying length. Note that this is a convenience notation to avoid
+/// repetitive documentation, not valid Rust syntax.
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
+/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
+/// may change:
 ///
-/// * [`Clone`]
 /// * [`PartialEq`]
 /// * [`Eq`]
 /// * [`PartialOrd`]
@@ -1454,15 +1459,50 @@ mod prim_ref {}
 /// * [`Pointer`]
 /// * [`Debug`]
 ///
+/// The following traits are implemented for function pointers with any number of arguments and
+/// any ABI. These traits have implementations that are automatically generated by the compiler,
+/// so are not limited by missing language features:
+///
+/// * [`Clone`]
+/// * [`Copy`]
+/// * [`Send`]
+/// * [`Sync`]
+/// * [`Unpin`]
+/// * [`UnwindSafe`]
+/// * [`RefUnwindSafe`]
+///
 /// [`Hash`]: hash::Hash
 /// [`Pointer`]: fmt::Pointer
+/// [`UnwindSafe`]: panic::UnwindSafe
+/// [`RefUnwindSafe`]: panic::RefUnwindSafe
 ///
-/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
-/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
-/// may change.
-///
-/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
-/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
-/// are specially known to the compiler.
+/// In addition, all *safe* function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`], because
+/// these traits are specially known to the compiler.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_fn {}
+
+// Required to make auto trait impls render.
+// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
+#[doc(hidden)]
+#[cfg(not(bootstrap))]
+impl<Ret, T> fn(T) -> Ret {}
+
+// Fake impl that's only really used for docs.
+#[cfg(doc)]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
+/// This trait is implemented on function pointers with any number of arguments.
+impl<Ret, T> Clone for fn(T) -> Ret {
+    fn clone(&self) -> Self {
+        loop {}
+    }
+}
+
+// Fake impl that's only really used for docs.
+#[cfg(doc)]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), doc(fake_variadic))]
+/// This trait is implemented on function pointers with any number of arguments.
+impl<Ret, T> Copy for fn(T) -> Ret {
+    // empty
+}
index 79964e2b2385fd24a732b551786682981846c4fe..a342f0f5e8597848fc6a2998bce3d62ba391842d 100644 (file)
@@ -151,7 +151,7 @@ fn clone() -> Vec<OsString> {
     }
 }
 
-#[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 @@ pub fn args() -> Args {
     // 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;
index 4d8391656a4dd6f1bd601875d067c1a5faa46b28..c9ba661c829fabe03506124a6f8ef522a40f9965 100644 (file)
@@ -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";
index 137ca3a763368dd92ab9204c39c534aed3a59754..30812dabb4e0dca3ed925240ca8fdd3c090d2314 100644 (file)
@@ -47,6 +47,7 @@
     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.
index 8b0bbd6a55c6bb2e7e8d4aebbb5a1f7509d8f842..7c8824694408c65d3fcc78970833d2b984876a55 100644 (file)
@@ -17,6 +17,7 @@
     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 @@
 #[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 @@ pub fn accessed(&self) -> io::Result<SystemTime> {
         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 @@ pub fn created(&self) -> io::Result<SystemTime> {
         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 @@ pub fn file_type(&self) -> io::Result<FileType> {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "linux",
         target_os = "emscripten",
         target_os = "android",
@@ -737,6 +742,7 @@ pub fn ino(&self) -> u64 {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "netbsd",
         target_os = "openbsd",
         target_os = "freebsd",
@@ -754,6 +760,7 @@ fn name_bytes(&self) -> &[u8] {
     #[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 @@ pub fn fsync(&self) -> io::Result<()> {
         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 @@ pub fn datasync(&self) -> io::Result<()> {
         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 @@ unsafe fn os_datasync(fd: c_int) -> c_int {
             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};
 
index 78f10f0534c031f8079c7236e9cc1a4f8db72dd2..abf27e7db78c7c0e30467e56289ede3c5f87e873 100644 (file)
@@ -37,6 +37,7 @@ pub const fn new() -> 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 @@ unsafe fn init(&mut self) {
     #[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 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
     #[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 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
     #[cfg(any(
         target_os = "macos",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "android",
         target_os = "espidf",
         target_os = "horizon"
index 34a023b02c4fe74e4ed5abd41a5a0cfaf997b6a9..3d0d91460f706229f4aa8ea786e926e22f874af8 100644 (file)
@@ -86,6 +86,7 @@ unsafe fn sanitize_standard_fds() {
             // 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 @@ pub fn abort_internal() -> ! {
         // 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")]
index 7252ad321844bd3b72c3e033cbe87b093f4c7e2e..46545a0839fe8b416a7cd17a8f57058d34f0f360 100644 (file)
@@ -61,7 +61,7 @@
     )]
     #[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 @@ unsafe fn fallback() -> Option<OsString> {
     #[cfg(not(any(
         target_os = "android",
         target_os = "ios",
+        target_os = "watchos",
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
index 56d01074c20edc69626e012367107b4d2544e33f..bf49204881d1643ef95ce45ca4f990698a88344f 100644 (file)
@@ -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 @@ pub fn fill_bytes(v: &mut [u8]) {
 // 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;
index d191e1fe7a650ffe0be849958ceac2f5b61c0f59..6533625876f8911de7643baf9a2ac78b70b2b950 100644 (file)
@@ -139,7 +139,7 @@ pub fn set_name(name: &CStr) {
         }
     }
 
-    #[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());
index 9f4d4f7e736e8af5712a689035c2fdeae427edbf..ca1a7138fded27f0b14f1c99c6f3fc0d0e501dc0 100644 (file)
@@ -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 @@ pub unsafe fn new(parker: *mut Parker) {
             if #[cfg(any(
                 target_os = "macos",
                 target_os = "ios",
+                target_os = "watchos",
                 target_os = "l4re",
                 target_os = "android",
                 target_os = "redox"
index d114af49d26c7154537ea0d53f9ca8041297308d..dff973f59d1a7dbbaedef118a4ff71aeadae1730 100644 (file)
@@ -141,7 +141,7 @@ fn from(t: libc::timespec) -> 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 @@ fn info_from_bits(bits: u64) -> mach_timebase_info {
     }
 }
 
-#[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;
index e9b1006907741a88ea82ae0aaeb4ae1284bd65d4..4d3162f1254628e6560265c95c387dcb263ea395 100644 (file)
@@ -155,22 +155,7 @@ pub fn file_type(&self) -> io::Result<FileType> {
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        Ok(FileAttr {
-            attributes: self.data.dwFileAttributes,
-            creation_time: self.data.ftCreationTime,
-            last_access_time: self.data.ftLastAccessTime,
-            last_write_time: self.data.ftLastWriteTime,
-            file_size: ((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64),
-            reparse_tag: if self.data.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
-                // reserved unless this is a reparse point
-                self.data.dwReserved0
-            } else {
-                0
-            },
-            volume_serial_number: None,
-            number_of_links: None,
-            file_index: None,
-        })
+        Ok(self.data.into())
     }
 }
 
@@ -879,6 +864,26 @@ pub fn file_index(&self) -> Option<u64> {
         self.file_index
     }
 }
+impl From<c::WIN32_FIND_DATAW> for FileAttr {
+    fn from(wfd: c::WIN32_FIND_DATAW) -> Self {
+        FileAttr {
+            attributes: wfd.dwFileAttributes,
+            creation_time: wfd.ftCreationTime,
+            last_access_time: wfd.ftLastAccessTime,
+            last_write_time: wfd.ftLastWriteTime,
+            file_size: ((wfd.nFileSizeHigh as u64) << 32) | (wfd.nFileSizeLow as u64),
+            reparse_tag: if wfd.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+                // reserved unless this is a reparse point
+                wfd.dwReserved0
+            } else {
+                0
+            },
+            volume_serial_number: None,
+            number_of_links: None,
+            file_index: None,
+        }
+    }
+}
 
 fn to_u64(ft: &c::FILETIME) -> u64 {
     (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32)
@@ -1145,22 +1150,73 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
 }
 
 pub fn stat(path: &Path) -> io::Result<FileAttr> {
-    let mut opts = OpenOptions::new();
-    // No read or write permissions are necessary
-    opts.access_mode(0);
-    // This flag is so we can open directories too
-    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
-    let file = File::open(path, &opts)?;
-    file.file_attr()
+    metadata(path, ReparsePoint::Follow)
 }
 
 pub fn lstat(path: &Path) -> io::Result<FileAttr> {
+    metadata(path, ReparsePoint::Open)
+}
+
+#[repr(u32)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+enum ReparsePoint {
+    Follow = 0,
+    Open = c::FILE_FLAG_OPEN_REPARSE_POINT,
+}
+impl ReparsePoint {
+    fn as_flag(self) -> u32 {
+        self as u32
+    }
+}
+
+fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
     let mut opts = OpenOptions::new();
     // No read or write permissions are necessary
     opts.access_mode(0);
-    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT);
-    let file = File::open(path, &opts)?;
-    file.file_attr()
+    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | reparse.as_flag());
+
+    // Attempt to open the file normally.
+    // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileW`.
+    // If the fallback fails for any reason we return the original error.
+    match File::open(path, &opts) {
+        Ok(file) => file.file_attr(),
+        Err(e) if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {
+            // `ERROR_SHARING_VIOLATION` will almost never be returned.
+            // Usually if a file is locked you can still read some metadata.
+            // However, there are special system files, such as
+            // `C:\hiberfil.sys`, that are locked in a way that denies even that.
+            unsafe {
+                let path = maybe_verbatim(path)?;
+
+                // `FindFirstFileW` accepts wildcard file names.
+                // Fortunately wildcards are not valid file names and
+                // `ERROR_SHARING_VIOLATION` means the file exists (but is locked)
+                // therefore it's safe to assume the file name given does not
+                // include wildcards.
+                let mut wfd = mem::zeroed();
+                let handle = c::FindFirstFileW(path.as_ptr(), &mut wfd);
+
+                if handle == c::INVALID_HANDLE_VALUE {
+                    // This can fail if the user does not have read access to the
+                    // directory.
+                    Err(e)
+                } else {
+                    // We no longer need the find handle.
+                    c::FindClose(handle);
+
+                    // `FindFirstFileW` reads the cached file information from the
+                    // directory. The downside is that this metadata may be outdated.
+                    let attrs = FileAttr::from(wfd);
+                    if reparse == ReparsePoint::Follow && attrs.file_type().is_symlink() {
+                        Err(e)
+                    } else {
+                        Ok(attrs)
+                    }
+                }
+            }
+        }
+        Err(e) => Err(e),
+    }
 }
 
 pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
index f5730a2cea52b5b4c469428f8fe156990b66c9bc..c13bda328232041d655a40f0182f2ae49b43d4bd 100644 (file)
@@ -18,7 +18,7 @@
 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;
index 7b78bda424bb02a14fa019d47ae115cf768a9fae..a5b6193b086fbf44aef522205179d07a7abefdcc 100644 (file)
@@ -30,10 +30,10 @@ pub enum _Unwind_Reason_Code {
 #[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 @@ pub enum _Unwind_Context {}
 }
 
 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)]
index 1aa79f5566aa68624d29db0e5a8e6532ef2956f5..575cbc3beb2e7cf2e6b976d560e5180134a0f008 100644 (file)
@@ -1468,45 +1468,39 @@ pub fn cargo(
             rustflags.arg("-Zunstable-options");
         }
 
-        // FIXME(Urgau): This a hack as it shouldn't be gated on stage 0 but until `rustc_llvm`
-        // is made to work with `--check-cfg` which is currently not easly possible until cargo
-        // get some support for setting `--check-cfg` within build script, it's the least invasive
-        // hack that still let's us have cfg checking for the vast majority of the codebase.
-        if stage != 0 {
-            // Enable cfg checking of cargo features for everything but std and also enable cfg
-            // checking of names and values.
-            //
-            // Note: `std`, `alloc` and `core` imports some dependencies by #[path] (like
-            // backtrace, core_simd, std_float, ...), those dependencies have their own
-            // features but cargo isn't involved in the #[path] process and so cannot pass the
-            // complete list of features, so for that reason we don't enable checking of
-            // features for std crates.
-            cargo.arg(if mode != Mode::Std {
-                "-Zcheck-cfg=names,values,features"
-            } else {
-                "-Zcheck-cfg=names,values"
-            });
+        // Enable cfg checking of cargo features for everything but std and also enable cfg
+        // checking of names and values.
+        //
+        // Note: `std`, `alloc` and `core` imports some dependencies by #[path] (like
+        // backtrace, core_simd, std_float, ...), those dependencies have their own
+        // features but cargo isn't involved in the #[path] process and so cannot pass the
+        // complete list of features, so for that reason we don't enable checking of
+        // features for std crates.
+        cargo.arg(if mode != Mode::Std {
+            "-Zcheck-cfg=names,values,output,features"
+        } else {
+            "-Zcheck-cfg=names,values,output"
+        });
 
-            // Add extra cfg not defined in/by rustc
-            //
-            // Note: Altrough it would seems that "-Zunstable-options" to `rustflags` is useless as
-            // cargo would implicitly add it, it was discover that sometimes bootstrap only use
-            // `rustflags` without `cargo` making it required.
-            rustflags.arg("-Zunstable-options");
-            for (restricted_mode, name, values) in EXTRA_CHECK_CFGS {
-                if *restricted_mode == None || *restricted_mode == Some(mode) {
-                    // Creating a string of the values by concatenating each value:
-                    // ',"tvos","watchos"' or '' (nothing) when there are no values
-                    let values = match values {
-                        Some(values) => values
-                            .iter()
-                            .map(|val| [",", "\"", val, "\""])
-                            .flatten()
-                            .collect::<String>(),
-                        None => String::new(),
-                    };
-                    rustflags.arg(&format!("--check-cfg=values({name}{values})"));
-                }
+        // Add extra cfg not defined in/by rustc
+        //
+        // Note: Altrough it would seems that "-Zunstable-options" to `rustflags` is useless as
+        // cargo would implicitly add it, it was discover that sometimes bootstrap only use
+        // `rustflags` without `cargo` making it required.
+        rustflags.arg("-Zunstable-options");
+        for (restricted_mode, name, values) in EXTRA_CHECK_CFGS {
+            if *restricted_mode == None || *restricted_mode == Some(mode) {
+                // Creating a string of the values by concatenating each value:
+                // ',"tvos","watchos"' or '' (nothing) when there are no values
+                let values = match values {
+                    Some(values) => values
+                        .iter()
+                        .map(|val| [",", "\"", val, "\""])
+                        .flatten()
+                        .collect::<String>(),
+                    None => String::new(),
+                };
+                rustflags.arg(&format!("--check-cfg=values({name}{values})"));
             }
         }
 
index 23af7d2ef1e2494173da3bc657f0469784c12d5e..ce10ca9aa3df434e90a76ff035f440787bd41578 100644 (file)
@@ -506,8 +506,8 @@ pub(crate) fn build_impl(
             for_,
             items: trait_items,
             polarity,
-            kind: if utils::has_doc_flag(tcx, did, sym::tuple_variadic) {
-                ImplKind::TupleVaradic
+            kind: if utils::has_doc_flag(tcx, did, sym::fake_variadic) {
+                ImplKind::FakeVaradic
             } else {
                 ImplKind::Normal
             },
index 671b40dbfe66df3e34f30ecd597e5464ec6b3fa8..9865601da5fc7f5b9aca672a0accebe0549507d2 100644 (file)
@@ -2037,8 +2037,8 @@ fn clean_impl<'tcx>(
             for_,
             items,
             polarity: tcx.impl_polarity(def_id),
-            kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::tuple_variadic) {
-                ImplKind::TupleVaradic
+            kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) {
+                ImplKind::FakeVaradic
             } else {
                 ImplKind::Normal
             },
index d29ba2dedaf717260094c80e9b54c62e5df03d13..8c08f77667904769c4a855f9f7ae5cd06bccda90 100644 (file)
@@ -1841,7 +1841,7 @@ pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
                 Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
                 // FIXME: This will be wrong if we ever add inherent impls
                 // for function pointers.
-                Fn => ArrayVec::new(),
+                Fn => single(FunctionSimplifiedType(1)),
                 Never => single(NeverSimplifiedType),
             }
         })
@@ -2394,7 +2394,7 @@ pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol
 pub(crate) enum ImplKind {
     Normal,
     Auto,
-    TupleVaradic,
+    FakeVaradic,
     Blanket(Box<Type>),
 }
 
@@ -2407,8 +2407,8 @@ pub(crate) fn is_blanket(&self) -> bool {
         matches!(self, ImplKind::Blanket(_))
     }
 
-    pub(crate) fn is_tuple_variadic(&self) -> bool {
-        matches!(self, ImplKind::TupleVaradic)
+    pub(crate) fn is_fake_variadic(&self) -> bool {
+        matches!(self, ImplKind::FakeVaradic)
     }
 
     pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
index 9f46ab54d3ece10c27fad80c6e3e8df2763e3017..36a47b05cb9d674b0dadd2a817fac9e35bdf7c3b 100644 (file)
@@ -1165,10 +1165,43 @@ pub(crate) fn print<'a, 'tcx: 'a>(
 
             if let clean::Type::Tuple(types) = &self.for_ &&
                 let [clean::Type::Generic(name)] = &types[..] &&
-                (self.kind.is_tuple_variadic() || self.kind.is_auto()) {
+                (self.kind.is_fake_variadic() || self.kind.is_auto())
+            {
                 // Hardcoded anchor library/core/src/primitive_docs.rs
                 // Link should match `# Trait implementations`
                 primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?;
+            } else if let clean::BareFunction(bare_fn) = &self.for_ &&
+                let [clean::Argument { type_: clean::Type::Generic(name), .. }] = &bare_fn.decl.inputs.values[..] &&
+                (self.kind.is_fake_variadic() || self.kind.is_auto())
+            {
+                // Hardcoded anchor library/core/src/primitive_docs.rs
+                // Link should match `# Trait implementations`
+
+                let hrtb = bare_fn.print_hrtb_with_space(cx);
+                let unsafety = bare_fn.unsafety.print_with_space();
+                let abi = print_abi_with_space(bare_fn.abi);
+                if f.alternate() {
+                    write!(
+                        f,
+                        "{hrtb:#}{unsafety}{abi:#}",
+                    )?;
+                } else {
+                    write!(
+                        f,
+                        "{hrtb}{unsafety}{abi}",
+                    )?;
+                }
+                let ellipsis = if bare_fn.decl.c_variadic {
+                    ", ..."
+                } else {
+                    ""
+                };
+                primitive_link_fragment(f, PrimitiveType::Tuple, &format!("fn ({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), "#trait-implementations-1", cx)?;
+                // Write output.
+                if let clean::FnRetTy::Return(ty) = &bare_fn.decl.output {
+                    write!(f, " -> ")?;
+                    fmt_type(ty, f, use_absolute, cx)?;
+                }
             } else if let Some(ty) = self.kind.as_blanket_ty() {
                 fmt_type(ty, f, use_absolute, cx)?;
             } else {
index 2598b9b0b28c20e982287ac7ee0eca48d972d056..9000ab472d96e43983f70ae1743e8ac895b69317 100644 (file)
@@ -574,7 +574,7 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
         // FIXME: use something like ImplKind in JSON?
         let (synthetic, blanket_impl) = match kind {
-            clean::ImplKind::Normal | clean::ImplKind::TupleVaradic => (false, None),
+            clean::ImplKind::Normal | clean::ImplKind::FakeVaradic => (false, None),
             clean::ImplKind::Auto => (true, None),
             clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
         };
diff --git a/src/test/codegen/noalias-box-off.rs b/src/test/codegen/noalias-box-off.rs
new file mode 100644 (file)
index 0000000..afd17c7
--- /dev/null
@@ -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 (file)
index 0000000..a3d1f09
--- /dev/null
@@ -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>) {}
index 11ce2dbe280500f201178295801dda910d0f1668..505de53481f85c9c11453cf650cfd41b24428876 100644 (file)
@@ -3,13 +3,13 @@
 trait Mine {}
 
 // This one is fine
-#[doc(tuple_variadic)]
+#[doc(fake_variadic)]
 impl<T> Mine for (T,) {}
 
 trait Mine2 {}
 
 // This one is not
-#[doc(tuple_variadic)] //~ ERROR
+#[doc(fake_variadic)] //~ ERROR
 impl<T, U> Mine for (T,U) {}
 
 fn main() {}
index 358d06d6a42dd4a5028eea021d2c83a5e3b9b4f5..d127fb858d176d303adfd5677956c9278f58e625 100644 (file)
@@ -1,8 +1,8 @@
-error: `#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity
+error: `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
   --> $DIR/tuple-variadic-check.rs:12:7
    |
-LL | #[doc(tuple_variadic)]
-   |       ^^^^^^^^^^^^^^
+LL | #[doc(fake_variadic)]
+   |       ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 7296b35788a9d019c08be4586ae3803dd49394f3..6f5248f5b18ce3ea364701aca366c7a20e4a5741 100644 (file)
@@ -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
index 71b0b07700958967dcec531d4233833c133260bb..a2fbbf078d5178468408174845ce1dfe99d1ea88 100644 (file)
@@ -16,7 +16,7 @@
 // @has - '//h2[@id="trait-implementations-1"]' 'Trait implementations'
 /// # Trait implementations
 ///
-/// This header is hard-coded in the HTML format linking for `#[doc(tuple_variadics)]`.
+/// This header is hard-coded in the HTML format linking for `#[doc(fake_variadics)]`.
 /// To make sure it gets linked correctly, we need to make sure the hardcoded anchor
 /// in the code matches what rustdoc generates for the header.
 mod tuple_prim {}
index 4fd6254f6740d0a2e8545445fb732b228023c2ee..db7cfd60c71a67e3dc8ab4d993d902fe21277700 100644 (file)
@@ -7,12 +7,12 @@ pub trait Foo {}
 
 // @has foo/trait.Foo.html
 // @has - '//section[@id="impl-Foo-for-(T%2C)"]/h3' 'impl<T> Foo for (T₁, T₂, …, Tₙ)'
-#[doc(tuple_variadic)]
+#[doc(fake_variadic)]
 impl<T> Foo for (T,) {}
 
 pub trait Bar {}
 
 // @has foo/trait.Bar.html
 // @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
-#[doc(tuple_variadic)]
+#[doc(fake_variadic)]
 impl<U: Foo> Bar for (U,) {}
diff --git a/src/test/ui/argument-suggestions/issue-99482.rs b/src/test/ui/argument-suggestions/issue-99482.rs
new file mode 100644 (file)
index 0000000..731b863
--- /dev/null
@@ -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 (file)
index 0000000..bc005e8
--- /dev/null
@@ -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`.
index e5887689690e76fd5066d2193ae5613782cfe0b2..ada6e357aea5ee7f17633dc7a2b3bf4b2999b9ae 100644 (file)
@@ -18,6 +18,14 @@ LL | |             break 0u8;
 LL | |         };
    | |_________- enclosing `async` block
 
+error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
+  --> $DIR/async-block-control-flow-static-semantics.rs:26:39
+   |
+LL |     let _: &dyn Future<Output = ()> = &block;
+   |                                       ^^^^^^ expected `()`, found `u8`
+   |
+   = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
+
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:21:58
    |
@@ -32,7 +40,7 @@ LL | | }
    | |_^ expected `u8`, found `()`
 
 error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
-  --> $DIR/async-block-control-flow-static-semantics.rs:26:39
+  --> $DIR/async-block-control-flow-static-semantics.rs:17:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
@@ -47,14 +55,6 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0271]: type mismatch resolving `<impl Future<Output = u8> as Future>::Output == ()`
-  --> $DIR/async-block-control-flow-static-semantics.rs:17:39
-   |
-LL |     let _: &dyn Future<Output = ()> = &block;
-   |                                       ^^^^^^ expected `()`, found `u8`
-   |
-   = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
-
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:47:44
    |
diff --git a/src/test/ui/const-generics/issues/issue-71547.rs b/src/test/ui/const-generics/issues/issue-71547.rs
new file mode 100644 (file)
index 0000000..60776a1
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+pub trait GetType<const N: &'static str> {
+    type Ty;
+    fn get(&self) -> &Self::Ty;
+}
+
+pub fn get_val<T>(value: &T) -> &T::Ty
+where
+    T: GetType<"hello">,
+{
+    value.get()
+}
+
+fn main() {}
index 542911537be7e62300fd979466d67273937e5a42..21fe663f06706da81320fc90a42ca695edc2ca0a 100644 (file)
@@ -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 { }
index aaef8113b8ae243bd7ea3a78be5aafe005faf4fa..a61ba7bbf328cee6aaaa5efde5e4e9125ec9f048 100644 (file)
@@ -1,4 +1,4 @@
-impl fn(u8) { //~ ERROR E0118
+impl<T> T { //~ ERROR E0118
     fn get_state(&self) -> String {
        String::new()
     }
index 296fb5d664a227308b5341cc8df579997e971328..8c6fa7947a8537746be07f1c35f7d2eaf8881367 100644 (file)
@@ -1,8 +1,8 @@
 error[E0118]: no nominal type found for inherent implementation
-  --> $DIR/E0118.rs:1:6
+  --> $DIR/E0118.rs:1:9
    |
-LL | impl fn(u8) {
-   |      ^^^^^^ impl requires a nominal type
+LL | impl<T> T {
+   |         ^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
index 4eb59a053b45b50f289b871ab8da398d54135f0b..507483dec2ee263c1b99c3ecda0946131774b5b4 100644 (file)
@@ -4,5 +4,7 @@ struct Foo {
 
 impl *mut Foo {} //~ ERROR E0390
 
+impl fn(Foo) {} //~ ERROR E0390
+
 fn main() {
 }
index e635d4ec196a271351a9dd1d8b52c68f2dc4077d..0e5a9ca762b768ff2bde803695dfcac6697a9108 100644 (file)
@@ -6,6 +6,14 @@ LL | impl *mut Foo {}
    |
    = help: consider using an extension trait instead
 
-error: aborting due to previous error
+error[E0390]: cannot define inherent `impl` for primitive types
+  --> $DIR/E0390.rs:7:6
+   |
+LL | impl fn(Foo) {}
+   |      ^^^^^^^
+   |
+   = help: consider using an extension trait instead
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0390`.
index 6a144412d0751541c914963d464d2bd25a6330dd..58306a4cfc9c9d03e342167e0d044c3cef27029f 100644 (file)
@@ -4,7 +4,7 @@ mod foo {}
 
 trait Mine {}
 
-#[doc(tuple_variadic)]  //~ ERROR: `#[doc(tuple_variadic)]` is meant for internal use only
+#[doc(fake_variadic)]  //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only
 impl<T> Mine for (T,) {}
 
 fn main() {}
index 9fe08afd4f05e116501cecad567b092e2fd109c6..c4272a2c04c2ae5d46e7cea98de233bda0cab7e0 100644 (file)
@@ -7,11 +7,11 @@ LL | #[doc(keyword = "match")]
    = note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
    = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
 
-error[E0658]: `#[doc(tuple_variadic)]` is meant for internal use only
+error[E0658]: `#[doc(fake_variadic)]` is meant for internal use only
   --> $DIR/feature-gate-rustdoc_internals.rs:7:1
    |
-LL | #[doc(tuple_variadic)]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL | #[doc(fake_variadic)]
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
    = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
diff --git a/src/test/ui/foreign/issue-99276-same-type-lifetimes.rs b/src/test/ui/foreign/issue-99276-same-type-lifetimes.rs
new file mode 100644 (file)
index 0000000..fce603c
--- /dev/null
@@ -0,0 +1,24 @@
+// Check that we do not ICE when structurally comparing types with lifetimes present.
+// check-pass
+
+pub struct Record<'a> {
+    pub args: &'a [(usize, &'a str)],
+}
+
+mod a {
+    extern "Rust" {
+        fn foo<'a, 'b>(record: &'a super::Record<'b>);
+
+        fn bar<'a, 'b>(record: &'a super::Record<'b>);
+    }
+}
+
+mod b {
+    extern "Rust" {
+        fn foo<'a, 'b>(record: &'a super::Record<'b>);
+
+        fn bar<'a, 'b>(record: &'a super::Record<'b>);
+    }
+}
+
+fn main() {}
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 (file)
index 0000000..bebd828
--- /dev/null
@@ -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 (file)
index 0000000..c1e4b82
--- /dev/null
@@ -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 (file)
index 0000000..1d75f60
--- /dev/null
@@ -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 (file)
index 0000000..b35d580
--- /dev/null
@@ -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`.
index d29a82f76a7938fcf6eb6c7d2ab55a851829e74f..b05579f216620d7b1635f5bc389d102f8f2add7a 100644 (file)
@@ -6,7 +6,7 @@
 
 impl Foo for Concrete {
     type Item = Concrete;
-    //~^ mismatched types
+    //~^ type mismatch resolving
 }
 
 impl Bar for Concrete {
index a25f0cd87616bee717ceff3add5b2b288f50af5e..f0dceb1b11a5ddbc245e48747f02fffc9c6bc6e5 100644 (file)
@@ -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`.
index 76a47c49bbafb40be760823fffec771f98d4fc3d..7ce3dedaa887bf7f6a777d0444967c2f1412eff8 100644 (file)
@@ -96,13 +96,13 @@ LL |     assert_eq!(Foo::Bar, i);
    = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
    = help: the following other types implement trait `Debug`:
              extern "C" fn() -> Ret
-             extern "C" fn(A) -> Ret
-             extern "C" fn(A, ...) -> Ret
              extern "C" fn(A, B) -> Ret
              extern "C" fn(A, B, ...) -> Ret
              extern "C" fn(A, B, C) -> Ret
              extern "C" fn(A, B, C, ...) -> Ret
              extern "C" fn(A, B, C, D) -> Ret
+             extern "C" fn(A, B, C, D, ...) -> Ret
+             extern "C" fn(A, B, C, D, E) -> Ret
            and 68 others
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 1c61c85368be9e9f5626eb784e40d22ef52bf470..025a5008d0f11f0d1aacfb8d041554be1dd149fc 100644 (file)
@@ -91,10 +91,10 @@ LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
 
 error[E0277]: the trait bound `Box<dyn Dummy>: Copy` is not satisfied
-  --> $DIR/kindck-copy.rs:42:5
+  --> $DIR/kindck-copy.rs:42:19
    |
 LL |     assert_copy::<Box<dyn Dummy>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy>`
+   |                   ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy>`
    |
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
@@ -103,10 +103,10 @@ LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
 
 error[E0277]: the trait bound `Box<dyn Dummy + Send>: Copy` is not satisfied
-  --> $DIR/kindck-copy.rs:43:5
+  --> $DIR/kindck-copy.rs:43:19
    |
 LL |     assert_copy::<Box<dyn Dummy + Send>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy + Send>`
+   |                   ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<dyn Dummy + Send>`
    |
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
diff --git a/src/test/ui/lint/auxiliary/add-impl.rs b/src/test/ui/lint/auxiliary/add-impl.rs
new file mode 100644 (file)
index 0000000..9d0e306
--- /dev/null
@@ -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 (file)
index 0000000..c2efbf5
--- /dev/null
@@ -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();
+}
index 95070322bddef1e812b3476debf9589d87cd045f..ddbdbdb0fd043eb0f5655c7545eaac7a94a03621 100644 (file)
@@ -5,6 +5,11 @@ LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
    |    -              ^^^^^ expected `isize`, found `()`
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+help: consider returning the local binding `a`
+   |
+LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a }
+   |                                                           +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/meta-variable-depth-outside-repeat.rs b/src/test/ui/macros/meta-variable-depth-outside-repeat.rs
new file mode 100644 (file)
index 0000000..b7fb947
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(macro_metavar_expr)]
+
+macro_rules! metavar {
+    ( $i:expr ) => {
+        ${length(0)}
+        //~^ ERROR meta-variable expression `length` with depth parameter must be called inside of a macro repetition
+    };
+}
+
+const _: i32 = metavar!(0);
+
+fn main() {}
diff --git a/src/test/ui/macros/meta-variable-depth-outside-repeat.stderr b/src/test/ui/macros/meta-variable-depth-outside-repeat.stderr
new file mode 100644 (file)
index 0000000..fad150c
--- /dev/null
@@ -0,0 +1,8 @@
+error: meta-variable expression `length` with depth parameter must be called inside of a macro repetition
+  --> $DIR/meta-variable-depth-outside-repeat.rs:5:10
+   |
+LL |         ${length(0)}
+   |          ^^^^^^^^^^^
+
+error: aborting due to previous error
+
index d81c8628bab26797343d1488c1d44131eefe97b5..6a0d68bd6b16a73ffb060d55f71ea384cc8a7803 100644 (file)
@@ -5,7 +5,7 @@ macro_rules! a {
         (
             ${count(foo, 0)},
             ${count(foo, 10)},
-            //~^ ERROR count depth must be less than 4
+            //~^ ERROR depth parameter on meta-variable expression `count` must be less than 4
         )
     };
 }
@@ -17,7 +17,7 @@ macro_rules! b {
                 ${ignore(foo)}
                 ${index(0)},
                 ${index(10)},
-                //~^ ERROR index depth must be less than 3
+                //~^ ERROR depth parameter on meta-variable expression `index` must be less than 3
             )* )* )*
         )
     };
@@ -30,15 +30,14 @@ macro_rules! c {
                 ${ignore(foo)}
                 ${length(0)}
                 ${length(10)}
-                //~^ ERROR length depth must be less than 2
+                //~^ ERROR depth parameter on meta-variable expression `length` must be less than 2
             )* )*
         )
     };
 }
 
-
 fn main() {
     a!( { [ (a) ] [ (b c) ] } );
     b!( { [ a b ] } );
-    c!( { a } );
+    c!({ a });
 }
index 7474c03c0f98ba31e613ef34c397deb72bcdb0d7..236122b6465b2cdfe9f8ab960d1187c2a89a9c1d 100644 (file)
@@ -1,16 +1,16 @@
-error: count depth must be less than 4
+error: depth parameter on meta-variable expression `count` must be less than 4
   --> $DIR/out-of-bounds-arguments.rs:7:14
    |
 LL |             ${count(foo, 10)},
    |              ^^^^^^^^^^^^^^^^
 
-error: index depth must be less than 3
+error: depth parameter on meta-variable expression `index` must be less than 3
   --> $DIR/out-of-bounds-arguments.rs:19:18
    |
 LL |                 ${index(10)},
    |                  ^^^^^^^^^^^
 
-error: length depth must be less than 2
+error: depth parameter on meta-variable expression `length` must be less than 2
   --> $DIR/out-of-bounds-arguments.rs:32:18
    |
 LL |                 ${length(10)}
index 3e54df12376ba6cd30a6b9e5fa3b5ac033b794d4..2cd51a439988db0102d10499e56f5e6aad70064b 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
-  --> $DIR/not-panic-safe.rs:8:5
+  --> $DIR/not-panic-safe.rs:8:14
    |
 LL |     assert::<&mut i32>();
-   |     ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
+   |              -^^^^^^^
+   |              |
+   |              `&mut i32` may not be safely transferred across an unwind boundary
+   |              help: consider removing the leading `&`-reference
    |
    = help: the trait `UnwindSafe` is not implemented for `&mut i32`
    = note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
index c2954868f78e4b00504f07eacfa25a071e18df43..8ff14fb1f304aee283b93b1bf8256a9d90c1ad83 100644 (file)
@@ -27,7 +27,7 @@ trait X {
     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 @@ extern "C" fn ft4() {}
         //~| 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 {
index 75d27c614e2028192f063c6179f8bae2b956001d..bc51ba8b8c5c51971799f77b3dea857c71f7243d 100644 (file)
@@ -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`.
index ac320f095a2389444aec93e1103982504279d178..b7250f3b0b539b5be0139162726c26271917c7ea 100644 (file)
@@ -11,6 +11,11 @@ LL |     fn f(*, a: u8) -> u8 {}
    |        -              ^^ expected `u8`, found `()`
    |        |
    |        implicitly returns `()` as its body has no tail or `return` expression
+   |
+help: consider returning the local binding `a`
+   |
+LL |     fn f(*, a: u8) -> u8 { a }
+   |                            +
 
 error: aborting due to 2 previous errors
 
index 6facc467f7a6fc56903cbacbea3e4975b6817a5b..aaf0f7eaef0dcdd3969dcb3d743d0b4fba8f69f0 100644 (file)
@@ -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() {}
index c144060a8597de7ffe617dd4f2bc4f463f125993..d3214458eac13cc8f89bedfcf498812c5aad6116 100644 (file)
@@ -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/stability-attribute/auxiliary/stability-attribute-implies.rs b/src/test/ui/stability-attribute/auxiliary/stability-attribute-implies.rs
new file mode 100644 (file)
index 0000000..468be1b
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(staged_api)]
+#![stable(feature = "stability_attribute_implies", since = "1.0.0")]
+
+#[stable(feature = "foo", since = "1.62.0")]
+pub fn foo() {}
+
+#[unstable(feature = "foobar", issue = "1", implied_by = "foo")]
+pub fn foobar() {}
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-missing.rs b/src/test/ui/stability-attribute/stability-attribute-implies-missing.rs
new file mode 100644 (file)
index 0000000..6138785
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(staged_api)]
+#![stable(feature = "stability_attribute_implies", since = "1.0.0")]
+
+// Tests that `implied_by = "bar"` results in an error being emitted if `bar` does not exist.
+
+#[unstable(feature = "foobar", issue = "1", implied_by = "bar")]
+//~^ ERROR feature `bar` implying `foobar` does not exist
+pub fn foobar() {}
+
+fn main() {}
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-missing.stderr b/src/test/ui/stability-attribute/stability-attribute-implies-missing.stderr
new file mode 100644 (file)
index 0000000..ff1856f
--- /dev/null
@@ -0,0 +1,8 @@
+error: feature `bar` implying `foobar` does not exist
+  --> $DIR/stability-attribute-implies-missing.rs:6:1
+   |
+LL | #[unstable(feature = "foobar", issue = "1", implied_by = "bar")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-no-feature.rs b/src/test/ui/stability-attribute/stability-attribute-implies-no-feature.rs
new file mode 100644 (file)
index 0000000..947f9f7
--- /dev/null
@@ -0,0 +1,13 @@
+// aux-build:stability-attribute-implies.rs
+
+// Tests that despite the `foobar` feature being implied by now-stable feature `foo`, if `foobar`
+// isn't allowed in this crate then an error will be emitted.
+
+extern crate stability_attribute_implies;
+use stability_attribute_implies::{foo, foobar};
+//~^ ERROR use of unstable library feature 'foobar'
+
+fn main() {
+    foo(); // no error - stable
+    foobar(); //~ ERROR use of unstable library feature 'foobar'
+}
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-no-feature.stderr b/src/test/ui/stability-attribute/stability-attribute-implies-no-feature.stderr
new file mode 100644 (file)
index 0000000..c2331f6
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0658]: use of unstable library feature 'foobar'
+  --> $DIR/stability-attribute-implies-no-feature.rs:7:40
+   |
+LL | use stability_attribute_implies::{foo, foobar};
+   |                                        ^^^^^^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(foobar)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'foobar'
+  --> $DIR/stability-attribute-implies-no-feature.rs:12:5
+   |
+LL |     foobar();
+   |     ^^^^^^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(foobar)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-using-stable.rs b/src/test/ui/stability-attribute/stability-attribute-implies-using-stable.rs
new file mode 100644 (file)
index 0000000..1a2d8e2
--- /dev/null
@@ -0,0 +1,15 @@
+// aux-build:stability-attribute-implies.rs
+#![deny(stable_features)]
+#![feature(foo)]
+//~^ ERROR the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
+
+// Tests that the use of `implied_by` in the `#[unstable]` attribute results in a diagnostic
+// mentioning partial stabilization, and that given the implied unstable feature is unused (there
+// is no `foobar` call), that the compiler suggests removing the flag.
+
+extern crate stability_attribute_implies;
+use stability_attribute_implies::foo;
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-using-stable.stderr b/src/test/ui/stability-attribute/stability-attribute-implies-using-stable.stderr
new file mode 100644 (file)
index 0000000..c9b3f07
--- /dev/null
@@ -0,0 +1,22 @@
+error: the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
+  --> $DIR/stability-attribute-implies-using-stable.rs:3:12
+   |
+LL | #![feature(foo)]
+   |            ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/stability-attribute-implies-using-stable.rs:2:9
+   |
+LL | #![deny(stable_features)]
+   |         ^^^^^^^^^^^^^^^
+help: if you are using features which are still unstable, change to using `foobar`
+   |
+LL | #![feature(foobar)]
+   |            ~~~~~~
+help: if you are using features which are now stable, remove this line
+   |
+LL - #![feature(foo)]
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-using-unstable.rs b/src/test/ui/stability-attribute/stability-attribute-implies-using-unstable.rs
new file mode 100644 (file)
index 0000000..3c73c5a
--- /dev/null
@@ -0,0 +1,17 @@
+// aux-build:stability-attribute-implies.rs
+#![deny(stable_features)]
+#![feature(foo)]
+//~^ ERROR the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
+
+// Tests that the use of `implied_by` in the `#[unstable]` attribute results in a diagnostic
+// mentioning partial stabilization and that given the implied unstable feature is used (there is a
+// `foobar` call), that the compiler suggests changing to that feature and doesn't error about its
+// use.
+
+extern crate stability_attribute_implies;
+use stability_attribute_implies::{foo, foobar};
+
+fn main() {
+    foo();
+    foobar(); // no error!
+}
diff --git a/src/test/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr b/src/test/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr
new file mode 100644 (file)
index 0000000..9a5c7ef
--- /dev/null
@@ -0,0 +1,22 @@
+error: the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar`
+  --> $DIR/stability-attribute-implies-using-unstable.rs:3:12
+   |
+LL | #![feature(foo)]
+   |            ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/stability-attribute-implies-using-unstable.rs:2:9
+   |
+LL | #![deny(stable_features)]
+   |         ^^^^^^^^^^^^^^^
+help: if you are using features which are still unstable, change to using `foobar`
+   |
+LL | #![feature(foobar)]
+   |            ~~~~~~
+help: if you are using features which are now stable, remove this line
+   |
+LL - #![feature(foo)]
+   |
+
+error: aborting due to previous error
+
index bd7b88da1584da0a2841b769d33e8d478bb57415..8dbcc6c97efd5fea50b7fe63657218a5f00c07c2 100644 (file)
@@ -8,7 +8,7 @@ error[E0541]: unknown meta item 'sinse'
   --> $DIR/stability-attribute-sanity-2.rs:10:25
    |
 LL | #[stable(feature = "a", sinse = "1.0.0")]
-   |                         ^^^^^^^^^^^^^^^ expected one of `since`, `note`
+   |                         ^^^^^^^^^^^^^^^ expected one of `feature`, `since`
 
 error[E0545]: `issue` must be a non-zero numeric string or "none"
   --> $DIR/stability-attribute-sanity-2.rs:13:27
index fcb1eefddbcef733b7777a3273d27a903b1a8c50..079230b2a3160e5462cb70d72b0655235be734a2 100644 (file)
@@ -14,7 +14,7 @@ error[E0541]: unknown meta item 'reason'
   --> $DIR/stability-attribute-sanity.rs:8:42
    |
 LL |     #[stable(feature = "a", since = "b", reason)]
-   |                                          ^^^^^^ expected one of `since`, `note`
+   |                                          ^^^^^^ expected one of `feature`, `since`
 
 error[E0539]: incorrect meta item
   --> $DIR/stability-attribute-sanity.rs:11:29
diff --git a/src/test/ui/suggestions/return-bindings-multi.rs b/src/test/ui/suggestions/return-bindings-multi.rs
new file mode 100644 (file)
index 0000000..8c3bd64
--- /dev/null
@@ -0,0 +1,9 @@
+fn a(i: i32) -> i32 {
+    //~^ ERROR mismatched types
+    let j = 2i32;
+}
+
+fn b(i: i32, j: i32) -> i32 {}
+//~^ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-bindings-multi.stderr b/src/test/ui/suggestions/return-bindings-multi.stderr
new file mode 100644 (file)
index 0000000..738e3f2
--- /dev/null
@@ -0,0 +1,34 @@
+error[E0308]: mismatched types
+  --> $DIR/return-bindings-multi.rs:1:17
+   |
+LL | fn a(i: i32) -> i32 {
+   |    -            ^^^ expected `i32`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+note: consider returning one of these bindings
+  --> $DIR/return-bindings-multi.rs:1:6
+   |
+LL | fn a(i: i32) -> i32 {
+   |      ^
+LL |
+LL |     let j = 2i32;
+   |         ^
+
+error[E0308]: mismatched types
+  --> $DIR/return-bindings-multi.rs:6:25
+   |
+LL | fn b(i: i32, j: i32) -> i32 {}
+   |    -                    ^^^ expected `i32`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+note: consider returning one of these bindings
+  --> $DIR/return-bindings-multi.rs:6:6
+   |
+LL | fn b(i: i32, j: i32) -> i32 {}
+   |      ^       ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/return-bindings.fixed b/src/test/ui/suggestions/return-bindings.fixed
new file mode 100644 (file)
index 0000000..4fabc41
--- /dev/null
@@ -0,0 +1,23 @@
+// run-rustfix
+
+#![allow(unused)]
+
+fn a(i: i32) -> i32 { i }
+//~^ ERROR mismatched types
+
+fn b(opt_str: Option<String>) {
+    let s: String = if let Some(s) = opt_str {
+        s
+    //~^ ERROR mismatched types
+    } else {
+        String::new()
+    };
+}
+
+fn c() -> Option<i32> {
+    //~^ ERROR mismatched types
+    let x = Some(1);
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-bindings.rs b/src/test/ui/suggestions/return-bindings.rs
new file mode 100644 (file)
index 0000000..d05b4ba
--- /dev/null
@@ -0,0 +1,21 @@
+// run-rustfix
+
+#![allow(unused)]
+
+fn a(i: i32) -> i32 {}
+//~^ ERROR mismatched types
+
+fn b(opt_str: Option<String>) {
+    let s: String = if let Some(s) = opt_str {
+        //~^ ERROR mismatched types
+    } else {
+        String::new()
+    };
+}
+
+fn c() -> Option<i32> {
+    //~^ ERROR mismatched types
+    let x = Some(1);
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-bindings.stderr b/src/test/ui/suggestions/return-bindings.stderr
new file mode 100644 (file)
index 0000000..e5d4925
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0308]: mismatched types
+  --> $DIR/return-bindings.rs:5:17
+   |
+LL | fn a(i: i32) -> i32 {}
+   |    -            ^^^ expected `i32`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+help: consider returning the local binding `i`
+   |
+LL | fn a(i: i32) -> i32 { i }
+   |                       +
+
+error[E0308]: mismatched types
+  --> $DIR/return-bindings.rs:9:46
+   |
+LL |       let s: String = if let Some(s) = opt_str {
+   |  ______________________________________________^
+LL | |
+LL | |     } else {
+   | |_____^ expected struct `String`, found `()`
+   |
+help: consider returning the local binding `s`
+   |
+LL ~     let s: String = if let Some(s) = opt_str {
+LL +         s
+LL ~
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/return-bindings.rs:16:11
+   |
+LL | fn c() -> Option<i32> {
+   |    -      ^^^^^^^^^^^ expected enum `Option`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+   = note:   expected enum `Option<i32>`
+           found unit type `()`
+help: consider returning the local binding `x`
+   |
+LL ~     let x = Some(1);
+LL +     x
+   |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 58055cd54561a85ccdb90b855a55ef2335f62bf8..56a68f3a2312c92f33d47fe4aba3f390344338ae 100644 (file)
@@ -7,6 +7,5 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
 fn main() {
     size_of_copy::<dyn Misc + Copy>();
     //~^ ERROR only auto traits can be used as additional traits in a trait object
-    //~| ERROR only auto traits can be used as additional traits in a trait object
     //~| ERROR the trait bound `dyn Misc: Copy` is not satisfied
 }
index 5e7762b32200a78df9f527e2b07738e0310724b2..bad45e54d64288053c9e35355542f3b95019a5a7 100644 (file)
@@ -9,22 +9,11 @@ LL |     size_of_copy::<dyn Misc + Copy>();
    = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}`
    = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
-error[E0225]: only auto traits can be used as additional traits in a trait object
-  --> $DIR/issue-32963.rs:8:31
-   |
-LL |     size_of_copy::<dyn Misc + Copy>();
-   |                        ----   ^^^^ additional non-auto trait
-   |                        |
-   |                        first non-auto trait
-   |
-   = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}`
-   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
-
 error[E0277]: the trait bound `dyn Misc: Copy` is not satisfied
-  --> $DIR/issue-32963.rs:8:5
+  --> $DIR/issue-32963.rs:8:20
    |
 LL |     size_of_copy::<dyn Misc + Copy>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc`
+   |                    ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc`
    |
 note: required by a bound in `size_of_copy`
   --> $DIR/issue-32963.rs:5:20
@@ -32,7 +21,7 @@ note: required by a bound in `size_of_copy`
 LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
    |                    ^^^^ required by this bound in `size_of_copy`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0225, E0277.
 For more information about an error, try `rustc --explain E0225`.
index 21b339d12a8de5d4fc17a301937e4949e608cd3f..d4d9b4967478ada0cedd6115bc14d1a5638b3b4b 100644 (file)
@@ -85,10 +85,10 @@ LL | pub const fn size_of<T>() -> usize {
    |                      ^ required by this bound in `std::mem::size_of`
 
 error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
-  --> $DIR/suggest-where-clause.rs:31:5
+  --> $DIR/suggest-where-clause.rs:31:20
    |
 LL |     mem::size_of::<[&U]>();
-   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[&U]`
 note: required by a bound in `std::mem::size_of`
index 9a50c0f988a568ac431906331fd54f9c624b2b32..811832848d9dd24f5206e3d160841e4fee7af808 100644 (file)
@@ -1,9 +1,8 @@
 // compile-flags: --edition=2021
-// check-pass
 #![feature(type_alias_impl_trait)]
 
 fn main() {
-    type T = impl Copy;
+    type T = impl Copy; //~ ERROR unconstrained opaque type
     let foo: T = (1u32, 2u32);
     let (a, b): (u32, u32) = foo;
 }
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr
new file mode 100644 (file)
index 0000000..03b172e
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/cross_inference_pattern_bug.rs:5:14
+   |
+LL |     type T = impl Copy;
+   |              ^^^^^^^^^
+   |
+   = note: `T` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
index b929122a6c23fccee8f2d15ea70ee4459b7885bf..328096d44b4b506161d68defef2d878e87bfb0bc 100644 (file)
@@ -1,13 +1,13 @@
+// known-bug: #96572
 // compile-flags: --edition=2021 --crate-type=lib
 // rustc-env:RUST_BACKTRACE=0
-// check-pass
 
 // tracked in https://github.com/rust-lang/rust/issues/96572
 
 #![feature(type_alias_impl_trait)]
 
 fn main() {
-    type T = impl Copy;
+    type T = impl Copy;  // error: unconstrained opaque type
     let foo: T = (1u32, 2u32);
-    let (a, b) = foo; // this line used to make the code fail
+    let (a, b) = foo; // removing this line makes the code compile
 }
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr
new file mode 100644 (file)
index 0000000..8aa1f49
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/cross_inference_pattern_bug_no_type.rs:10:14
+   |
+LL |     type T = impl Copy;  // error: unconstrained opaque type
+   |              ^^^^^^^^^
+   |
+   = note: `T` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
index 377ce85e8b221521da2d223ed81ccb67836f6ed3..4a11bb5020e6d21aa3a0da8725a843b5b4684f9b 100644 (file)
@@ -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
 }
 
index d20b1cc6d851bb135b3dd00fd87cc535e20c9141..00c682b21939c81a461f5754cde9ce41d9e56495 100644 (file)
@@ -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 (file)
index 0000000..472886c
--- /dev/null
@@ -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 (file)
index 0000000..ed4caf6
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs
deleted file mode 100644 (file)
index 8257108..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(type_alias_impl_trait)]
-
-fn main() {
-    type T = impl Copy;
-    let foo: T = Some((1u32, 2u32));
-    match foo {
-        None => (),
-        Some((a, b, c)) => (), //~ ERROR mismatched types
-    }
-}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr
deleted file mode 100644 (file)
index 728244a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-96572-unconstrained-mismatch.rs:8:14
-   |
-LL |     match foo {
-   |           --- this expression has type `T`
-LL |         None => (),
-LL |         Some((a, b, c)) => (),
-   |              ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
-   |
-   = note: expected tuple `(u32, u32)`
-              found tuple `(_, _, _)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-only-pattern-rpit.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-only-pattern-rpit.rs
deleted file mode 100644 (file)
index c0a371e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// check-pass
-
-#[allow(unconditional_recursion)]
-fn foo(b: bool) -> impl Copy {
-    let (mut x, mut y) = foo(false);
-    x = 42;
-    y = "foo";
-    if b {
-        panic!()
-    } else {
-        foo(true)
-    }
-}
-
-fn bar(b: bool) -> Option<impl Copy> {
-    if b {
-        return None;
-    }
-    match bar(!b) {
-        Some((mut x, mut y)) => {
-            x = 42;
-            y = "foo";
-        }
-        None => {}
-    }
-    None
-}
-
-fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-only-pattern.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-only-pattern.rs
deleted file mode 100644 (file)
index ec24995..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#![feature(type_alias_impl_trait)]
-// check-pass
-
-type T = impl Copy;
-
-fn foo(foo: T) {
-    let (mut x, mut y) = foo;
-    x = 42;
-    y = "foo";
-}
-
-type U = impl Copy;
-
-fn bar(bar: Option<U>) {
-    match bar {
-        Some((mut x, mut y)) => {
-            x = 42;
-            y = "foo";
-        }
-        None => {}
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-struct.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-struct.rs
deleted file mode 100644 (file)
index 3351d9b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(type_alias_impl_trait)]
-// check-pass
-
-#[derive(Copy, Clone)]
-struct Foo((u32, u32));
-
-fn main() {
-    type U = impl Copy;
-    let foo: U = Foo((1u32, 2u32));
-    let Foo((a, b)) = foo;
-}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-upvar-enum.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-upvar-enum.rs
deleted file mode 100644 (file)
index ef3279a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(type_alias_impl_trait)]
-// check-pass
-
-fn main() {
-    type T = impl Copy;
-    let foo: T = Some((1u32, 2u32));
-    let x = move || {
-        match foo {
-            None => (),
-            Some((a, b)) => (),
-        }
-    };
-}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-upvar.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-upvar.rs
deleted file mode 100644 (file)
index bb0fc7c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(type_alias_impl_trait)]
-// check-pass
-
-#[derive(Copy, Clone)]
-struct Foo((u32, u32));
-
-fn main() {
-    type T = impl Copy;
-    let foo: T = Foo((1u32, 2u32));
-    let x = move || {
-        let Foo((a, b)) = foo;
-    };
-}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
deleted file mode 100644 (file)
index 4b9ed7f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(type_alias_impl_trait)]
-// check-pass
-
-fn main() {
-    type T = impl Copy;
-    let foo: T = Some((1u32, 2u32));
-    match foo {
-        None => (),
-        Some((a, b)) => (),
-    }
-}
index 7aefa0646114cbba773be5f63430a8c8b35a246e..468a14762c0d70e14504c26b6e1993f745896b7a 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `<T as Trait>::AssocType` cannot be sent between threads safely
-  --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5
+  --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:15
    |
 LL |     is_send::<T::AssocType>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
+   |               ^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `<T as Trait>::AssocType`
 note: required by a bound in `is_send`
index 09d3eec6b2148db0149685cdbb7cf99e773d5896..a3b32d2c1c8ceeabc6986304b9878eb2dac09496 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq<dyn Foo<(isize,), Output = ()>>` is not satisfied
-  --> $DIR/unboxed-closure-sugar-default.rs:21:5
+  --> $DIR/unboxed-closure-sugar-default.rs:21:10
    |
 LL |     eq::<dyn Foo<(isize,), isize, Output=()>, dyn Foo(isize)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
    |
 note: required by a bound in `eq`
   --> $DIR/unboxed-closure-sugar-default.rs:14:40
index 0fc3e23ec73ef17c4995c71630ab2e9a2b6db9b4..acf0227a79b8c523702c3245721656ab39707e1a 100644 (file)
@@ -42,7 +42,7 @@ fn test<'a,'b>() {
     // Errors expected:
     eq::< dyn Foo<(),Output=()>,
           dyn Foo(char)                                               >();
-    //~^^ ERROR E0277
+    //~^ ERROR E0277
 }
 
 fn main() { }
index a1cbf842a683b9972676599f3a368f7c2a6efd6a..bccbf307ae15734e6212a7e1f7e3b2b6d17b1313 100644 (file)
@@ -1,9 +1,8 @@
 error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq<dyn Foo<(), Output = ()>>` is not satisfied
-  --> $DIR/unboxed-closure-sugar-equiv.rs:43:5
+  --> $DIR/unboxed-closure-sugar-equiv.rs:44:11
    |
-LL | /     eq::< dyn Foo<(),Output=()>,
-LL | |           dyn Foo(char)                                               >();
-   | |_______________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
+LL |           dyn Foo(char)                                               >();
+   |           ^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
    |
 note: required by a bound in `eq`
   --> $DIR/unboxed-closure-sugar-equiv.rs:16:28
index 8827baaa781b37872134c1ba692a6f0aeb37890e..d8d30a75376f78bb0fabe3d28ee9d87aa8035309 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8827baaa781b37872134c1ba692a6f0aeb37890e
+Subproject commit d8d30a75376f78bb0fabe3d28ee9d87aa8035309
index 9690ad2777177c8e66477f457044e44693a8a398..3bf75bcbee83e85d779b96ba2478d91b76d96450 100644 (file)
@@ -252,7 +252,6 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
                 }
             },
             ProjectionElem::ConstantIndex { .. }
-            | ProjectionElem::OpaqueCast(..)
             | ProjectionElem::Downcast(..)
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Deref