]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #101573 - lcnr:param-kind-ord, r=BoxyUwU
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>
Fri, 9 Sep 2022 16:32:18 +0000 (22:02 +0530)
committerGitHub <noreply@github.com>
Fri, 9 Sep 2022 16:32:18 +0000 (22:02 +0530)
update `ParamKindOrd`

https://github.com/rust-lang/rust/pull/90207#discussion_r767160854 :grin:

writing comments "for future prs" sure works well :3

r? `@BoxyUwU`

186 files changed:
RELEASES.md
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast_lowering/src/errors.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/pat.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/errors.rs
compiler/rustc_borrowck/src/diagnostics/region_name.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
compiler/rustc_error_messages/locales/en-US/parser.ftl
compiler/rustc_error_messages/locales/en-US/session.ftl
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir/src/pat_util.rs
compiler/rustc_hir/src/target.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_lexer/src/lib.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/passes.rs
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/table.rs
compiler/rustc_middle/src/arena.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/mir/syntax.rs
compiler/rustc_middle/src/mir/terminator.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/diagnostics.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/ty/visit.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/hir_stats.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_save_analysis/src/sig.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/errors.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_ty_utils/src/implied_bounds.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/closure.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/intrinsicck.rs
compiler/rustc_typeck/src/check/method/mod.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/item_bounds.rs
compiler/rustc_typeck/src/collect/type_of.rs
library/core/src/fmt/mod.rs
library/core/src/num/int_macros.rs
library/core/src/ops/generator.rs
library/core/tests/lib.rs
library/core/tests/num/int_macros.rs
library/core/tests/num/uint_macros.rs
library/std/src/sys/hermit/mutex.rs
library/std/src/sys/hermit/net.rs
library/std/src/sys/hermit/rwlock.rs
library/std/src/sys/windows/path.rs
library/std/src/sys/windows/path/tests.rs
src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
src/doc/rustc/src/platform-support.md
src/librustdoc/clean/mod.rs
src/librustdoc/clean/utils.rs
src/librustdoc/formats/item_type.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/passes/collect_intra_doc_links.rs
src/test/rustdoc-gui/code-tags.goml
src/test/rustdoc-gui/codeblock-tooltip.goml [new file with mode: 0644]
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
src/test/ui/array-slice-vec/suggest-array-length.fixed
src/test/ui/array-slice-vec/suggest-array-length.rs
src/test/ui/array-slice-vec/suggest-array-length.stderr
src/test/ui/asm/aarch64/type-check-3.stderr
src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
src/test/ui/asm/x86_64/type-check-3.stderr
src/test/ui/associated-types/issue-62200.rs
src/test/ui/associated-types/issue-62200.stderr
src/test/ui/async-await/async-trait-fn.rs
src/test/ui/async-await/async-trait-fn.stderr
src/test/ui/async-await/edition-deny-async-fns-2015.rs
src/test/ui/async-await/edition-deny-async-fns-2015.stderr
src/test/ui/async-await/issues/issue-95307.stderr
src/test/ui/binop/binary-op-on-double-ref.stderr
src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/missing-bounds.fixed
src/test/ui/generic-associated-types/missing-bounds.stderr
src/test/ui/impl-trait/in-trait/deep-match-works.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/deep-match.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/deep-match.stderr [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/nested-rpitit.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/opaque-in-impl.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/reveal.rs [new file with mode: 0644]
src/test/ui/impl-trait/in-trait/success.rs [new file with mode: 0644]
src/test/ui/impl-trait/where-allowed.stderr
src/test/ui/issues/issue-47511.stderr
src/test/ui/parser/fn-header-semantic-fail.rs
src/test/ui/parser/fn-header-semantic-fail.stderr
src/test/ui/parser/issue-101477-enum.fixed [new file with mode: 0644]
src/test/ui/parser/issue-101477-enum.rs [new file with mode: 0644]
src/test/ui/parser/issue-101477-enum.stderr [new file with mode: 0644]
src/test/ui/parser/issue-101477-let.fixed [new file with mode: 0644]
src/test/ui/parser/issue-101477-let.rs [new file with mode: 0644]
src/test/ui/parser/issue-101477-let.stderr [new file with mode: 0644]
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/sanitize/memory-eager.rs [new file with mode: 0644]
src/test/ui/sanitize/memory.rs
src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
src/test/ui/stats/hir-stats.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/issue-97677.fixed
src/test/ui/suggestions/issue-97677.stderr
src/test/ui/suggestions/restrict-type-not-param.rs [new file with mode: 0644]
src/test/ui/suggestions/restrict-type-not-param.stderr [new file with mode: 0644]
src/test/ui/traits/resolution-in-overloaded-op.stderr
src/test/ui/type-alias-impl-trait/constrain_inputs.rs
src/test/ui/type-alias-impl-trait/constrain_inputs.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr [new file with mode: 0644]
src/test/ui/typeck/assign-non-lval-derefmut.stderr
src/test/ui/typeck/assign-non-lval-mut-ref.stderr
src/tools/clippy/clippy_dev/src/new_lint.rs
src/tools/clippy/clippy_lints/src/equatable_if_let.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/lifetimes.rs
src/tools/clippy/clippy_lints/src/manual_async_fn.rs
src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
src/tools/clippy/clippy_lints/src/matches/single_match.rs
src/tools/clippy/clippy_lints/src/question_mark.rs
src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
src/tools/clippy/clippy_utils/src/hir_utils.rs
src/tools/clippy/clippy_utils/src/lib.rs

index 72b2c16a01f83b63ce9d1f448ab652c21aeb5450..89fd4f2703b5d3a2dee4b205e478adc3902b5345 100644 (file)
@@ -217,6 +217,7 @@ Language
 - [Fix constants not getting dropped if part of a diverging expression][94775]
 - [Support unit struct/enum variant in destructuring assignment][95380]
 - [Remove mutable_borrow_reservation_conflict lint and allow the code pattern][96268]
+- [`const` functions may now specify `extern "C"` or `extern "Rust"`][95346]
 
 Compiler
 --------
@@ -306,6 +307,7 @@ and related tools.
 [94872]: https://github.com/rust-lang/rust/pull/94872/
 [95006]: https://github.com/rust-lang/rust/pull/95006/
 [95035]: https://github.com/rust-lang/rust/pull/95035/
+[95346]: https://github.com/rust-lang/rust/pull/95346/
 [95372]: https://github.com/rust-lang/rust/pull/95372/
 [95380]: https://github.com/rust-lang/rust/pull/95380/
 [95431]: https://github.com/rust-lang/rust/pull/95431/
index 75cc5b72582e1d704ef80879b21edd941653a122..3f4911c4ecfcf63313fb68728f334d5d38a12d8c 100644 (file)
@@ -2337,9 +2337,9 @@ pub fn is_async(self) -> bool {
     }
 
     /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
-    pub fn opt_return_id(self) -> Option<NodeId> {
+    pub fn opt_return_id(self) -> Option<(NodeId, Span)> {
         match self {
-            Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
+            Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)),
             Async::No => None,
         }
     }
index 4adeaef9bbfa832d708a5275c5209229c105c37f..c87d0ca96570e74f2904068202102ce712b68a9a 100644 (file)
@@ -334,3 +334,14 @@ pub struct InclusiveRangeWithNoEnd {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(SessionDiagnostic, Clone, Copy)]
+#[diag(ast_lowering::trait_fn_async, code = "E0706")]
+#[note]
+#[note(ast_lowering::note2)]
+pub struct TraitFnAsync {
+    #[primary_span]
+    pub fn_span: Span,
+    #[label]
+    pub span: Span,
+}
index 6fa8d7f0fcdd9b52c0b0b75fe6012791c6d25354..f929549d70448100ea8c7f2516e4ac440f02066b 100644 (file)
@@ -849,21 +849,22 @@ fn lower_expr_closure(
             (body_id, generator_option)
         });
 
-        let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
-        // Lower outside new scope to preserve `is_in_loop_condition`.
-        let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
-
-        let c = self.arena.alloc(hir::Closure {
-            binder: binder_clause,
-            capture_clause,
-            bound_generic_params,
-            fn_decl,
-            body: body_id,
-            fn_decl_span: self.lower_span(fn_decl_span),
-            movability: generator_option,
-        });
+        self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| {
+            // Lower outside new scope to preserve `is_in_loop_condition`.
+            let fn_decl = lctx.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
+
+            let c = lctx.arena.alloc(hir::Closure {
+                binder: binder_clause,
+                capture_clause,
+                bound_generic_params,
+                fn_decl,
+                body: body_id,
+                fn_decl_span: lctx.lower_span(fn_decl_span),
+                movability: generator_option,
+            });
 
-        hir::ExprKind::Closure(c)
+            hir::ExprKind::Closure(c)
+        })
     }
 
     fn generator_movability_for_fn(
@@ -950,23 +951,24 @@ fn lower_expr_async_closure(
             body_id
         });
 
-        let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
-
-        // We need to lower the declaration outside the new scope, because we
-        // have to conserve the state of being inside a loop condition for the
-        // closure argument types.
-        let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
-
-        let c = self.arena.alloc(hir::Closure {
-            binder: binder_clause,
-            capture_clause,
-            bound_generic_params,
-            fn_decl,
-            body,
-            fn_decl_span: self.lower_span(fn_decl_span),
-            movability: None,
-        });
-        hir::ExprKind::Closure(c)
+        self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| {
+            // We need to lower the declaration outside the new scope, because we
+            // have to conserve the state of being inside a loop condition for the
+            // closure argument types.
+            let fn_decl =
+                lctx.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
+
+            let c = lctx.arena.alloc(hir::Closure {
+                binder: binder_clause,
+                capture_clause,
+                bound_generic_params,
+                fn_decl,
+                body,
+                fn_decl_span: lctx.lower_span(fn_decl_span),
+                movability: None,
+            });
+            hir::ExprKind::Closure(c)
+        })
     }
 
     /// Destructure the LHS of complex assignments.
@@ -1128,8 +1130,11 @@ fn destructure_assign_mut(
                         &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     );
                     // Destructure like a tuple struct.
-                    let tuple_struct_pat =
-                        hir::PatKind::TupleStruct(qpath, pats, rest.map(|r| r.0));
+                    let tuple_struct_pat = hir::PatKind::TupleStruct(
+                        qpath,
+                        pats,
+                        hir::DotDotPos::new(rest.map(|r| r.0)),
+                    );
                     return self.pat_without_dbm(lhs.span, tuple_struct_pat);
                 }
             }
@@ -1184,13 +1189,13 @@ fn destructure_assign_mut(
             ExprKind::Tup(elements) => {
                 let (pats, rest) =
                     self.destructure_sequence(elements, "tuple", eq_sign_span, assignments);
-                let tuple_pat = hir::PatKind::Tuple(pats, rest.map(|r| r.0));
+                let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0)));
                 return self.pat_without_dbm(lhs.span, tuple_pat);
             }
             ExprKind::Paren(e) => {
                 // We special-case `(..)` for consistency with patterns.
                 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
-                    let tuple_pat = hir::PatKind::Tuple(&[], Some(0));
+                    let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0)));
                     return self.pat_without_dbm(lhs.span, tuple_pat);
                 } else {
                     return self.destructure_assign_mut(e, eq_sign_span, assignments);
index f0717b51d4b18f8489090d69692a86e21055613e..52273778dcc009233e9cfe554c97e13163e092de 100644 (file)
@@ -1,6 +1,6 @@
 use super::errors::{InvalidAbi, MisplacedRelaxTraitBound};
 use super::ResolverAstLoweringExt;
-use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
+use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition};
 use super::{FnDeclKind, LoweringContext, ParamMode};
 
 use rustc_ast::ptr::P;
@@ -25,6 +25,7 @@
 pub(super) struct ItemLowerer<'a, 'hir> {
     pub(super) tcx: TyCtxt<'hir>,
     pub(super) resolver: &'a mut ResolverAstLowering,
+    pub(super) ast_arena: &'a Arena<'static>,
     pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>,
     pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
 }
@@ -60,6 +61,7 @@ fn with_lctx(
             tcx: self.tcx,
             resolver: self.resolver,
             arena: self.tcx.hir_arena,
+            ast_arena: self.ast_arena,
 
             // HirId handling.
             bodies: Vec::new(),
@@ -267,7 +269,7 @@ fn lower_item_kind(
                     let mut itctx = ImplTraitContext::Universal;
                     let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
                         let ret_id = asyncness.opt_return_id();
-                        this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id)
+                        this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id)
                     });
                     let sig = hir::FnSig {
                         decl,
@@ -659,7 +661,13 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir
                         self.lower_generics(generics, i.id, &mut itctx, |this| {
                             (
                                 // Disallow `impl Trait` in foreign items.
-                                this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
+                                this.lower_fn_decl(
+                                    fdec,
+                                    None,
+                                    sig.span,
+                                    FnDeclKind::ExternFn,
+                                    None,
+                                ),
                                 this.lower_fn_params_to_names(fdec),
                             )
                         });
@@ -769,9 +777,15 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
             }
             AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
+                let asyncness = sig.header.asyncness;
                 let names = self.lower_fn_params_to_names(&sig.decl);
-                let (generics, sig) =
-                    self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None);
+                let (generics, sig) = self.lower_method_sig(
+                    generics,
+                    sig,
+                    i.id,
+                    FnDeclKind::Trait,
+                    asyncness.opt_return_id(),
+                );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
             }
             AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
@@ -1238,12 +1252,12 @@ fn lower_method_sig(
         sig: &FnSig,
         id: NodeId,
         kind: FnDeclKind,
-        is_async: Option<NodeId>,
+        is_async: Option<(NodeId, Span)>,
     ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
         let header = self.lower_fn_header(sig.header);
         let mut itctx = ImplTraitContext::Universal;
         let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
-            this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
+            this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
         });
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
index e7bbf7dbdec295d2084e5d4f5845a279fa27414b..0720f23ed756d449ad3c7f50155ee323912cfa54 100644 (file)
@@ -42,8 +42,9 @@
 #[macro_use]
 extern crate tracing;
 
-use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
+use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync};
 
+use rustc_arena::declare_arena;
 use rustc_ast::ptr::P;
 use rustc_ast::visit;
 use rustc_ast::{self as ast, *};
@@ -95,6 +96,13 @@ struct LoweringContext<'a, 'hir> {
     /// Used to allocate HIR nodes.
     arena: &'hir hir::Arena<'hir>,
 
+    /// Used to allocate temporary AST nodes for use during lowering.
+    /// This allows us to create "fake" AST -- these nodes can sometimes
+    /// be allocated on the stack, but other times we need them to live longer
+    /// than the current stack frame, so they can be collected into vectors
+    /// and things like that.
+    ast_arena: &'a Arena<'static>,
+
     /// Bodies inside the owner being lowered.
     bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
     /// Attributes inside the owner being lowered.
@@ -140,6 +148,15 @@ struct LoweringContext<'a, 'hir> {
     generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
 }
 
+declare_arena!([
+    [] tys: rustc_ast::Ty,
+    [] aba: rustc_ast::AngleBracketedArgs,
+    [] ptr: rustc_ast::PolyTraitRef,
+    // This _marker field is needed because `declare_arena` creates `Arena<'tcx>` and we need to
+    // use `'tcx`. If we don't have this we get a compile error.
+    [] _marker: std::marker::PhantomData<&'tcx ()>,
+]);
+
 trait ResolverAstLoweringExt {
     fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
     fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
@@ -235,6 +252,7 @@ enum ImplTraitContext {
     ReturnPositionOpaqueTy {
         /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
         origin: hir::OpaqueTyOrigin,
+        in_trait: bool,
     },
     /// Impl trait in type aliases.
     TypeAliasesOpaqueTy,
@@ -294,7 +312,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
 enum FnDeclKind {
     Fn,
     Inherent,
@@ -306,9 +324,17 @@ enum FnDeclKind {
 }
 
 impl FnDeclKind {
-    fn impl_trait_return_allowed(&self) -> bool {
+    fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool {
         match self {
             FnDeclKind::Fn | FnDeclKind::Inherent => true,
+            FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
+            _ => false,
+        }
+    }
+
+    fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
+        match self {
+            FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
             _ => false,
         }
     }
@@ -401,10 +427,13 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
         tcx.definitions_untracked().def_index_count(),
     );
 
+    let ast_arena = Arena::default();
+
     for def_id in ast_index.indices() {
         item::ItemLowerer {
             tcx,
             resolver: &mut resolver,
+            ast_arena: &ast_arena,
             ast_index: &ast_index,
             owners: &mut owners,
         }
@@ -810,23 +839,31 @@ fn lifetime_res_to_generic_param(
     /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id
     /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime
     /// parameters will be successful.
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self, in_binder))]
     #[inline]
-    fn lower_lifetime_binder(
+    fn lower_lifetime_binder<R>(
         &mut self,
         binder: NodeId,
         generic_params: &[GenericParam],
-    ) -> &'hir [hir::GenericParam<'hir>] {
-        let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
+        in_binder: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> R,
+    ) -> R {
         let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
         debug!(?extra_lifetimes);
-        generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
-            self.lifetime_res_to_generic_param(ident, node_id, res)
-        }));
+        let extra_lifetimes: Vec<_> = extra_lifetimes
+            .into_iter()
+            .filter_map(|(ident, node_id, res)| {
+                self.lifetime_res_to_generic_param(ident, node_id, res)
+            })
+            .collect();
+
+        let generic_params: Vec<_> = self
+            .lower_generic_params_mut(generic_params)
+            .chain(extra_lifetimes.into_iter())
+            .collect();
         let generic_params = self.arena.alloc_from_iter(generic_params);
         debug!(?generic_params);
 
-        generic_params
+        in_binder(self, generic_params)
     }
 
     fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
@@ -966,12 +1003,8 @@ fn lower_assoc_ty_constraint(
                 }
                 GenericArgs::Parenthesized(ref data) => {
                     self.emit_bad_parenthesized_trait_in_assoc_ty(data);
-                    self.lower_angle_bracketed_parameter_data(
-                        &data.as_angle_bracketed_args(),
-                        ParamMode::Explicit,
-                        itctx,
-                    )
-                    .0
+                    let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args());
+                    self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0
                 }
             };
             gen_args_ctor.into_generic_args(self)
@@ -1040,15 +1073,13 @@ fn lower_assoc_ty_constraint(
 
                     self.with_dyn_type_scope(false, |this| {
                         let node_id = this.next_node_id();
-                        let ty = this.lower_ty(
-                            &Ty {
-                                id: node_id,
-                                kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
-                                span: this.lower_span(constraint.span),
-                                tokens: None,
-                            },
-                            itctx,
-                        );
+                        let ty = this.ast_arena.tys.alloc(Ty {
+                            id: node_id,
+                            kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
+                            span: this.lower_span(constraint.span),
+                            tokens: None,
+                        });
+                        let ty = this.lower_ty(ty, itctx);
 
                         hir::TypeBindingKind::Equality { term: ty.into() }
                     })
@@ -1184,19 +1215,20 @@ fn lower_path_ty(
             && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
         {
             let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
+                let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
+                    bound_generic_params: vec![],
+                    trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
+                    span: t.span
+                });
                 let bound = this.lower_poly_trait_ref(
-                    &PolyTraitRef {
-                        bound_generic_params: vec![],
-                        trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
-                        span: t.span
-                    },
+                    poly_trait_ref,
                     itctx,
                 );
                 let bounds = this.arena.alloc_from_iter([bound]);
                 let lifetime_bound = this.elided_dyn_bound(t.span);
                 (bounds, lifetime_bound)
             });
-            let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None);
+            let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None);
             return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
         }
 
@@ -1236,14 +1268,15 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: &mut ImplTraitContext) -> hir::Ty<'
                 hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
             }
             TyKind::BareFn(ref f) => {
-                let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
-                hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
-                    generic_params,
-                    unsafety: self.lower_unsafety(f.unsafety),
-                    abi: self.lower_extern(f.ext),
-                    decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
-                    param_names: self.lower_fn_params_to_names(&f.decl),
-                }))
+                self.lower_lifetime_binder(t.id, &f.generic_params, |lctx, generic_params| {
+                    hir::TyKind::BareFn(lctx.arena.alloc(hir::BareFnTy {
+                        generic_params,
+                        unsafety: lctx.lower_unsafety(f.unsafety),
+                        abi: lctx.lower_extern(f.ext),
+                        decl: lctx.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
+                        param_names: lctx.lower_fn_params_to_names(&f.decl),
+                    }))
+                })
             }
             TyKind::Never => hir::TyKind::Never,
             TyKind::Tup(ref tys) => hir::TyKind::Tup(
@@ -1309,19 +1342,23 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: &mut ImplTraitContext) -> hir::Ty<'
             TyKind::ImplTrait(def_node_id, ref bounds) => {
                 let span = t.span;
                 match itctx {
-                    ImplTraitContext::ReturnPositionOpaqueTy { origin } => {
-                        self.lower_opaque_impl_trait(span, *origin, def_node_id, bounds, itctx)
-                    }
-                    ImplTraitContext::TypeAliasesOpaqueTy => {
-                        let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
-                        self.lower_opaque_impl_trait(
+                    ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
+                        .lower_opaque_impl_trait(
                             span,
-                            hir::OpaqueTyOrigin::TyAlias,
+                            *origin,
                             def_node_id,
                             bounds,
-                            &mut nested_itctx,
-                        )
-                    }
+                            *in_trait,
+                            itctx,
+                        ),
+                    ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
+                        span,
+                        hir::OpaqueTyOrigin::TyAlias,
+                        def_node_id,
+                        bounds,
+                        false,
+                        &mut ImplTraitContext::TypeAliasesOpaqueTy,
+                    ),
                     ImplTraitContext::Universal => {
                         let span = t.span;
                         let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
@@ -1333,6 +1370,21 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: &mut ImplTraitContext) -> hir::Ty<'
                         }
                         path
                     }
+                    ImplTraitContext::Disallowed(
+                        position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
+                    ) => {
+                        self.tcx
+                            .sess
+                            .create_feature_err(
+                                MisplacedImplTrait {
+                                    span: t.span,
+                                    position: DiagnosticArgFromDisplay(&position),
+                                },
+                                sym::return_position_impl_trait_in_trait,
+                            )
+                            .emit();
+                        hir::TyKind::Err
+                    }
                     ImplTraitContext::Disallowed(position) => {
                         self.tcx.sess.emit_err(MisplacedImplTrait {
                             span: t.span,
@@ -1391,6 +1443,7 @@ fn lower_opaque_impl_trait(
         origin: hir::OpaqueTyOrigin,
         opaque_ty_node_id: NodeId,
         bounds: &GenericBounds,
+        in_trait: bool,
         itctx: &mut ImplTraitContext,
     ) -> hir::TyKind<'hir> {
         // Make sure we know that some funky desugaring has been going on here.
@@ -1479,6 +1532,7 @@ fn lower_opaque_impl_trait(
                     }),
                     bounds: hir_bounds,
                     origin,
+                    in_trait,
                 };
                 debug!(?opaque_ty_item);
 
@@ -1505,7 +1559,7 @@ fn lower_opaque_impl_trait(
         debug!(?lifetimes);
 
         // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
-        hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
+        hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait)
     }
 
     /// Registers a new opaque type with the proper `NodeId`s and
@@ -1613,19 +1667,17 @@ fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
     // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the
     //      given DefId, otherwise impl Trait is disallowed. Must be `Some` if
     //      `make_ret_async` is also `Some`.
-    // `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position.
-    //      This guards against trait declarations and implementations where `impl Trait` is
-    //      disallowed.
     // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
     //      return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
-    //      return type `impl Trait` item.
+    //      return type `impl Trait` item, and the `Span` points to the `async` keyword.
     #[instrument(level = "debug", skip(self))]
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
         fn_node_id: Option<NodeId>,
+        fn_span: Span,
         kind: FnDeclKind,
-        make_ret_async: Option<NodeId>,
+        make_ret_async: Option<(NodeId, Span)>,
     ) -> &'hir hir::FnDecl<'hir> {
         let c_variadic = decl.c_variadic();
 
@@ -1656,20 +1708,63 @@ fn lower_fn_decl(
             }
         }));
 
-        let output = if let Some(ret_id) = make_ret_async {
-            self.lower_async_fn_ret_ty(
-                &decl.output,
-                fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
-                ret_id,
-            )
+        let output = if let Some((ret_id, span)) = make_ret_async {
+            match kind {
+                FnDeclKind::Trait => {
+                    if !kind.impl_trait_in_trait_allowed(self.tcx) {
+                        self.tcx
+                            .sess
+                            .create_feature_err(
+                                TraitFnAsync { fn_span, span },
+                                sym::return_position_impl_trait_in_trait,
+                            )
+                            .emit();
+                    }
+                    self.lower_async_fn_ret_ty(
+                        &decl.output,
+                        fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
+                        ret_id,
+                        true,
+                    )
+                }
+                _ => {
+                    if !kind.impl_trait_return_allowed(self.tcx) {
+                        if kind == FnDeclKind::Impl {
+                            self.tcx
+                                .sess
+                                .create_feature_err(
+                                    TraitFnAsync { fn_span, span },
+                                    sym::return_position_impl_trait_in_trait,
+                                )
+                                .emit();
+                        } else {
+                            self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
+                        }
+                    }
+                    self.lower_async_fn_ret_ty(
+                        &decl.output,
+                        fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
+                        ret_id,
+                        false,
+                    )
+                }
+            }
         } else {
             match decl.output {
                 FnRetTy::Ty(ref ty) => {
                     let mut context = match fn_node_id {
-                        Some(fn_node_id) if kind.impl_trait_return_allowed() => {
+                        Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => {
+                            let fn_def_id = self.local_def_id(fn_node_id);
+                            ImplTraitContext::ReturnPositionOpaqueTy {
+                                origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+                                in_trait: false,
+                            }
+                        }
+                        Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => {
                             let fn_def_id = self.local_def_id(fn_node_id);
                             ImplTraitContext::ReturnPositionOpaqueTy {
                                 origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+                                in_trait: true,
                             }
                         }
                         _ => ImplTraitContext::Disallowed(match kind {
@@ -1733,6 +1828,7 @@ fn lower_async_fn_ret_ty(
         output: &FnRetTy,
         fn_node_id: NodeId,
         opaque_ty_node_id: NodeId,
+        in_trait: bool,
     ) -> hir::FnRetTy<'hir> {
         let span = output.span();
 
@@ -1859,8 +1955,14 @@ fn lower_async_fn_ret_ty(
                 //
                 // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
                 // hence the elision takes place at the fn site.
-                let future_bound =
-                    this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
+                let future_bound = this.lower_async_fn_output_type_to_future_bound(
+                    output,
+                    span,
+                    ImplTraitContext::ReturnPositionOpaqueTy {
+                        origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+                        in_trait,
+                    },
+                );
 
                 let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map(
                     |&(new_node_id, lifetime, _)| {
@@ -1898,6 +2000,7 @@ fn lower_async_fn_ret_ty(
                     }),
                     bounds: arena_vec![this; future_bound],
                     origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+                    in_trait,
                 };
 
                 trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
@@ -1934,8 +2037,7 @@ fn lower_async_fn_ret_ty(
                 let res = res.unwrap_or(
                     self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
                 );
-                let l = self.new_named_lifetime_with_res(id, span, ident, res);
-                hir::GenericArg::Lifetime(l)
+                hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
             },
         ));
 
@@ -1943,8 +2045,11 @@ fn lower_async_fn_ret_ty(
         // Foo = impl Trait` is, internally, created as a child of the
         // async fn, so the *type parameters* are inherited.  It's
         // only the lifetime parameters that we must supply.
-        let opaque_ty_ref =
-            hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args);
+        let opaque_ty_ref = hir::TyKind::OpaqueDef(
+            hir::ItemId { def_id: opaque_ty_def_id },
+            generic_args,
+            in_trait,
+        );
         let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
         hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
     }
@@ -1953,8 +2058,8 @@ fn lower_async_fn_ret_ty(
     fn lower_async_fn_output_type_to_future_bound(
         &mut self,
         output: &FnRetTy,
-        fn_def_id: LocalDefId,
         span: Span,
+        mut nested_impl_trait_context: ImplTraitContext,
     ) -> hir::GenericBound<'hir> {
         // Compute the `T` in `Future<Output = T>` from the return type.
         let output_ty = match output {
@@ -1962,10 +2067,7 @@ fn lower_async_fn_output_type_to_future_bound(
                 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
                 // `impl Future` opaque type that `async fn` implicitly
                 // generates.
-                let mut context = ImplTraitContext::ReturnPositionOpaqueTy {
-                    origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
-                };
-                self.lower_ty(ty, &mut context)
+                self.lower_ty(ty, &mut nested_impl_trait_context)
             }
             FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
         };
@@ -2004,7 +2106,7 @@ fn lower_param_bound(
         }
     }
 
-    fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
+    fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
         let span = self.lower_span(l.ident.span);
         let ident = self.lower_ident(l.ident);
         self.new_named_lifetime(l.id, l.id, span, ident)
@@ -2017,7 +2119,7 @@ fn new_named_lifetime_with_res(
         span: Span,
         ident: Ident,
         res: LifetimeRes,
-    ) -> hir::Lifetime {
+    ) -> &'hir hir::Lifetime {
         let name = match res {
             LifetimeRes::Param { param, .. } => {
                 let p_name = ParamName::Plain(ident);
@@ -2038,7 +2140,11 @@ fn new_named_lifetime_with_res(
         };
 
         debug!(?name);
-        hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name }
+        self.arena.alloc(hir::Lifetime {
+            hir_id: self.lower_node_id(id),
+            span: self.lower_span(span),
+            name,
+        })
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -2048,7 +2154,7 @@ fn new_named_lifetime(
         new_id: NodeId,
         span: Span,
         ident: Ident,
-    ) -> hir::Lifetime {
+    ) -> &'hir hir::Lifetime {
         let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
         self.new_named_lifetime_with_res(new_id, span, ident, res)
     }
@@ -2140,10 +2246,14 @@ fn lower_poly_trait_ref(
         p: &PolyTraitRef,
         itctx: &mut ImplTraitContext,
     ) -> hir::PolyTraitRef<'hir> {
-        let bound_generic_params =
-            self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
-        let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
-        hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
+        self.lower_lifetime_binder(
+            p.trait_ref.ref_id,
+            &p.bound_generic_params,
+            |lctx, bound_generic_params| {
+                let trait_ref = lctx.lower_trait_ref(&p.trait_ref, itctx);
+                hir::PolyTraitRef { bound_generic_params, trait_ref, span: lctx.lower_span(p.span) }
+            },
+        )
     }
 
     fn lower_mt(&mut self, mt: &MutTy, itctx: &mut ImplTraitContext) -> hir::MutTy<'hir> {
@@ -2462,14 +2572,14 @@ fn ty_path(
     /// bound, like the bound in `Box<dyn Debug>`. This method is not invoked
     /// when the bound is written, even if it is written with `'_` like in
     /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
-    fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
+    fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
         let r = hir::Lifetime {
             hir_id: self.next_id(),
             span: self.lower_span(span),
             name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
         };
         debug!("elided_dyn_bound: r={:?}", r);
-        r
+        self.arena.alloc(r)
     }
 }
 
index 69e6c2c8ad0bc2ea9d5ad69d168fdc0eb1a71c25..1ea76fdbfcbbbab5996de26b9a163f8229d37792 100644 (file)
@@ -116,7 +116,7 @@ fn lower_pat_tuple(
         &mut self,
         pats: &[P<Pat>],
         ctx: &str,
-    ) -> (&'hir [hir::Pat<'hir>], Option<usize>) {
+    ) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) {
         let mut elems = Vec::with_capacity(pats.len());
         let mut rest = None;
 
@@ -160,7 +160,7 @@ fn lower_pat_tuple(
             }
         }
 
-        (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
+        (self.arena.alloc_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos)))
     }
 
     /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
index 26813f2c19c71d7d2e064eca49cb81829edd4187..6a0a1b08360133296069b79a284e80cfd2873707 100644 (file)
@@ -290,12 +290,6 @@ fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Iden
         }
     }
 
-    fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
-        if let Async::Yes { span, .. } = asyncness {
-            self.session.emit_err(TraitFnAsync { fn_span, span });
-        }
-    }
-
     fn check_trait_fn_not_const(&self, constness: Const) {
         if let Const::Yes(span) = constness {
             self.session.emit_err(TraitFnConst { span });
@@ -1596,7 +1590,6 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
             self.invalid_visibility(&item.vis, None);
             if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
                 self.check_trait_fn_not_const(sig.header.constness);
-                self.check_trait_fn_not_async(item.span, sig.header.asyncness);
             }
         }
 
index 21467e57651983fc78b918370d749af62bb78372..4f3b09c587113597d816dfc5bec14ca21283b91b 100644 (file)
@@ -79,17 +79,6 @@ pub enum InvalidVisibilityNote {
     IndividualForeignItems,
 }
 
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::trait_fn_async, code = "E0706")]
-#[note]
-#[note(ast_passes::note2)]
-pub struct TraitFnAsync {
-    #[primary_span]
-    pub fn_span: Span,
-    #[label]
-    pub span: Span,
-}
-
 #[derive(SessionDiagnostic)]
 #[diag(ast_passes::trait_fn_const, code = "E0379")]
 pub struct TraitFnConst {
index 75fde53b6cdecd24452e0293db2118ad598f9620..0707ff5ed02a0abf81f53c14173db134235f45a5 100644 (file)
@@ -772,7 +772,7 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
     fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
         let hir = self.infcx.tcx.hir();
 
-        let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else {
+        let hir::TyKind::OpaqueDef(id, _, _) = hir_ty.kind else {
             span_bug!(
                 hir_ty.span,
                 "lowered return type of async fn is not OpaqueDef: {:?}",
index 8dc9368a0b994d197943ea914fa19b6578b554dc..de70b17e44ccd77204faa0d68b6be9091c984f91 100644 (file)
@@ -135,7 +135,6 @@ pub struct RegionInferenceContext<'tcx> {
 /// adds a new lower bound to the SCC it is analyzing: so you wind up
 /// with `'R: 'O` where `'R` is the pick-region and `'O` is the
 /// minimal viable option.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub(crate) struct AppliedMemberConstraint {
     /// The SCC that was affected. (The "member region".)
     ///
index 0ce161d7e756cfbc2960375df513f12bd917733f..26f5225f6b445b820518fc74c26cada13e98308f 100644 (file)
@@ -19,6 +19,7 @@
 pub use rustc_target::abi::call::*;
 use rustc_target::abi::{self, HasDataLayout, Int};
 pub use rustc_target::spec::abi::Abi;
+use rustc_target::spec::SanitizerSet;
 
 use libc::c_uint;
 use smallvec::SmallVec;
@@ -90,6 +91,13 @@ fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
         if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) {
             attrs.push(llvm::AttributeKind::NoAlias.create_attr(cx.llcx));
         }
+    } else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
+        // If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
+        // memory sanitizer's behavior.
+
+        if regular.contains(ArgAttribute::NoUndef) {
+            attrs.push(llvm::AttributeKind::NoUndef.create_attr(cx.llcx));
+        }
     }
 
     attrs
index 783ab350faac3842d51627525c5f827d6945a00c..8576e0f0f7c16ad856d9f41ef09b6eefb7423944 100644 (file)
@@ -90,20 +90,21 @@ pub fn equal_up_to_regions<'tcx>(
 
     // Normalize lifetimes away on both sides, then compare.
     let normalize = |ty: Ty<'tcx>| {
-        let ty = ty.fold_with(&mut BottomUpFolder {
-            tcx,
-            // FIXME: We erase all late-bound lifetimes, but this is not fully correct.
-            // If you have a type like `<for<'a> fn(&'a u32) as SomeTrait>::Assoc`,
-            // this is not necessarily equivalent to `<fn(&'static u32) as SomeTrait>::Assoc`,
-            // since one may have an `impl SomeTrait for fn(&32)` and
-            // `impl SomeTrait for fn(&'static u32)` at the same time which
-            // specify distinct values for Assoc. (See also #56105)
-            lt_op: |_| tcx.lifetimes.re_erased,
-            // Leave consts and types unchanged.
-            ct_op: |ct| ct,
-            ty_op: |ty| ty,
-        });
-        tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty)
+        tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty).fold_with(
+            &mut BottomUpFolder {
+                tcx,
+                // FIXME: We erase all late-bound lifetimes, but this is not fully correct.
+                // If you have a type like `<for<'a> fn(&'a u32) as SomeTrait>::Assoc`,
+                // this is not necessarily equivalent to `<fn(&'static u32) as SomeTrait>::Assoc`,
+                // since one may have an `impl SomeTrait for fn(&32)` and
+                // `impl SomeTrait for fn(&'static u32)` at the same time which
+                // specify distinct values for Assoc. (See also #56105)
+                lt_op: |_| tcx.lifetimes.re_erased,
+                // Leave consts and types unchanged.
+                ct_op: |ct| ct,
+                ty_op: |ty| ty,
+            },
+        )
     };
     tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok())
 }
index f2790531aba44de40e247d6d7a8b4d956fd08684..c45e045b4dba0d27d159382a181f94e10dc7368d 100644 (file)
@@ -131,3 +131,9 @@ ast_lowering_arbitrary_expression_in_pattern =
     arbitrary expressions aren't allowed in patterns
 
 ast_lowering_inclusive_range_with_no_end = inclusive range with no end
+
+ast_lowering_trait_fn_async =
+    functions in traits cannot be declared `async`
+    .label = `async` because of this
+    .note = `async` trait functions are not currently supported
+    .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
index d7108e1e2de35e5dbc22da59213a42b39cf8388b..e5cd1142b20c8c8738055ac3d52d845fb801b24d 100644 (file)
@@ -26,12 +26,6 @@ ast_passes_invalid_visibility =
     .individual_impl_items = place qualifiers on individual impl items instead
     .individual_foreign_items = place qualifiers on individual foreign items instead
 
-ast_passes_trait_fn_async =
-    functions in traits cannot be declared `async`
-    .label = `async` because of this
-    .note = `async` trait functions are not currently supported
-    .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 ast_passes_trait_fn_const =
     functions in traits cannot be declared const
     .label = functions in traits cannot be const
index bc17754c56ae309882e2980508c3fc1623b42812..f74df3d9746aec4173e0d566dc53c13d8198f055 100644 (file)
@@ -153,3 +153,6 @@ parser_left_arrow_operator = unexpected token: `<-`
 
 parser_remove_let = expected pattern, found `let`
     .suggestion = remove the unnecessary `let` keyword
+
+parser_use_eq_instead = unexpected `==`
+    .suggestion = try using `=` instead
index 983e5cee8237d801c8295fb85e706c993f0d5e7e..d2a2958f62436180cee3436fec51d91694485772 100644 (file)
@@ -14,3 +14,45 @@ session_feature_diagnostic_for_issue =
 
 session_feature_diagnostic_help =
     add `#![feature({$feature})]` to the crate attributes to enable
+
+session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
+
+session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
+
+session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
+
+session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
+
+session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
+
+session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
+
+session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
+
+session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
+
+session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
+
+session_sanitizer_cfi_enabled = `-Zsanitizer=cfi` requires `-Clto`
+
+session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
+
+session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
+
+session_target_invalid_address_space = invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
+
+session_target_invalid_bits = invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
+
+session_target_missing_alignment = missing alignment for `{$cause}` in "data-layout"
+
+session_target_invalid_alignment = invalid alignment for `{$cause}` in "data-layout": {$err}
+
+session_target_inconsistent_architecture = inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
+
+session_target_inconsistent_pointer_width = inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
+
+session_target_invalid_bits_size = {$err}
+
+session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
+
+session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
index a052aaee047567610702f244baf0a1910f193464..a774b52c8a592e75a321efa8b377c04167b2fd92 100644 (file)
 use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::{edition::Edition, Span, DUMMY_SP};
-use rustc_target::spec::PanicStrategy;
+use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
 use std::borrow::Cow;
 use std::fmt;
 use std::hash::{Hash, Hasher};
+use std::num::ParseIntError;
 use std::path::{Path, PathBuf};
 
 /// Error type for `Diagnostic`'s `suggestions` field, indicating that
@@ -91,6 +92,10 @@ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
     Edition,
     Ident,
     MacroRulesNormalizedIdent,
+    ParseIntError,
+    StackProtector,
+    &TargetTriple,
+    SplitDebuginfo
 );
 
 impl IntoDiagnosticArg for bool {
index 513225e1606452e73cb63c6fe1296e4673007994..3e02d2ebb7e3e05bc207fc72d01fb657e5c5a2d7 100644 (file)
@@ -456,7 +456,7 @@ struct HandlerInner {
 }
 
 /// A key denoting where from a diagnostic was stashed.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum StashKey {
     ItemNoType,
     UnderscoreForArrayLengths,
index f71b3d59e2c04cb8d41d5586bfe802d2156e258b..3b8032040e76cc53aea112f497c74ed1325ea3e2 100644 (file)
@@ -487,6 +487,8 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (incomplete, repr128, "1.16.0", Some(56071), None),
     /// Allows `repr(simd)` and importing the various simd intrinsics.
     (active, repr_simd, "1.4.0", Some(27731), None),
+    /// Allows return-position `impl Trait` in traits.
+    (incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None),
     /// Allows `extern "rust-cold"`.
     (active, rust_cold_cc, "1.63.0", Some(97544), None),
     /// Allows the use of SIMD types in functions declared in `extern` blocks.
index d5ac07f1e6315d23023a8679fca60331fa1d36c4..e7c26bd726fbfd69fa45532d5658d752de9a4232 100644 (file)
@@ -109,6 +109,8 @@ pub enum DefKind {
     InlineConst,
     /// Opaque type, aka `impl Trait`.
     OpaqueTy,
+    /// A return-position `impl Trait` in a trait definition
+    ImplTraitPlaceholder,
     Field,
     /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`
     LifetimeParam,
@@ -138,6 +140,7 @@ pub fn descr(self, def_id: DefId) -> &'static str {
                 panic!("impossible struct constructor")
             }
             DefKind::OpaqueTy => "opaque type",
+            DefKind::ImplTraitPlaceholder => "opaque type in trait",
             DefKind::TyAlias => "type alias",
             DefKind::TraitAlias => "trait alias",
             DefKind::AssocTy => "associated type",
@@ -217,7 +220,8 @@ pub fn ns(&self) -> Option<Namespace> {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::GlobalAsm
-            | DefKind::Impl => None,
+            | DefKind::Impl
+            | DefKind::ImplTraitPlaceholder => None,
         }
     }
 
@@ -254,6 +258,7 @@ pub fn has_codegen_attrs(self) -> bool {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::OpaqueTy
+            | DefKind::ImplTraitPlaceholder
             | DefKind::Impl
             | DefKind::Field
             | DefKind::TyParam
@@ -457,7 +462,7 @@ pub fn unresolved_segments(&self) -> usize {
 
 /// Different kinds of symbols can coexist even if they share the same textual name.
 /// Therefore, they each have a separate universe (known as a "namespace").
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Namespace {
     /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s
     /// (and, by extension, crates).
index ce60bab9e0275a422faa795d123e6806c8e0c448..c0f93b7c3382a32d3aa4cdbd4cd7085dc8c0313e 100644 (file)
@@ -259,7 +259,7 @@ pub fn to_ty(&self) -> Ty<'_> {
 
 #[derive(Debug, HashStable_Generic)]
 pub enum GenericArg<'hir> {
-    Lifetime(Lifetime),
+    Lifetime(&'hir Lifetime),
     Type(&'hir Ty<'hir>),
     Const(ConstArg),
     Infer(InferArg),
@@ -430,7 +430,7 @@ pub enum GenericBound<'hir> {
     Trait(PolyTraitRef<'hir>, TraitBoundModifier),
     // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
     LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
-    Outlives(Lifetime),
+    Outlives(&'hir Lifetime),
 }
 
 impl GenericBound<'_> {
@@ -756,7 +756,7 @@ pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
 pub struct WhereRegionPredicate<'hir> {
     pub span: Span,
     pub in_where_clause: bool,
-    pub lifetime: Lifetime,
+    pub lifetime: &'hir Lifetime,
     pub bounds: GenericBounds<'hir>,
 }
 
@@ -1059,6 +1059,35 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+// Equivalent to `Option<usize>`. That type takes up 16 bytes on 64-bit, but
+// this type only takes up 4 bytes, at the cost of being restricted to a
+// maximum value of `u32::MAX - 1`. In practice, this is more than enough.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable_Generic)]
+pub struct DotDotPos(u32);
+
+impl DotDotPos {
+    // Panics if n >= u32::MAX.
+    pub fn new(n: Option<usize>) -> Self {
+        match n {
+            Some(n) => {
+                assert!(n < u32::MAX as usize);
+                Self(n as u32)
+            }
+            None => Self(u32::MAX),
+        }
+    }
+
+    pub fn as_opt_usize(&self) -> Option<usize> {
+        if self.0 == u32::MAX { None } else { Some(self.0 as usize) }
+    }
+}
+
+impl fmt::Debug for DotDotPos {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.as_opt_usize().fmt(f)
+    }
+}
+
 #[derive(Debug, HashStable_Generic)]
 pub enum PatKind<'hir> {
     /// Represents a wildcard pattern (i.e., `_`).
@@ -1075,9 +1104,9 @@ pub enum PatKind<'hir> {
     Struct(QPath<'hir>, &'hir [PatField<'hir>], bool),
 
     /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
-    /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
+    /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position.
     /// `0 <= position <= subpats.len()`
-    TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], Option<usize>),
+    TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], DotDotPos),
 
     /// An or-pattern `A | B | C`.
     /// Invariant: `pats.len() >= 2`.
@@ -1089,7 +1118,7 @@ pub enum PatKind<'hir> {
     /// A tuple pattern (e.g., `(a, b)`).
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
     /// `0 <= position <= subpats.len()`
-    Tuple(&'hir [Pat<'hir>], Option<usize>),
+    Tuple(&'hir [Pat<'hir>], DotDotPos),
 
     /// A `box` pattern.
     Box(&'hir Pat<'hir>),
@@ -2372,6 +2401,14 @@ pub fn as_generic_param(&self) -> Option<(DefId, Ident)> {
             _ => None,
         }
     }
+
+    pub fn peel_refs(&self) -> &Self {
+        let mut final_ty = self;
+        while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
+            final_ty = &ty;
+        }
+        final_ty
+    }
 }
 
 /// Not represented directly in the AST; referred to by name through a `ty_path`.
@@ -2476,6 +2513,7 @@ pub struct OpaqueTy<'hir> {
     pub generics: &'hir Generics<'hir>,
     pub bounds: GenericBounds<'hir>,
     pub origin: OpaqueTyOrigin,
+    pub in_trait: bool,
 }
 
 /// From whence the opaque type came.
@@ -2499,7 +2537,7 @@ pub enum TyKind<'hir> {
     /// A raw pointer (i.e., `*const T` or `*mut T`).
     Ptr(MutTy<'hir>),
     /// A reference (i.e., `&'a T` or `&'a mut T`).
-    Rptr(Lifetime, MutTy<'hir>),
+    Rptr(&'hir Lifetime, MutTy<'hir>),
     /// A bare function (e.g., `fn(usize) -> bool`).
     BareFn(&'hir BareFnTy<'hir>),
     /// The never type (`!`).
@@ -2515,10 +2553,12 @@ pub enum TyKind<'hir> {
     ///
     /// The generic argument list contains the lifetimes (and in the future
     /// possibly parameters) that are actually bound on the `impl Trait`.
-    OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
+    ///
+    /// The last parameter specifies whether this opaque appears in a trait definition.
+    OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
-    TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime, TraitObjectSyntax),
+    TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
     /// Unused for now.
     Typeof(AnonConst),
     /// `TyKind::Infer` means the type should be inferred instead of it having been
@@ -3474,7 +3514,7 @@ mod size_asserts {
     static_assert_size!(ForeignItem<'_>, 72);
     static_assert_size!(ForeignItemKind<'_>, 40);
     #[cfg(not(bootstrap))]
-    static_assert_size!(GenericArg<'_>, 32);
+    static_assert_size!(GenericArg<'_>, 24);
     static_assert_size!(GenericBound<'_>, 48);
     static_assert_size!(Generics<'_>, 56);
     static_assert_size!(Impl<'_>, 80);
@@ -3486,17 +3526,17 @@ mod size_asserts {
     static_assert_size!(ItemKind<'_>, 48);
     static_assert_size!(Local<'_>, 64);
     static_assert_size!(Param<'_>, 32);
-    static_assert_size!(Pat<'_>, 88);
-    static_assert_size!(PatKind<'_>, 64);
+    static_assert_size!(Pat<'_>, 72);
+    static_assert_size!(PatKind<'_>, 48);
     static_assert_size!(Path<'_>, 48);
     static_assert_size!(PathSegment<'_>, 56);
     static_assert_size!(QPath<'_>, 24);
     static_assert_size!(Stmt<'_>, 32);
     static_assert_size!(StmtKind<'_>, 16);
     #[cfg(not(bootstrap))]
-    static_assert_size!(TraitItem<'static>, 88);
+    static_assert_size!(TraitItem<'_>, 88);
     #[cfg(not(bootstrap))]
     static_assert_size!(TraitItemKind<'_>, 48);
-    static_assert_size!(Ty<'_>, 72);
-    static_assert_size!(TyKind<'_>, 56);
+    static_assert_size!(Ty<'_>, 48);
+    static_assert_size!(TyKind<'_>, 32);
 }
index 20ec788463ac011e9938b6a4f0372125091afe1d..bf4ab06638bb15855eab275864e001dfacc3b400 100644 (file)
@@ -670,7 +670,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
         TyKind::Path(ref qpath) => {
             visitor.visit_qpath(qpath, typ.hir_id, typ.span);
         }
-        TyKind::OpaqueDef(item_id, lifetimes) => {
+        TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
             visitor.visit_nested_item(item_id);
             walk_list!(visitor, visit_generic_arg, lifetimes);
         }
index bc1ea1c4c736f4f3ba1bcc1e040b3c6d0bec0c34..ea17c1de9b70037c48ce828ea917c16e0434f591 100644 (file)
@@ -238,7 +238,6 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
     Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
     GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum,           GenericRequirement::None;
     Generator,               sym::generator,           gen_trait,                  Target::Trait,          GenericRequirement::Minimum(1);
-    GeneratorReturn,         sym::generator_return,    generator_return,           Target::AssocTy,        GenericRequirement::None;
     Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
     Pin,                     sym::pin,                 pin_type,                   Target::Struct,         GenericRequirement::None;
 
index 9baaf9390f2c5aa181bfde02841de865236339af..0c1819bb0c745ef45190480c5cb3460b5bd757b2 100644 (file)
@@ -35,7 +35,7 @@ pub trait EnumerateAndAdjustIterator {
     fn enumerate_and_adjust(
         self,
         expected_len: usize,
-        gap_pos: Option<usize>,
+        gap_pos: hir::DotDotPos,
     ) -> EnumerateAndAdjust<Self>
     where
         Self: Sized;
@@ -45,7 +45,7 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
     fn enumerate_and_adjust(
         self,
         expected_len: usize,
-        gap_pos: Option<usize>,
+        gap_pos: hir::DotDotPos,
     ) -> EnumerateAndAdjust<Self>
     where
         Self: Sized,
@@ -53,7 +53,7 @@ fn enumerate_and_adjust(
         let actual_len = self.len();
         EnumerateAndAdjust {
             enumerate: self.enumerate(),
-            gap_pos: gap_pos.unwrap_or(expected_len),
+            gap_pos: gap_pos.as_opt_usize().unwrap_or(expected_len),
             gap_len: expected_len - actual_len,
         }
     }
index 78bfd7191dba9b3f713377ff4830ac3667644988..5917d5e346e371d2a1da00c227dcf2924f4bf51f 100644 (file)
@@ -36,6 +36,7 @@ pub enum Target {
     GlobalAsm,
     TyAlias,
     OpaqueTy,
+    ImplTraitPlaceholder,
     Enum,
     Variant,
     Struct,
@@ -79,7 +80,13 @@ pub fn from_item(item: &Item<'_>) -> Target {
             ItemKind::ForeignMod { .. } => Target::ForeignMod,
             ItemKind::GlobalAsm(..) => Target::GlobalAsm,
             ItemKind::TyAlias(..) => Target::TyAlias,
-            ItemKind::OpaqueTy(..) => Target::OpaqueTy,
+            ItemKind::OpaqueTy(ref opaque) => {
+                if opaque.in_trait {
+                    Target::ImplTraitPlaceholder
+                } else {
+                    Target::OpaqueTy
+                }
+            }
             ItemKind::Enum(..) => Target::Enum,
             ItemKind::Struct(..) => Target::Struct,
             ItemKind::Union(..) => Target::Union,
@@ -103,6 +110,7 @@ pub fn from_def_kind(def_kind: DefKind) -> Target {
             DefKind::GlobalAsm => Target::GlobalAsm,
             DefKind::TyAlias => Target::TyAlias,
             DefKind::OpaqueTy => Target::OpaqueTy,
+            DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder,
             DefKind::Enum => Target::Enum,
             DefKind::Struct => Target::Struct,
             DefKind::Union => Target::Union,
@@ -157,6 +165,7 @@ pub fn name(self) -> &'static str {
             Target::GlobalAsm => "global asm",
             Target::TyAlias => "type alias",
             Target::OpaqueTy => "opaque type",
+            Target::ImplTraitPlaceholder => "opaque type in trait",
             Target::Enum => "enum",
             Target::Variant => "enum variant",
             Target::Struct => "struct",
index 1220755f44b30866aa3394a31fc4588e55d1fd02..35a58296e370e4aa0daf15caa39690d9dc7cc46c 100644 (file)
@@ -1761,7 +1761,8 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
             PatKind::TupleStruct(ref qpath, elts, ddpos) => {
                 self.print_qpath(qpath, true);
                 self.popen();
-                if let Some(ddpos) = ddpos {
+                if let Some(ddpos) = ddpos.as_opt_usize() {
+                    let ddpos = ddpos as usize;
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
                     if ddpos != 0 {
                         self.word_space(",");
@@ -1804,7 +1805,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
             }
             PatKind::Tuple(elts, ddpos) => {
                 self.popen();
-                if let Some(ddpos) = ddpos {
+                if let Some(ddpos) = ddpos.as_opt_usize() {
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
                     if ddpos != 0 {
                         self.word_space(",");
index 0196bd262179eac45c502a874f2b6d5f7df2cd4d..08460463998fdaca6829be873d158fe65f72aa6b 100644 (file)
@@ -61,6 +61,7 @@
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::Node;
@@ -1682,6 +1683,19 @@ enum Mismatch<'a> {
                                 pos.col.to_usize() + 1,
                             )
                         }
+                        (true, ty::Projection(proj))
+                            if self.tcx.def_kind(proj.item_def_id)
+                                == DefKind::ImplTraitPlaceholder =>
+                        {
+                            let sm = self.tcx.sess.source_map();
+                            let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
+                            format!(
+                                " (trait associated opaque type at <{}:{}:{}>)",
+                                sm.filename_for_diagnostics(&pos.file.name),
+                                pos.line,
+                                pos.col.to_usize() + 1,
+                            )
+                        }
                         (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
                         (false, _) => "".to_string(),
                     };
@@ -1758,7 +1772,7 @@ enum Mismatch<'a> {
 
         // In some (most?) cases cause.body_id points to actual body, but in some cases
         // it's an actual definition. According to the comments (e.g. in
-        // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
+        // librustc_typeck/check/compare_method.rs:compare_predicates_and_trait_impl_trait_tys) the latter
         // is relied upon by some other code. This might (or might not) need cleanup.
         let body_owner_def_id =
             self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
index f804569b0747ea0c45771f7f6be92de3fc603e02..b115ac8b3df954ba0f388bd07b27fe85e9a70fe1 100644 (file)
@@ -300,7 +300,7 @@ pub fn suggest_new_region_bound(
             continue;
         }
         match fn_return.kind {
-            TyKind::OpaqueDef(item_id, _) => {
+            TyKind::OpaqueDef(item_id, _, _) => {
                 let item = tcx.hir().item(item_id);
                 let ItemKind::OpaqueTy(opaque) = &item.kind else {
                     return;
index 178366f7d8045a9263ec22a7081bef423f103ffa..a79c982649afca775168aa27d61a4a875bad075a 100644 (file)
@@ -141,7 +141,7 @@ pub enum TokenKind {
     Unknown,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum DocStyle {
     Outer,
     Inner,
index 9a163cf207e97ba7dc6bc0a56d81c4af6c21edcc..7ca6ec5d9623475eaeabb13eba62360d85cd7d8c 100644 (file)
 use std::iter;
 use std::slice;
 
+type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync;
+type LateLintPassFactory =
+    dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync;
+
 /// Information about the registered lints.
 ///
 /// This is basically the subset of `Context` that we can
@@ -64,11 +68,11 @@ pub struct LintStore {
     /// interior mutability, we don't enforce this (and lints should, in theory,
     /// be compatible with being constructed more than once, though not
     /// necessarily in a sane manner. This is safe though.)
-    pub pre_expansion_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
-    pub early_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
-    pub late_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
+    pub pre_expansion_passes: Vec<Box<EarlyLintPassFactory>>,
+    pub early_passes: Vec<Box<EarlyLintPassFactory>>,
+    pub late_passes: Vec<Box<LateLintPassFactory>>,
     /// This is unique in that we construct them per-module, so not once.
-    pub late_module_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
+    pub late_module_passes: Vec<Box<LateLintPassFactory>>,
 
     /// Lints indexed by name.
     by_name: FxHashMap<String, TargetLint>,
@@ -186,14 +190,20 @@ pub fn register_pre_expansion_pass(
 
     pub fn register_late_pass(
         &mut self,
-        pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
+        pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
+        + 'static
+        + sync::Send
+        + sync::Sync,
     ) {
         self.late_passes.push(Box::new(pass));
     }
 
     pub fn register_late_mod_pass(
         &mut self,
-        pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
+        pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
+        + 'static
+        + sync::Send
+        + sync::Sync,
     ) {
         self.late_module_passes.push(Box::new(pass));
     }
@@ -558,7 +568,7 @@ pub trait LintPassObject: Sized {}
 
 impl LintPassObject for EarlyLintPassObject {}
 
-impl LintPassObject for LateLintPassObject {}
+impl LintPassObject for LateLintPassObject<'_> {}
 
 pub trait LintContext: Sized {
     type PassObject: LintPassObject;
@@ -949,8 +959,8 @@ pub(crate) fn new(
     }
 }
 
-impl LintContext for LateContext<'_> {
-    type PassObject = LateLintPassObject;
+impl<'tcx> LintContext for LateContext<'tcx> {
+    type PassObject = LateLintPassObject<'tcx>;
 
     /// Gets the overall compiler `Session` object.
     fn sess(&self) -> &Session {
index 8a336844dc2fac73f02f7c0fb003ae23ac77181c..66dc3ed59a3841b00b64b19196f14151382ab1e7 100644 (file)
@@ -306,12 +306,12 @@ fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) {
     }
 }
 
-struct LateLintPassObjects<'a> {
-    lints: &'a mut [LateLintPassObject],
+struct LateLintPassObjects<'a, 'tcx> {
+    lints: &'a mut [LateLintPassObject<'tcx>],
 }
 
 #[allow(rustc::lint_pass_impl_without_macro)]
-impl LintPass for LateLintPassObjects<'_> {
+impl LintPass for LateLintPassObjects<'_, '_> {
     fn name(&self) -> &'static str {
         panic!()
     }
@@ -329,7 +329,7 @@ macro_rules! expand_late_lint_pass_impl_methods {
 
 macro_rules! late_lint_pass_impl {
     ([], [$hir:tt], $methods:tt) => {
-        impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_> {
+        impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> {
             expand_late_lint_pass_impl_methods!([$hir], $methods);
         }
     };
@@ -382,7 +382,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
     late_lint_mod_pass(tcx, module_def_id, builtin_lints);
 
     let mut passes: Vec<_> =
-        unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
+        unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
 
     if !passes.is_empty() {
         late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
@@ -418,7 +418,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
 }
 
 fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
-    let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
+    let mut passes =
+        unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
 
     if !tcx.sess.opts.unstable_opts.no_interleave_lints {
         if !passes.is_empty() {
@@ -434,7 +435,7 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints
         }
 
         let mut passes: Vec<_> =
-            unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
+            unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
 
         for pass in &mut passes {
             tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run(
index 370a75cf700691d81485c3a13f15f54ccc40e93a..e0e6f1a8c080caf0b3dbbe2748262041acd6ca2b 100644 (file)
@@ -260,26 +260,41 @@ macro_rules! add_lint_group {
         )
     }
 
-    macro_rules! register_pass {
+    macro_rules! register_early_pass {
         ($method:ident, $ty:ident, $constructor:expr) => {
             store.register_lints(&$ty::get_lints());
             store.$method(|| Box::new($constructor));
         };
     }
 
-    macro_rules! register_passes {
+    macro_rules! register_late_pass {
+        ($method:ident, $ty:ident, $constructor:expr) => {
+            store.register_lints(&$ty::get_lints());
+            store.$method(|_| Box::new($constructor));
+        };
+    }
+
+    macro_rules! register_early_passes {
+        ($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
+            $(
+                register_early_pass!($method, $passes, $constructor);
+            )*
+        )
+    }
+
+    macro_rules! register_late_passes {
         ($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
             $(
-                register_pass!($method, $passes, $constructor);
+                register_late_pass!($method, $passes, $constructor);
             )*
         )
     }
 
     if no_interleave_lints {
-        pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass);
-        early_lint_passes!(register_passes, register_early_pass);
-        late_lint_passes!(register_passes, register_late_pass);
-        late_lint_mod_passes!(register_passes, register_late_mod_pass);
+        pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass);
+        early_lint_passes!(register_early_passes, register_early_pass);
+        late_lint_passes!(register_late_passes, register_late_pass);
+        late_lint_mod_passes!(register_late_passes, register_late_mod_pass);
     } else {
         store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
         store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
@@ -510,19 +525,19 @@ fn register_internals(store: &mut LintStore) {
     store.register_lints(&LintPassImpl::get_lints());
     store.register_early_pass(|| Box::new(LintPassImpl));
     store.register_lints(&DefaultHashTypes::get_lints());
-    store.register_late_pass(|| Box::new(DefaultHashTypes));
+    store.register_late_pass(|_| Box::new(DefaultHashTypes));
     store.register_lints(&QueryStability::get_lints());
-    store.register_late_pass(|| Box::new(QueryStability));
+    store.register_late_pass(|_| Box::new(QueryStability));
     store.register_lints(&ExistingDocKeyword::get_lints());
-    store.register_late_pass(|| Box::new(ExistingDocKeyword));
+    store.register_late_pass(|_| Box::new(ExistingDocKeyword));
     store.register_lints(&TyTyKind::get_lints());
-    store.register_late_pass(|| Box::new(TyTyKind));
+    store.register_late_pass(|_| Box::new(TyTyKind));
     store.register_lints(&Diagnostics::get_lints());
-    store.register_late_pass(|| Box::new(Diagnostics));
+    store.register_late_pass(|_| Box::new(Diagnostics));
     store.register_lints(&BadOptAccess::get_lints());
-    store.register_late_pass(|| Box::new(BadOptAccess));
+    store.register_late_pass(|_| Box::new(BadOptAccess));
     store.register_lints(&PassByValue::get_lints());
-    store.register_late_pass(|| Box::new(PassByValue));
+    store.register_late_pass(|_| Box::new(PassByValue));
     // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
     // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
     // these lints will trigger all of the time - change this once migration to diagnostic structs
index 90c554c2e040bf248c36969efdbccb8409cca4ea..666e61b85acfc8c21eeaac9705da51e98f5678d0 100644 (file)
@@ -244,4 +244,4 @@ fn name(&self) -> &'static str {
 
 /// A lint pass boxed up as a trait object.
 pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>;
-pub type LateLintPassObject = Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + 'static>;
+pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + sync::Send + 'tcx>;
index 05d2a214d0b79374b73454ab9c7592fe2d7b9255..24e18826048983f2e51cc4f0f2546328b8aa16a4 100644 (file)
@@ -134,7 +134,12 @@ extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool
   const bool CompileKernel = false;
 
   return wrap(createMemorySanitizerLegacyPassPass(
-      MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
+#if LLVM_VERSION_GE(14, 0)
+      MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel, /*EagerChecks=*/true}
+#else
+      MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}
+#endif
+  ));
 #else
   report_fatal_error("Legacy PM not supported with LLVM 15");
 #endif
@@ -930,18 +935,28 @@ LLVMRustOptimizeWithNewPassManager(
 
   if (SanitizerOptions) {
     if (SanitizerOptions->SanitizeMemory) {
+#if LLVM_VERSION_GE(14, 0)
+      MemorySanitizerOptions Options(
+          SanitizerOptions->SanitizeMemoryTrackOrigins,
+          SanitizerOptions->SanitizeMemoryRecover,
+          /*CompileKernel=*/false,
+          /*EagerChecks=*/true);
+#else
       MemorySanitizerOptions Options(
           SanitizerOptions->SanitizeMemoryTrackOrigins,
           SanitizerOptions->SanitizeMemoryRecover,
           /*CompileKernel=*/false);
+#endif
       OptimizerLastEPCallbacks.push_back(
         [Options](ModulePassManager &MPM, OptimizationLevel Level) {
-#if LLVM_VERSION_GE(14, 0)
+#if LLVM_VERSION_GE(14, 0) && LLVM_VERSION_LT(16, 0)
           MPM.addPass(ModuleMemorySanitizerPass(Options));
 #else
           MPM.addPass(MemorySanitizerPass(Options));
 #endif
+#if LLVM_VERSION_LT(16, 0)
           MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
+#endif
         }
       );
     }
@@ -972,7 +987,11 @@ LLVMRustOptimizeWithNewPassManager(
             /*UseAfterScope=*/true,
             AsanDetectStackUseAfterReturnMode::Runtime,
           };
+#if LLVM_VERSION_LT(16, 0)
           MPM.addPass(ModuleAddressSanitizerPass(opts));
+#else
+          MPM.addPass(AddressSanitizerPass(opts));
+#endif
 #else
           MPM.addPass(ModuleAddressSanitizerPass(
               /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
index b807663b10fd05fd0642d059e5eebb841fab9a61..f967ac9a4dc3ed25dc05f26b60107eef1d7edcd1 100644 (file)
@@ -847,6 +847,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::Use
         | DefKind::ForeignMod
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Impl
         | DefKind::Field => true,
         DefKind::TyParam
@@ -879,6 +880,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         | DefKind::ForeignMod
         | DefKind::TyAlias
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Enum
         | DefKind::Union
         | DefKind::Impl
@@ -967,6 +969,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::ForeignMod
         | DefKind::TyAlias
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Impl
         | DefKind::Trait
         | DefKind::TraitAlias
@@ -1003,6 +1006,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Impl
         | DefKind::Field
         | DefKind::TyParam
@@ -1032,6 +1036,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::Static(..)
         | DefKind::TyAlias
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::ForeignTy
         | DefKind::Impl
         | DefKind::AssocFn
@@ -1081,6 +1086,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
         | DefKind::Static(..)
         | DefKind::TyAlias
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::ForeignTy
         | DefKind::Impl
         | DefKind::AssocFn
index d5f151f0ed8e50a4116de32d27be14044bf589eb..e7c1abd126e044893aa805a08888281e8a0a2ff4 100644 (file)
@@ -90,6 +90,7 @@ impl FixedSizeEncoding for Option<$ty> {
         ( AnonConst                                )
         ( InlineConst                              )
         ( OpaqueTy                                 )
+        ( ImplTraitPlaceholder                     )
         ( Field                                    )
         ( LifetimeParam                            )
         ( GlobalAsm                                )
index 65d5f755f72482173aafada909ce89241ff9ebaf..9b1fedd0b533c404e0c51802426ea77f930ecddd 100644 (file)
@@ -101,6 +101,8 @@ macro_rules! arena_types {
             [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
 
             [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
+
+            [] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
         ]);
     )
 }
index 6217bffb8f76c206b4df1840eb12dd9586c7277a..5a65ec9a4765a21865125d834ea371c87cc4f092 100644 (file)
@@ -212,7 +212,13 @@ pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> {
                 ItemKind::Fn(..) => DefKind::Fn,
                 ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
                 ItemKind::Mod(..) => DefKind::Mod,
-                ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
+                ItemKind::OpaqueTy(ref opaque) => {
+                    if opaque.in_trait {
+                        DefKind::ImplTraitPlaceholder
+                    } else {
+                        DefKind::OpaqueTy
+                    }
+                }
                 ItemKind::TyAlias(..) => DefKind::TyAlias,
                 ItemKind::Enum(..) => DefKind::Enum,
                 ItemKind::Struct(..) => DefKind::Struct,
@@ -1187,7 +1193,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
                 ItemKind::ForeignMod { .. } => "foreign mod",
                 ItemKind::GlobalAsm(..) => "global asm",
                 ItemKind::TyAlias(..) => "ty",
-                ItemKind::OpaqueTy(..) => "opaque type",
+                ItemKind::OpaqueTy(ref opaque) => {
+                    if opaque.in_trait {
+                        "opaque type in trait"
+                    } else {
+                        "opaque type"
+                    }
+                }
                 ItemKind::Enum(..) => "enum",
                 ItemKind::Struct(..) => "struct",
                 ItemKind::Union(..) => "union",
index e149535bec7b56e13e66304a05f9c901d2163a19..1f7643a76afe505a3ab21c71399a36b439a9d837 100644 (file)
@@ -741,7 +741,7 @@ pub enum TerminatorKind<'tcx> {
 }
 
 /// Information about an assertion failure.
-#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)]
+#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
 pub enum AssertKind<O> {
     BoundsCheck { len: O, index: O },
     Overflow(BinOp, O, O),
index 9ccf5aea63ca83c634f4e6969894ef4bb4ea0984..02a9958525b2229ebd8fc3d825a2449ffee2ef10 100644 (file)
@@ -14,7 +14,7 @@
 
 pub use super::query::*;
 
-#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)]
+#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
 pub struct SwitchTargets {
     /// Possible values. The locations to branch to in each case
     /// are found in the corresponding indices from the `targets` vector.
index 4478b45cf1437e833d4faa8e4a775f5b2932439e..adf479c423604afe7b456af3055c30e21d4d75f6 100644 (file)
         separate_provide_extern
     }
 
+    query compare_predicates_and_trait_impl_trait_tys(key: DefId)
+        -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
+    {
+        desc { "better description please" }
+        separate_provide_extern
+    }
+
     query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
         eval_always
         desc { "running analysis passes on this crate" }
index ab7e5ba3a1067f56cae54bf1e87489231a80114b..a56fac7c4dd2ca8bd7b8a1beee419a7b195aff2d 100644 (file)
@@ -12,7 +12,7 @@
 use crate::infer::canonical::Canonical;
 use crate::ty::abstract_const::NotConstEvaluatable;
 use crate::ty::subst::SubstsRef;
-use crate::ty::{self, AdtKind, Predicate, Ty, TyCtxt};
+use crate::ty::{self, AdtKind, Ty, TyCtxt};
 
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diagnostic};
@@ -416,7 +416,7 @@ pub enum ObligationCauseCode<'tcx> {
     BinOp {
         rhs_span: Option<Span>,
         is_lit: bool,
-        output_pred: Option<Predicate<'tcx>>,
+        output_ty: Option<Ty<'tcx>>,
     },
 }
 
index c2e5decfc786ed2d8af6a9ac74df8cb58cfa746d..53e91e48c24d013275e5de85b3edd8ffa5fc9414 100644 (file)
@@ -1252,7 +1252,7 @@ pub fn create_global_ctxt(
         output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| {
-            s.fatal(&err);
+            s.emit_fatal(err);
         });
         let interners = CtxtInterners::new(arena);
         let common_types = CommonTypes::new(
index dd2f43210603abb6c0e13a1fe88bbd7489ed0541..648f5f7161fa6ead00fd41a5d75357a0e56ba909 100644 (file)
@@ -102,13 +102,25 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
     generics: &hir::Generics<'_>,
     err: &mut Diagnostic,
     trait_pred: PolyTraitPredicate<'tcx>,
+    associated_ty: Option<(&'static str, Ty<'tcx>)>,
 ) -> bool {
     if !trait_pred.is_suggestable(tcx, false) {
         return false;
     }
 
     let param_name = trait_pred.skip_binder().self_ty().to_string();
-    let constraint = trait_pred.print_modifiers_and_trait_path().to_string();
+    let mut constraint = trait_pred.print_modifiers_and_trait_path().to_string();
+
+    if let Some((name, term)) = associated_ty {
+        // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
+        // That should be extracted into a helper function.
+        if constraint.ends_with('>') {
+            constraint = format!("{}, {} = {}>", &constraint[..constraint.len() - 1], name, term);
+        } else {
+            constraint.push_str(&format!("<{} = {}>", name, term));
+        }
+    }
+
     let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
 
     // Skip, there is a param named Self
@@ -396,7 +408,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
             ) => {
                 self.0.push(ty);
             }
-            hir::TyKind::OpaqueDef(item_id, _) => {
+            hir::TyKind::OpaqueDef(item_id, _, _) => {
                 self.0.push(ty);
                 let item = self.1.item(item_id);
                 hir::intravisit::walk_item(self, item);
index da564c66a70e1519ea72e29c5886d3596bfab84f..279c8c8d6d16db9ff922115c0bbf7cb3bb94084d 100644 (file)
@@ -2,6 +2,7 @@
 use crate::ty::diagnostics::suggest_constraining_type_param;
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
+use hir::def::DefKind;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, Diagnostic, MultiSpan};
 use rustc_hir as hir;
@@ -538,7 +539,7 @@ fn foo(&self, x: T) -> T { x }
                             diag.span_label(p_span, "this type parameter");
                         }
                     }
-                    (ty::Projection(proj_ty), _) => {
+                    (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
                         self.expected_projection(
                             diag,
                             proj_ty,
@@ -547,7 +548,7 @@ fn foo(&self, x: T) -> T { x }
                             cause.code(),
                         );
                     }
-                    (_, ty::Projection(proj_ty)) => {
+                    (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
                         let msg = format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
index 37136ff2ef5d324170e01e7848c4c6d3ef723a3d..df72260597f9f5a5c63309a6a7268444098071b2 100644 (file)
@@ -915,12 +915,25 @@ pub struct CoercePredicate<'tcx> {
 }
 pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Term<'tcx> {
     ptr: NonZeroUsize,
     marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
 }
 
+impl Debug for Term<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let data = if let Some(ty) = self.ty() {
+            format!("Term::Ty({:?})", ty)
+        } else if let Some(ct) = self.ct() {
+            format!("Term::Ct({:?})", ct)
+        } else {
+            unreachable!()
+        };
+        f.write_str(&data)
+    }
+}
+
 impl<'tcx> From<Ty<'tcx>> for Term<'tcx> {
     fn from(ty: Ty<'tcx>) -> Self {
         TermKind::Ty(ty).pack()
@@ -2471,6 +2484,14 @@ pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
     pub fn is_const_default_method(self, def_id: DefId) -> bool {
         matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
     }
+
+    pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId {
+        while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
+            debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
+            def_id = self.parent(def_id);
+        }
+        def_id
+    }
 }
 
 /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
index 1ae3063dae4e7f51d3ffcb0704c3e27d0cccdd87..5166372878fe958c3e7aa94bb2a8136e7ab48b10 100644 (file)
@@ -632,7 +632,13 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
             ty::Foreign(def_id) => {
                 p!(print_def_path(def_id, &[]));
             }
-            ty::Projection(ref data) => p!(print(data)),
+            ty::Projection(ref data) => {
+                if self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder {
+                    return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
+                } else {
+                    p!(print(data))
+                }
+            }
             ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
             ty::Opaque(def_id, substs) => {
                 // FIXME(eddyb) print this with `print_def_path`.
@@ -916,12 +922,14 @@ fn pretty_print_opaque_impl_type(
                         // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
                         // unless we can find out what generator return type it comes from.
                         let term = if let Some(ty) = term.skip_binder().ty()
-                            && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind()
-                            && Some(*item_def_id) == tcx.lang_items().generator_return()
+                            && let ty::Projection(proj) = ty.kind()
+                            && let assoc = tcx.associated_item(proj.item_def_id)
+                            && assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
+                            && assoc.name == rustc_span::sym::Return
                         {
                             if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
                                 let return_ty = substs.as_generator().return_ty();
-                                if !return_ty.is_ty_infer() {
+                                if !return_ty.is_ty_var() {
                                     return_ty.into()
                                 } else {
                                     continue;
index 9fb91b5fe8700032585acf97aaf3b88d4a38c116..c5c5d3473418c3f9c5397d540feb844a88615a1c 100644 (file)
@@ -11,6 +11,7 @@
     TypeVisitor,
 };
 use crate::ty::{List, ParamEnv};
+use hir::def::DefKind;
 use polonius_engine::Atom;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
@@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> {
 
 impl<'tcx> ProjectionTy<'tcx> {
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        tcx.parent(self.item_def_id)
+        let parent = tcx.parent(self.item_def_id);
+        assert_eq!(tcx.def_kind(parent), DefKind::Trait);
+        parent
     }
 
     /// Extracts the underlying trait reference and own substs from this projection.
index a3837512bce2652c1155ca2672e06bcb1cd07bdb..0c73ae54bc31af83084703c146ea490d889b2a75 100644 (file)
@@ -651,6 +651,13 @@ pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
         ty::EarlyBinder(self.type_of(def_id))
     }
 
+    pub fn bound_trait_impl_trait_tys(
+        self,
+        def_id: DefId,
+    ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
+        ty::EarlyBinder(self.compare_predicates_and_trait_impl_trait_tys(def_id))
+    }
+
     pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
         ty::EarlyBinder(self.fn_sig(def_id))
     }
index 5e042c3acfce25897621b4b4215df93554a266ed..5f8cb578202103e26f38aca5f58639f022af4913 100644 (file)
@@ -666,7 +666,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // ignore the inputs to a projection, as they may not appear
         // in the normalized form
         if self.just_constrained {
-            if let ty::Projection(..) = t.kind() {
+            if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
                 return ControlFlow::CONTINUE;
             }
         }
index 7e09efe5972a3a100e9a5f07196861e60d5867c5..4968032b416b0ce1fdc4785b59d61e3319dff357 100644 (file)
@@ -338,7 +338,7 @@ fn lower_tuple_subpats(
         &mut self,
         pats: &'tcx [hir::Pat<'tcx>],
         expected_len: usize,
-        gap_pos: Option<usize>,
+        gap_pos: hir::DotDotPos,
     ) -> Vec<FieldPat<'tcx>> {
         pats.iter()
             .enumerate_and_adjust(expected_len, gap_pos)
index af4b35db3bace8bbaefb9b7808e01bd05aaf75ed..98156a94ec4b4c1f11dc6c146a8d439f4dbb55a2 100644 (file)
@@ -170,6 +170,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
index ad49227222b2c1772de880e45f7de602503749c6..be524db785bc0bfd84d87371d28ab1e7625879a3 100644 (file)
@@ -713,6 +713,14 @@ pub(crate) struct RemoveLet {
     pub span: Span,
 }
 
+#[derive(SessionDiagnostic)]
+#[diag(parser::use_eq_instead)]
+pub(crate) struct UseEqInstead {
+    #[primary_span]
+    #[suggestion_short(applicability = "machine-applicable", code = "=")]
+    pub span: Span,
+}
+
 // SnapshotParser is used to create a snapshot of the parser
 // without causing duplicate errors being emitted when the `Parser`
 // is dropped.
@@ -957,6 +965,14 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
             }
         }
 
+        if self.token.kind == TokenKind::EqEq
+            && self.prev_token.is_ident()
+            && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq)))
+        {
+            // Likely typo: `=` â†’ `==` in let expr or enum item
+            return Err(self.sess.create_err(UseEqInstead { span: self.token.span }));
+        }
+
         let expect = tokens_to_string(&expected);
         let actual = super::token_descr(&self.token);
         let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
index d0b46aa2c4530a97893b48e77f15c17603ee0990..bb684e784c58a65d854c37fea989baa6b55799c6 100644 (file)
@@ -661,6 +661,7 @@ fn check_doc_alias_value(
             | Target::GlobalAsm
             | Target::TyAlias
             | Target::OpaqueTy
+            | Target::ImplTraitPlaceholder
             | Target::Enum
             | Target::Variant
             | Target::Struct
index 625c854ea77a5dd7363aff05d995751edc5bf220..f141d7beeb921b895bc4903e5bc3995eac043416 100644 (file)
@@ -226,19 +226,16 @@ fn handle_tuple_field_pattern_match(
         lhs: &hir::Pat<'_>,
         res: Res,
         pats: &[hir::Pat<'_>],
-        dotdot: Option<usize>,
+        dotdot: hir::DotDotPos,
     ) {
         let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
             ty::Adt(adt, _) => adt.variant_of_res(res),
             _ => span_bug!(lhs.span, "non-ADT in tuple struct pattern"),
         };
-        let first_n = pats.iter().enumerate().take(dotdot.unwrap_or(pats.len()));
+        let dotdot = dotdot.as_opt_usize().unwrap_or(pats.len());
+        let first_n = pats.iter().enumerate().take(dotdot);
         let missing = variant.fields.len() - pats.len();
-        let last_n = pats
-            .iter()
-            .enumerate()
-            .skip(dotdot.unwrap_or(pats.len()))
-            .map(|(idx, pat)| (idx + missing, pat));
+        let last_n = pats.iter().enumerate().skip(dotdot).map(|(idx, pat)| (idx + missing, pat));
         for (idx, pat) in first_n.chain(last_n) {
             if let PatKind::Wild = pat.kind {
                 continue;
@@ -450,7 +447,7 @@ fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) {
     }
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
-        if let TyKind::OpaqueDef(item_id, _) = ty.kind {
+        if let TyKind::OpaqueDef(item_id, _, _) = ty.kind {
             let item = self.tcx.hir().item(item_id);
             intravisit::walk_item(self, item);
         }
index 81ac0e1b6d445a5455a69a9e9782ff788a62728b..075069feb52d5661f97c16fd338b02bc2852270d 100644 (file)
@@ -437,6 +437,11 @@ fn visit_generic_arg(&mut self, ga: &'v hir::GenericArg<'v>) {
         }
     }
 
+    fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
+        self.record("Lifetime", Id::Node(lifetime.hir_id), lifetime);
+        hir_visit::walk_lifetime(self, lifetime)
+    }
+
     fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
         self.record("Path", Id::None, path);
         hir_visit::walk_path(self, path)
index b2966f0d21801319b72f022890c1ee507e771180..afd423dc5fa1abfa29dcdd83cd14a14c134903e2 100644 (file)
@@ -596,6 +596,7 @@ fn update_macro_reachable_def(
             | DefKind::ForeignTy
             | DefKind::Fn
             | DefKind::OpaqueTy
+            | DefKind::ImplTraitPlaceholder
             | DefKind::AssocFn
             | DefKind::Trait
             | DefKind::TyParam
@@ -706,12 +707,12 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::Use(..) => {}
             // The interface is empty.
             hir::ItemKind::GlobalAsm(..) => {}
-            hir::ItemKind::OpaqueTy(..) => {
+            hir::ItemKind::OpaqueTy(ref opaque) => {
                 // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
                 // Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
                 // mark this as unreachable.
                 // See https://github.com/rust-lang/rust/issues/75100
-                if !self.tcx.sess.opts.actually_rustdoc {
+                if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc {
                     // FIXME: This is some serious pessimization intended to workaround deficiencies
                     // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
                     // reachable if they are returned via `impl Trait`, even from private functions.
@@ -2033,7 +2034,8 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
                 //   Visibility on them should have no effect, but to avoid the visibility
                 //   query failing on some items, we provide it for opaque types as well.
                 | Node::Item(hir::Item {
-                    kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..),
+                    kind: hir::ItemKind::Use(_, hir::UseKind::ListStem)
+                        | hir::ItemKind::OpaqueTy(..),
                     ..
                 }) => ty::Visibility::Restricted(tcx.parent_module(hir_id)),
                 // Visibilities of trait impl items are inherited from their traits
index 9cb735b36856c6aa09fa4d562683b42af7a36a42..81b67b758f7e12393262b31a362252a180032a29 100644 (file)
@@ -972,6 +972,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: ModChild) {
                 | DefKind::TyAlias
                 | DefKind::ForeignTy
                 | DefKind::OpaqueTy
+                | DefKind::ImplTraitPlaceholder
                 | DefKind::TraitAlias
                 | DefKind::AssocTy,
                 _,
index b37feb15890ba22ff080b55f34c231a67318536f..2d6e76c451bfa3ea1a525e167f187874338f06f9 100644 (file)
@@ -851,7 +851,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
                         // We include all lifetime parameters, either named or "Fresh".
                         // The order of those parameters does not matter, as long as it is
                         // deterministic.
-                        if let Some(async_node_id) = async_node_id {
+                        if let Some((async_node_id, _)) = async_node_id {
                             let mut extra_lifetime_params = this
                                 .r
                                 .extra_lifetime_params_map
index 101679aa6dc93fade0f481b74e1cd03dff34f7dd..6ff56f9a89114cd4367d7a18d0e8b71b3e98d912 100644 (file)
@@ -715,7 +715,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                 };
                 self.with(scope, |this| this.visit_ty(&mt.ty));
             }
-            hir::TyKind::OpaqueDef(item_id, lifetimes) => {
+            hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
                 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
                 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
index f7b7313d1049d2271a6930aa1863e4752c605d7c..749a78a7552ed366f9463672d1c59d4df3bf5ccd 100644 (file)
@@ -57,7 +57,7 @@
 use smallvec::{smallvec, SmallVec};
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
-use std::{cmp, fmt, ptr};
+use std::{fmt, ptr};
 
 use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
 use imports::{Import, ImportKind, ImportResolver, NameResolution};
@@ -163,7 +163,6 @@ enum ImplTraitContext {
     Universal(LocalDefId),
 }
 
-#[derive(Eq)]
 struct BindingError {
     name: Symbol,
     origin: BTreeSet<Span>,
@@ -171,24 +170,6 @@ struct BindingError {
     could_be_path: bool,
 }
 
-impl PartialOrd for BindingError {
-    fn partial_cmp(&self, other: &BindingError) -> Option<cmp::Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl PartialEq for BindingError {
-    fn eq(&self, other: &BindingError) -> bool {
-        self.name == other.name
-    }
-}
-
-impl Ord for BindingError {
-    fn cmp(&self, other: &BindingError) -> cmp::Ordering {
-        self.name.cmp(&other.name)
-    }
-}
-
 enum ResolutionError<'a> {
     /// Error E0401: can't use type or const parameters from outer function.
     GenericParamsFromOuterFunction(Res, HasGenericParams),
@@ -845,7 +826,7 @@ fn may_appear_after(
     }
 }
 
-#[derive(Debug, Default, Clone)]
+#[derive(Default, Clone)]
 pub struct ExternPreludeEntry<'a> {
     extern_crate_item: Option<&'a NameBinding<'a>>,
     pub introduced_by_item: bool,
index 6658892881d4b9bbf365734f6d83a9e938890c2c..94f222251d3dc7b0787ccbdd26698d10925d93a3 100644 (file)
@@ -1321,7 +1321,7 @@ fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
                         }),
                 }
             }
-            hir::TyKind::OpaqueDef(item_id, _) => {
+            hir::TyKind::OpaqueDef(item_id, _, _) => {
                 let item = self.tcx.hir().item(item_id);
                 self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item));
             }
index 89bca39512f52554250cab4ad0894128cae84752..ebe44a56449d32ec5b75ac6578f921316250759e 100644 (file)
@@ -685,6 +685,7 @@ fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
                 | HirDefKind::AssocTy
                 | HirDefKind::Trait
                 | HirDefKind::OpaqueTy
+                | HirDefKind::ImplTraitPlaceholder
                 | HirDefKind::TyParam,
                 def_id,
             ) => Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }),
index d1286c9b8b0dfeb083a4e2585f57aa3d4d8eb1a5..bae1828cd182df3f7f6380c4c325ed01e6cd30b7 100644 (file)
@@ -316,7 +316,7 @@ fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<
                 let text = format!("[{}; {}]", nested_ty.text, expr);
                 Ok(replace_text(nested_ty, text))
             }
-            hir::TyKind::OpaqueDef(item_id, _) => {
+            hir::TyKind::OpaqueDef(item_id, _, _) => {
                 let item = scx.tcx.hir().item(item_id);
                 item.make(offset, Some(item_id.hir_id()), scx)
             }
@@ -561,7 +561,13 @@ fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<
             hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
             hir::ItemKind::GlobalAsm(_) => Err("global asm"),
             hir::ItemKind::ExternCrate(_) => Err("extern crate"),
-            hir::ItemKind::OpaqueTy(..) => Err("opaque type"),
+            hir::ItemKind::OpaqueTy(ref opaque) => {
+                if opaque.in_trait {
+                    Err("opaque type in trait")
+                } else {
+                    Err("opaque type")
+                }
+            }
             // FIXME should implement this (e.g., pub use).
             hir::ItemKind::Use(..) => Err("import"),
         }
index 04bd685f19001ed99d9bb01e4ba4cd55389ba3c7..8bb3878fbbb4752c8d7f4371cab537ba6b39a658 100644 (file)
@@ -898,7 +898,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     let max_atomic_width = sess.target.max_atomic_width();
     let atomic_cas = sess.target.atomic_cas;
     let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| {
-        sess.fatal(&err);
+        sess.emit_fatal(err);
     });
 
     let mut ret = CrateConfig::default();
index 7252f1799dac178297ebcb0d024fea2444256e2f..3c93cfab183d24206e796c2ebd9e0e808fc00e0a 100644 (file)
@@ -1,10 +1,12 @@
 use std::num::NonZeroU32;
 
-use crate as rustc_session;
 use crate::cgu_reuse_tracker::CguReuse;
-use rustc_errors::MultiSpan;
+use crate::{self as rustc_session, SessionDiagnostic};
+use rustc_errors::{fluent, DiagnosticBuilder, Handler, MultiSpan};
 use rustc_macros::SessionDiagnostic;
 use rustc_span::{Span, Symbol};
+use rustc_target::abi::TargetDataLayoutErrors;
+use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
 
 #[derive(SessionDiagnostic)]
 #[diag(session::incorrect_cgu_reuse_type)]
@@ -43,3 +45,128 @@ pub struct FeatureDiagnosticForIssue {
 pub struct FeatureDiagnosticHelp {
     pub feature: Symbol,
 }
+
+impl SessionDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
+    fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, !> {
+        let mut diag;
+        match self {
+            TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
+                diag = sess.struct_fatal(fluent::session::target_invalid_address_space);
+                diag.set_arg("addr_space", addr_space);
+                diag.set_arg("cause", cause);
+                diag.set_arg("err", err);
+                diag
+            }
+            TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
+                diag = sess.struct_fatal(fluent::session::target_invalid_bits);
+                diag.set_arg("kind", kind);
+                diag.set_arg("bit", bit);
+                diag.set_arg("cause", cause);
+                diag.set_arg("err", err);
+                diag
+            }
+            TargetDataLayoutErrors::MissingAlignment { cause } => {
+                diag = sess.struct_fatal(fluent::session::target_missing_alignment);
+                diag.set_arg("cause", cause);
+                diag
+            }
+            TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
+                diag = sess.struct_fatal(fluent::session::target_invalid_alignment);
+                diag.set_arg("cause", cause);
+                diag.set_arg("err", err);
+                diag
+            }
+            TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
+                diag = sess.struct_fatal(fluent::session::target_inconsistent_architecture);
+                diag.set_arg("dl", dl);
+                diag.set_arg("target", target);
+                diag
+            }
+            TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
+                diag = sess.struct_fatal(fluent::session::target_inconsistent_pointer_width);
+                diag.set_arg("pointer_size", pointer_size);
+                diag.set_arg("target", target);
+                diag
+            }
+            TargetDataLayoutErrors::InvalidBitsSize { err } => {
+                diag = sess.struct_fatal(fluent::session::target_invalid_bits_size);
+                diag.set_arg("err", err);
+                diag
+            }
+        }
+    }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::not_circumvent_feature)]
+pub struct NotCircumventFeature;
+
+#[derive(SessionDiagnostic)]
+#[diag(session::linker_plugin_lto_windows_not_supported)]
+pub struct LinkerPluginToWindowsNotSupported;
+
+#[derive(SessionDiagnostic)]
+#[diag(session::profile_use_file_does_not_exist)]
+pub struct ProfileUseFileDoesNotExist<'a> {
+    pub path: &'a std::path::Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::profile_sample_use_file_does_not_exist)]
+pub struct ProfileSampleUseFileDoesNotExist<'a> {
+    pub path: &'a std::path::Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::target_requires_unwind_tables)]
+pub struct TargetRequiresUnwindTables;
+
+#[derive(SessionDiagnostic)]
+#[diag(session::sanitizer_not_supported)]
+pub struct SanitizerNotSupported {
+    pub us: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::sanitizers_not_supported)]
+pub struct SanitizersNotSupported {
+    pub us: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::cannot_mix_and_match_sanitizers)]
+pub struct CannotMixAndMatchSanitizers {
+    pub first: String,
+    pub second: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::cannot_enable_crt_static_linux)]
+pub struct CannotEnableCrtStaticLinux;
+
+#[derive(SessionDiagnostic)]
+#[diag(session::sanitizer_cfi_enabled)]
+pub struct SanitizerCfiEnabled;
+
+#[derive(SessionDiagnostic)]
+#[diag(session::unstable_virtual_function_elimination)]
+pub struct UnstableVirtualFunctionElimination;
+
+#[derive(SessionDiagnostic)]
+#[diag(session::unsupported_dwarf_version)]
+pub struct UnsupportedDwarfVersion {
+    pub dwarf_version: u32,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::target_stack_protector_not_supported)]
+pub struct StackProtectorNotSupportedForTarget<'a> {
+    pub stack_protector: StackProtector,
+    pub target_triple: &'a TargetTriple,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(session::split_debuginfo_unstable_platform)]
+pub struct SplitDebugInfoUnstablePlatform {
+    pub debuginfo: SplitDebuginfo,
+}
index 557edad548c64a2a3b0de2679bf7e65e41391b1c..caf9d582ab09970db94218b3da91b47994f89fe6 100644 (file)
@@ -2,6 +2,13 @@
 use crate::code_stats::CodeStats;
 pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
+use crate::errors::{
+    CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
+    NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
+    SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
+    SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
+    TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion,
+};
 use crate::parse::{add_feature_diagnostics, ParseSess};
 use crate::search_paths::{PathKind, SearchPath};
 use crate::{filesearch, lint};
@@ -235,6 +242,9 @@ fn check_miri_unleashed_features(&self) {
         if !unleashed_features.is_empty() {
             let mut must_err = false;
             // Create a diagnostic pointing at where things got unleashed.
+            // FIXME(#100717): needs eager translation/lists
+            #[allow(rustc::untranslatable_diagnostic)]
+            #[allow(rustc::diagnostic_outside_of_impl)]
             let mut diag = self.struct_warn("skipping const checks");
             for &(span, feature_gate) in unleashed_features.iter() {
                 // FIXME: `span_label` doesn't do anything, so we use "help" as a hack.
@@ -250,10 +260,7 @@ fn check_miri_unleashed_features(&self) {
             // If we should err, make sure we did.
             if must_err && self.has_errors().is_none() {
                 // We have skipped a feature gate, and not run into other errors... reject.
-                self.err(
-                    "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \
-                     gates, except when testing error paths in the CTFE engine",
-                );
+                self.emit_err(NotCircumventFeature);
             }
         }
     }
@@ -534,9 +541,13 @@ pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorGuaranteed>
             Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
         }
     }
+    #[allow(rustc::untranslatable_diagnostic)]
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.diagnostic().span_warn(sp, msg)
     }
+    #[allow(rustc::untranslatable_diagnostic)]
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_warn_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -585,6 +596,8 @@ pub fn span_note_without_error<S: Into<MultiSpan>>(
     ) {
         self.diagnostic().span_note_without_error(sp, msg)
     }
+    #[allow(rustc::untranslatable_diagnostic)]
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_note_without_error(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -1469,40 +1482,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         && sess.opts.cg.prefer_dynamic
         && sess.target.is_like_windows
     {
-        sess.err(
-            "Linker plugin based LTO is not supported together with \
-                  `-C prefer-dynamic` when targeting Windows-like targets",
-        );
+        sess.emit_err(LinkerPluginToWindowsNotSupported);
     }
 
     // Make sure that any given profiling data actually exists so LLVM can't
     // decide to silently skip PGO.
     if let Some(ref path) = sess.opts.cg.profile_use {
         if !path.exists() {
-            sess.err(&format!(
-                "File `{}` passed to `-C profile-use` does not exist.",
-                path.display()
-            ));
+            sess.emit_err(ProfileUseFileDoesNotExist { path });
         }
     }
 
     // Do the same for sample profile data.
     if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use {
         if !path.exists() {
-            sess.err(&format!(
-                "File `{}` passed to `-C profile-sample-use` does not exist.",
-                path.display()
-            ));
+            sess.emit_err(ProfileSampleUseFileDoesNotExist { path });
         }
     }
 
     // Unwind tables cannot be disabled if the target requires them.
     if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
         if sess.target.requires_uwtable && !include_uwtables {
-            sess.err(
-                "target requires unwind tables, they cannot be disabled with \
-                     `-C force-unwind-tables=no`.",
-            );
+            sess.emit_err(TargetRequiresUnwindTables);
         }
     }
 
@@ -1512,64 +1513,55 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     match unsupported_sanitizers.into_iter().count() {
         0 => {}
         1 => {
-            sess.err(&format!(
-                "{} sanitizer is not supported for this target",
-                unsupported_sanitizers
-            ));
+            sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
         }
         _ => {
-            sess.err(&format!(
-                "{} sanitizers are not supported for this target",
-                unsupported_sanitizers
-            ));
+            sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() });
         }
     }
     // Cannot mix and match sanitizers.
     let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
     if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
-        sess.err(&format!("`-Zsanitizer={first}` is incompatible with `-Zsanitizer={second}`"));
+        sess.emit_err(CannotMixAndMatchSanitizers {
+            first: first.to_string(),
+            second: second.to_string(),
+        });
     }
 
     // Cannot enable crt-static with sanitizers on Linux
     if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
-        sess.err(
-            "sanitizer is incompatible with statically linked libc, \
-                                disable it using `-C target-feature=-crt-static`",
-        );
+        sess.emit_err(CannotEnableCrtStaticLinux);
     }
 
     // LLVM CFI and VFE both require LTO.
     if sess.lto() != config::Lto::Fat {
         if sess.is_sanitizer_cfi_enabled() {
-            sess.err("`-Zsanitizer=cfi` requires `-Clto`");
+            sess.emit_err(SanitizerCfiEnabled);
         }
         if sess.opts.unstable_opts.virtual_function_elimination {
-            sess.err("`-Zvirtual-function-elimination` requires `-Clto`");
+            sess.emit_err(UnstableVirtualFunctionElimination);
         }
     }
 
     if sess.opts.unstable_opts.stack_protector != StackProtector::None {
         if !sess.target.options.supports_stack_protector {
-            sess.warn(&format!(
-                "`-Z stack-protector={}` is not supported for target {} and will be ignored",
-                sess.opts.unstable_opts.stack_protector, sess.opts.target_triple
-            ))
+            sess.emit_warning(StackProtectorNotSupportedForTarget {
+                stack_protector: sess.opts.unstable_opts.stack_protector,
+                target_triple: &sess.opts.target_triple,
+            });
         }
     }
 
     if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
         if dwarf_version > 5 {
-            sess.err(&format!("requested DWARF version {} is greater than 5", dwarf_version));
+            sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
         }
     }
 
     if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
         && !sess.opts.unstable_opts.unstable_options
     {
-        sess.err(&format!(
-            "`-Csplit-debuginfo={}` is unstable on this platform",
-            sess.split_debuginfo()
-        ));
+        sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
     }
 }
 
@@ -1614,14 +1606,20 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
     rustc_errors::Handler::with_emitter(true, None, emitter)
 }
 
+#[allow(rustc::untranslatable_diagnostic)]
+#[allow(rustc::diagnostic_outside_of_impl)]
 pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
     early_error_handler(output).struct_err(msg).emit()
 }
 
+#[allow(rustc::untranslatable_diagnostic)]
+#[allow(rustc::diagnostic_outside_of_impl)]
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
     early_error_handler(output).struct_fatal(msg).emit()
 }
 
+#[allow(rustc::untranslatable_diagnostic)]
+#[allow(rustc::diagnostic_outside_of_impl)]
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
     early_error_handler(output).struct_warn(msg).emit()
 }
index 75b1dfc856ac715c0877b252b45df38dbf01dd25..f2876344c65ede23ebd8577e2ac7753d279f0923 100644 (file)
         gen_future,
         gen_kill,
         generator,
-        generator_return,
         generator_state,
         generators,
         generic_arg_infer,
         require,
         residual,
         result,
+        return_position_impl_trait_in_trait,
         rhs,
         rintf32,
         rintf64,
index bcaf209f84b65dcf6e14ac18c0adbc16595e0e5f..ec334e5887ab765bfcacababdd2823bfe026a7f1 100644 (file)
@@ -7,7 +7,7 @@
 use std::convert::{TryFrom, TryInto};
 use std::fmt;
 use std::iter::Step;
-use std::num::NonZeroUsize;
+use std::num::{NonZeroUsize, ParseIntError};
 use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
@@ -69,34 +69,46 @@ fn default() -> TargetDataLayout {
     }
 }
 
+pub enum TargetDataLayoutErrors<'a> {
+    InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
+    InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
+    MissingAlignment { cause: &'a str },
+    InvalidAlignment { cause: &'a str, err: String },
+    InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
+    InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
+    InvalidBitsSize { err: String },
+}
+
 impl TargetDataLayout {
-    pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
+    pub fn parse<'a>(target: &'a Target) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
         // Parse an address space index from a string.
-        let parse_address_space = |s: &str, cause: &str| {
+        let parse_address_space = |s: &'a str, cause: &'a str| {
             s.parse::<u32>().map(AddressSpace).map_err(|err| {
-                format!("invalid address space `{}` for `{}` in \"data-layout\": {}", s, cause, err)
+                TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err }
             })
         };
 
         // Parse a bit count from a string.
-        let parse_bits = |s: &str, kind: &str, cause: &str| {
-            s.parse::<u64>().map_err(|err| {
-                format!("invalid {} `{}` for `{}` in \"data-layout\": {}", kind, s, cause, err)
+        let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
+            s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits {
+                kind,
+                bit: s,
+                cause,
+                err,
             })
         };
 
         // Parse a size string.
-        let size = |s: &str, cause: &str| parse_bits(s, "size", cause).map(Size::from_bits);
+        let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
 
         // Parse an alignment string.
-        let align = |s: &[&str], cause: &str| {
+        let align = |s: &[&'a str], cause: &'a str| {
             if s.is_empty() {
-                return Err(format!("missing alignment for `{}` in \"data-layout\"", cause));
+                return Err(TargetDataLayoutErrors::MissingAlignment { cause });
             }
             let align_from_bits = |bits| {
-                Align::from_bits(bits).map_err(|err| {
-                    format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err)
-                })
+                Align::from_bits(bits)
+                    .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
             };
             let abi = parse_bits(s[0], "alignment", cause)?;
             let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
@@ -158,25 +170,24 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
 
         // Perform consistency checks against the Target information.
         if dl.endian != target.endian {
-            return Err(format!(
-                "inconsistent target specification: \"data-layout\" claims \
-                 architecture is {}-endian, while \"target-endian\" is `{}`",
-                dl.endian.as_str(),
-                target.endian.as_str(),
-            ));
+            return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
+                dl: dl.endian.as_str(),
+                target: target.endian.as_str(),
+            });
         }
 
         let target_pointer_width: u64 = target.pointer_width.into();
         if dl.pointer_size.bits() != target_pointer_width {
-            return Err(format!(
-                "inconsistent target specification: \"data-layout\" claims \
-                 pointers are {}-bit, while \"target-pointer-width\" is `{}`",
-                dl.pointer_size.bits(),
-                target.pointer_width
-            ));
+            return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
+                pointer_size: dl.pointer_size.bits(),
+                target: target.pointer_width,
+            });
         }
 
-        dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?;
+        dl.c_enum_min_size = match Integer::from_size(Size::from_bits(target.c_enum_min_bits)) {
+            Ok(bits) => bits,
+            Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }),
+        };
 
         Ok(dl)
     }
index b012073f7719d2d4270ea7363483b9c393b75fcb..ecbeb9d79b118923057e35e56b48e91f911e1de2 100644 (file)
@@ -25,8 +25,7 @@
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
     GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
-    ProjectionPredicate, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
-    TypeVisitable,
+    ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
 };
 use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_session::Limit;
@@ -174,7 +173,7 @@ fn suggest_restricting_param_bound(
         &self,
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
-        proj_pred: Option<ty::PolyProjectionPredicate<'tcx>>,
+        associated_item: Option<(&'static str, Ty<'tcx>)>,
         body_id: hir::HirId,
     );
 
@@ -467,7 +466,7 @@ fn suggest_restricting_param_bound(
         &self,
         mut err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
-        proj_pred: Option<ty::PolyProjectionPredicate<'tcx>>,
+        associated_ty: Option<(&'static str, Ty<'tcx>)>,
         body_id: hir::HirId,
     ) {
         let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
@@ -604,21 +603,18 @@ fn suggest_restricting_param_bound(
                         trait_pred.print_modifiers_and_trait_path().to_string()
                     );
 
-                    if let Some(proj_pred) = proj_pred {
-                        let ProjectionPredicate { projection_ty, term } = proj_pred.skip_binder();
-                        let item = self.tcx.associated_item(projection_ty.item_def_id);
-
+                    if let Some((name, term)) = associated_ty {
                         // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
                         // That should be extracted into a helper function.
                         if constraint.ends_with('>') {
                             constraint = format!(
-                                "{}, {}={}>",
+                                "{}, {} = {}>",
                                 &constraint[..constraint.len() - 1],
-                                item.name,
+                                name,
                                 term
                             );
                         } else {
-                            constraint.push_str(&format!("<{}={}>", item.name, term));
+                            constraint.push_str(&format!("<{} = {}>", name, term));
                         }
                     }
 
@@ -648,7 +644,13 @@ fn suggest_restricting_param_bound(
                     ..
                 }) if !param_ty => {
                     // Missing generic type parameter bound.
-                    if suggest_arbitrary_trait_bound(self.tcx, generics, &mut err, trait_pred) {
+                    if suggest_arbitrary_trait_bound(
+                        self.tcx,
+                        generics,
+                        &mut err,
+                        trait_pred,
+                        associated_ty,
+                    ) {
                         return;
                     }
                 }
index 8a093bf4281cb751b7a32556587611beabe8dc80..8a65262a007230d0858e43ecf1a35f02512b3463 100644 (file)
@@ -32,6 +32,7 @@
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
+use rustc_middle::ty::DefIdTree;
 use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 
@@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> {
 
     /// From an "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
+
+    ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
 }
 
 enum ProjectionCandidateSet<'tcx> {
@@ -1265,6 +1268,8 @@ fn project<'cx, 'tcx>(
 
     let mut candidates = ProjectionCandidateSet::None;
 
+    assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
+
     // Make sure that the following procedures are kept in order. ParamEnv
     // needs to be first because it has highest priority, and Select checks
     // the return value of push_candidate which assumes it's ran at last.
@@ -1303,6 +1308,48 @@ fn project<'cx, 'tcx>(
     }
 }
 
+/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the
+/// corresponding trait ref. If this yields an `impl`, then we're able to project
+/// to a concrete type, since we have an `impl`'s method  to provide the RPITIT.
+fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    candidate_set: &mut ProjectionCandidateSet<'tcx>,
+) {
+    let tcx = selcx.tcx();
+    if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+        let trait_def_id = tcx.parent(trait_fn_def_id);
+        let trait_substs =
+            obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
+        // FIXME(named-returns): Binders
+        let trait_predicate =
+            ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs })
+                .to_poly_trait_predicate();
+
+        let _ =
+            selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
+                Ok(Some(super::ImplSource::UserDefined(data))) => {
+                    candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
+                    Ok(())
+                }
+                Ok(None) => {
+                    candidate_set.mark_ambiguous();
+                    return Err(());
+                }
+                Ok(Some(_)) => {
+                    // Don't know enough about the impl to provide a useful signature
+                    return Err(());
+                }
+                Err(e) => {
+                    debug!(error = ?e, "selection error");
+                    candidate_set.mark_error(e);
+                    return Err(());
+                }
+            });
+    }
+}
+
 /// The first thing we have to do is scan through the parameter
 /// environment to see whether there are any projection predicates
 /// there that can answer this question.
@@ -1465,6 +1512,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
+    // Can't assemble candidate from impl for RPITIT
+    if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+        return;
+    }
+
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
     let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
@@ -1740,6 +1792,9 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, impl_source)
         }
+        ProjectionCandidate::ImplTraitInTrait(data) => {
+            confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
+        }
     };
 
     // When checking for cycle during evaluation, we compare predicates with
@@ -2102,6 +2157,72 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     }
 }
 
+fn confirm_impl_trait_in_trait_candidate<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+    let mut obligations = data.nested;
+
+    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
+        return Progress { term: tcx.ty_error().into(), obligations };
+    };
+    if !leaf_def.item.defaultness(tcx).has_value() {
+        return Progress { term: tcx.ty_error().into(), obligations };
+    }
+
+    let impl_fn_def_id = leaf_def.item.def_id;
+    let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs);
+
+    let cause = ObligationCause::new(
+        obligation.cause.span,
+        obligation.cause.body_id,
+        super::ItemObligation(impl_fn_def_id),
+    );
+    let predicates = normalize_with_depth_to(
+        selcx,
+        obligation.param_env,
+        cause.clone(),
+        obligation.recursion_depth + 1,
+        tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
+        &mut obligations,
+    );
+    obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map(
+        |(pred, span)| {
+            Obligation::with_depth(
+                ObligationCause::new(
+                    obligation.cause.span,
+                    obligation.cause.body_id,
+                    if span.is_dummy() {
+                        super::ItemObligation(impl_fn_def_id)
+                    } else {
+                        super::BindingObligation(impl_fn_def_id, span)
+                    },
+                ),
+                obligation.recursion_depth + 1,
+                obligation.param_env,
+                pred,
+            )
+        },
+    ));
+
+    let ty = super::normalize_to(
+        selcx,
+        obligation.param_env,
+        cause.clone(),
+        tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
+            .map_bound(|tys| {
+                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id])
+            })
+            .subst(tcx, impl_fn_substs),
+        &mut obligations,
+    );
+
+    Progress { term: ty.into(), obligations }
+}
+
 // Get obligations corresponding to the predicates from the where-clause of the
 // associated type itself.
 // Note: `feature(generic_associated_types)` is required to write such
index a77ea440aaaea90fb02f9d27c333a82eb8468c47..f0d8c240ea588bbcdde326ef58e5c240de00e5bc 100644 (file)
@@ -51,6 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
index 801063583e633e42928ee7b42e1ab92092d4bf19..d9789d5aaf0312e9be5018dc95e1f5810d77c410 100644 (file)
@@ -2360,7 +2360,7 @@ pub fn res_to_ty(
 
         let span = path.span;
         match path.res {
-            Res::Def(DefKind::OpaqueTy, did) => {
+            Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
                 // Check for desugared `impl Trait`.
                 assert!(ty::is_impl_trait_defn(tcx, did).is_none());
                 let item_segment = path.segments.split_last().unwrap();
@@ -2627,13 +2627,13 @@ fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
                 self.res_to_ty(opt_self_ty, path, false)
             }
-            hir::TyKind::OpaqueDef(item_id, lifetimes) => {
+            hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
                 let opaque_ty = tcx.hir().item(item_id);
                 let def_id = item_id.def_id.to_def_id();
 
                 match opaque_ty.kind {
                     hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
-                        self.impl_trait_ty_to_ty(def_id, lifetimes, origin)
+                        self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait)
                     }
                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 }
@@ -2703,6 +2703,7 @@ fn impl_trait_ty_to_ty(
         def_id: DefId,
         lifetimes: &[hir::GenericArg<'_>],
         origin: OpaqueTyOrigin,
+        in_trait: bool,
     ) -> Ty<'tcx> {
         debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
         let tcx = self.tcx();
@@ -2746,7 +2747,7 @@ fn impl_trait_ty_to_ty(
         });
         debug!("impl_trait_ty_to_ty: substs={:?}", substs);
 
-        tcx.mk_opaque(def_id, substs)
+        if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) }
     }
 
     pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
@@ -2940,8 +2941,9 @@ fn validate_late_bound_regions(
                 // though we can easily give a hint that ought to be
                 // relevant.
                 err.note(
-                    "lifetimes appearing in an associated type are not considered constrained",
+                    "lifetimes appearing in an associated or opaque type are not considered constrained",
                 );
+                err.note("consider introducing a named lifetime parameter");
             }
 
             err.emit();
index bc3fec6e7d66a371dc57dfb0fd8a0039a30838fa..55cbaf71e7cfdd9b8f49a257fde93e89318e6df1 100644 (file)
@@ -4,6 +4,7 @@
 
 use crate::astconv::AstConv;
 use crate::rustc_middle::ty::subst::Subst;
+use hir::def::DefKind;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
@@ -680,9 +681,18 @@ fn deduce_future_output_from_obligations(
                 .map(|e| e.map_bound(|e| *e).transpose_tuple2())
                 .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
             ty::Error(_) => return None,
+            ty::Projection(proj)
+                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            {
+                self.tcx
+                    .bound_explicit_item_bounds(proj.item_def_id)
+                    .transpose_iter()
+                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
+                    .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))?
+            }
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
-                "async fn generator return type not an inference variable"
+                "async fn generator return type not an inference variable: {ret_ty}"
             ),
         };
 
index b6bc244d2b14447a5c3d4a96c942a87f8ca0f58a..1152a2477a2a8bfa5dce09d7a4a2bc8280dcae3f 100644 (file)
@@ -1,18 +1,22 @@
 use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
-use rustc_data_structures::fx::FxHashSet;
+use hir::def_id::DefId;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{self, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::util::ExplicitSelf;
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::ty::{
+    self, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+};
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
@@ -64,10 +68,7 @@ pub(crate) fn compare_impl_method<'tcx>(
         return;
     }
 
-    if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
-    {
-        return;
-    }
+    tcx.ensure().compare_predicates_and_trait_impl_trait_tys(impl_m.def_id);
 }
 
 /// This function is best explained by example. Consider a trait:
@@ -136,13 +137,15 @@ pub(crate) fn compare_impl_method<'tcx>(
 ///
 /// Finally we register each of these predicates as an obligation and check that
 /// they hold.
-fn compare_predicate_entailment<'tcx>(
+pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    impl_m_span: Span,
-    trait_m: &ty::AssocItem,
-    impl_trait_ref: ty::TraitRef<'tcx>,
-) -> Result<(), ErrorGuaranteed> {
+    def_id: DefId,
+) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
+    let impl_m = tcx.opt_associated_item(def_id).unwrap();
+    let impl_m_span = tcx.def_span(def_id);
+    let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
+    let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
+
     let trait_to_impl_substs = impl_trait_ref.substs;
 
     // This node-id should be used for the `body_id` field on each
@@ -161,6 +164,7 @@ fn compare_predicate_entailment<'tcx>(
             kind: impl_m.kind,
         },
     );
+    let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
 
     // Create mapping from impl to placeholder.
     let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
@@ -266,6 +270,13 @@ fn compare_predicate_entailment<'tcx>(
 
         let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
+        let mut collector =
+            ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
+        // FIXME(RPITIT): This should only be needed on the output type, but
+        // RPITIT placeholders shouldn't show up anywhere except for there,
+        // so I think this is fine.
+        let trait_sig = trait_sig.fold_with(&mut collector);
+
         // Next, add all inputs and output as well-formed tys. Importantly,
         // we have to do this before normalization, since the normalized ty may
         // not contain the input parameters. See issue #87748.
@@ -411,10 +422,115 @@ fn compare_predicate_entailment<'tcx>(
             &outlives_environment,
         );
 
-        Ok(())
+        let mut collected_tys = FxHashMap::default();
+        for (def_id, (ty, substs)) in collector.types {
+            match infcx.fully_resolve(ty) {
+                Ok(ty) => {
+                    // `ty` contains free regions that we created earlier while liberating the
+                    // trait fn signature.  However, projection normalization expects `ty` to
+                    // contains `def_id`'s early-bound regions.
+                    let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
+                    debug!(?id_substs, ?substs);
+                    let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> = substs
+                        .iter()
+                        .enumerate()
+                        .map(|(index, arg)| (arg, id_substs[index]))
+                        .collect();
+                    debug!(?map);
+
+                    let ty = tcx.fold_regions(ty, |region, _| {
+                        if let ty::ReFree(_) = region.kind() {
+                            map[&region.into()].expect_region()
+                        } else {
+                            region
+                        }
+                    });
+                    collected_tys.insert(def_id, ty);
+                }
+                Err(err) => {
+                    tcx.sess.delay_span_bug(
+                        return_span,
+                        format!("could not fully resolve: {ty} => {err:?}"),
+                    );
+                    collected_tys.insert(def_id, tcx.ty_error());
+                }
+            }
+        }
+
+        Ok(&*tcx.arena.alloc(collected_tys))
     })
 }
 
+struct ImplTraitInTraitCollector<'a, 'tcx> {
+    ocx: &'a ObligationCtxt<'a, 'tcx>,
+    types: FxHashMap<DefId, (Ty<'tcx>, ty::SubstsRef<'tcx>)>,
+    span: Span,
+    param_env: ty::ParamEnv<'tcx>,
+    body_id: hir::HirId,
+}
+
+impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
+    fn new(
+        ocx: &'a ObligationCtxt<'a, 'tcx>,
+        span: Span,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+    ) -> Self {
+        ImplTraitInTraitCollector { ocx, types: FxHashMap::default(), span, param_env, body_id }
+    }
+}
+
+impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.ocx.infcx.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if let ty::Projection(proj) = ty.kind()
+            && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+        {
+            if let Some((ty, _)) = self.types.get(&proj.item_def_id) {
+                return *ty;
+            }
+            //FIXME(RPITIT): Deny nested RPITIT in substs too
+            if proj.substs.has_escaping_bound_vars() {
+                bug!("FIXME(RPITIT): error here");
+            }
+            // Replace with infer var
+            let infer_ty = self.ocx.infcx.next_ty_var(TypeVariableOrigin {
+                span: self.span,
+                kind: TypeVariableOriginKind::MiscVariable,
+            });
+            self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
+            // Recurse into bounds
+            for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
+                let pred_span = pred.0.1;
+
+                let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
+                let pred = pred.fold_with(self);
+                let pred = self.ocx.normalize(
+                    ObligationCause::misc(self.span, self.body_id),
+                    self.param_env,
+                    pred,
+                );
+
+                self.ocx.register_obligation(traits::Obligation::new(
+                    ObligationCause::new(
+                        self.span,
+                        self.body_id,
+                        ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span),
+                    ),
+                    self.param_env,
+                    pred,
+                ));
+            }
+            infer_ty
+        } else {
+            ty.super_fold_with(self)
+        }
+    }
+}
+
 fn check_region_bounds_on_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
@@ -1191,7 +1307,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
     })();
 }
 
-/// The equivalent of [compare_predicate_entailment], but for associated types
+/// The equivalent of [compare_predicates_and_trait_impl_trait_tys], but for associated types
 /// instead of associated functions.
 fn compare_type_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
index 0e6a8ef8265b2c15e8e2dbb965ad18ad87e243ab..21392001364138f601c5c42b30aa6a8c9a4a7c1b 100644 (file)
@@ -1305,31 +1305,30 @@ fn check_expr_array(
     }
 
     fn suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64) {
-        if let Some(parent_hir_id) = self.tcx.hir().find_parent_node(expr.hir_id) {
-            let ty = match self.tcx.hir().find(parent_hir_id) {
-                Some(
-                    hir::Node::Local(hir::Local { ty: Some(ty), .. })
-                    | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }),
-                ) => Some(ty),
-                _ => None,
-            };
-            if let Some(ty) = ty
-                && let hir::TyKind::Array(_, length) = ty.kind
-                && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
-                && let Some(span) = self.tcx.hir().opt_span(hir_id)
-            {
-                match self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
-                    Some(mut err) => {
-                        err.span_suggestion(
-                            span,
-                            "consider specifying the array length",
-                            array_len,
-                            Applicability::MaybeIncorrect,
-                        );
-                        err.emit();
-                    }
-                    None => ()
+        let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| {
+            !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }))
+        });
+        let Some((_,
+            hir::Node::Local(hir::Local { ty: Some(ty), .. })
+            | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }))
+        ) = parent_node else {
+            return
+        };
+        if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
+            && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
+            && let Some(span) = self.tcx.hir().opt_span(hir_id)
+        {
+            match self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
+                Some(mut err) => {
+                    err.span_suggestion(
+                        span,
+                        "consider specifying the array length",
+                        array_len,
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.emit();
                 }
+                None => ()
             }
         }
     }
index b07edd43c0716e430cc408a537648d98e5d3ebdc..a40478db96901719f5392fff5481c634f393aaaa 100644 (file)
@@ -409,7 +409,7 @@ pub(in super::super) fn normalize_op_associated_types_in_as_infer_ok<T>(
                     rhs_span: opt_input_expr.map(|expr| expr.span),
                     is_lit: opt_input_expr
                         .map_or(false, |expr| matches!(expr.kind, ExprKind::Lit(_))),
-                    output_pred: None,
+                    output_ty: None,
                 },
             ),
             self.param_env,
index 721ebba6514779066e486d8214ebe3ab2bd76aea..d8fe63dbf084aee940e8bfb7a283a647c6e6b754 100644 (file)
@@ -333,10 +333,10 @@ fn check_asm_operand_type(
                         let mut err = lint.build(msg);
                         err.span_label(expr.span, "for this argument");
                         err.help(&format!(
-                            "use the `{suggested_modifier}` modifier to have the register formatted as `{suggested_result}`",
+                            "use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}`",
                         ));
                         err.help(&format!(
-                            "or use the `{default_modifier}` modifier to keep the default formatting of `{default_result}`",
+                            "or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`",
                         ));
                         err.emit();
                     },
index c597efbe7468ebce3b6d12ffb5bd6967a242b186..249e9c66ba72ad958334b0613d826abefdaee4a7 100644 (file)
 use rustc_infer::infer::{self, InferOk};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
-use rustc_middle::ty::{
-    self, AssocKind, DefIdTree, GenericParamDefKind, ProjectionPredicate, ProjectionTy,
-    ToPredicate, Ty, TypeVisitable,
-};
+use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
@@ -337,22 +334,7 @@ pub(super) fn obligation_for_op_method(
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
-        let opt_output_ty =
-            expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
-        let opt_output_assoc_item = self.tcx.associated_items(trait_def_id).find_by_name_and_kind(
-            self.tcx,
-            Ident::from_str("Output"),
-            AssocKind::Type,
-            trait_def_id,
-        );
-        let output_pred =
-            opt_output_ty.zip(opt_output_assoc_item).map(|(output_ty, output_assoc_item)| {
-                ty::Binder::dummy(ty::PredicateKind::Projection(ProjectionPredicate {
-                    projection_ty: ProjectionTy { substs, item_def_id: output_assoc_item.def_id },
-                    term: output_ty.into(),
-                }))
-                .to_predicate(self.tcx)
-            });
+        let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
 
         (
             traits::Obligation::new(
@@ -363,7 +345,7 @@ pub(super) fn obligation_for_op_method(
                         rhs_span: opt_input_expr.map(|expr| expr.span),
                         is_lit: opt_input_expr
                             .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
-                        output_pred,
+                        output_ty,
                     },
                 ),
                 self.param_env,
@@ -518,7 +500,7 @@ fn construct_obligation_for_trait(
                     rhs_span: opt_input_expr.map(|expr| expr.span),
                     is_lit: opt_input_expr
                         .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
-                    output_pred: None,
+                    output_ty: None,
                 },
             )
         } else {
index 69eb34b5f802d25b6f5073377be737bf91893b7f..8811b38fc555afb364efbaa12868cebbb67c9adf 100644 (file)
 use crate::util::common::indenter;
 
 use self::coercion::DynamicCoerceMany;
+use self::compare_method::compare_predicates_and_trait_impl_trait_tys;
 use self::region::region_scope_tree;
 pub use self::Expectation::*;
 
@@ -249,6 +250,7 @@ pub fn provide(providers: &mut Providers) {
         used_trait_imports,
         check_mod_item_types,
         region_scope_tree,
+        compare_predicates_and_trait_impl_trait_tys,
         ..*providers
     };
 }
index 0d9dbb5bc11c24ece1ef00c329fff37c1cf5a55f..4754717c29aba777494a494f9822e8f7b9cfdad9 100644 (file)
@@ -11,9 +11,8 @@
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
-use rustc_middle::ty::{
-    self, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
-};
+use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
@@ -22,8 +21,6 @@
 use rustc_trait_selection::traits::{FulfillmentError, TraitEngine, TraitEngineExt};
 use rustc_type_ir::sty::TyKind::*;
 
-use std::ops::ControlFlow;
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Checks a `a <op>= b`
     pub fn check_binop_assign(
@@ -313,8 +310,11 @@ fn check_overloaded_binop(
             // error types are considered "builtin"
             Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => self.tcx.ty_error(),
             Err(errors) => {
-                let source_map = self.tcx.sess.source_map();
-                let (mut err, missing_trait, use_output) = match is_assign {
+                let (_, trait_def_id) =
+                    lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
+                let missing_trait = trait_def_id
+                    .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id)));
+                let (mut err, output_def_id) = match is_assign {
                     IsAssign::Yes => {
                         let mut err = struct_span_err!(
                             self.tcx.sess,
@@ -328,112 +328,63 @@ fn check_overloaded_binop(
                             lhs_expr.span,
                             format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
                         );
-                        let missing_trait = match op.node {
-                            hir::BinOpKind::Add => Some("std::ops::AddAssign"),
-                            hir::BinOpKind::Sub => Some("std::ops::SubAssign"),
-                            hir::BinOpKind::Mul => Some("std::ops::MulAssign"),
-                            hir::BinOpKind::Div => Some("std::ops::DivAssign"),
-                            hir::BinOpKind::Rem => Some("std::ops::RemAssign"),
-                            hir::BinOpKind::BitAnd => Some("std::ops::BitAndAssign"),
-                            hir::BinOpKind::BitXor => Some("std::ops::BitXorAssign"),
-                            hir::BinOpKind::BitOr => Some("std::ops::BitOrAssign"),
-                            hir::BinOpKind::Shl => Some("std::ops::ShlAssign"),
-                            hir::BinOpKind::Shr => Some("std::ops::ShrAssign"),
-                            _ => None,
-                        };
                         self.note_unmet_impls_on_type(&mut err, errors);
-                        (err, missing_trait, false)
+                        (err, None)
                     }
                     IsAssign::No => {
-                        let (message, missing_trait, use_output) = match op.node {
-                            hir::BinOpKind::Add => (
-                                format!("cannot add `{rhs_ty}` to `{lhs_ty}`"),
-                                Some("std::ops::Add"),
-                                true,
-                            ),
-                            hir::BinOpKind::Sub => (
-                                format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`"),
-                                Some("std::ops::Sub"),
-                                true,
-                            ),
-                            hir::BinOpKind::Mul => (
-                                format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`"),
-                                Some("std::ops::Mul"),
-                                true,
-                            ),
-                            hir::BinOpKind::Div => (
-                                format!("cannot divide `{lhs_ty}` by `{rhs_ty}`"),
-                                Some("std::ops::Div"),
-                                true,
-                            ),
-                            hir::BinOpKind::Rem => (
-                                format!("cannot mod `{lhs_ty}` by `{rhs_ty}`"),
-                                Some("std::ops::Rem"),
-                                true,
-                            ),
-                            hir::BinOpKind::BitAnd => (
-                                format!("no implementation for `{lhs_ty} & {rhs_ty}`"),
-                                Some("std::ops::BitAnd"),
-                                true,
-                            ),
-                            hir::BinOpKind::BitXor => (
-                                format!("no implementation for `{lhs_ty} ^ {rhs_ty}`"),
-                                Some("std::ops::BitXor"),
-                                true,
-                            ),
-                            hir::BinOpKind::BitOr => (
-                                format!("no implementation for `{lhs_ty} | {rhs_ty}`"),
-                                Some("std::ops::BitOr"),
-                                true,
-                            ),
-                            hir::BinOpKind::Shl => (
-                                format!("no implementation for `{lhs_ty} << {rhs_ty}`"),
-                                Some("std::ops::Shl"),
-                                true,
-                            ),
-                            hir::BinOpKind::Shr => (
-                                format!("no implementation for `{lhs_ty} >> {rhs_ty}`"),
-                                Some("std::ops::Shr"),
-                                true,
-                            ),
-                            hir::BinOpKind::Eq | hir::BinOpKind::Ne => (
-                                format!(
-                                    "binary operation `{}` cannot be applied to type `{}`",
-                                    op.node.as_str(),
-                                    lhs_ty
-                                ),
-                                Some("std::cmp::PartialEq"),
-                                false,
-                            ),
-                            hir::BinOpKind::Lt
-                            | hir::BinOpKind::Le
-                            | hir::BinOpKind::Gt
-                            | hir::BinOpKind::Ge => (
-                                format!(
-                                    "binary operation `{}` cannot be applied to type `{}`",
-                                    op.node.as_str(),
-                                    lhs_ty
-                                ),
-                                Some("std::cmp::PartialOrd"),
-                                false,
-                            ),
-                            _ => (
-                                format!(
-                                    "binary operation `{}` cannot be applied to type `{}`",
-                                    op.node.as_str(),
-                                    lhs_ty
-                                ),
-                                None,
-                                false,
+                        let message = match op.node {
+                            hir::BinOpKind::Add => {
+                                format!("cannot add `{rhs_ty}` to `{lhs_ty}`")
+                            }
+                            hir::BinOpKind::Sub => {
+                                format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`")
+                            }
+                            hir::BinOpKind::Mul => {
+                                format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`")
+                            }
+                            hir::BinOpKind::Div => {
+                                format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
+                            }
+                            hir::BinOpKind::Rem => {
+                                format!("cannot mod `{lhs_ty}` by `{rhs_ty}`")
+                            }
+                            hir::BinOpKind::BitAnd => {
+                                format!("no implementation for `{lhs_ty} & {rhs_ty}`")
+                            }
+                            hir::BinOpKind::BitXor => {
+                                format!("no implementation for `{lhs_ty} ^ {rhs_ty}`")
+                            }
+                            hir::BinOpKind::BitOr => {
+                                format!("no implementation for `{lhs_ty} | {rhs_ty}`")
+                            }
+                            hir::BinOpKind::Shl => {
+                                format!("no implementation for `{lhs_ty} << {rhs_ty}`")
+                            }
+                            hir::BinOpKind::Shr => {
+                                format!("no implementation for `{lhs_ty} >> {rhs_ty}`")
+                            }
+                            _ => format!(
+                                "binary operation `{}` cannot be applied to type `{}`",
+                                op.node.as_str(),
+                                lhs_ty
                             ),
                         };
+                        let output_def_id = trait_def_id.and_then(|def_id| {
+                            self.tcx
+                                .associated_item_def_ids(def_id)
+                                .iter()
+                                .find(|item_def_id| {
+                                    self.tcx.associated_item(*item_def_id).name == sym::Output
+                                })
+                                .cloned()
+                        });
                         let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{message}");
                         if !lhs_expr.span.eq(&rhs_expr.span) {
                             err.span_label(lhs_expr.span, lhs_ty.to_string());
                             err.span_label(rhs_expr.span, rhs_ty.to_string());
                         }
                         self.note_unmet_impls_on_type(&mut err, errors);
-                        (err, missing_trait, use_output)
+                        (err, output_def_id)
                     }
                 };
 
@@ -448,24 +399,21 @@ fn check_overloaded_binop(
                         )
                         .is_ok()
                     {
-                        if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
-                            let msg = &format!(
-                                "`{}{}` can be used on `{}`, you can dereference `{}`",
-                                op.node.as_str(),
-                                match is_assign {
-                                    IsAssign::Yes => "=",
-                                    IsAssign::No => "",
-                                },
-                                lhs_deref_ty.peel_refs(),
-                                lstring,
-                            );
-                            err.span_suggestion_verbose(
-                                lhs_expr.span.shrink_to_lo(),
-                                msg,
-                                "*",
-                                rustc_errors::Applicability::MachineApplicable,
-                            );
-                        }
+                        let msg = &format!(
+                            "`{}{}` can be used on `{}` if you dereference the left-hand side",
+                            op.node.as_str(),
+                            match is_assign {
+                                IsAssign::Yes => "=",
+                                IsAssign::No => "",
+                            },
+                            lhs_deref_ty,
+                        );
+                        err.span_suggestion_verbose(
+                            lhs_expr.span.shrink_to_lo(),
+                            msg,
+                            "*",
+                            rustc_errors::Applicability::MachineApplicable,
+                        );
                     }
                 };
 
@@ -514,9 +462,6 @@ fn check_overloaded_binop(
                 }
 
                 if let Some(missing_trait) = missing_trait {
-                    let mut visitor = TypeParamVisitor(vec![]);
-                    visitor.visit_ty(lhs_ty);
-
                     if op.node == hir::BinOpKind::Add
                         && self.check_str_addition(
                             lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, is_assign, op,
@@ -525,7 +470,7 @@ fn check_overloaded_binop(
                         // This has nothing here because it means we did string
                         // concatenation (e.g., "Hello " + "World!"). This means
                         // we don't want the note in the else clause to be emitted
-                    } else if let [ty] = &visitor.0[..] {
+                    } else if lhs_ty.has_param_types_or_consts() {
                         // Look for a TraitPredicate in the Fulfillment errors,
                         // and use it to generate a suggestion.
                         //
@@ -547,12 +492,21 @@ fn check_overloaded_binop(
                                 if let Some(trait_pred) =
                                     error.obligation.predicate.to_opt_poly_trait_pred()
                                 {
-                                    let proj_pred = match error.obligation.cause.code() {
+                                    let output_associated_item = match error.obligation.cause.code()
+                                    {
                                         ObligationCauseCode::BinOp {
-                                            output_pred: Some(output_pred),
+                                            output_ty: Some(output_ty),
                                             ..
-                                        } if use_output => {
-                                            output_pred.to_opt_poly_projection_pred()
+                                        } => {
+                                            // Make sure that we're attaching `Output = ..` to the right trait predicate
+                                            if let Some(output_def_id) = output_def_id
+                                                && let Some(trait_def_id) = trait_def_id
+                                                && self.tcx.parent(output_def_id) == trait_def_id
+                                            {
+                                                Some(("Output", *output_ty))
+                                            } else {
+                                                None
+                                            }
                                         }
                                         _ => None,
                                     };
@@ -560,12 +514,12 @@ fn check_overloaded_binop(
                                     self.suggest_restricting_param_bound(
                                         &mut err,
                                         trait_pred,
-                                        proj_pred,
+                                        output_associated_item,
                                         self.body_id,
                                     );
                                 }
                             }
-                        } else if *ty != lhs_ty {
+                        } else {
                             // When we know that a missing bound is responsible, we don't show
                             // this note as it is redundant.
                             err.note(&format!(
@@ -702,14 +656,10 @@ pub fn check_user_unop(
                         format!("cannot apply unary operator `{}`", op.as_str()),
                     );
 
-                    let mut visitor = TypeParamVisitor(vec![]);
-                    visitor.visit_ty(operand_ty);
-                    if let [_] = &visitor.0[..] && let ty::Param(_) = *operand_ty.kind() {
-                        let predicates = errors
-                            .iter()
-                            .filter_map(|error| {
-                                error.obligation.predicate.to_opt_poly_trait_pred()
-                            });
+                    if operand_ty.has_param_types_or_consts() {
+                        let predicates = errors.iter().filter_map(|error| {
+                            error.obligation.predicate.to_opt_poly_trait_pred()
+                        });
                         for pred in predicates {
                             self.suggest_restricting_param_bound(
                                 &mut err,
@@ -777,64 +727,11 @@ fn lookup_op_method(
         op: Op,
         expected: Expectation<'tcx>,
     ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> {
-        let lang = self.tcx.lang_items();
-
         let span = match op {
             Op::Binary(op, _) => op.span,
             Op::Unary(_, span) => span,
         };
-        let (opname, trait_did) = if let Op::Binary(op, IsAssign::Yes) = op {
-            match op.node {
-                hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()),
-                hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()),
-                hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()),
-                hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()),
-                hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()),
-                hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()),
-                hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()),
-                hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()),
-                hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()),
-                hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()),
-                hir::BinOpKind::Lt
-                | hir::BinOpKind::Le
-                | hir::BinOpKind::Ge
-                | hir::BinOpKind::Gt
-                | hir::BinOpKind::Eq
-                | hir::BinOpKind::Ne
-                | hir::BinOpKind::And
-                | hir::BinOpKind::Or => {
-                    span_bug!(span, "impossible assignment operation: {}=", op.node.as_str())
-                }
-            }
-        } else if let Op::Binary(op, IsAssign::No) = op {
-            match op.node {
-                hir::BinOpKind::Add => (sym::add, lang.add_trait()),
-                hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()),
-                hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()),
-                hir::BinOpKind::Div => (sym::div, lang.div_trait()),
-                hir::BinOpKind::Rem => (sym::rem, lang.rem_trait()),
-                hir::BinOpKind::BitXor => (sym::bitxor, lang.bitxor_trait()),
-                hir::BinOpKind::BitAnd => (sym::bitand, lang.bitand_trait()),
-                hir::BinOpKind::BitOr => (sym::bitor, lang.bitor_trait()),
-                hir::BinOpKind::Shl => (sym::shl, lang.shl_trait()),
-                hir::BinOpKind::Shr => (sym::shr, lang.shr_trait()),
-                hir::BinOpKind::Lt => (sym::lt, lang.partial_ord_trait()),
-                hir::BinOpKind::Le => (sym::le, lang.partial_ord_trait()),
-                hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()),
-                hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()),
-                hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()),
-                hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()),
-                hir::BinOpKind::And | hir::BinOpKind::Or => {
-                    span_bug!(span, "&& and || are not overloadable")
-                }
-            }
-        } else if let Op::Unary(hir::UnOp::Not, _) = op {
-            (sym::not, lang.not_trait())
-        } else if let Op::Unary(hir::UnOp::Neg, _) = op {
-            (sym::neg, lang.neg_trait())
-        } else {
-            bug!("lookup_op_method: op not supported: {:?}", op)
-        };
+        let (opname, trait_did) = lang_item_for_op(self.tcx, op, span);
 
         debug!(
             "lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})",
@@ -895,6 +792,66 @@ fn lookup_op_method(
     }
 }
 
+fn lang_item_for_op(
+    tcx: TyCtxt<'_>,
+    op: Op,
+    span: Span,
+) -> (rustc_span::Symbol, Option<hir::def_id::DefId>) {
+    let lang = tcx.lang_items();
+    if let Op::Binary(op, IsAssign::Yes) = op {
+        match op.node {
+            hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()),
+            hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()),
+            hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()),
+            hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()),
+            hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()),
+            hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()),
+            hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()),
+            hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()),
+            hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()),
+            hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()),
+            hir::BinOpKind::Lt
+            | hir::BinOpKind::Le
+            | hir::BinOpKind::Ge
+            | hir::BinOpKind::Gt
+            | hir::BinOpKind::Eq
+            | hir::BinOpKind::Ne
+            | hir::BinOpKind::And
+            | hir::BinOpKind::Or => {
+                span_bug!(span, "impossible assignment operation: {}=", op.node.as_str())
+            }
+        }
+    } else if let Op::Binary(op, IsAssign::No) = op {
+        match op.node {
+            hir::BinOpKind::Add => (sym::add, lang.add_trait()),
+            hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()),
+            hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()),
+            hir::BinOpKind::Div => (sym::div, lang.div_trait()),
+            hir::BinOpKind::Rem => (sym::rem, lang.rem_trait()),
+            hir::BinOpKind::BitXor => (sym::bitxor, lang.bitxor_trait()),
+            hir::BinOpKind::BitAnd => (sym::bitand, lang.bitand_trait()),
+            hir::BinOpKind::BitOr => (sym::bitor, lang.bitor_trait()),
+            hir::BinOpKind::Shl => (sym::shl, lang.shl_trait()),
+            hir::BinOpKind::Shr => (sym::shr, lang.shr_trait()),
+            hir::BinOpKind::Lt => (sym::lt, lang.partial_ord_trait()),
+            hir::BinOpKind::Le => (sym::le, lang.partial_ord_trait()),
+            hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()),
+            hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()),
+            hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()),
+            hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()),
+            hir::BinOpKind::And | hir::BinOpKind::Or => {
+                span_bug!(span, "&& and || are not overloadable")
+            }
+        }
+    } else if let Op::Unary(hir::UnOp::Not, _) = op {
+        (sym::not, lang.not_trait())
+    } else if let Op::Unary(hir::UnOp::Neg, _) = op {
+        (sym::neg, lang.neg_trait())
+    } else {
+        bug!("lookup_op_method: op not supported: {:?}", op)
+    }
+}
+
 // Binary operator categories. These categories summarize the behavior
 // with respect to the builtin operations supported.
 enum BinOpCategory {
@@ -1017,17 +974,6 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool
     }
 }
 
-struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
-
-impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if let ty::Param(_) = ty.kind() {
-            self.0.push(ty);
-        }
-        ty.super_visit_with(self)
-    }
-}
-
 struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span);
 
 impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> {
index 9fb915a056ab654b9be3f2241f3611bcd6c1a2cc..8906b622b68e4d8291ed407169e3fec202b5fabb 100644 (file)
@@ -981,7 +981,7 @@ fn check_pat_tuple_struct(
         pat: &'tcx Pat<'tcx>,
         qpath: &'tcx hir::QPath<'tcx>,
         subpats: &'tcx [Pat<'tcx>],
-        ddpos: Option<usize>,
+        ddpos: hir::DotDotPos,
         expected: Ty<'tcx>,
         def_bm: BindingMode,
         ti: TopInfo<'tcx>,
@@ -1066,7 +1066,7 @@ fn check_pat_tuple_struct(
 
         // Type-check subpatterns.
         if subpats.len() == variant.fields.len()
-            || subpats.len() < variant.fields.len() && ddpos.is_some()
+            || subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
         {
             let ty::Adt(_, substs) = pat_ty.kind() else {
                 bug!("unexpected pattern type {:?}", pat_ty);
@@ -1254,14 +1254,14 @@ fn check_pat_tuple(
         &self,
         span: Span,
         elements: &'tcx [Pat<'tcx>],
-        ddpos: Option<usize>,
+        ddpos: hir::DotDotPos,
         expected: Ty<'tcx>,
         def_bm: BindingMode,
         ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let mut expected_len = elements.len();
-        if ddpos.is_some() {
+        if ddpos.as_opt_usize().is_some() {
             // Require known type only when `..` is present.
             if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() {
                 expected_len = tys.len();
index e70f728d7dcce3db1bdff7e48aa5e20b8be200a5..ceb5684fdf0a8f4c98c9a49526b09a92bebc0df5 100644 (file)
@@ -1585,8 +1585,16 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             ItemKind::OpaqueTy(hir::OpaqueTy {
                 origin:
                     hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+                in_trait,
                 ..
-            }) => Some(fn_def_id.to_def_id()),
+            }) => {
+                if in_trait {
+                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
+                } else {
+                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
+                }
+                Some(fn_def_id.to_def_id())
+            }
             ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
                 let parent_id = tcx.hir().get_parent_item(hir_id);
                 assert_ne!(parent_id, CRATE_DEF_ID);
@@ -1787,7 +1795,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
         }
         Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
         Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
-        OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
+        OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
         Path(hir::QPath::TypeRelative(ty, segment)) => {
             is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
         }
index 318e8f581f7c8b42f711887229ff2133ebfe058b..0d34a8bfee333d3d457fd32e15cfc101eb5ad474 100644 (file)
@@ -59,10 +59,15 @@ fn opaque_type_bounds<'tcx>(
     opaque_def_id: DefId,
     ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
+    in_trait: bool,
 ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
     ty::print::with_no_queries!({
-        let item_ty =
-            tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
+        let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id);
+        let item_ty = if in_trait {
+            tcx.mk_projection(opaque_def_id, substs)
+        } else {
+            tcx.mk_opaque(opaque_def_id, substs)
+        };
 
         let icx = ItemCtxt::new(tcx, opaque_def_id);
         let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
@@ -86,10 +91,10 @@ pub(super) fn explicit_item_bounds(
             ..
         }) => associated_type_bounds(tcx, def_id, bounds, *span),
         hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
+            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
             span,
             ..
-        }) => opaque_type_bounds(tcx, def_id, bounds, *span),
+        }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait),
         _ => bug!("item_bounds called on {:?}", def_id),
     }
 }
index dd894dc709bd627663205ae84c9c559cf6f804a0..70e259b46bf20c7c990d9fe9679c02064543bbf2 100644 (file)
@@ -333,8 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     find_opaque_ty_constraints_for_tait(tcx, def_id)
                 }
                 // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => {
-                    find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => {
+                    if in_trait {
+                        span_bug!(item.span, "impl-trait in trait has no default")
+                    } else {
+                        find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+                    }
                 }
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
index 9d3e9abf557792c9c490f969e7da5d798af8dce6..905212eb372b12f8dfe185691abd435563c6deb1 100644 (file)
@@ -1819,7 +1819,7 @@ pub fn precision(&self) -> Option<usize> {
     ///             write!(formatter,
     ///                    "Foo({}{})",
     ///                    if self.0 < 0 { '-' } else { '+' },
-    ///                    self.0)
+    ///                    self.0.abs())
     ///         } else {
     ///             write!(formatter, "Foo({})", self.0)
     ///         }
@@ -1827,6 +1827,7 @@ pub fn precision(&self) -> Option<usize> {
     /// }
     ///
     /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)");
+    /// assert_eq!(&format!("{:+}", Foo(-23)), "Foo(-23)");
     /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
     /// ```
     #[must_use]
index 92b12ed33528db86c9cf897d785bc6347bf72353..e7deb728d15d893cce10a6a96909a258f11a0365 100644 (file)
@@ -1518,6 +1518,51 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
             (a as Self, b)
         }
 
+        /// Calculates `self + rhs + carry` without the ability to overflow.
+        ///
+        /// Performs "signed ternary addition" which takes in an extra bit to add, and may return an
+        /// additional bit of overflow. This signed function is used only on the highest-ordered data,
+        /// for which the signed overflow result indicates whether the big integer overflowed or not.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (", stringify!($SelfT), "::MIN, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (", stringify!($SelfT), "::MIN, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, true));")]
+        #[doc = concat!("assert_eq!(",
+            stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
+            "(-1, true));"
+        )]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.carrying_add(-1, true), (", stringify!($SelfT), "::MIN, false));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".carrying_add(", stringify!($SelfT), "::MAX, true), (", stringify!($SelfT), "::MIN, true));")]
+        /// ```
+        ///
+        /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
+            // note: longer-term this should be done via an intrinsic.
+            // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946).
+            let (a, b) = self.overflowing_add(rhs);
+            let (c, d) = a.overflowing_add(carry as $SelfT);
+            (c, b != d)
+        }
+
         /// Calculates `self` + `rhs` with an unsigned `rhs`
         ///
         /// Returns a tuple of the addition along with a boolean indicating
@@ -1569,6 +1614,39 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
             (a as Self, b)
         }
 
+        /// Calculates `self - rhs - borrow` without the ability to overflow.
+        ///
+        /// Performs "signed ternary subtraction" which takes in an extra bit to subtract, and may return an
+        /// additional bit of overflow. This signed function is used only on the highest-ordered data,
+        /// for which the signed overflow result indicates whether the big integer overflowed or not.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (-1, false));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (-2, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, false), (", stringify!($SelfT), "::MIN, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.borrowing_sub(-1, true), (", stringify!($SelfT), "::MAX, false));")]
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
+            // note: longer-term this should be done via an intrinsic.
+            // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946).
+            let (a, b) = self.overflowing_sub(rhs);
+            let (c, d) = a.overflowing_sub(borrow as $SelfT);
+            (c, b != d)
+        }
+
         /// Calculates `self` - `rhs` with an unsigned `rhs`
         ///
         /// Returns a tuple of the subtraction along with a boolean indicating
index b651b7b233edeabc4e9afed2ce676a4f21d9f4cc..3ebd6f8cdbdc03e598b2d2c0a1d55c2b05a1533f 100644 (file)
@@ -83,7 +83,7 @@ pub trait Generator<R = ()> {
     /// `return` statement or implicitly as the last expression of a generator
     /// literal. For example futures would use this as `Result<T, E>` as it
     /// represents a completed future.
-    #[lang = "generator_return"]
+    #[cfg_attr(bootstrap, lang = "generator_return")]
     type Return;
 
     /// Resumes the execution of this generator.
index c315f3a7975129399459a37c48f8fcc63a1c15c7..4a0e162bc4a50b7c2584cbba730c68297caa0483 100644 (file)
@@ -3,6 +3,7 @@
 #![feature(array_methods)]
 #![feature(array_windows)]
 #![feature(bench_black_box)]
+#![feature(bigint_helper_methods)]
 #![feature(cell_update)]
 #![feature(const_assume)]
 #![feature(const_black_box)]
index 8b84a78e6be08823a33a1abb9ad07f7724778d73..18c55e43aac81958d897a9e85141f7483eb24387 100644 (file)
@@ -338,6 +338,32 @@ fn test_checked_next_multiple_of() {
                 assert_eq!(MIN.checked_next_multiple_of(-3), None);
                 assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN));
             }
+
+            #[test]
+            fn test_carrying_add() {
+                assert_eq!($T::MAX.carrying_add(1, false), ($T::MIN, true));
+                assert_eq!($T::MAX.carrying_add(0, true), ($T::MIN, true));
+                assert_eq!($T::MAX.carrying_add(1, true), ($T::MIN + 1, true));
+                assert_eq!($T::MAX.carrying_add(-1, false), ($T::MAX - 1, false));
+                assert_eq!($T::MAX.carrying_add(-1, true), ($T::MAX, false)); // no intermediate overflow
+                assert_eq!($T::MIN.carrying_add(-1, false), ($T::MAX, true));
+                assert_eq!($T::MIN.carrying_add(-1, true), ($T::MIN, false)); // no intermediate overflow
+                assert_eq!((0 as $T).carrying_add($T::MAX, true), ($T::MIN, true));
+                assert_eq!((0 as $T).carrying_add($T::MIN, true), ($T::MIN + 1, false));
+            }
+
+            #[test]
+            fn test_borrowing_sub() {
+                assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true));
+                assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true));
+                assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true));
+                assert_eq!($T::MIN.borrowing_sub(-1, false), ($T::MIN + 1, false));
+                assert_eq!($T::MIN.borrowing_sub(-1, true), ($T::MIN, false)); // no intermediate overflow
+                assert_eq!($T::MAX.borrowing_sub(-1, false), ($T::MIN, true));
+                assert_eq!($T::MAX.borrowing_sub(-1, true), ($T::MAX, false)); // no intermediate overflow
+                assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true));
+                assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false));
+            }
         }
     };
 }
index 93ae620c23302413da250988dd8b0592d8c19d8a..15ae9f2324f6c8a29605576e793f9609571f42ab 100644 (file)
@@ -230,6 +230,28 @@ fn test_checked_next_multiple_of() {
                 assert_eq!((1 as $T).checked_next_multiple_of(0), None);
                 assert_eq!(MAX.checked_next_multiple_of(2), None);
             }
+
+            #[test]
+            fn test_carrying_add() {
+                assert_eq!($T::MAX.carrying_add(1, false), (0, true));
+                assert_eq!($T::MAX.carrying_add(0, true), (0, true));
+                assert_eq!($T::MAX.carrying_add(1, true), (1, true));
+
+                assert_eq!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false));
+                assert_eq!($T::MIN.carrying_add(0, true), (1, false));
+                assert_eq!($T::MIN.carrying_add($T::MAX, true), (0, true));
+            }
+
+            #[test]
+            fn test_borrowing_sub() {
+                assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true));
+                assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true));
+                assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true));
+
+                assert_eq!($T::MAX.borrowing_sub($T::MAX, false), (0, false));
+                assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
+                assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
+            }
         }
     };
 }
index e0184eb5baf69b03195945e0b385dbdcfcde5d7d..30c8fc4562d52dd4ce2affa0dad5459ebda821cb 100644 (file)
@@ -2,7 +2,6 @@
 use crate::collections::VecDeque;
 use crate::hint;
 use crate::ops::{Deref, DerefMut, Drop};
-use crate::ptr;
 use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sys::hermit::abi;
 
index 74547617150b0b48bd22294456d8fbe43766072e..8a13879d8cc837ebc76fc35213c28819a944b853 100644 (file)
@@ -487,6 +487,4 @@ pub struct sockaddr_in6 {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr {}
-
-    pub type socklen_t = usize;
 }
index 9701bab1f660be75a09848c0d4117567d4f649a6..1adf0b2be6b7342d3e5d0bfec3a234a43b3e5308 100644 (file)
@@ -1,6 +1,5 @@
 use crate::cell::UnsafeCell;
 use crate::sys::locks::{MovableCondvar, Mutex};
-use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 
 pub struct RwLock {
     lock: Mutex,
index a0f822070992f5032e6f54a5c16b77d19c0eaa85..beeca1917a9af74e40516748a93c8aa26594c5ca 100644 (file)
@@ -198,14 +198,7 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
 
     match path.bytes().iter().position(|&x| separator(x)) {
         Some(separator_start) => {
-            let mut separator_end = separator_start + 1;
-
-            // a series of multiple separator characters is treated as a single separator,
-            // except in verbatim paths
-            while !verbatim && separator_end < path.len() && separator(path.bytes()[separator_end])
-            {
-                separator_end += 1;
-            }
+            let separator_end = separator_start + 1;
 
             let component = &path.bytes()[..separator_start];
 
index a71175069052f0539c8af1b850fc9ad48eee3d7d..623c6236166da6e3ce7a6768fb66e157553dab24 100644 (file)
@@ -31,16 +31,6 @@ fn test_parse_next_component() {
         parse_next_component(OsStr::new(r"servershare"), false),
         (OsStr::new(r"servershare"), OsStr::new(""))
     );
-
-    assert_eq!(
-        parse_next_component(OsStr::new(r"server/\//\/\\\\/////\/share"), false),
-        (OsStr::new(r"server"), OsStr::new(r"share"))
-    );
-
-    assert_eq!(
-        parse_next_component(OsStr::new(r"server\\\\\\\\\\\\\\share"), true),
-        (OsStr::new(r"server"), OsStr::new(r"\\\\\\\\\\\\\share"))
-    );
 }
 
 #[test]
@@ -126,3 +116,22 @@ fn test_windows_prefix_components() {
     assert_eq!(drive.as_os_str(), OsStr::new("C:"));
     assert_eq!(components.as_path(), Path::new(""));
 }
+
+/// See #101358.
+///
+/// Note that the exact behaviour here may change in the future.
+/// In which case this test will need to adjusted.
+#[test]
+fn broken_unc_path() {
+    use crate::path::Component;
+
+    let mut components = Path::new(r"\\foo\\bar\\").components();
+    assert_eq!(components.next(), Some(Component::RootDir));
+    assert_eq!(components.next(), Some(Component::Normal("foo".as_ref())));
+    assert_eq!(components.next(), Some(Component::Normal("bar".as_ref())));
+
+    let mut components = Path::new("//foo//bar//").components();
+    assert_eq!(components.next(), Some(Component::RootDir));
+    assert_eq!(components.next(), Some(Component::Normal("foo".as_ref())));
+    assert_eq!(components.next(), Some(Component::Normal("bar".as_ref())));
+}
index 1025f5bce802cd5bd815696fbc9594522c741a61..fa780e1e45ea6df07991992ca1cc912693f1c3be 100755 (executable)
@@ -4,7 +4,7 @@ set -ex
 
 source shared.sh
 
-LLVM=llvmorg-14.0.5
+LLVM=llvmorg-15.0.0
 
 mkdir llvm-project
 cd llvm-project
index 742fbe11d9c6fbab4ae13be216ad7a35e65643c8..fe090a73327ce2f538bbbafb29ddb1b138f2b9ff 100644 (file)
@@ -213,7 +213,7 @@ target | std | host | notes
 [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | âœ“ | âœ“ |
 `aarch64-unknown-freebsd` | âœ“ | âœ“ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | âœ“ |  | ARM64 HermitCore
-`aarch64-unknown-uefi` | * |  | ARM64 UEFI
+[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * |  | ARM64 UEFI
 `aarch64-unknown-linux-gnu_ilp32` | âœ“ | âœ“ | ARM64 Linux (ILP32 ABI)
 `aarch64-unknown-netbsd` | âœ“ | âœ“ |
 [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | âœ“ | âœ“ | ARM64 OpenBSD
@@ -250,7 +250,7 @@ target | std | host | notes
 `i686-unknown-haiku` | âœ“ | âœ“ | 32-bit Haiku
 `i686-unknown-netbsd` | âœ“ | âœ“ | NetBSD/i386 with SSE2
 [`i686-unknown-openbsd`](platform-support/openbsd.md) | âœ“ | âœ“ | 32-bit OpenBSD
-`i686-unknown-uefi` | * |  | 32-bit UEFI
+[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * |  | 32-bit UEFI
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
@@ -307,7 +307,7 @@ target | std | host | notes
 `x86_64-unknown-l4re-uclibc` | ? |  |
 `x86_64-unknown-none-linuxkernel` | * |  | Linux kernel modules
 [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | âœ“ | âœ“ | 64-bit OpenBSD
-`x86_64-unknown-uefi` | * |  | 64-bit UEFI
+[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * |  | 64-bit UEFI
 `x86_64-uwp-windows-gnu` | âœ“ |  |
 `x86_64-uwp-windows-msvc` | âœ“ |  |
 `x86_64-wrs-vxworks` | ? |  |
index c2baea839f6384eef1dc8e754a068ed2bf985db4..08b696e65eb3b0c10b10245cb819c285a56bd6be 100644 (file)
@@ -190,7 +190,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
     )
 }
 
-fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
+fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
     let def = cx.tcx.named_region(lifetime.hir_id);
     if let Some(
         rl::Region::EarlyBound(node_id)
@@ -495,7 +495,7 @@ fn clean_generic_param<'tcx>(
                     .filter(|bp| !bp.in_where_clause)
                     .flat_map(|bp| bp.bounds)
                     .map(|bound| match bound {
-                        hir::GenericBound::Outlives(lt) => clean_lifetime(*lt, cx),
+                        hir::GenericBound::Outlives(lt) => clean_lifetime(lt, cx),
                         _ => panic!(),
                     })
                     .collect()
@@ -1392,7 +1392,7 @@ fn maybe_expand_private_type_alias<'tcx>(
                     }
                     _ => None,
                 });
-                if let Some(lt) = lifetime.cloned() {
+                if let Some(lt) = lifetime {
                     let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
                     let cleaned =
                         if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() };
@@ -1492,7 +1492,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
             Array(Box::new(clean_ty(ty, cx)), length)
         }
         TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
-        TyKind::OpaqueDef(item_id, _) => {
+        TyKind::OpaqueDef(item_id, _, _) => {
             let item = cx.tcx.hir().item(item_id);
             if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
                 ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
index a9d511ae11e8b92db472859e788db67d7b317d99..395f213ca87c353836a89a36537f84b36dcd99ca 100644 (file)
@@ -511,8 +511,8 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
         | Res::Err => return res.def_id(),
         Res::Def(
             TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst
-            | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure
-            | Generator,
+            | InlineConst | OpaqueTy | ImplTraitPlaceholder | Field | LifetimeParam | GlobalAsm
+            | Impl | Closure | Generator,
             id,
         ) => return id,
     };
index 0a7ee2005915baa6cbb977aefd12b44361962fdf..f21e60a64e0055f87060c44de8b5b492866deb66 100644 (file)
@@ -135,6 +135,7 @@ fn from(other: DefKind) -> Self {
             | DefKind::AnonConst
             | DefKind::InlineConst
             | DefKind::OpaqueTy
+            | DefKind::ImplTraitPlaceholder
             | DefKind::Field
             | DefKind::LifetimeParam
             | DefKind::GlobalAsm
index 7665417cb5c9beff84f5a80d359a0fc7f5c8cfd9..22217a390124647e577231428547c00d5f36d487 100644 (file)
@@ -197,10 +197,6 @@ h4.code-header {
        position: relative;
 }
 
-div.impl-items > div {
-       padding-left: 0;
-}
-
 h1, h2, h3, h4, h5, h6,
 .sidebar,
 .mobile-topbar,
@@ -212,7 +208,6 @@ a.source,
 span.since,
 #source-sidebar, #sidebar-toggle,
 details.rustdoc-toggle > summary::before,
-div.impl-items > div:not(.docblock):not(.item-info),
 .content ul.crate a.crate,
 a.srclink,
 #help-button > button,
@@ -1165,6 +1160,42 @@ pre.rust .question-mark {
        font-weight: bold;
 }
 
+pre.compile_fail,
+pre.should_panic {
+       border-left: 2px solid var(--codeblock-error-color);
+}
+
+pre.ignore {
+       border-left: 2px solid var(--codeblock-ignore-color);
+}
+
+pre.compile_fail:hover, .information:hover + .example-wrap pre.compile_fail,
+pre.should_panic:hover, .information:hover + .example-wrap pre.should_panic {
+       border-left: 2px solid var(--codeblock-error-hover-color);
+}
+
+pre.ignore:hover, .information:hover + .example-wrap pre.ignore {
+       border-left: 2px solid var(--codeblock-ignore-hover-color);
+}
+
+.tooltip.compile_fail,
+.tooltip.should_panic {
+       color: var(--codeblock-error-color);
+}
+
+.tooltip.ignore {
+       color:  var(--codeblock-ignore-color);
+}
+
+.information > .compile_fail:hover,
+.information > .should_panic:hover {
+       color: var(--codeblock-error-hover-color);
+}
+
+.information > .ignore:hover {
+       color: var(--codeblock-ignore-hover-color);
+}
+
 a.test-arrow {
        display: inline-block;
        visibility: hidden;
@@ -1449,9 +1480,7 @@ pre.rust {
        border-radius: 2px;
        cursor: pointer;
 }
-#settings-menu {
-       padding: 0;
-}
+
 #settings-menu > a, #help-button > button {
        padding: 5px;
        height: 100%;
@@ -1528,10 +1557,6 @@ kbd {
        cursor: default;
 }
 
-#implementations-list > h3 > span.in-band {
-       width: 100%;
-}
-
 #main-content > ul {
        padding-left: 10px;
 }
index be359a8e72d25d250631a2f651dfb343454b9f04..74de113495c2ed017d218d5b64dea56e499463b2 100644 (file)
@@ -23,6 +23,10 @@ Original by Dempfi (https://github.com/dempfi/ayu)
        --copy-path-button-color: #fff;
        --copy-path-img-filter: invert(70%);
        --copy-path-img-hover-filter: invert(100%);
+       --codeblock-error-hover-color: rgb(255, 0, 0);
+       --codeblock-error-color: rgba(255, 0, 0, .5);
+       --codeblock-ignore-hover-color: rgb(255, 142, 0);
+       --codeblock-ignore-color: rgba(255, 142, 0, .6);
 }
 
 .slider {
@@ -244,54 +248,6 @@ a.test-arrow:hover {
        border-right: 3px solid rgba(255, 180, 76, 0.85);
 }
 
-pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.4);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
-       border-left: 2px solid #f00;
-}
-
-pre.should_panic {
-       border-left: 2px solid rgba(255,0,0,.4);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
-       border-left: 2px solid #f00;
-}
-
-pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
-       border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .compile_fail:hover {
-       color: #f00;
-}
-
-.tooltip.should_panic {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .should_panic:hover {
-       color: #f00;
-}
-
-.tooltip.ignore {
-       color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
-       color: #ff9200;
-}
-
 .search-failed a {
        color: #39AFD7;
 }
index f633abe94e5af075b6b14973faadc2b88ab71623..153b40f05d8de108e28fdea657dc686e4a7c01bb 100644 (file)
        --copy-path-button-color: #999;
        --copy-path-img-filter: invert(50%);
        --copy-path-img-hover-filter: invert(65%);
+       --codeblock-error-hover-color: rgb(255, 0, 0);
+       --codeblock-error-color: rgba(255, 0, 0, .5);
+       --codeblock-ignore-hover-color: rgb(255, 142, 0);
+       --codeblock-ignore-color: rgba(255, 142, 0, .6);
 }
 
 .slider {
@@ -194,54 +198,6 @@ a.test-arrow:hover{
        border-right: 3px solid #bb7410;
 }
 
-pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.8);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
-       border-left: 2px solid #f00;
-}
-
-pre.should_panic {
-       border-left: 2px solid rgba(255,0,0,.8);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
-       border-left: 2px solid #f00;
-}
-
-pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
-       border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
-       color: rgba(255,0,0,.8);
-}
-
-.information > .compile_fail:hover {
-       color: #f00;
-}
-
-.tooltip.should_panic {
-       color: rgba(255,0,0,.8);
-}
-
-.information > .should_panic:hover {
-       color: #f00;
-}
-
-.tooltip.ignore {
-       color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
-       color: #ff9200;
-}
-
 .search-failed a {
        color: #0089ff;
 }
index 875bb79302560f4b1754ab6a5c78470123abf6cb..9ced9e7b5ce32ea8e4754e7fd71dba5a78a7e424 100644 (file)
        --copy-path-button-color: #999;
        --copy-path-img-filter: invert(50%);
        --copy-path-img-hover-filter: invert(35%);
+       --codeblock-error-hover-color: rgb(255, 0, 0);
+       --codeblock-error-color: rgba(255, 0, 0, .5);
+       --codeblock-ignore-hover-color: rgb(255, 142, 0);
+       --codeblock-ignore-color: rgba(255, 142, 0, .6);
 }
 
 .slider {
@@ -180,54 +184,6 @@ a.test-arrow:hover{
        border-right: 3px solid #AD7C37;
 }
 
-pre.compile_fail {
-       border-left: 2px solid rgba(255,0,0,.5);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
-       border-left: 2px solid #f00;
-}
-
-pre.should_panic {
-       border-left: 2px solid rgba(255,0,0,.5);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
-       border-left: 2px solid #f00;
-}
-
-pre.ignore {
-       border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
-       border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .compile_fail:hover {
-       color: #f00;
-}
-
-.tooltip.should_panic {
-       color: rgba(255,0,0,.5);
-}
-
-.information > .should_panic:hover {
-       color: #f00;
-}
-
-.tooltip.ignore {
-       color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
-       color: #ff9200;
-}
-
 .search-failed a {
        color: #3873AD;
 }
index c27f0ce18c1414d027453b4e8d2799105c980cfa..cfd6ce402c28a823249482d2a9e997065c0b0615 100644 (file)
@@ -1805,8 +1805,8 @@ fn split(path: &str) -> Option<(&str, &str)> {
                                 }
                                 return;
                             }
-                            Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam
-                            | Static(_) => "associated item",
+                            Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder
+                            | TraitAlias | TyParam | Static(_) => "associated item",
                             Impl | GlobalAsm => unreachable!("not a path"),
                         }
                     } else {
index 200569a28d4a43e2ad466cb0399104d134cf9e76..8d399a9a589767f21fb112d7844f11647d0ce3af 100644 (file)
@@ -1,9 +1,9 @@
 // This test ensures that items and documentation code blocks are wrapped in <pre><code>
 goto: file://|DOC_PATH|/test_docs/fn.foo.html
 size: (1080, 600)
-// There should be three doc codeblocks
+// There should be four doc codeblocks.
 // Check that their content is inside <pre><code>
-assert-count: (".example-wrap pre > code", 3)
+assert-count: (".example-wrap pre > code", 4)
 // Check that function signature is inside <pre><code>
 assert: "pre.rust.fn > code"
 
diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml
new file mode 100644 (file)
index 0000000..a0bb40f
--- /dev/null
@@ -0,0 +1,96 @@
+// Checking the colors of the codeblocks tooltips.
+goto: file://|DOC_PATH|/test_docs/fn.foo.html
+show-text: true
+
+// Dark theme.
+local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
+reload:
+
+// compile_fail block
+assert-css: (".docblock .information .compile_fail", {"color": "rgba(255, 0, 0, 0.5)"})
+assert-css: (".docblock .example-wrap .compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
+
+move-cursor-to: ".docblock .information .compile_fail"
+
+assert-css: (".docblock .information .compile_fail", {"color": "rgb(255, 0, 0)"})
+assert-css: (".docblock .example-wrap .compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"})
+
+// should_panic block
+assert-css: (".docblock .information .should_panic", {"color": "rgba(255, 0, 0, 0.5)"})
+assert-css: (".docblock .example-wrap .should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
+
+move-cursor-to: ".docblock .information .should_panic"
+
+assert-css: (".docblock .information .should_panic", {"color": "rgb(255, 0, 0)"})
+assert-css: (".docblock .example-wrap .should_panic", {"border-left": "2px solid rgb(255, 0, 0)"})
+
+// ignore block
+assert-css: (".docblock .information .ignore", {"color": "rgba(255, 142, 0, 0.6)"})
+assert-css: (".docblock .example-wrap .ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"})
+
+move-cursor-to: ".docblock .information .ignore"
+
+assert-css: (".docblock .information .ignore", {"color": "rgb(255, 142, 0)"})
+assert-css: (".docblock .example-wrap .ignore", {"border-left": "2px solid rgb(255, 142, 0)"})
+
+
+// Light theme.
+local-storage: {"rustdoc-theme": "light"}
+reload:
+
+assert-css: (".docblock .information .compile_fail", {"color": "rgba(255, 0, 0, 0.5)"})
+assert-css: (".docblock .example-wrap .compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
+
+move-cursor-to: ".docblock .information .compile_fail"
+
+assert-css: (".docblock .information .compile_fail", {"color": "rgb(255, 0, 0)"})
+assert-css: (".docblock .example-wrap .compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"})
+
+// should_panic block
+assert-css: (".docblock .information .should_panic", {"color": "rgba(255, 0, 0, 0.5)"})
+assert-css: (".docblock .example-wrap .should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
+
+move-cursor-to: ".docblock .information .should_panic"
+
+assert-css: (".docblock .information .should_panic", {"color": "rgb(255, 0, 0)"})
+assert-css: (".docblock .example-wrap .should_panic", {"border-left": "2px solid rgb(255, 0, 0)"})
+
+// ignore block
+assert-css: (".docblock .information .ignore", {"color": "rgba(255, 142, 0, 0.6)"})
+assert-css: (".docblock .example-wrap .ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"})
+
+move-cursor-to: ".docblock .information .ignore"
+
+assert-css: (".docblock .information .ignore", {"color": "rgb(255, 142, 0)"})
+assert-css: (".docblock .example-wrap .ignore", {"border-left": "2px solid rgb(255, 142, 0)"})
+
+
+// Ayu theme.
+local-storage: {"rustdoc-theme": "ayu"}
+reload:
+
+assert-css: (".docblock .information .compile_fail", {"color": "rgba(255, 0, 0, 0.5)"})
+assert-css: (".docblock .example-wrap .compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
+
+move-cursor-to: ".docblock .information .compile_fail"
+
+assert-css: (".docblock .information .compile_fail", {"color": "rgb(255, 0, 0)"})
+assert-css: (".docblock .example-wrap .compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"})
+
+// should_panic block
+assert-css: (".docblock .information .should_panic", {"color": "rgba(255, 0, 0, 0.5)"})
+assert-css: (".docblock .example-wrap .should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
+
+move-cursor-to: ".docblock .information .should_panic"
+
+assert-css: (".docblock .information .should_panic", {"color": "rgb(255, 0, 0)"})
+assert-css: (".docblock .example-wrap .should_panic", {"border-left": "2px solid rgb(255, 0, 0)"})
+
+// ignore block
+assert-css: (".docblock .information .ignore", {"color": "rgba(255, 142, 0, 0.6)"})
+assert-css: (".docblock .example-wrap .ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"})
+
+move-cursor-to: ".docblock .information .ignore"
+
+assert-css: (".docblock .information .ignore", {"color": "rgb(255, 142, 0)"})
+assert-css: (".docblock .example-wrap .ignore", {"border-left": "2px solid rgb(255, 142, 0)"})
index a02d5934cc2457e2a8a6198ceac300c722b0f0e4..4eedf7f15c3d4f8df273f9a726d533d1cfa178aa 100644 (file)
 /// Let's say I'm just some text will ya?
 /// ```
 ///
+/// A failing to run one:
+///
+/// ```should_panic
+/// panic!("tadam");
+/// ```
+///
 /// An inlined `code`!
 pub fn foo() {}
 
index 802b867a301aa5611bcdba471fbad793da7299b3..03ad3ca826146a9b47aeb37e638cbcba272c66b7 100644 (file)
@@ -21,7 +21,7 @@
 #[no_mangle]
 fn __rustc_plugin_registrar(reg: &mut Registry) {
     reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]);
-    reg.lint_store.register_late_pass(|| Box::new(MissingAllowedAttrPass));
+    reg.lint_store.register_late_pass(|_| Box::new(MissingAllowedAttrPass));
 }
 
 declare_lint! {
index bc153faa8925a73d952df3740a1a5a5bf63d1d9a..a3b570ad8c40c5e572ba483eb4963980dfda68af 100644 (file)
@@ -74,7 +74,7 @@ fn __rustc_plugin_registrar(reg: &mut Registry) {
         &CRATE_NOT_GREY,
         &CRATE_NOT_GREEN,
     ]);
-    reg.lint_store.register_late_pass(|| Box::new(PassOkay));
-    reg.lint_store.register_late_pass(|| Box::new(PassRedBlue));
-    reg.lint_store.register_late_pass(|| Box::new(PassGreyGreen));
+    reg.lint_store.register_late_pass(|_| Box::new(PassOkay));
+    reg.lint_store.register_late_pass(|_| Box::new(PassRedBlue));
+    reg.lint_store.register_late_pass(|_| Box::new(PassGreyGreen));
 }
index 29d0abfbe53889e19ff961526ea02e8b6ed20c93..0b1534939b778fdbdd3be1e68b5a4950f9b37d11 100644 (file)
@@ -39,5 +39,5 @@ fn check_crate(&mut self, cx: &LateContext) {
 #[no_mangle]
 fn __rustc_plugin_registrar(reg: &mut Registry) {
     reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]);
-    reg.lint_store.register_late_pass(|| Box::new(Pass));
+    reg.lint_store.register_late_pass(|_| Box::new(Pass));
 }
index 691cfb97d921858e5bec59e96f900620de8fbd08..2d41b5f30e975e2f7c330da40962f54dcd2d8af1 100644 (file)
@@ -36,7 +36,7 @@ fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) {
 #[no_mangle]
 fn __rustc_plugin_registrar(reg: &mut Registry) {
     reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]);
-    reg.lint_store.register_late_pass(|| Box::new(Pass));
+    reg.lint_store.register_late_pass(|_| Box::new(Pass));
     reg.lint_store.register_group(
         true,
         "lint_me",
index bae3ab74af676db8da8f3786edeff26580e41a3a..867c18a7d5e6b2acee746b91e0740e30a7e1bd68 100644 (file)
@@ -5,10 +5,22 @@ fn main() {
     const Foo: [i32; 3] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    const REF_FOO: &[u8; 1] = &[1];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
     let foo: [i32; 3] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
     let bar: [i32; 3] = [0; 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    let ref_foo: &[i32; 3] = &[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let ref_bar: &[i32; 3] = &[0; 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let multiple_ref_foo: &&[i32; 3] = &&[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
 }
index b0867f4e39676f033b83cf0f984629c5fe3ea72b..f66b3d4a899912376be45458fcb781a3c292bf55 100644 (file)
@@ -5,10 +5,22 @@ fn main() {
     const Foo: [i32; _] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    const REF_FOO: &[u8; _] = &[1];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
     let foo: [i32; _] = [1, 2, 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
     let bar: [i32; _] = [0; 3];
     //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
     //~| ERROR using `_` for array lengths is unstable
+    let ref_foo: &[i32; _] = &[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let ref_bar: &[i32; _] = &[0; 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
+    let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
+    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
+    //~| ERROR using `_` for array lengths is unstable
 }
index 9000f71602850453b4c8c2c50a0b019ac990092c..16c90a04784d0e674565e6ef86f10dbc50b9211c 100644 (file)
@@ -1,21 +1,45 @@
 error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:8:20
+  --> $DIR/suggest-array-length.rs:11:20
    |
 LL |     let foo: [i32; _] = [1, 2, 3];
    |                    ^ `_` not allowed here
 
 error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:11:20
+  --> $DIR/suggest-array-length.rs:14:20
    |
 LL |     let bar: [i32; _] = [0; 3];
    |                    ^ `_` not allowed here
 
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:17:25
+   |
+LL |     let ref_foo: &[i32; _] = &[1, 2, 3];
+   |                         ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:20:25
+   |
+LL |     let ref_bar: &[i32; _] = &[0; 3];
+   |                         ^ `_` not allowed here
+
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:23:35
+   |
+LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
+   |                                   ^ `_` not allowed here
+
 error: in expressions, `_` can only be used on the left-hand side of an assignment
   --> $DIR/suggest-array-length.rs:5:22
    |
 LL |     const Foo: [i32; _] = [1, 2, 3];
    |                      ^ `_` not allowed here
 
+error: in expressions, `_` can only be used on the left-hand side of an assignment
+  --> $DIR/suggest-array-length.rs:8:26
+   |
+LL |     const REF_FOO: &[u8; _] = &[1];
+   |                          ^ `_` not allowed here
+
 error[E0658]: using `_` for array lengths is unstable
   --> $DIR/suggest-array-length.rs:5:22
    |
@@ -26,7 +50,16 @@ LL |     const Foo: [i32; _] = [1, 2, 3];
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:8:20
+  --> $DIR/suggest-array-length.rs:8:26
+   |
+LL |     const REF_FOO: &[u8; _] = &[1];
+   |                          ^ help: consider specifying the array length: `1`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:11:20
    |
 LL |     let foo: [i32; _] = [1, 2, 3];
    |                    ^ help: consider specifying the array length: `3`
@@ -35,7 +68,7 @@ LL |     let foo: [i32; _] = [1, 2, 3];
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:11:20
+  --> $DIR/suggest-array-length.rs:14:20
    |
 LL |     let bar: [i32; _] = [0; 3];
    |                    ^ help: consider specifying the array length: `3`
@@ -43,6 +76,33 @@ LL |     let bar: [i32; _] = [0; 3];
    = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
 
-error: aborting due to 6 previous errors
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:17:25
+   |
+LL |     let ref_foo: &[i32; _] = &[1, 2, 3];
+   |                         ^ help: consider specifying the array length: `3`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:20:25
+   |
+LL |     let ref_bar: &[i32; _] = &[0; 3];
+   |                         ^ help: consider specifying the array length: `3`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/suggest-array-length.rs:23:35
+   |
+LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
+   |                                   ^ help: consider specifying the array length: `3`
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index b320abdc01b721a1cea17ae89b34cf7cfe025430..49292982eec7c99dfdc19dfde108d74a2b21026f 100644 (file)
@@ -5,8 +5,8 @@ LL |         asm!("{}", in(reg) 0u8);
    |               ^^           --- for this argument
    |
    = note: `#[warn(asm_sub_register)]` on by default
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:50:15
@@ -14,8 +14,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(reg) 0u16);
    |               ^^           ---- for this argument
    |
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:52:15
@@ -23,8 +23,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(reg) 0i32);
    |               ^^           ---- for this argument
    |
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:54:15
@@ -32,8 +32,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(reg) 0f32);
    |               ^^           ---- for this argument
    |
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:57:15
@@ -41,8 +41,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(vreg) 0i16);
    |               ^^            ---- for this argument
    |
-   = help: use the `h` modifier to have the register formatted as `h0`
-   = help: or use the `v` modifier to keep the default formatting of `v0`
+   = help: use `{0:h}` to have the register formatted as `h0`
+   = help: or use `{0:v}` to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:59:15
@@ -50,8 +50,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(vreg) 0f32);
    |               ^^            ---- for this argument
    |
-   = help: use the `s` modifier to have the register formatted as `s0`
-   = help: or use the `v` modifier to keep the default formatting of `v0`
+   = help: use `{0:s}` to have the register formatted as `s0`
+   = help: or use `{0:v}` to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:61:15
@@ -59,8 +59,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(vreg) 0f64);
    |               ^^            ---- for this argument
    |
-   = help: use the `d` modifier to have the register formatted as `d0`
-   = help: or use the `v` modifier to keep the default formatting of `v0`
+   = help: use `{0:d}` to have the register formatted as `d0`
+   = help: or use `{0:v}` to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:63:15
@@ -68,8 +68,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(vreg_low16) 0f64);
    |               ^^                  ---- for this argument
    |
-   = help: use the `d` modifier to have the register formatted as `d0`
-   = help: or use the `v` modifier to keep the default formatting of `v0`
+   = help: use `{0:d}` to have the register formatted as `d0`
+   = help: or use `{0:v}` to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:66:15
@@ -77,8 +77,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{0} {0}", in(reg) 0i16);
    |               ^^^ ^^^           ---- for this argument
    |
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:68:15
@@ -86,8 +86,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{0} {0:x}", in(reg) 0i16);
    |               ^^^                 ---- for this argument
    |
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 error: type `i128` cannot be used with this register class
   --> $DIR/type-check-3.rs:73:28
index 7ef93e15f5ba1cbfc31493e5be0acab675062257..5dac693cc2740063d03e182ad3fd4237b0284fe8 100644 (file)
@@ -190,8 +190,8 @@ LL |         asm!("{:foo}", in(reg) foo);
    |               ^^^^^^           --- for this argument
    |
    = note: `#[warn(asm_sub_register)]` on by default
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 error: aborting due to 21 previous errors; 1 warning emitted
 
index 7ef93e15f5ba1cbfc31493e5be0acab675062257..5dac693cc2740063d03e182ad3fd4237b0284fe8 100644 (file)
@@ -190,8 +190,8 @@ LL |         asm!("{:foo}", in(reg) foo);
    |               ^^^^^^           --- for this argument
    |
    = note: `#[warn(asm_sub_register)]` on by default
-   = help: use the `w` modifier to have the register formatted as `w0`
-   = help: or use the `x` modifier to keep the default formatting of `x0`
+   = help: use `{0:w}` to have the register formatted as `w0`
+   = help: or use `{0:x}` to keep the default formatting of `x0`
 
 error: aborting due to 21 previous errors; 1 warning emitted
 
index 250bc3be42ebb42fed995abba4b73aafb986173d..b29b74bac80b1d075938ab02f2a5636181dc3d74 100644 (file)
@@ -190,8 +190,8 @@ LL |         asm!("{:foo}", in(reg) foo);
    |               ^^^^^^           --- for this argument
    |
    = note: `#[warn(asm_sub_register)]` on by default
-   = help: use the `e` modifier to have the register formatted as `eax`
-   = help: or use the `r` modifier to keep the default formatting of `rax`
+   = help: use `{0:e}` to have the register formatted as `eax`
+   = help: or use `{0:r}` to keep the default formatting of `rax`
 
 error: aborting due to 21 previous errors; 1 warning emitted
 
index 250bc3be42ebb42fed995abba4b73aafb986173d..b29b74bac80b1d075938ab02f2a5636181dc3d74 100644 (file)
@@ -190,8 +190,8 @@ LL |         asm!("{:foo}", in(reg) foo);
    |               ^^^^^^           --- for this argument
    |
    = note: `#[warn(asm_sub_register)]` on by default
-   = help: use the `e` modifier to have the register formatted as `eax`
-   = help: or use the `r` modifier to keep the default formatting of `rax`
+   = help: use `{0:e}` to have the register formatted as `eax`
+   = help: or use `{0:r}` to keep the default formatting of `rax`
 
 error: aborting due to 21 previous errors; 1 warning emitted
 
index b38ea8cc4d8ee7bfe8dbfbd5098af4b035128754..366038fea2340ac5ddb2d6d6db1167c4c299f8c7 100644 (file)
@@ -45,8 +45,8 @@ LL |         asm!("{0} {0}", in(reg) 0i16);
    |               ^^^ ^^^           ---- for this argument
    |
    = note: `#[warn(asm_sub_register)]` on by default
-   = help: use the `x` modifier to have the register formatted as `ax`
-   = help: or use the `r` modifier to keep the default formatting of `rax`
+   = help: use `{0:x}` to have the register formatted as `ax`
+   = help: or use `{0:r}` to keep the default formatting of `rax`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:36:15
@@ -54,8 +54,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{0} {0:x}", in(reg) 0i16);
    |               ^^^                 ---- for this argument
    |
-   = help: use the `x` modifier to have the register formatted as `ax`
-   = help: or use the `r` modifier to keep the default formatting of `rax`
+   = help: use `{0:x}` to have the register formatted as `ax`
+   = help: or use `{0:r}` to keep the default formatting of `rax`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:38:15
@@ -63,8 +63,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(reg) 0i32);
    |               ^^           ---- for this argument
    |
-   = help: use the `e` modifier to have the register formatted as `eax`
-   = help: or use the `r` modifier to keep the default formatting of `rax`
+   = help: use `{0:e}` to have the register formatted as `eax`
+   = help: or use `{0:r}` to keep the default formatting of `rax`
 
 warning: formatting may not be suitable for sub-register argument
   --> $DIR/type-check-3.rs:41:15
@@ -72,8 +72,8 @@ warning: formatting may not be suitable for sub-register argument
 LL |         asm!("{}", in(ymm_reg) 0i64);
    |               ^^               ---- for this argument
    |
-   = help: use the `x` modifier to have the register formatted as `xmm0`
-   = help: or use the `y` modifier to keep the default formatting of `ymm0`
+   = help: use `{0:x}` to have the register formatted as `xmm0`
+   = help: or use `{0:y}` to keep the default formatting of `ymm0`
 
 error: type `i8` cannot be used with this register class
   --> $DIR/type-check-3.rs:52:28
index 9d18690e96049a189cf6190449d3d1060b762e8e..499bbd6b6fad2e1a6cdcf821cbe26c39a2254487 100644 (file)
@@ -10,6 +10,7 @@ impl T<'_> for S {
 
 fn foo(x: impl Fn(<S as T<'_>>::A) -> <S as T<'_>>::A) {}
 //~^ ERROR binding for associated type `Output` references an anonymous lifetime
-//~^^ NOTE lifetimes appearing in an associated type are not considered constrained
+//~| NOTE lifetimes appearing in an associated or opaque type are not considered constrained
+//~| NOTE consider introducing a named lifetime parameter
 
 fn main() {}
index f14cd81fdfe1f43583bb1b429d07437e93894eff..04f0728f58ea86bb68a6d0df3130080757797c79 100644 (file)
@@ -4,7 +4,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet
 LL | fn foo(x: impl Fn(<S as T<'_>>::A) -> <S as T<'_>>::A) {}
    |                                       ^^^^^^^^^^^^^^^
    |
-   = note: lifetimes appearing in an associated type are not considered constrained
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
 
 error: aborting due to previous error
 
index e2062e82725c0507fad934ec9f6720dfab28ea71..0ea685986db4057dcbf376b0913d06428de24a71 100644 (file)
@@ -1,8 +1,11 @@
 // edition:2018
 trait T {
     async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
+    //~^ ERROR mismatched types
     async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async`
+    //~^ ERROR mismatched types
     async fn baz() { //~ ERROR functions in traits cannot be declared `async`
+        //~^ ERROR mismatched types
         // Nested item must not ICE.
         fn a() {}
     }
index 1eb8969a80d20047db21c886240c0dc11aebc73d..e5c584e31e8158326f67a14d306d75805cfa9d55 100644 (file)
@@ -2,40 +2,89 @@ error[E0706]: functions in traits cannot be declared `async`
   --> $DIR/async-trait-fn.rs:3:5
    |
 LL |     async fn foo() {}
-   |     -----^^^^^^^^^^^^
+   |     -----^^^^^^^^^
    |     |
    |     `async` because of this
    |
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:4:5
+  --> $DIR/async-trait-fn.rs:5:5
    |
 LL |     async fn bar(&self) {}
-   |     -----^^^^^^^^^^^^^^^^^
+   |     -----^^^^^^^^^^^^^^
    |     |
    |     `async` because of this
    |
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:5:5
+  --> $DIR/async-trait-fn.rs:7:5
+   |
+LL |     async fn baz() {
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/async-trait-fn.rs:3:20
+   |
+LL |     async fn foo() {}
+   |                    ^^ expected associated type, found opaque type
+   |
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                           ------------------------------- the found opaque type
+   |
+   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>)
+                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+
+error[E0308]: mismatched types
+  --> $DIR/async-trait-fn.rs:5:25
+   |
+LL |     async fn bar(&self) {}
+   |                         ^^ expected associated type, found opaque type
+   |
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                           ------------------------------- the found opaque type
+   |
+   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>)
+                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+
+error[E0308]: mismatched types
+  --> $DIR/async-trait-fn.rs:7:20
    |
 LL |       async fn baz() {
-   |       ^----
-   |       |
-   |  _____`async` because of this
-   | |
+   |  ____________________^
+LL | |
 LL | |         // Nested item must not ICE.
 LL | |         fn a() {}
 LL | |     }
-   | |_____^
+   | |_____^ expected associated type, found opaque type
    |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                             ------------------------------- the found opaque type
+   |
+   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>)
+                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0706`.
+Some errors have detailed explanations: E0308, E0706.
+For more information about an error, try `rustc --explain E0308`.
index e5dc9c8a5fee8bee0aaafc2528c9b22e494065e3..22a61dcd25f98835921c47d2aef5a281347f73c9 100644 (file)
@@ -16,7 +16,8 @@ async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
 
 trait Bar {
     async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
-                      //~^ ERROR functions in traits cannot be declared `async`
+    //~^ ERROR functions in traits cannot be declared `async`
+    //~| ERROR mismatched types
 }
 
 fn main() {
index 35f9c581c7b21b254a4add1f516668fa17c24229..8c2902d9b00d137ca47e799f5f26f90fc760758e 100644 (file)
@@ -53,7 +53,7 @@ LL |     async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:36:9
+  --> $DIR/edition-deny-async-fns-2015.rs:37:9
    |
 LL |         async fn bar() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -62,7 +62,7 @@ LL |         async fn bar() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:26:9
+  --> $DIR/edition-deny-async-fns-2015.rs:27:9
    |
 LL |         async fn foo() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -71,7 +71,7 @@ LL |         async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:31:13
+  --> $DIR/edition-deny-async-fns-2015.rs:32:13
    |
 LL |             async fn bar() {}
    |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -83,14 +83,30 @@ error[E0706]: functions in traits cannot be declared `async`
   --> $DIR/edition-deny-async-fns-2015.rs:18:5
    |
 LL |     async fn foo() {}
-   |     -----^^^^^^^^^^^^
+   |     -----^^^^^^^^^
    |     |
    |     `async` because of this
    |
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error: aborting due to 10 previous errors
+error[E0308]: mismatched types
+  --> $DIR/edition-deny-async-fns-2015.rs:18:20
+   |
+LL |     async fn foo() {}
+   |                    ^^ expected associated type, found opaque type
+   |
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                           ------------------------------- the found opaque type
+   |
+   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>)
+                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+
+error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0670, E0706.
-For more information about an error, try `rustc --explain E0670`.
+Some errors have detailed explanations: E0308, E0670, E0706.
+For more information about an error, try `rustc --explain E0308`.
index 29aebb719d66f506e61e68bb13c871be8456263e..1c12f1e4862e8a2b36af6d9006fd7514484cb11c 100644 (file)
@@ -8,6 +8,8 @@ LL |     async fn new() -> [u8; _];
    |
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error: in expressions, `_` can only be used on the left-hand side of an assignment
   --> $DIR/issue-95307.rs:7:28
index 1651f70d5cde739dcb4b4d64463fe1625485b1a4..34826d2f4bf7ab2932657a08c53a606ded25d406 100644 (file)
@@ -6,7 +6,7 @@ LL |         x % 2 == 0
    |         |
    |         &&{integer}
    |
-help: `%` can be used on `{integer}`, you can dereference `x`
+help: `%` can be used on `&{integer}` if you dereference the left-hand side
    |
 LL |         *x % 2 == 0
    |         +
diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
new file mode 100644 (file)
index 0000000..de7966c
--- /dev/null
@@ -0,0 +1,5 @@
+trait Foo {
+    fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
new file mode 100644 (file)
index 0000000..36177bb
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+  --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:2:17
+   |
+LL |     fn bar() -> impl Sized;
+   |                 ^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
index 2315810a47ace850f1f6b27ae385604690f2cfc7..ee758f19ec105345066f5437ce2e17aaf125cc63 100644 (file)
@@ -24,7 +24,7 @@ impl<B: Add + Add<Output = B>> Add for C<B> {
 
 struct D<B>(B);
 
-impl<B: std::ops::Add<Output=B>> Add for D<B> {
+impl<B: std::ops::Add<Output = B>> Add for D<B> {
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
index 138c642dd7952181918a88d5e492b826d6af4cbb..c913483a8747c15ef849f859570306d64a177578 100644 (file)
@@ -66,8 +66,8 @@ LL |         Self(self.0 + rhs.0)
    |
 help: consider restricting type parameter `B`
    |
-LL | impl<B: std::ops::Add<Output=B>> Add for D<B> {
-   |       +++++++++++++++++++++++++
+LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
+   |       +++++++++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/missing-bounds.rs:42:14
diff --git a/src/test/ui/impl-trait/in-trait/deep-match-works.rs b/src/test/ui/impl-trait/in-trait/deep-match-works.rs
new file mode 100644 (file)
index 0000000..772da84
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+struct Wrapper<T>(T);
+
+trait Foo {
+    fn bar() -> Wrapper<impl Sized>;
+}
+
+impl Foo for () {
+    fn bar() -> Wrapper<i32> { Wrapper(0) }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/deep-match.rs b/src/test/ui/impl-trait/in-trait/deep-match.rs
new file mode 100644 (file)
index 0000000..5a220bc
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+struct Wrapper<T>(T);
+
+trait Foo {
+    fn bar() -> Wrapper<impl Sized>;
+}
+
+impl Foo for () {
+    fn bar() -> i32 { 0 }
+    //~^ ERROR method `bar` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/deep-match.stderr b/src/test/ui/impl-trait/in-trait/deep-match.stderr
new file mode 100644 (file)
index 0000000..af44986
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/deep-match.rs:11:17
+   |
+LL |     fn bar() -> i32 { 0 }
+   |                 ^^^
+   |                 |
+   |                 expected struct `Wrapper`, found `i32`
+   |                 help: change the output type to match the trait: `Wrapper<_>`
+   |
+note: type in trait
+  --> $DIR/deep-match.rs:7:17
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                 ^^^^^^^^^^^^^^^^^^^
+   = note: expected fn pointer `fn() -> Wrapper<_>`
+              found fn pointer `fn() -> i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs
new file mode 100644 (file)
index 0000000..bb4e0d4
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    fn bar() -> impl std::fmt::Display;
+}
+
+impl Foo for () {
+    fn bar() -> () {}
+    //~^ ERROR `()` doesn't implement `std::fmt::Display`
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr
new file mode 100644 (file)
index 0000000..aa5492d
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/doesnt-satisfy.rs:9:17
+   |
+LL |     fn bar() -> () {}
+   |                 ^^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `Foo::bar::{opaque#0}`
+  --> $DIR/doesnt-satisfy.rs:5:22
+   |
+LL |     fn bar() -> impl std::fmt::Display;
+   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/in-trait/nested-rpitit.rs b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs
new file mode 100644 (file)
index 0000000..65285e3
--- /dev/null
@@ -0,0 +1,32 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+use std::ops::Deref;
+
+trait Foo {
+    fn bar(self) -> impl Deref<Target = impl Display + ?Sized>;
+}
+
+struct A;
+
+impl Foo for A {
+    fn bar(self) -> &'static str {
+        "Hello, world"
+    }
+}
+
+struct B;
+
+impl Foo for B {
+    fn bar(self) -> Box<i32> {
+        Box::new(42)
+    }
+}
+
+fn main() {
+    println!("Message for you: {:?}", &*A.bar());
+    println!("Another for you: {:?}", &*B.bar());
+}
diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs
new file mode 100644 (file)
index 0000000..3ac264e
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+
+trait Foo {
+    fn bar(&self) -> impl Display;
+}
+
+impl Foo for () {
+    fn bar(&self) -> impl Display {
+        "Hello, world"
+    }
+}
+
+fn main() {
+    let x: &str = ().bar();
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr
new file mode 100644 (file)
index 0000000..15edda4
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/opaque-in-impl-is-opaque.rs:17:19
+   |
+LL |     fn bar(&self) -> impl Display {
+   |                      ------------ the found opaque type
+...
+LL |     let x: &str = ().bar();
+   |            ----   ^^^^^^^^ expected `&str`, found opaque type
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&str`
+            found opaque type `impl std::fmt::Display`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs
new file mode 100644 (file)
index 0000000..2e06629
--- /dev/null
@@ -0,0 +1,48 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait Foo {
+    fn foo(&self) -> impl Debug;
+}
+
+impl Foo for () {
+    fn foo(&self) -> impl Debug {
+        "Hello, world"
+    }
+}
+
+impl<T: Default + Debug> Foo for std::marker::PhantomData<T> {
+    fn foo(&self) -> impl Debug {
+        T::default()
+    }
+}
+
+trait Bar {
+    fn bar<T>(&self) -> impl Debug;
+}
+
+impl Bar for () {
+    fn bar<T>(&self) -> impl Debug {
+        format!("Hello with generic {}", std::any::type_name::<T>())
+    }
+}
+
+trait Baz {
+    fn baz(&self) -> impl Debug + '_;
+}
+
+impl Baz for String {
+    fn baz(&self) -> impl Debug + '_ {
+        (self,)
+    }
+}
+
+fn main() {
+    println!("{:?}", ().foo());
+    println!("{:?}", ().bar::<u64>());
+    println!("{:?}", "hi".to_string().baz());
+}
diff --git a/src/test/ui/impl-trait/in-trait/reveal.rs b/src/test/ui/impl-trait/in-trait/reveal.rs
new file mode 100644 (file)
index 0000000..d6ede1c
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    fn f() -> Box<impl Sized>;
+}
+
+impl Foo for () {
+    fn f() -> Box<String> {
+        Box::new(String::new())
+    }
+}
+
+fn main() {
+    let x: Box<String> = <() as Foo>::f();
+}
diff --git a/src/test/ui/impl-trait/in-trait/success.rs b/src/test/ui/impl-trait/in-trait/success.rs
new file mode 100644 (file)
index 0000000..4cbe682
--- /dev/null
@@ -0,0 +1,40 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+
+trait Foo {
+    fn bar(&self) -> impl Display;
+}
+
+impl Foo for i32 {
+    fn bar(&self) -> i32 {
+        *self
+    }
+}
+
+impl Foo for &'static str {
+    fn bar(&self) -> &'static str {
+        *self
+    }
+}
+
+struct Yay;
+
+impl Foo for Yay {
+    fn bar(&self) -> String {
+        String::from(":^)")
+    }
+}
+
+fn foo_generically<T: Foo>(t: T) {
+    println!("{}", t.bar());
+}
+
+fn main() {
+    println!("{}", "Hello, world.".bar());
+    println!("The answer is {}!", 42.bar());
+    foo_generically(Yay);
+}
index 58a2f79efb4c643e5f0cecdfbbb25faf395064b1..9b346387d61064cbf9bd4d01a47fb4fd0cc1028a 100644 (file)
@@ -162,12 +162,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t
    |
 LL |     fn in_return() -> impl Debug;
    |                       ^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
   --> $DIR/where-allowed.rs:125:34
    |
 LL |     fn in_trait_impl_return() -> impl Debug { () }
    |                                  ^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param
   --> $DIR/where-allowed.rs:138:33
index 5b84f7ed62c3a18239eb36191ebbe7795660b496..9998ee0e8d0c69c801528a509eb6371d10af4f86 100644 (file)
@@ -4,7 +4,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra
 LL | fn f(_: X) -> X {
    |               ^
    |
-   = note: lifetimes appearing in an associated type are not considered constrained
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
 
 error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
   --> $DIR/issue-47511.rs:12:23
index 8ff14fb1f304aee283b93b1bf8256a9d90c1ad83..cf5d3dab4aadad1f5b3e73b5f4b98db565906d25 100644 (file)
@@ -27,7 +27,6 @@ trait X {
     struct Y;
     impl X for Y {
         async fn ft1() {} //~ ERROR functions in traits cannot be declared `async`
-        //~^ 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 +35,6 @@ extern "C" fn ft4() {}
         //~| ERROR functions in traits cannot be declared const
         //~| ERROR functions cannot be both `const` and `async`
         //~| ERROR cycle detected
-        //~| ERROR has an incompatible type for trait
     }
 
     impl Y {
index bc51ba8b8c5c51971799f77b3dea857c71f7243d..36304779df36fa6ee620f90cd7c15cbb98266da7 100644 (file)
@@ -7,17 +7,6 @@ LL |     const async unsafe extern "C" fn ff5() {}
    |     |     `async` because of this
    |     `const` because of this
 
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:17:9
-   |
-LL |         async fn ft1();
-   |         -----^^^^^^^^^^
-   |         |
-   |         `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 error[E0379]: functions in traits cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:19:9
    |
@@ -30,17 +19,6 @@ error[E0379]: functions in traits cannot be declared const
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^ functions in traits cannot be const
 
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:21:9
-   |
-LL |         const async unsafe extern "C" fn ft5();
-   |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |               |
-   |               `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:21:9
    |
@@ -50,42 +28,20 @@ LL |         const async unsafe extern "C" fn ft5();
    |         |     `async` because of this
    |         `const` because of this
 
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:29:9
-   |
-LL |         async fn ft1() {}
-   |         -----^^^^^^^^^^^^
-   |         |
-   |         `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:32:9
+  --> $DIR/fn-header-semantic-fail.rs:31:9
    |
 LL |         const fn ft3() {}
    |         ^^^^^ functions in traits cannot be const
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:34:9
+  --> $DIR/fn-header-semantic-fail.rs:33:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^ functions in traits cannot be const
 
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:34:9
-   |
-LL |         const async unsafe extern "C" fn ft5() {}
-   |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |               |
-   |               `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:34:9
+  --> $DIR/fn-header-semantic-fail.rs:33:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^-^^^^^------------------------------
@@ -94,7 +50,7 @@ LL |         const async unsafe extern "C" fn ft5() {}
    |         `const` because of this
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:47:9
+  --> $DIR/fn-header-semantic-fail.rs:45:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |         ^^^^^-^^^^^------------------------------
@@ -103,7 +59,7 @@ LL |         const async unsafe extern "C" fn fi5() {}
    |         `const` because of this
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:53:18
+  --> $DIR/fn-header-semantic-fail.rs:51:18
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -116,7 +72,7 @@ LL |         fn fe1();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:54:19
+  --> $DIR/fn-header-semantic-fail.rs:52:19
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -130,7 +86,7 @@ LL |         fn fe2();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:55:18
+  --> $DIR/fn-header-semantic-fail.rs:53:18
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -144,7 +100,7 @@ LL |         fn fe3();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:56:23
+  --> $DIR/fn-header-semantic-fail.rs:54:23
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -158,7 +114,7 @@ LL |         fn fe4();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:57:42
+  --> $DIR/fn-header-semantic-fail.rs:55:42
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -172,7 +128,7 @@ LL |         fn fe5();
    |         ~~
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:57:9
+  --> $DIR/fn-header-semantic-fail.rs:55:9
    |
 LL |         const async unsafe extern "C" fn fe5();
    |         ^^^^^-^^^^^----------------------------
@@ -180,6 +136,58 @@ LL |         const async unsafe extern "C" fn fe5();
    |         |     `async` because of this
    |         `const` because of this
 
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:17:9
+   |
+LL |         async fn ft1();
+   |         -----^^^^^^^^^^
+   |         |
+   |         `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:21:9
+   |
+LL |         const async unsafe extern "C" fn ft5();
+   |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               |
+   |               `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:29:9
+   |
+LL |         async fn ft1() {}
+   |         -----^^^^^^^^^
+   |         |
+   |         `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:33:9
+   |
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               |
+   |               `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
 error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}`
   --> $DIR/fn-header-semantic-fail.rs:12:44
    |
@@ -216,60 +224,24 @@ LL | |     }
 LL | | }
    | |_^
 
-error[E0053]: method `ft1` has an incompatible type for trait
-  --> $DIR/fn-header-semantic-fail.rs:29:24
-   |
-LL |         async fn ft1() {}
-   |                        ^
-   |                        |
-   |                        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[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() {}
-   |                                                ^
-   |                                                |
-   |                                                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
+  --> $DIR/fn-header-semantic-fail.rs:33:48
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |                                                ^
    |
 note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`...
-  --> $DIR/fn-header-semantic-fail.rs:34:9
+  --> $DIR/fn-header-semantic-fail.rs:33:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`...
-  --> $DIR/fn-header-semantic-fail.rs:34:9
+  --> $DIR/fn-header-semantic-fail.rs:33:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`...
-  --> $DIR/fn-header-semantic-fail.rs:34:9
+  --> $DIR/fn-header-semantic-fail.rs:33:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -288,30 +260,30 @@ LL | |     }
 LL | | }
    | |_^
 
-error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5::{opaque#0}`
-  --> $DIR/fn-header-semantic-fail.rs:47:48
+error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}`
+  --> $DIR/fn-header-semantic-fail.rs:45:48
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |                                                ^
    |
-note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5`...
-  --> $DIR/fn-header-semantic-fail.rs:47:9
+note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:45:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5`...
-  --> $DIR/fn-header-semantic-fail.rs:47:9
+note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:45:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5`...
-  --> $DIR/fn-header-semantic-fail.rs:47:9
+note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:45:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
    = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
-   = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5::{opaque#0}`, completing the cycle
+   = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/fn-header-semantic-fail.rs:5:1
    |
@@ -324,7 +296,7 @@ LL | |     }
 LL | | }
    | |_^
 
-error: aborting due to 23 previous errors
+error: aborting due to 21 previous errors
 
-Some errors have detailed explanations: E0053, E0379, E0391, E0706.
-For more information about an error, try `rustc --explain E0053`.
+Some errors have detailed explanations: E0379, E0391, E0706.
+For more information about an error, try `rustc --explain E0379`.
diff --git a/src/test/ui/parser/issue-101477-enum.fixed b/src/test/ui/parser/issue-101477-enum.fixed
new file mode 100644 (file)
index 0000000..1dfeae2
--- /dev/null
@@ -0,0 +1,10 @@
+// run-rustfix
+
+#[allow(dead_code)]
+enum Demo {
+    A = 1,
+    B = 2 //~ ERROR unexpected `==`
+    //~^ expected item, found `==`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-101477-enum.rs b/src/test/ui/parser/issue-101477-enum.rs
new file mode 100644 (file)
index 0000000..ea7051d
--- /dev/null
@@ -0,0 +1,10 @@
+// run-rustfix
+
+#[allow(dead_code)]
+enum Demo {
+    A = 1,
+    B == 2 //~ ERROR unexpected `==`
+    //~^ expected item, found `==`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr
new file mode 100644 (file)
index 0000000..bffc881
--- /dev/null
@@ -0,0 +1,14 @@
+error: unexpected `==`
+  --> $DIR/issue-101477-enum.rs:6:7
+   |
+LL |     B == 2
+   |       ^^ help: try using `=` instead
+
+error: expected item, found `==`
+  --> $DIR/issue-101477-enum.rs:6:7
+   |
+LL |     B == 2
+   |       ^^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-101477-let.fixed b/src/test/ui/parser/issue-101477-let.fixed
new file mode 100644 (file)
index 0000000..9989ad8
--- /dev/null
@@ -0,0 +1,6 @@
+// run-rustfix
+
+fn main() {
+    let x = 2; //~ ERROR unexpected `==`
+    println!("x: {}", x)
+}
diff --git a/src/test/ui/parser/issue-101477-let.rs b/src/test/ui/parser/issue-101477-let.rs
new file mode 100644 (file)
index 0000000..8b0e8be
--- /dev/null
@@ -0,0 +1,6 @@
+// run-rustfix
+
+fn main() {
+    let x == 2; //~ ERROR unexpected `==`
+    println!("x: {}", x)
+}
diff --git a/src/test/ui/parser/issue-101477-let.stderr b/src/test/ui/parser/issue-101477-let.stderr
new file mode 100644 (file)
index 0000000..1b30d4b
--- /dev/null
@@ -0,0 +1,8 @@
+error: unexpected `==`
+  --> $DIR/issue-101477-let.rs:4:11
+   |
+LL |     let x == 2;
+   |           ^^ help: try using `=` instead
+
+error: aborting due to previous error
+
index aaf0f7eaef0dcdd3969dcb3d743d0b4fba8f69f0..49462f52fb4c2355375bd633eb76b28dcd730501 100644 (file)
@@ -14,7 +14,6 @@ trait B {
 impl B for A {
     async fn associated(); //~ ERROR without body
     //~^ ERROR cannot be declared `async`
-    //~| ERROR has an incompatible type for trait
 }
 
 fn main() {}
index d3214458eac13cc8f89bedfcf498812c5aad6116..55c3b66f1363df29fbb58a8bd48d844aa9ff699d 100644 (file)
@@ -14,17 +14,6 @@ LL |     async fn inherent();
    |                        |
    |                        help: provide a definition for the function: `{ <body> }`
 
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5
-   |
-LL |     async fn associated();
-   |     -----^^^^^^^^^^^^^^^^^
-   |     |
-   |     `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 error: associated function in `impl` without body
   --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
    |
@@ -34,7 +23,7 @@ LL |     async fn associated();
    |                          help: provide a definition for the function: `{ <body> }`
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5
    |
 LL |     async fn associated();
    |     -----^^^^^^^^^^^^^^^^^
@@ -43,26 +32,22 @@ 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
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error[E0053]: method `associated` has an incompatible type for trait
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
    |
 LL |     async fn associated();
-   |                          ^
-   |                          |
-   |                          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
+   |     -----^^^^^^^^^^^^^^^^^
+   |     |
+   |     `async` because of this
    |
-LL |     async fn associated();
-   |                          ^
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn() -> impl Future<Output = ()>`
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0053, E0706.
-For more information about an error, try `rustc --explain E0053`.
+For more information about this error, try `rustc --explain E0706`.
diff --git a/src/test/ui/sanitize/memory-eager.rs b/src/test/ui/sanitize/memory-eager.rs
new file mode 100644 (file)
index 0000000..8a0590b
--- /dev/null
@@ -0,0 +1,38 @@
+// needs-sanitizer-support
+// needs-sanitizer-memory
+// min-llvm-version: 14.0.0
+//
+// revisions: unoptimized optimized
+//
+// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
+// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins
+//
+// run-fail
+// error-pattern: MemorySanitizer: use-of-uninitialized-value
+// error-pattern: Uninitialized value was created by an allocation
+// error-pattern: in the stack frame of function 'random'
+//
+// This test case intentionally limits the usage of the std,
+// since it will be linked with an uninstrumented version of it.
+
+#![feature(core_intrinsics)]
+#![feature(start)]
+#![feature(bench_black_box)]
+
+use std::hint::black_box;
+use std::mem::MaybeUninit;
+
+#[inline(never)]
+#[no_mangle]
+#[allow(invalid_value)]
+fn random() -> char {
+    let r = unsafe { MaybeUninit::uninit().assume_init() };
+    // Avoid optimizing everything out.
+    black_box(r)
+}
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    random();
+    0
+}
index adda51f6be0ecb97eddee6bae8a86136153594ce..14d4de65dd378ed0358cbda7de43503b7a1e5630 100644 (file)
@@ -1,7 +1,10 @@
 // needs-sanitizer-support
 // needs-sanitizer-memory
 //
-// compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
+// revisions: unoptimized optimized
+//
+// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
+// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins
 //
 // run-fail
 // error-pattern: MemorySanitizer: use-of-uninitialized-value
@@ -22,9 +25,9 @@
 #[inline(never)]
 #[no_mangle]
 fn random() -> [isize; 32] {
-    let r = unsafe { MaybeUninit::uninit().assume_init() };
+    let r = MaybeUninit::uninit();
     // Avoid optimizing everything out.
-    black_box(r)
+    unsafe { std::intrinsics::volatile_load(r.as_ptr()) }
 }
 
 #[inline(never)]
@@ -39,6 +42,6 @@ fn xor(a: &[isize]) -> isize {
 
 #[start]
 fn main(_: isize, _: *const *const u8) -> isize {
-    let r = random();
+    let r = black_box(random as fn() -> [isize; 32])();
     xor(&r)
 }
index b280c8ab6e2b270e61fc77ec2204d56975ce4a32..94f578af209a8593e10a87e0928556d558833152 100644 (file)
@@ -12,7 +12,8 @@ async fn create(path: impl AsRef<std::path::Path>)  { //~ ERROR  `async fn` is n
 
 trait C{async fn new(val: T) {} //~ ERROR  `async fn` is not permitted in Rust 2015
 //~^ ERROR functions in traits cannot be declared `async`
-//~^^ ERROR cannot find type `T` in this scope
-//~^^^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
+//~| ERROR mismatched types
+//~| ERROR cannot find type `T` in this scope
+//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
 
 //~ ERROR  this file contains an unclosed delimiter
index 50de2322907edb3a3e2ca20133d2cd7426112174..3814c568e72c1b555c30e67a61d57f6e8e57725c 100644 (file)
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53
    |
 LL | trait C{async fn new(val: T) {}
    |        - unclosed delimiter
@@ -25,17 +25,6 @@ LL | trait C{async fn new(val: T) {}
    = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
-   |
-LL | trait C{async fn new(val: T) {}
-   |         -----^^^^^^^^^^^^^^^^^^
-   |         |
-   |         `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-
 error[E0423]: expected function, found module `crate`
   --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5
    |
@@ -51,6 +40,19 @@ LL | pub struct A {}
 LL | trait C{async fn new(val: T) {}
    |                           ^ help: a struct with a similar name exists: `A`
 
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
+   |
+LL | trait C{async fn new(val: T) {}
+   |         -----^^^^^^^^^^^^^^^
+   |         |
+   |         `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
 warning: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57
    |
@@ -72,6 +74,20 @@ help: add a dummy let to cause `path` to be fully captured
 LL |     async fn create(path: impl AsRef<std::path::Path>)  { let _ = &path;
    |                                                           ++++++++++++++
 
+error[E0308]: mismatched types
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
+   |
+LL | trait C{async fn new(val: T) {}
+   |                              ^^ expected associated type, found opaque type
+   |
+  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+   |                                           ------------------------------- the found opaque type
+   |
+   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>)
+                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+
 warning: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
    |
@@ -87,7 +103,7 @@ help: add a dummy let to cause `val` to be fully captured
 LL | trait C{async fn new(val: T) { let _ = &val;}
    |                                +++++++++++++
 
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to 7 previous errors; 2 warnings emitted
 
-Some errors have detailed explanations: E0412, E0423, E0670, E0706.
-For more information about an error, try `rustc --explain E0412`.
+Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706.
+For more information about an error, try `rustc --explain E0308`.
index c8ceb6ff22df24a731d4ee4f7d5e7df3361197c1..8d977606530819efa8130b87708010ad839d81f3 100644 (file)
@@ -119,59 +119,60 @@ hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
 hir-stats ----------------------------------------------------------------
 hir-stats ForeignItemRef            24 ( 0.2%)             1            24
+hir-stats Lifetime                  32 ( 0.3%)             1            32
 hir-stats Mod                       32 ( 0.3%)             1            32
 hir-stats ExprField                 40 ( 0.4%)             1            40
 hir-stats TraitItemRef              56 ( 0.6%)             2            28
-hir-stats Param                     64 ( 0.6%)             2            32
-hir-stats Local                     64 ( 0.6%)             1            64
+hir-stats Local                     64 ( 0.7%)             1            64
+hir-stats Param                     64 ( 0.7%)             2            32
 hir-stats InlineAsm                 72 ( 0.7%)             1            72
 hir-stats ImplItemRef               72 ( 0.7%)             2            36
-hir-stats FieldDef                  96 ( 0.9%)             2            48
-hir-stats Arm                       96 ( 0.9%)             2            48
-hir-stats Body                      96 ( 0.9%)             3            32
-hir-stats Stmt                      96 ( 0.9%)             3            32
+hir-stats Body                      96 ( 1.0%)             3            32
+hir-stats GenericArg                96 ( 1.0%)             4            24
+hir-stats - Type                      24 ( 0.2%)             1
+hir-stats - Lifetime                  72 ( 0.7%)             3
+hir-stats FieldDef                  96 ( 1.0%)             2            48
+hir-stats Arm                       96 ( 1.0%)             2            48
+hir-stats Stmt                      96 ( 1.0%)             3            32
 hir-stats - Local                     32 ( 0.3%)             1
 hir-stats - Semi                      32 ( 0.3%)             1
 hir-stats - Expr                      32 ( 0.3%)             1
 hir-stats FnDecl                   120 ( 1.2%)             3            40
 hir-stats Attribute                128 ( 1.3%)             4            32
-hir-stats GenericArg               128 ( 1.3%)             4            32
-hir-stats - Type                      32 ( 0.3%)             1
-hir-stats - Lifetime                  96 ( 0.9%)             3
-hir-stats GenericArgs              144 ( 1.4%)             3            48
-hir-stats Variant                  160 ( 1.6%)             2            80
-hir-stats GenericBound             192 ( 1.9%)             4            48
-hir-stats - Trait                    192 ( 1.9%)             4
-hir-stats WherePredicate           216 ( 2.1%)             3            72
-hir-stats - BoundPredicate           216 ( 2.1%)             3
-hir-stats Block                    288 ( 2.8%)             6            48
-hir-stats GenericParam             400 ( 3.9%)             5            80
-hir-stats Pat                      440 ( 4.3%)             5            88
-hir-stats - Wild                      88 ( 0.9%)             1
-hir-stats - Struct                    88 ( 0.9%)             1
-hir-stats - Binding                  264 ( 2.6%)             3
-hir-stats Generics                 560 ( 5.5%)            10            56
-hir-stats Expr                     768 ( 7.6%)            12            64
-hir-stats - Path                      64 ( 0.6%)             1
-hir-stats - Struct                    64 ( 0.6%)             1
-hir-stats - Match                     64 ( 0.6%)             1
-hir-stats - InlineAsm                 64 ( 0.6%)             1
+hir-stats GenericArgs              144 ( 1.5%)             3            48
+hir-stats Variant                  160 ( 1.7%)             2            80
+hir-stats WherePredicate           168 ( 1.7%)             3            56
+hir-stats - BoundPredicate           168 ( 1.7%)             3
+hir-stats GenericBound             192 ( 2.0%)             4            48
+hir-stats - Trait                    192 ( 2.0%)             4
+hir-stats Block                    288 ( 3.0%)             6            48
+hir-stats Pat                      360 ( 3.7%)             5            72
+hir-stats - Wild                      72 ( 0.7%)             1
+hir-stats - Struct                    72 ( 0.7%)             1
+hir-stats - Binding                  216 ( 2.2%)             3
+hir-stats GenericParam             400 ( 4.1%)             5            80
+hir-stats Generics                 560 ( 5.8%)            10            56
+hir-stats Ty                       720 ( 7.4%)            15            48
+hir-stats - Ptr                       48 ( 0.5%)             1
+hir-stats - Rptr                      48 ( 0.5%)             1
+hir-stats - Path                     624 ( 6.4%)            13
+hir-stats Expr                     768 ( 7.9%)            12            64
+hir-stats - Path                      64 ( 0.7%)             1
+hir-stats - Struct                    64 ( 0.7%)             1
+hir-stats - Match                     64 ( 0.7%)             1
+hir-stats - InlineAsm                 64 ( 0.7%)             1
 hir-stats - Lit                      128 ( 1.3%)             2
-hir-stats - Block                    384 ( 3.8%)             6
-hir-stats Item                     960 ( 9.4%)            12            80
+hir-stats - Block                    384 ( 4.0%)             6
+hir-stats Item                     960 ( 9.9%)            12            80
 hir-stats - Trait                     80 ( 0.8%)             1
 hir-stats - Enum                      80 ( 0.8%)             1
 hir-stats - ExternCrate               80 ( 0.8%)             1
 hir-stats - ForeignMod                80 ( 0.8%)             1
 hir-stats - Impl                      80 ( 0.8%)             1
-hir-stats - Fn                       160 ( 1.6%)             2
-hir-stats - Use                      400 ( 3.9%)             5
-hir-stats Ty                     1_080 (10.6%)            15            72
-hir-stats - Ptr                       72 ( 0.7%)             1
-hir-stats - Rptr                      72 ( 0.7%)             1
-hir-stats - Path                     936 ( 9.2%)            13
-hir-stats Path                   1_536 (15.1%)            32            48
-hir-stats PathSegment            2_240 (22.0%)            40            56
+hir-stats - Fn                       160 ( 1.7%)             2
+hir-stats - Use                      400 ( 4.1%)             5
+hir-stats Path                   1_536 (15.9%)            32            48
+hir-stats PathSegment            2_240 (23.1%)            40            56
 hir-stats ----------------------------------------------------------------
-hir-stats Total                 10_168
+hir-stats Total                  9_680
 hir-stats
index e43a4e79bfe8c54c1e433d7ef0ddf184fe7567ce..77cef485f30e9a477108aa3e29914a0544e46f80 100644 (file)
@@ -91,7 +91,7 @@ LL |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
    |                                             ------------------------------- the found opaque type
    |
    = note:   expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
-           found opaque type `impl Future`
+           found opaque type `impl Future<Output = {integer}>`
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
index 73ca9f97b43a360b986a47f9be217e01ba766851..1e7569fa45106c60b8660a83af58f6c6c3757648 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-fn add_ten<N: std::ops::Add<i32, Output=N>>(n: N) -> N {
+fn add_ten<N: std::ops::Add<i32, Output = N>>(n: N) -> N {
     n + 10
     //~^ ERROR cannot add `{integer}` to `N`
 }
index 069b184ac636c45bdfaa6dc045afca4f647f3c57..575d79267f20d718957f456241a28b7ec1c3d66a 100644 (file)
@@ -8,8 +8,8 @@ LL |     n + 10
    |
 help: consider restricting type parameter `N`
    |
-LL | fn add_ten<N: std::ops::Add<i32, Output=N>>(n: N) -> N {
-   |             ++++++++++++++++++++++++++++++
+LL | fn add_ten<N: std::ops::Add<i32, Output = N>>(n: N) -> N {
+   |             ++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/restrict-type-not-param.rs b/src/test/ui/suggestions/restrict-type-not-param.rs
new file mode 100644 (file)
index 0000000..60f5ba4
--- /dev/null
@@ -0,0 +1,12 @@
+use std::ops::Add;
+
+struct Wrapper<T>(T);
+
+trait Foo {}
+
+fn qux<T>(a: Wrapper<T>, b: T) -> T {
+    a + b
+    //~^ ERROR cannot add `T` to `Wrapper<T>`
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/restrict-type-not-param.stderr b/src/test/ui/suggestions/restrict-type-not-param.stderr
new file mode 100644 (file)
index 0000000..e7d9c5e
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0369]: cannot add `T` to `Wrapper<T>`
+  --> $DIR/restrict-type-not-param.rs:8:7
+   |
+LL |     a + b
+   |     - ^ - T
+   |     |
+   |     Wrapper<T>
+   |
+note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
+  --> $DIR/restrict-type-not-param.rs:3:1
+   |
+LL | struct Wrapper<T>(T);
+   | ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
+note: the following trait must be implemented
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL | pub trait Add<Rhs = Self> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn qux<T>(a: Wrapper<T>, b: T) -> T where Wrapper<T>: Add<T, Output = T> {
+   |                                     ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
index 34fae64e4d20fe9b2d682c78125d25ec812dab79..fe5e1d6d2854de0b98f0588d188734ff3404213b 100644 (file)
@@ -8,8 +8,8 @@ LL |     a * b
    |
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
-LL | fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 where &T: Mul<f64> {
-   |                                                  ++++++++++++++++++
+LL | fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 where &T: Mul<f64, Output = f64> {
+   |                                                  ++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
index c32174288ee684069c391825a168785e6c0d8aef..03fb64b7b94d7ea02224ae7cc4b5060e847a1133 100644 (file)
@@ -1,17 +1,33 @@
-// check-pass
-
 #![feature(type_alias_impl_trait)]
 
-mod foo {
+mod lifetime_params {
     type Ty<'a> = impl Sized;
     fn defining(s: &str) -> Ty<'_> { s }
     fn execute(ty: Ty<'_>) -> &str { todo!() }
+    //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types
+
+    type BadFnSig = fn(Ty<'_>) -> &str;
+    //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types
+    type BadTraitRef = dyn Fn(Ty<'_>) -> &str;
+    //~^ ERROR binding for associated type `Output` references an anonymous lifetime
 }
 
-mod bar {
+mod lifetime_params_2 {
     type Ty<'a> = impl FnOnce() -> &'a str;
     fn defining(s: &str) -> Ty<'_> { move || s }
     fn execute(ty: Ty<'_>) -> &str { ty() }
+    //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types
+}
+
+// regression test for https://github.com/rust-lang/rust/issues/97104
+mod type_params {
+    type Ty<T> = impl Sized;
+    fn define<T>(s: T) -> Ty<T> { s }
+
+    type BadFnSig = fn(Ty<&str>) -> &str;
+    //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types
+    type BadTraitRef = dyn Fn(Ty<&str>) -> &str;
+    //~^ ERROR binding for associated type `Output` references an anonymous lifetime
 }
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr
new file mode 100644 (file)
index 0000000..93953fd
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
+  --> $DIR/constrain_inputs.rs:6:31
+   |
+LL |     fn execute(ty: Ty<'_>) -> &str { todo!() }
+   |                               ^^^^
+   |
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
+
+error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
+  --> $DIR/constrain_inputs.rs:9:35
+   |
+LL |     type BadFnSig = fn(Ty<'_>) -> &str;
+   |                                   ^^^^
+   |
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
+
+error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types
+  --> $DIR/constrain_inputs.rs:11:42
+   |
+LL |     type BadTraitRef = dyn Fn(Ty<'_>) -> &str;
+   |                                          ^^^^
+   |
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
+
+error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
+  --> $DIR/constrain_inputs.rs:18:31
+   |
+LL |     fn execute(ty: Ty<'_>) -> &str { ty() }
+   |                               ^^^^
+   |
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
+
+error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
+  --> $DIR/constrain_inputs.rs:27:37
+   |
+LL |     type BadFnSig = fn(Ty<&str>) -> &str;
+   |                                     ^^^^
+   |
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
+
+error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types
+  --> $DIR/constrain_inputs.rs:29:44
+   |
+LL |     type BadTraitRef = dyn Fn(Ty<&str>) -> &str;
+   |                                            ^^^^
+   |
+   = note: lifetimes appearing in an associated or opaque type are not considered constrained
+   = note: consider introducing a named lifetime parameter
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0581, E0582.
+For more information about an error, try `rustc --explain E0581`.
diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs
new file mode 100644 (file)
index 0000000..3bae0f1
--- /dev/null
@@ -0,0 +1,31 @@
+#![feature(type_alias_impl_trait)]
+
+trait Static: 'static {}
+impl Static for () {}
+
+type Gal<T> = impl Static;
+fn _defining<T>() -> Gal<T> {}
+
+trait Callable<Arg> { type Output; }
+
+/// We can infer `<C as Callable<Arg>>::Output: 'static`,
+/// because we know `C: 'static` and `Arg: 'static`,
+fn box_str<C, Arg>(s: C::Output) -> Box<dyn AsRef<str> + 'static>
+where
+    Arg: Static,
+    C: ?Sized + Callable<Arg> + 'static,
+    C::Output: AsRef<str>,
+{
+    Box::new(s)
+}
+
+fn extend_lifetime(s: &str) -> Box<dyn AsRef<str> + 'static> {
+    type MalformedTy = dyn for<'a> Callable<Gal<&'a ()>, Output = &'a str>;
+    //~^ ERROR binding for associated type `Output` references lifetime `'a`
+    box_str::<MalformedTy, _>(s)
+}
+
+fn main() {
+    let extended = extend_lifetime(&String::from("hello"));
+    println!("{}", extended.as_ref().as_ref());
+}
diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr
new file mode 100644 (file)
index 0000000..d5fc46c
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/constrain_inputs_unsound.rs:23:58
+   |
+LL |     type MalformedTy = dyn for<'a> Callable<Gal<&'a ()>, Output = &'a str>;
+   |                                                          ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0582`.
index a6fcdfe21f481a3fb99435827c80454274974b32..e394cf8206edef45077760f28886f310e09c0e3c 100644 (file)
@@ -19,7 +19,7 @@ LL |     x.lock().unwrap() += 1;
    |     |
    |     cannot use `+=` on type `MutexGuard<'_, usize>`
    |
-help: `+=` can be used on `usize`, you can dereference `x.lock().unwrap()`
+help: `+=` can be used on `usize` if you dereference the left-hand side
    |
 LL |     *x.lock().unwrap() += 1;
    |     +
@@ -47,7 +47,7 @@ LL |     y += 1;
    |     |
    |     cannot use `+=` on type `MutexGuard<'_, usize>`
    |
-help: `+=` can be used on `usize`, you can dereference `y`
+help: `+=` can be used on `usize` if you dereference the left-hand side
    |
 LL |     *y += 1;
    |     +
index be2e9fe95e87144a3e27ffcfe1d4d14267c2d14e..cbdc960baab8e7cafaa456825299b800c3c122ad 100644 (file)
@@ -19,7 +19,7 @@ LL |     x.last_mut().unwrap() += 1;
    |     |
    |     cannot use `+=` on type `&mut usize`
    |
-help: `+=` can be used on `usize`, you can dereference `x.last_mut().unwrap()`
+help: `+=` can be used on `usize` if you dereference the left-hand side
    |
 LL |     *x.last_mut().unwrap() += 1;
    |     +
@@ -45,7 +45,7 @@ LL |     y += 1;
    |     |
    |     cannot use `+=` on type `&mut usize`
    |
-help: `+=` can be used on `usize`, you can dereference `y`
+help: `+=` can be used on `usize` if you dereference the left-hand side
    |
 LL |     *y += 1;
    |     +
index be05e67d724dfc120acfec0d1385dda0cd3df741..331b76484b8a5d5f62992a34d73de6fadbf72c93 100644 (file)
@@ -120,15 +120,17 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
 
     let new_lint = if enable_msrv {
         format!(
-            "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n    ",
+            "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv)));\n    ",
             lint_pass = lint.pass,
+            ctor_arg = if lint.pass == "late" { "_" } else { "" },
             module_name = lint.name,
             camel_name = to_camel_case(lint.name),
         )
     } else {
         format!(
-            "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n    ",
+            "store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n    ",
             lint_pass = lint.pass,
+            ctor_arg = if lint.pass == "late" { "_" } else { "" },
             module_name = lint.name,
             camel_name = to_camel_case(lint.name),
         )
index fdfb821ac7895becb9fa97f56463dad42f0b7632..bce49165e5b18060f96430be8356f5fb979d14ac 100644 (file)
@@ -51,7 +51,9 @@ fn array_rec(pats: &[Pat<'_>]) -> bool {
             false
         },
         PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
-        PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => !etc.is_some() && array_rec(a),
+        PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => {
+            !etc.as_opt_usize().is_some() && array_rec(a)
+        }
         PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
         PatKind::Path(_) | PatKind::Lit(_) => true,
     }
index dfdaf90f09f48151eda7964dd3d2a02cba705271..c70aa79ac8dcffdcfcece1c391a850f547a3e61b 100644 (file)
@@ -523,7 +523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     #[cfg(feature = "internal")]
     {
         if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
-            store.register_late_pass(|| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
+            store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
             return;
         }
     }
@@ -533,69 +533,69 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     {
         store.register_early_pass(|| Box::new(utils::internal_lints::ClippyLintsInternal));
         store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce));
-        store.register_late_pass(|| Box::new(utils::internal_lints::CollapsibleCalls));
-        store.register_late_pass(|| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
-        store.register_late_pass(|| Box::new(utils::internal_lints::IfChainStyle));
-        store.register_late_pass(|| Box::new(utils::internal_lints::InvalidPaths));
-        store.register_late_pass(|| Box::new(utils::internal_lints::InterningDefinedSymbol::default()));
-        store.register_late_pass(|| Box::new(utils::internal_lints::LintWithoutLintPass::default()));
-        store.register_late_pass(|| Box::new(utils::internal_lints::MatchTypeOnDiagItem));
-        store.register_late_pass(|| Box::new(utils::internal_lints::OuterExpnDataPass));
-        store.register_late_pass(|| Box::new(utils::internal_lints::MsrvAttrImpl));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::CollapsibleCalls));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::IfChainStyle));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::InterningDefinedSymbol::default()));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::LintWithoutLintPass::default()));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::MatchTypeOnDiagItem));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::OuterExpnDataPass));
+        store.register_late_pass(|_| Box::new(utils::internal_lints::MsrvAttrImpl));
     }
 
     let arithmetic_allowed = conf.arithmetic_allowed.clone();
-    store.register_late_pass(move || Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone())));
-    store.register_late_pass(|| Box::new(utils::dump_hir::DumpHir));
-    store.register_late_pass(|| Box::new(utils::author::Author));
+    store.register_late_pass(move |_| Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone())));
+    store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
+    store.register_late_pass(|_| Box::new(utils::author::Author));
     let await_holding_invalid_types = conf.await_holding_invalid_types.clone();
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(await_holding_invalid::AwaitHolding::new(
             await_holding_invalid_types.clone(),
         ))
     });
-    store.register_late_pass(|| Box::new(serde_api::SerdeApi));
+    store.register_late_pass(|_| Box::new(serde_api::SerdeApi));
     let vec_box_size_threshold = conf.vec_box_size_threshold;
     let type_complexity_threshold = conf.type_complexity_threshold;
     let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(types::Types::new(
             vec_box_size_threshold,
             type_complexity_threshold,
             avoid_breaking_exported_api,
         ))
     });
-    store.register_late_pass(|| Box::new(booleans::NonminimalBool));
-    store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
-    store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
-    store.register_late_pass(|| Box::new(ptr::Ptr));
-    store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
-    store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
-    store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach));
-    store.register_late_pass(|| Box::new(misc::MiscLints));
-    store.register_late_pass(|| Box::new(eta_reduction::EtaReduction));
-    store.register_late_pass(|| Box::new(mut_mut::MutMut));
-    store.register_late_pass(|| Box::new(mut_reference::UnnecessaryMutPassed));
-    store.register_late_pass(|| Box::new(len_zero::LenZero));
-    store.register_late_pass(|| Box::new(attrs::Attributes));
-    store.register_late_pass(|| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
-    store.register_late_pass(|| Box::new(unicode::Unicode));
-    store.register_late_pass(|| Box::new(uninit_vec::UninitVec));
-    store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
-    store.register_late_pass(|| Box::new(strings::StringAdd));
-    store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn));
-    store.register_late_pass(|| Box::new(implicit_saturating_sub::ImplicitSaturatingSub));
-    store.register_late_pass(|| Box::new(default_numeric_fallback::DefaultNumericFallback));
-    store.register_late_pass(|| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
-    store.register_late_pass(|| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
+    store.register_late_pass(|_| Box::new(booleans::NonminimalBool));
+    store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant));
+    store.register_late_pass(|_| Box::new(float_literal::FloatLiteral));
+    store.register_late_pass(|_| Box::new(ptr::Ptr));
+    store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
+    store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
+    store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
+    store.register_late_pass(|_| Box::new(misc::MiscLints));
+    store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
+    store.register_late_pass(|_| Box::new(mut_mut::MutMut));
+    store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
+    store.register_late_pass(|_| Box::new(len_zero::LenZero));
+    store.register_late_pass(|_| Box::new(attrs::Attributes));
+    store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
+    store.register_late_pass(|_| Box::new(unicode::Unicode));
+    store.register_late_pass(|_| Box::new(uninit_vec::UninitVec));
+    store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
+    store.register_late_pass(|_| Box::new(strings::StringAdd));
+    store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn));
+    store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub));
+    store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback));
+    store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
+    store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
     store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
 
     let msrv = read_msrv(conf, sess);
     let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
     let allow_expect_in_tests = conf.allow_expect_in_tests;
     let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
-    store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv)));
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv)));
+    store.register_late_pass(move |_| {
         Box::new(methods::Methods::new(
             avoid_breaking_exported_api,
             msrv,
@@ -603,74 +603,74 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             allow_unwrap_in_tests,
         ))
     });
-    store.register_late_pass(move || Box::new(matches::Matches::new(msrv)));
+    store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv)));
     store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv)));
-    store.register_late_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv)));
-    store.register_late_pass(move || Box::new(manual_strip::ManualStrip::new(msrv)));
+    store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv)));
+    store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv)));
     store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv)));
     store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv)));
-    store.register_late_pass(move || Box::new(checked_conversions::CheckedConversions::new(msrv)));
-    store.register_late_pass(move || Box::new(mem_replace::MemReplace::new(msrv)));
-    store.register_late_pass(move || Box::new(ranges::Ranges::new(msrv)));
-    store.register_late_pass(move || Box::new(from_over_into::FromOverInto::new(msrv)));
-    store.register_late_pass(move || Box::new(use_self::UseSelf::new(msrv)));
-    store.register_late_pass(move || Box::new(missing_const_for_fn::MissingConstForFn::new(msrv)));
-    store.register_late_pass(move || Box::new(needless_question_mark::NeedlessQuestionMark));
-    store.register_late_pass(move || Box::new(casts::Casts::new(msrv)));
+    store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv)));
+    store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv)));
+    store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv)));
+    store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv)));
+    store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv)));
+    store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv)));
+    store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark));
+    store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv)));
     store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv)));
-    store.register_late_pass(|| Box::new(size_of_in_element_count::SizeOfInElementCount));
-    store.register_late_pass(|| Box::new(same_name_method::SameNameMethod));
+    store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount));
+    store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod));
     let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(index_refutable_slice::IndexRefutableSlice::new(
             max_suggested_slice_pattern_length,
             msrv,
         ))
     });
-    store.register_late_pass(|| Box::new(shadow::Shadow::default()));
-    store.register_late_pass(|| Box::new(unit_types::UnitTypes));
-    store.register_late_pass(|| Box::new(loops::Loops));
-    store.register_late_pass(|| Box::new(main_recursion::MainRecursion::default()));
-    store.register_late_pass(|| Box::new(lifetimes::Lifetimes));
-    store.register_late_pass(|| Box::new(entry::HashMapPass));
-    store.register_late_pass(|| Box::new(minmax::MinMaxPass));
-    store.register_late_pass(|| Box::new(zero_div_zero::ZeroDiv));
-    store.register_late_pass(|| Box::new(mutex_atomic::Mutex));
-    store.register_late_pass(|| Box::new(needless_update::NeedlessUpdate));
-    store.register_late_pass(|| Box::new(needless_borrowed_ref::NeedlessBorrowedRef));
-    store.register_late_pass(|| Box::new(borrow_deref_ref::BorrowDerefRef));
-    store.register_late_pass(|| Box::new(no_effect::NoEffect));
-    store.register_late_pass(|| Box::new(temporary_assignment::TemporaryAssignment));
-    store.register_late_pass(move || Box::new(transmute::Transmute::new(msrv)));
+    store.register_late_pass(|_| Box::new(shadow::Shadow::default()));
+    store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
+    store.register_late_pass(|_| Box::new(loops::Loops));
+    store.register_late_pass(|_| Box::new(main_recursion::MainRecursion::default()));
+    store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
+    store.register_late_pass(|_| Box::new(entry::HashMapPass));
+    store.register_late_pass(|_| Box::new(minmax::MinMaxPass));
+    store.register_late_pass(|_| Box::new(zero_div_zero::ZeroDiv));
+    store.register_late_pass(|_| Box::new(mutex_atomic::Mutex));
+    store.register_late_pass(|_| Box::new(needless_update::NeedlessUpdate));
+    store.register_late_pass(|_| Box::new(needless_borrowed_ref::NeedlessBorrowedRef));
+    store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef));
+    store.register_late_pass(|_| Box::new(no_effect::NoEffect));
+    store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment));
+    store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv)));
     let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(cognitive_complexity::CognitiveComplexity::new(
             cognitive_complexity_threshold,
         ))
     });
     let too_large_for_stack = conf.too_large_for_stack;
-    store.register_late_pass(move || Box::new(escape::BoxedLocal { too_large_for_stack }));
-    store.register_late_pass(move || Box::new(vec::UselessVec { too_large_for_stack }));
-    store.register_late_pass(|| Box::new(panic_unimplemented::PanicUnimplemented));
-    store.register_late_pass(|| Box::new(strings::StringLitAsBytes));
-    store.register_late_pass(|| Box::new(derive::Derive));
-    store.register_late_pass(|| Box::new(derivable_impls::DerivableImpls));
-    store.register_late_pass(|| Box::new(drop_forget_ref::DropForgetRef));
-    store.register_late_pass(|| Box::new(empty_enum::EmptyEnum));
-    store.register_late_pass(|| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
-    store.register_late_pass(|| Box::new(regex::Regex));
-    store.register_late_pass(|| Box::new(copies::CopyAndPaste));
-    store.register_late_pass(|| Box::new(copy_iterator::CopyIterator));
-    store.register_late_pass(|| Box::new(format::UselessFormat));
-    store.register_late_pass(|| Box::new(swap::Swap));
-    store.register_late_pass(|| Box::new(overflow_check_conditional::OverflowCheckConditional));
-    store.register_late_pass(|| Box::new(new_without_default::NewWithoutDefault::default()));
+    store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack }));
+    store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack }));
+    store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
+    store.register_late_pass(|_| Box::new(strings::StringLitAsBytes));
+    store.register_late_pass(|_| Box::new(derive::Derive));
+    store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls));
+    store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
+    store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
+    store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
+    store.register_late_pass(|_| Box::new(regex::Regex));
+    store.register_late_pass(|_| Box::new(copies::CopyAndPaste));
+    store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));
+    store.register_late_pass(|_| Box::new(format::UselessFormat));
+    store.register_late_pass(|_| Box::new(swap::Swap));
+    store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional));
+    store.register_late_pass(|_| Box::new(new_without_default::NewWithoutDefault::default()));
     let disallowed_names = conf.disallowed_names.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_late_pass(move || Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone())));
+    store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone())));
     let too_many_arguments_threshold = conf.too_many_arguments_threshold;
     let too_many_lines_threshold = conf.too_many_lines_threshold;
     let large_error_threshold = conf.large_error_threshold;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(functions::Functions::new(
             too_many_arguments_threshold,
             too_many_lines_threshold,
@@ -678,73 +678,73 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_late_pass(move || Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
-    store.register_late_pass(|| Box::new(neg_multiply::NegMultiply));
-    store.register_late_pass(|| Box::new(mem_forget::MemForget));
-    store.register_late_pass(|| Box::new(let_if_seq::LetIfSeq));
-    store.register_late_pass(|| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
-    store.register_late_pass(|| Box::new(missing_doc::MissingDoc::new()));
-    store.register_late_pass(|| Box::new(missing_inline::MissingInline));
-    store.register_late_pass(move || Box::new(exhaustive_items::ExhaustiveItems));
-    store.register_late_pass(|| Box::new(match_result_ok::MatchResultOk));
-    store.register_late_pass(|| Box::new(partialeq_ne_impl::PartialEqNeImpl));
-    store.register_late_pass(|| Box::new(unused_io_amount::UnusedIoAmount));
+    store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
+    store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply));
+    store.register_late_pass(|_| Box::new(mem_forget::MemForget));
+    store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
+    store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
+    store.register_late_pass(|_| Box::new(missing_doc::MissingDoc::new()));
+    store.register_late_pass(|_| Box::new(missing_inline::MissingInline));
+    store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems));
+    store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk));
+    store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl));
+    store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount));
     let enum_variant_size_threshold = conf.enum_variant_size_threshold;
-    store.register_late_pass(move || Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)));
-    store.register_late_pass(|| Box::new(explicit_write::ExplicitWrite));
-    store.register_late_pass(|| Box::new(needless_pass_by_value::NeedlessPassByValue));
+    store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)));
+    store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite));
+    store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue));
     let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
         conf.trivial_copy_size_limit,
         conf.pass_by_value_size_limit,
         conf.avoid_breaking_exported_api,
         &sess.target,
     );
-    store.register_late_pass(move || Box::new(pass_by_ref_or_value));
-    store.register_late_pass(|| Box::new(ref_option_ref::RefOptionRef));
-    store.register_late_pass(|| Box::new(infinite_iter::InfiniteIter));
-    store.register_late_pass(|| Box::new(inline_fn_without_body::InlineFnWithoutBody));
-    store.register_late_pass(|| Box::new(useless_conversion::UselessConversion::default()));
-    store.register_late_pass(|| Box::new(implicit_hasher::ImplicitHasher));
-    store.register_late_pass(|| Box::new(fallible_impl_from::FallibleImplFrom));
-    store.register_late_pass(|| Box::new(question_mark::QuestionMark));
+    store.register_late_pass(move |_| Box::new(pass_by_ref_or_value));
+    store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef));
+    store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter));
+    store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody));
+    store.register_late_pass(|_| Box::new(useless_conversion::UselessConversion::default()));
+    store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher));
+    store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom));
+    store.register_late_pass(|_| Box::new(question_mark::QuestionMark));
     store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings));
-    store.register_late_pass(|| Box::new(suspicious_trait_impl::SuspiciousImpl));
-    store.register_late_pass(|| Box::new(map_unit_fn::MapUnit));
-    store.register_late_pass(|| Box::new(inherent_impl::MultipleInherentImpl));
-    store.register_late_pass(|| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
-    store.register_late_pass(|| Box::new(unwrap::Unwrap));
-    store.register_late_pass(|| Box::new(indexing_slicing::IndexingSlicing));
-    store.register_late_pass(|| Box::new(non_copy_const::NonCopyConst));
-    store.register_late_pass(|| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
-    store.register_late_pass(|| Box::new(redundant_clone::RedundantClone));
-    store.register_late_pass(|| Box::new(slow_vector_initialization::SlowVectorInit));
-    store.register_late_pass(move || Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api)));
-    store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants));
-    store.register_late_pass(|| Box::new(assertions_on_result_states::AssertionsOnResultStates));
-    store.register_late_pass(|| Box::new(inherent_to_string::InherentToString));
+    store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl));
+    store.register_late_pass(|_| Box::new(map_unit_fn::MapUnit));
+    store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl));
+    store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
+    store.register_late_pass(|_| Box::new(unwrap::Unwrap));
+    store.register_late_pass(|_| Box::new(indexing_slicing::IndexingSlicing));
+    store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst));
+    store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
+    store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
+    store.register_late_pass(|_| Box::new(slow_vector_initialization::SlowVectorInit));
+    store.register_late_pass(move |_| Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api)));
+    store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants));
+    store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates));
+    store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString));
     let max_trait_bounds = conf.max_trait_bounds;
-    store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
-    store.register_late_pass(|| Box::new(comparison_chain::ComparisonChain));
-    store.register_late_pass(|| Box::new(mut_key::MutableKeyType));
+    store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
+    store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
+    store.register_late_pass(|_| Box::new(mut_key::MutableKeyType));
     store.register_early_pass(|| Box::new(reference::DerefAddrOf));
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
-    store.register_late_pass(|| Box::new(format_impl::FormatImpl::new()));
+    store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new()));
     store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
     store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
     store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
     store.register_early_pass(|| Box::new(formatting::Formatting));
     store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints));
     store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall));
-    store.register_late_pass(|| Box::new(redundant_closure_call::RedundantClosureCall));
+    store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
-    store.register_late_pass(|| Box::new(returns::Return));
+    store.register_late_pass(|_| Box::new(returns::Return));
     store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
     store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements));
     store.register_early_pass(|| Box::new(precedence::Precedence));
-    store.register_late_pass(|| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
+    store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
     store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue));
     store.register_early_pass(|| Box::new(redundant_else::RedundantElse));
-    store.register_late_pass(|| Box::new(create_dir::CreateDir));
+    store.register_late_pass(|_| Box::new(create_dir::CreateDir));
     store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType));
     let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
     store.register_early_pass(move || {
@@ -759,7 +759,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     let enum_variant_name_threshold = conf.enum_variant_name_threshold;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(enum_variants::EnumVariantNames::new(
             enum_variant_name_threshold,
             avoid_breaking_exported_api,
@@ -767,23 +767,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
     let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(upper_case_acronyms::UpperCaseAcronyms::new(
             avoid_breaking_exported_api,
             upper_case_acronyms_aggressive,
         ))
     });
-    store.register_late_pass(|| Box::new(default::Default::default()));
-    store.register_late_pass(move || Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api)));
-    store.register_late_pass(|| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
-    store.register_late_pass(|| Box::new(exit::Exit));
-    store.register_late_pass(|| Box::new(to_digit_is_some::ToDigitIsSome));
+    store.register_late_pass(|_| Box::new(default::Default::default()));
+    store.register_late_pass(move |_| Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api)));
+    store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
+    store.register_late_pass(|_| Box::new(exit::Exit));
+    store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome));
     let array_size_threshold = conf.array_size_threshold;
-    store.register_late_pass(move || Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
-    store.register_late_pass(move || Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
-    store.register_late_pass(|| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
+    store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
+    store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
+    store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
     store.register_early_pass(|| Box::new(as_conversions::AsConversions));
-    store.register_late_pass(|| Box::new(let_underscore::LetUnderscore));
+    store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
     store.register_early_pass(|| Box::new(single_component_path_imports::SingleComponentPathImports));
     let max_fn_params_bools = conf.max_fn_params_bools;
     let max_struct_bools = conf.max_struct_bools;
@@ -795,17 +795,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
     let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
-    store.register_late_pass(move || Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)));
-    store.register_late_pass(|| Box::new(redundant_pub_crate::RedundantPubCrate::default()));
-    store.register_late_pass(|| Box::new(unnamed_address::UnnamedAddress));
-    store.register_late_pass(move || Box::new(dereference::Dereferencing::new(msrv)));
-    store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse));
-    store.register_late_pass(|| Box::new(future_not_send::FutureNotSend));
-    store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex));
-    store.register_late_pass(|| Box::new(if_not_else::IfNotElse));
-    store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality));
-    store.register_late_pass(|| Box::new(manual_async_fn::ManualAsyncFn));
-    store.register_late_pass(|| Box::new(panic_in_result_fn::PanicInResultFn));
+    store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)));
+    store.register_late_pass(|_| Box::new(redundant_pub_crate::RedundantPubCrate::default()));
+    store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
+    store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv)));
+    store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
+    store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
+    store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex));
+    store.register_late_pass(|_| Box::new(if_not_else::IfNotElse));
+    store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality));
+    store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn));
+    store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn));
     let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
     store.register_early_pass(move || {
         Box::new(non_expressive_names::NonExpressiveNames {
@@ -814,92 +814,92 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::<FxHashSet<_>>();
     store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(&macro_matcher)));
-    store.register_late_pass(|| Box::new(macro_use::MacroUseImports::default()));
-    store.register_late_pass(|| Box::new(pattern_type_mismatch::PatternTypeMismatch));
-    store.register_late_pass(|| Box::new(unwrap_in_result::UnwrapInResult));
-    store.register_late_pass(|| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned));
-    store.register_late_pass(|| Box::new(async_yields_async::AsyncYieldsAsync));
+    store.register_late_pass(|_| Box::new(macro_use::MacroUseImports::default()));
+    store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch));
+    store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult));
+    store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned));
+    store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync));
     let disallowed_methods = conf.disallowed_methods.clone();
-    store.register_late_pass(move || Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
+    store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
-    store.register_late_pass(|| Box::new(empty_drop::EmptyDrop));
-    store.register_late_pass(|| Box::new(strings::StrToString));
-    store.register_late_pass(|| Box::new(strings::StringToString));
-    store.register_late_pass(|| Box::new(zero_sized_map_values::ZeroSizedMapValues));
-    store.register_late_pass(|| Box::new(vec_init_then_push::VecInitThenPush::default()));
-    store.register_late_pass(|| Box::new(redundant_slicing::RedundantSlicing));
-    store.register_late_pass(|| Box::new(from_str_radix_10::FromStrRadix10));
-    store.register_late_pass(move || Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv)));
-    store.register_late_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison));
+    store.register_late_pass(|_| Box::new(empty_drop::EmptyDrop));
+    store.register_late_pass(|_| Box::new(strings::StrToString));
+    store.register_late_pass(|_| Box::new(strings::StringToString));
+    store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues));
+    store.register_late_pass(|_| Box::new(vec_init_then_push::VecInitThenPush::default()));
+    store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing));
+    store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10));
+    store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv)));
+    store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison));
     store.register_early_pass(move || Box::new(module_style::ModStyle));
-    store.register_late_pass(|| Box::new(unused_async::UnusedAsync));
+    store.register_late_pass(|_| Box::new(unused_async::UnusedAsync));
     let disallowed_types = conf.disallowed_types.clone();
-    store.register_late_pass(move || Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone())));
+    store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone())));
     let import_renames = conf.enforced_import_renames.clone();
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(missing_enforced_import_rename::ImportRename::new(
             import_renames.clone(),
         ))
     });
     let scripts = conf.allowed_scripts.clone();
     store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts)));
-    store.register_late_pass(|| Box::new(strlen_on_c_strings::StrlenOnCStrings));
-    store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors));
-    store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
-    store.register_late_pass(move || Box::new(manual_assert::ManualAssert));
+    store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings));
+    store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors));
+    store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator));
+    store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert));
     let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(
             enable_raw_pointer_heuristic_for_send,
         ))
     });
-    store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
-    store.register_late_pass(move || Box::new(format_args::FormatArgs));
-    store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray));
+    store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
+    store.register_late_pass(move |_| Box::new(format_args::FormatArgs));
+    store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
     store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
-    store.register_late_pass(|| Box::new(needless_late_init::NeedlessLateInit));
-    store.register_late_pass(|| Box::new(return_self_not_must_use::ReturnSelfNotMustUse));
-    store.register_late_pass(|| Box::new(init_numbered_fields::NumberedFields));
+    store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit));
+    store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse));
+    store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields));
     store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
-    store.register_late_pass(move || Box::new(manual_bits::ManualBits::new(msrv)));
-    store.register_late_pass(|| Box::new(default_union_representation::DefaultUnionRepresentation));
+    store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv)));
+    store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
     store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes));
-    store.register_late_pass(|| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default()));
+    store.register_late_pass(|_| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default()));
     let allow_dbg_in_tests = conf.allow_dbg_in_tests;
-    store.register_late_pass(move || Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
+    store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
     let cargo_ignore_publish = conf.cargo_ignore_publish;
-    store.register_late_pass(move || {
+    store.register_late_pass(move |_| {
         Box::new(cargo::Cargo {
             ignore_publish: cargo_ignore_publish,
         })
     });
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
     store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
-    store.register_late_pass(|| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
+    store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
     store.register_early_pass(|| Box::new(pub_use::PubUse));
-    store.register_late_pass(|| Box::new(format_push_string::FormatPushString));
+    store.register_late_pass(|_| Box::new(format_push_string::FormatPushString));
     let max_include_file_size = conf.max_include_file_size;
-    store.register_late_pass(move || Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size)));
-    store.register_late_pass(|| Box::new(strings::TrimSplitWhitespace));
-    store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
+    store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size)));
+    store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace));
+    store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
     store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
     store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
     store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
-    store.register_late_pass(|| Box::new(swap_ptr_to_ref::SwapPtrToRef));
-    store.register_late_pass(|| Box::new(mismatching_type_param_order::TypeParamMismatch));
-    store.register_late_pass(|| Box::new(read_zero_byte_vec::ReadZeroByteVec));
-    store.register_late_pass(|| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
-    store.register_late_pass(move || Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv)));
-    store.register_late_pass(move || Box::new(manual_retain::ManualRetain::new(msrv)));
+    store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
+    store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
+    store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
+    store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
+    store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv)));
+    store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv)));
     let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
-    store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
-    store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
-    store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports::default()));
-    store.register_late_pass(|| Box::new(manual_instant_elapsed::ManualInstantElapsed));
-    store.register_late_pass(|| Box::new(partialeq_to_none::PartialeqToNone));
-    store.register_late_pass(|| Box::new(manual_string_new::ManualStringNew));
-    store.register_late_pass(|| Box::new(unused_peekable::UnusedPeekable));
+    store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
+    store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
+    store.register_late_pass(|_| Box::new(std_instead_of_core::StdReexports::default()));
+    store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed));
+    store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
+    store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
+    store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
     store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
index 573a7c016b8e8c8c6d708fccb3ccd42c0f6f2792..5995675bd969c7ca3e3c98d1bdedfedab8e22bdc 100644 (file)
@@ -441,7 +441,7 @@ fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>, tbm: Tra
 
     fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
         match ty.kind {
-            TyKind::OpaqueDef(item, bounds) => {
+            TyKind::OpaqueDef(item, bounds, _) => {
                 let map = self.cx.tcx.hir();
                 let item = map.item(item);
                 let len = self.lts.len();
index 2502c8f880ddce76aa1045cfcdc815aaa315209d..754b0e78a148cc989f46f7c7534d4962da0e464d 100644 (file)
@@ -103,7 +103,7 @@ fn future_trait_ref<'tcx>(
     ty: &'tcx Ty<'tcx>,
 ) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
     if_chain! {
-        if let TyKind::OpaqueDef(item_id, bounds) = ty.kind;
+        if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind;
         let item = cx.tcx.hir().item(item_id);
         if let ItemKind::OpaqueTy(opaque) = &item.kind;
         if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
index e32ef9933afe5c2b16a062fd81aed35b3439b340..93874b103b461d92bb06f73842e441b5e26d41b3 100644 (file)
@@ -248,7 +248,7 @@ fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) ->
                 } else {
                     (None, adt.non_enum_variant())
                 };
-                let (front, back) = match wild_idx {
+                let (front, back) = match wild_idx.as_opt_usize() {
                     Some(i) => pats.split_at(i),
                     None => (pats, [].as_slice()),
                 };
@@ -268,7 +268,7 @@ fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) ->
                     ty::Tuple(subs) => subs.len(),
                     _ => return Self::Wild,
                 };
-                let (front, back) = match wild_idx {
+                let (front, back) = match wild_idx.as_opt_usize() {
                     Some(i) => pats.split_at(i),
                     None => (pats, [].as_slice()),
                 };
index 95478af45b4bf3fa687149fa8f76d5e5587306b4..1bf1c4d1078952cab5deb3f2c756cfb78d1842b4 100644 (file)
@@ -200,6 +200,8 @@ fn form_exhaustive_matches<'a>(cx: &LateContext<'a>, ty: Ty<'a>, left: &Pat<'_>,
             // We don't actually know the position and the presence of the `..` (dotdot) operator
             // in the arms, so we need to evaluate the correct offsets here in order to iterate in
             // both arms at the same time.
+            let left_pos = left_pos.as_opt_usize();
+            let right_pos = right_pos.as_opt_usize();
             let len = max(
                 left_in.len() + {
                     if left_pos.is_some() { 1 } else { 0 }
index f4f1fd336df7cc81c4a60786da7e95ccb5ed85bb..569870ab2b7f41ae3d4b4b2fd53083ba3b71d9ed 100644 (file)
@@ -122,7 +122,8 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
     if_chain! {
         if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
         if !is_else_clause(cx.tcx, expr);
-        if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind;
+        if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind;
+        if ddpos.as_opt_usize().is_none();
         if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
         let caller_ty = cx.typeck_results().expr_ty(let_expr);
         let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
index 35824b03170afb87e139373715ad3b1caca492e5..ce9ebad8c89a85e98687ef486fc410dca262993f 100644 (file)
@@ -19,10 +19,12 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
         && cx.typeck_results().pat_ty(local.pat).is_unit()
     {
         if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
-            || matches!(local.pat.kind, PatKind::Tuple([], None)))
+            || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
             && expr_needs_inferred_result(cx, init)
         {
-            if !matches!(local.pat.kind, PatKind::Wild | PatKind::Tuple([], None)) {
+            if !matches!(local.pat.kind, PatKind::Wild)
+               && !matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none())
+            {
                 span_lint_and_then(
                     cx,
                     LET_UNIT_VALUE,
index 57448f716d4941e023d2a7112c7e6f919ebcac34..f45cec9f0b430a0f7be230ddadb22aabcc8642e9 100644 (file)
@@ -929,7 +929,7 @@ pub fn hash_guard(&mut self, g: &Guard<'_>) {
         }
     }
 
-    pub fn hash_lifetime(&mut self, lifetime: Lifetime) {
+    pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
         std::mem::discriminant(&lifetime.name).hash(&mut self.s);
         if let LifetimeName::Param(param_id, ref name) = lifetime.name {
             std::mem::discriminant(name).hash(&mut self.s);
@@ -987,8 +987,9 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
                 }
             },
             TyKind::Path(ref qpath) => self.hash_qpath(qpath),
-            TyKind::OpaqueDef(_, arg_list) => {
+            TyKind::OpaqueDef(_, arg_list, in_trait) => {
                 self.hash_generic_args(arg_list);
+                in_trait.hash(&mut self.s);
             },
             TyKind::TraitObject(_, lifetime, _) => {
                 self.hash_lifetime(*lifetime);
index b27439cbec278bec5bafb3fd46e47b7d0deb0422..3cf043f22df5dc60e92265bb06133cc341a3b9d9 100644 (file)
@@ -1552,7 +1552,8 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It
 pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
         if_chain! {
-            if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind;
+            if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
+            if ddpos.as_opt_usize().is_none();
             if is_lang_ctor(cx, path, ResultOk);
             if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
             if path_to_local_id(arm.body, hir_id);