]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #90701 - michaelwoerister:more-artifact-sizes, r=davidtwco
authorMatthias Krüger <matthias.krueger@famsik.de>
Tue, 9 Nov 2021 18:00:45 +0000 (19:00 +0100)
committerGitHub <noreply@github.com>
Tue, 9 Nov 2021 18:00:45 +0000 (19:00 +0100)
Record more artifact sizes during self-profiling.

This PR adds artifact size recording for

- "linked artifacts" (executables, RLIBs, dylibs, static libs)
- object files
- dwo files
- assembly files
- crate metadata
- LLVM bitcode files
- LLVM IR files
- codegen unit size estimates

Currently the identifiers emitted for these are hard-coded as string literals. Is it worth adding constants to https://github.com/rust-lang/measureme/blob/master/measureme/src/rustc.rs instead? We don't do that for query names and the like -- but artifact kinds might be more stable than query names.

192 files changed:
Cargo.lock
compiler/rustc_ast/src/util/comments.rs
compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/nll.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_borrowck/src/universal_regions.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_ssa/src/back/write.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_infer/src/infer/canonical/query_response.rs
compiler/rustc_infer/src/infer/outlives/env.rs
compiler/rustc_infer/src/traits/engine.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/mir/pretty.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
compiler/rustc_trait_selection/src/traits/codegen.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
compiler/rustc_trait_selection/src/traits/specialize/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_traits/src/implied_outlives_bounds.rs
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/closure.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/dropck.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.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/check/regionck.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/coherence/builtin.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/hir_wf_check.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/outlives_bounds.rs
library/alloc/src/rc.rs
library/backtrace
library/core/src/cell.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/bootstrap/util.rs
src/doc/unstable-book/src/language-features/type-changing-struct-update.md [new file with mode: 0644]
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/formats/item_type.rs
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/test/pretty/dollar-crate.pp
src/test/pretty/issue-4264.pp
src/test/rustdoc/include_str_cut.rs [new file with mode: 0644]
src/test/rustdoc/short-line.md [new file with mode: 0644]
src/test/ui-fulldeps/lint-tool-test.rs
src/test/ui-fulldeps/lint-tool-test.stderr
src/test/ui/attributes/key-value-expansion.stderr
src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
src/test/ui/const-generics/impl-trait-with-const-arguments.stderr
src/test/ui/deprecation/deprecation-lint.rs
src/test/ui/deprecation/deprecation-lint.stderr
src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs [deleted file]
src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr [deleted file]
src/test/ui/generic-associated-types/issue-88595.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-88595.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-90014.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-90014.stderr [new file with mode: 0644]
src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr
src/test/ui/impl-trait/issues/universal-issue-48703.stderr
src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
src/test/ui/impl-trait/where-allowed.rs
src/test/ui/impl-trait/where-allowed.stderr
src/test/ui/inline-const/const-expr-inference.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime-err.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime-err.stderr [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-inference.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-lifetime-err.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-lifetime.rs [new file with mode: 0644]
src/test/ui/intrinsics/intrinsic-alignment.rs
src/test/ui/issues/issue-7246.rs
src/test/ui/issues/issue-7246.stderr
src/test/ui/lint/crate_level_only_lint.rs
src/test/ui/lint/crate_level_only_lint.stderr
src/test/ui/lint/forbid-group-group-2.rs
src/test/ui/lint/forbid-group-group-2.stderr
src/test/ui/lint/lint-forbid-internal-unsafe.rs
src/test/ui/lint/lint-forbid-internal-unsafe.stderr
src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs
src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr
src/test/ui/reachable/expr_cast.rs
src/test/ui/reachable/expr_cast.stderr
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
src/test/ui/statics/uninhabited-static.rs
src/test/ui/statics/uninhabited-static.stderr
src/test/ui/structs-enums/rec-align-u64.rs
src/test/ui/synthetic-param.stderr
src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs
src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
src/test/ui/use/use-nested-groups-unused-imports.rs
src/test/ui/use/use-nested-groups-unused-imports.stderr
src/test/ui/x86stdcall.rs
src/tools/cargo
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/matches.rs
src/tools/clippy/clippy_utils/src/higher.rs
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
src/tools/clippy/tests/ui/deref_addrof.fixed
src/tools/clippy/tests/ui/deref_addrof.rs
src/tools/clippy/tests/ui/double_neg.rs
src/tools/clippy/tests/ui/double_neg.stderr
src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
src/tools/clippy/tests/ui/formatting.rs
src/tools/clippy/tests/ui/formatting.stderr
src/tools/clippy/tests/ui/literals.rs
src/tools/clippy/tests/ui/many_single_char_names.rs
src/tools/clippy/tests/ui/many_single_char_names.stderr
src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr
src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr
src/tools/clippy/tests/ui/needless_continue.rs
src/tools/clippy/tests/ui/needless_continue.stderr
src/tools/clippy/tests/ui/non_expressive_names.rs
src/tools/clippy/tests/ui/non_expressive_names.stderr
src/tools/clippy/tests/ui/redundant_closure_call_early.rs
src/tools/clippy/tests/ui/redundant_else.rs
src/tools/clippy/tests/ui/similar_names.rs
src/tools/clippy/tests/ui/similar_names.stderr
src/tools/clippy/tests/ui/suspicious_else_formatting.rs
src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
src/tools/rust-analyzer
src/tools/rustdoc-js/tester.js

index 6f95dae42a4ab1a9edd126739aacfde5914fdcb8..7cd07e3847282b9d9405a5244414c2f49283adc8 100644 (file)
@@ -888,9 +888,9 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9"
+checksum = "877cc2f9b8367e32b6dabb9d581557e651cb3aa693a37f8679091bbf42687d5d"
 dependencies = [
  "curl-sys",
  "libc",
@@ -903,9 +903,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.49+curl-7.79.1"
+version = "0.4.50+curl-7.79.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0f44960aea24a786a46907b8824ebc0e66ca06bf4e4978408c7499620343483"
+checksum = "4856b76919dd599f31236bb18db5f5bd36e2ce131e64f857ca5c259665b76171"
 dependencies = [
  "cc",
  "libc",
index 542a330a031414f469f52a256793b93c311f1fc7..c40aec4b671dd4ec0db312e12249802a822f0038 100644 (file)
@@ -38,7 +38,7 @@ fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
             i += 1;
         }
         // like the first, a last line of all stars should be omitted
-        if j > i && lines[j - 1].chars().skip(1).all(|c| c == '*') {
+        if j > i && !lines[j - 1].is_empty() && lines[j - 1].chars().all(|c| c == '*') {
             j -= 1;
         }
 
index 15309ccd8df278ef157210533c15436bd75780ad..1bc9f8cf3ccc8660d83d41b83cfdee1ec85e4e04 100644 (file)
@@ -339,7 +339,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
     // We generally shouldn't have errors here because the query was
     // already run, but there's no point using `delay_span_bug`
     // when we're going to emit an error here anyway.
-    let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);
+    let _errors = fulfill_cx.select_all_or_error(infcx);
 
     let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
         debug!("{:#?}", region_constraints);
index 439c728798d3a42b1b8c1717fd61a4a873103820..46a3c0fa1015248cfcc806148757693432b26c00 100644 (file)
@@ -408,7 +408,7 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                     let param = generics.type_param(&param_ty, tcx);
                     if let Some(generics) = tcx
                         .hir()
-                        .get_generics(tcx.closure_base_def_id(self.mir_def_id().to_def_id()))
+                        .get_generics(tcx.typeck_root_def_id(self.mir_def_id().to_def_id()))
                     {
                         suggest_constraining_type_param(
                             tcx,
index e5924f9d08478ff484bcf5feef030bb7a48419cc..6ffab16577908fcbc747a0a4ff2d5b72620628fb 100644 (file)
@@ -376,7 +376,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
     errors_buffer: &mut Vec<Diagnostic>,
 ) {
     let tcx = infcx.tcx;
-    let base_def_id = tcx.closure_base_def_id(body.source.def_id());
+    let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
     if !tcx.has_attr(base_def_id, sym::rustc_regions) {
         return;
     }
index f4a5da1fe36fa8d0f6d2c9465c9f56f65f6b5784..b39a28f79aaddc3f2eda6882bf5bd7b934fb2f9b 100644 (file)
@@ -569,7 +569,7 @@ pub(super) fn solve(
         // to store those. Otherwise, we'll pass in `None` to the
         // functions below, which will trigger them to report errors
         // eagerly.
-        let mut outlives_requirements = infcx.tcx.is_closure(mir_def_id).then(Vec::new);
+        let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
 
         self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer);
 
@@ -2229,7 +2229,7 @@ fn apply_requirements(
             tcx,
             closure_substs,
             self.num_external_vids,
-            tcx.closure_base_def_id(closure_def_id),
+            tcx.typeck_root_def_id(closure_def_id),
         );
         debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
 
index 06e34bdce3f8678284b5c5abf55706eef0737ea7..ddd077c22faf86662dfb93c482f2374dc249cd07 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
@@ -1343,13 +1344,9 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                 // though.
                 let category = match place.as_local() {
                     Some(RETURN_PLACE) => {
-                        if let BorrowCheckContext {
-                            universal_regions:
-                                UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. },
-                            ..
-                        } = self.borrowck_context
-                        {
-                            if tcx.is_static(*def_id) {
+                        let defining_ty = &self.borrowck_context.universal_regions.defining_ty;
+                        if defining_ty.is_const() {
+                            if tcx.is_static(defining_ty.def_id()) {
                                 ConstraintCategory::UseAsStatic
                             } else {
                                 ConstraintCategory::UseAsConst
@@ -1527,6 +1524,8 @@ fn check_terminator(
                 }
             }
             TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+                self.check_operand(discr, term_location);
+
                 let discr_ty = discr.ty(body, tcx);
                 if let Err(terr) = self.sub_types(
                     discr_ty,
@@ -1549,6 +1548,11 @@ fn check_terminator(
                 // FIXME: check the values
             }
             TerminatorKind::Call { ref func, ref args, ref destination, from_hir_call, .. } => {
+                self.check_operand(func, term_location);
+                for arg in args {
+                    self.check_operand(arg, term_location);
+                }
+
                 let func_ty = func.ty(body, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.kind() {
@@ -1593,6 +1597,8 @@ fn check_terminator(
                 self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
             }
             TerminatorKind::Assert { ref cond, ref msg, .. } => {
+                self.check_operand(cond, term_location);
+
                 let cond_ty = cond.ty(body, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
@@ -1608,6 +1614,8 @@ fn check_terminator(
                 }
             }
             TerminatorKind::Yield { ref value, .. } => {
+                self.check_operand(value, term_location);
+
                 let value_ty = value.ty(body, tcx);
                 match body.yield_ty() {
                     None => span_mirbug!(self, term, "yield in non-generator"),
@@ -1650,7 +1658,12 @@ fn check_call_dest(
                     Some(RETURN_PLACE) => {
                         if let BorrowCheckContext {
                             universal_regions:
-                                UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. },
+                                UniversalRegions {
+                                    defining_ty:
+                                        DefiningTy::Const(def_id, _)
+                                        | DefiningTy::InlineConst(def_id, _),
+                                    ..
+                                },
                             ..
                         } = self.borrowck_context
                         {
@@ -1931,15 +1944,51 @@ fn aggregate_field_ty(
         }
     }
 
+    fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.literal {
+                ConstantKind::Ty(ct) => match ct.val {
+                    ty::ConstKind::Unevaluated(uv) => Some(uv),
+                    _ => None,
+                },
+                _ => None,
+            };
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let tcx = self.tcx();
+                    let def_id = uv.def.def_id_for_type_of();
+                    if tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let predicates = self.prove_closure_bounds(
+                            tcx,
+                            def_id.expect_local(),
+                            uv.substs(tcx),
+                            location,
+                        );
+                        self.normalize_and_prove_instantiated_predicates(
+                            def_id,
+                            predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
         let tcx = self.tcx();
 
         match rvalue {
             Rvalue::Aggregate(ak, ops) => {
+                for op in ops {
+                    self.check_operand(op, location);
+                }
                 self.check_aggregate_rvalue(&body, rvalue, ak, ops, location)
             }
 
             Rvalue::Repeat(operand, len) => {
+                self.check_operand(operand, location);
+
                 // If the length cannot be evaluated we must assume that the length can be larger
                 // than 1.
                 // If the length is larger than 1, the repeat expression will need to copy the
@@ -1990,7 +2039,22 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
-            Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => {
+            Rvalue::NullaryOp(_, ty) => {
+                let trait_ref = ty::TraitRef {
+                    def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
+                    substs: tcx.mk_substs_trait(ty, &[]),
+                };
+
+                self.prove_trait_ref(
+                    trait_ref,
+                    location.to_locations(),
+                    ConstraintCategory::SizedBound,
+                );
+            }
+
+            Rvalue::ShallowInitBox(operand, ty) => {
+                self.check_operand(operand, location);
+
                 let trait_ref = ty::TraitRef {
                     def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                     substs: tcx.mk_substs_trait(ty, &[]),
@@ -2004,6 +2068,8 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
             }
 
             Rvalue::Cast(cast_kind, op, ty) => {
+                self.check_operand(op, location);
+
                 match cast_kind {
                     CastKind::Pointer(PointerCast::ReifyFnPointer) => {
                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
@@ -2250,6 +2316,9 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
                 box (left, right),
             ) => {
+                self.check_operand(left, location);
+                self.check_operand(right, location);
+
                 let ty_left = left.ty(body, tcx);
                 match ty_left.kind() {
                     // Types with regions are comparable if they have a common super-type.
@@ -2300,13 +2369,19 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
+            Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
+                self.check_operand(operand, location);
+            }
+
+            Rvalue::BinaryOp(_, box (left, right))
+            | Rvalue::CheckedBinaryOp(_, box (left, right)) => {
+                self.check_operand(left, location);
+                self.check_operand(right, location);
+            }
+
             Rvalue::AddressOf(..)
             | Rvalue::ThreadLocalRef(..)
-            | Rvalue::Use(..)
             | Rvalue::Len(..)
-            | Rvalue::BinaryOp(..)
-            | Rvalue::CheckedBinaryOp(..)
-            | Rvalue::UnaryOp(..)
             | Rvalue::Discriminant(..) => {}
         }
     }
index 147e2aead648db509356fe9e77b8cd02f6f72c12..b986df403f9f3f2c97789bad02c2b9720708bd71 100644 (file)
@@ -23,7 +23,7 @@
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
 use std::iter;
 
 use crate::nll::ToRegionVid;
@@ -108,6 +108,10 @@ pub enum DefiningTy<'tcx> {
     /// is that it has no inputs and a single return value, which is
     /// the value of the constant.
     Const(DefId, SubstsRef<'tcx>),
+
+    /// The MIR represents an inline const. The signature has no inputs and a
+    /// single return value found via `InlineConstSubsts::ty`.
+    InlineConst(DefId, SubstsRef<'tcx>),
 }
 
 impl<'tcx> DefiningTy<'tcx> {
@@ -121,7 +125,7 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
             DefiningTy::Generator(_, substs, _) => {
                 Either::Right(Either::Left(substs.as_generator().upvar_tys()))
             }
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) => {
+            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
                 Either::Right(Either::Right(iter::empty()))
             }
         }
@@ -133,7 +137,7 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
     pub fn implicit_inputs(self) -> usize {
         match self {
             DefiningTy::Closure(..) | DefiningTy::Generator(..) => 1,
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) => 0,
+            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
         }
     }
 
@@ -142,7 +146,7 @@ pub fn is_fn_def(&self) -> bool {
     }
 
     pub fn is_const(&self) -> bool {
-        matches!(*self, DefiningTy::Const(..))
+        matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..))
     }
 
     pub fn def_id(&self) -> DefId {
@@ -150,7 +154,8 @@ pub fn def_id(&self) -> DefId {
             DefiningTy::Closure(def_id, ..)
             | DefiningTy::Generator(def_id, ..)
             | DefiningTy::FnDef(def_id, ..)
-            | DefiningTy::Const(def_id, ..) => def_id,
+            | DefiningTy::Const(def_id, ..)
+            | DefiningTy::InlineConst(def_id, ..) => def_id,
         }
     }
 }
@@ -242,7 +247,7 @@ pub fn closure_mapping(
         tcx: TyCtxt<'tcx>,
         closure_substs: SubstsRef<'tcx>,
         expected_num_vars: usize,
-        closure_base_def_id: DefId,
+        typeck_root_def_id: DefId,
     ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
         let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
         region_mapping.push(tcx.lifetimes.re_static);
@@ -250,7 +255,7 @@ pub fn closure_mapping(
             region_mapping.push(fr);
         });
 
-        for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+        for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
             region_mapping.push(r);
         });
 
@@ -344,8 +349,8 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                 // tests, and the resulting print-outs include def-ids
                 // and other things that are not stable across tests!
                 // So we just include the region-vid. Annoying.
-                let closure_base_def_id = tcx.closure_base_def_id(def_id);
-                for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+                for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
                     err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
                 });
             }
@@ -359,8 +364,8 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                 // FIXME: As above, we'd like to print out the region
                 // `r` but doing so is not stable across architectures
                 // and so forth.
-                let closure_base_def_id = tcx.closure_base_def_id(def_id);
-                for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+                for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
                     err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
                 });
             }
@@ -376,6 +381,12 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                     tcx.def_path_str_with_substs(def_id, substs),
                 ));
             }
+            DefiningTy::InlineConst(def_id, substs) => {
+                err.note(&format!(
+                    "defining inline constant type: {}",
+                    tcx.def_path_str_with_substs(def_id, substs),
+                ));
+            }
         }
     }
 }
@@ -411,7 +422,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         let mut indices = self.compute_indices(fr_static, defining_ty);
         debug!("build: indices={:?}", indices);
 
-        let closure_base_def_id = self.infcx.tcx.closure_base_def_id(self.mir_def.did.to_def_id());
+        let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
         // If this is a closure or generator, then the late-bound regions from the enclosing
         // function are actually external regions to us. For example, here, 'a is not local
@@ -419,7 +430,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         // fn foo<'a>() {
         //     let c = || { let x: &'a u32 = ...; }
         // }
-        if self.mir_def.did.to_def_id() != closure_base_def_id {
+        if self.mir_def.did.to_def_id() != typeck_root_def_id {
             self.infcx
                 .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices)
         }
@@ -437,7 +448,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         );
         // Converse of above, if this is a function then the late-bound regions declared on its
         // signature are local to the fn.
-        if self.mir_def.did.to_def_id() == closure_base_def_id {
+        if self.mir_def.did.to_def_id() == typeck_root_def_id {
             self.infcx
                 .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
         }
@@ -502,12 +513,12 @@ fn build(self) -> UniversalRegions<'tcx> {
     /// see `DefiningTy` for details.
     fn defining_ty(&self) -> DefiningTy<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
         match tcx.hir().body_owner_kind(self.mir_hir_id) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
-                let defining_ty = if self.mir_def.did.to_def_id() == closure_base_def_id {
-                    tcx.type_of(closure_base_def_id)
+                let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
+                    tcx.type_of(typeck_root_def_id)
                 } else {
                     let tables = tcx.typeck(self.mir_def.did);
                     tables.node_type(self.mir_hir_id)
@@ -534,11 +545,21 @@ fn defining_ty(&self) -> DefiningTy<'tcx> {
             }
 
             BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
-                assert_eq!(self.mir_def.did.to_def_id(), closure_base_def_id);
-                let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
-                let substs =
-                    self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
-                DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+                let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
+                if self.mir_def.did.to_def_id() == typeck_root_def_id {
+                    let substs =
+                        self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
+                    DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+                } else {
+                    let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
+                    let substs = InlineConstSubsts::new(
+                        tcx,
+                        InlineConstSubstsParts { parent_substs: identity_substs, ty },
+                    )
+                    .substs;
+                    let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
+                    DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs)
+                }
             }
         }
     }
@@ -553,17 +574,19 @@ fn compute_indices(
         defining_ty: DefiningTy<'tcx>,
     ) -> UniversalRegionIndices<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
-        let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
+        let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, ref substs) | DefiningTy::Generator(_, ref substs, _) => {
+            DefiningTy::Closure(_, ref substs)
+            | DefiningTy::Generator(_, ref substs, _)
+            | DefiningTy::InlineConst(_, ref substs) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureSubsts are
-                // inherited from the `closure_base_def_id`.
+                // inherited from the `typeck_root_def_id`.
                 // Therefore, when we zip together (below) with
                 // `identity_substs`, we will get only those regions
                 // that correspond to early-bound regions declared on
-                // the `closure_base_def_id`.
+                // the `typeck_root_def_id`.
                 assert!(substs.len() >= identity_substs.len());
                 assert_eq!(substs.regions().count(), identity_substs.regions().count());
                 substs
@@ -648,6 +671,12 @@ fn compute_inputs_and_output(
                 let ty = indices.fold_to_region_vids(tcx, ty);
                 ty::Binder::dummy(tcx.intern_type_list(&[ty]))
             }
+
+            DefiningTy::InlineConst(def_id, substs) => {
+                assert_eq!(self.mir_def.did.to_def_id(), def_id);
+                let ty = substs.as_inline_const().ty();
+                ty::Binder::dummy(tcx.intern_type_list(&[ty]))
+            }
         }
     }
 }
@@ -736,8 +765,8 @@ fn replace_late_bound_regions_with_nll_infer_vars(
         indices: &mut UniversalRegionIndices<'tcx>,
     ) {
         debug!("replace_late_bound_regions_with_nll_infer_vars(mir_def_id={:?})", mir_def_id);
-        let closure_base_def_id = self.tcx.closure_base_def_id(mir_def_id.to_def_id());
-        for_each_late_bound_region_defined_on(self.tcx, closure_base_def_id, |r| {
+        let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
+        for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
             debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = self.next_nll_region_var(FR);
index f0056cb79766a49f4db2f34a68a81b93c5176063..52b00a2bc74746d9d0fddbe3ff592ebd4f690774 100644 (file)
@@ -760,16 +760,11 @@ fn build_piece(
     /// Actually builds the expression which the format_args! block will be
     /// expanded to.
     fn into_expr(self) -> P<ast::Expr> {
-        let mut locals =
-            Vec::with_capacity((0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum());
-        let mut counts = Vec::with_capacity(self.count_args.len());
-        let mut pats = Vec::with_capacity(self.args.len());
+        let mut args = Vec::with_capacity(
+            self.arg_unique_types.iter().map(|v| v.len()).sum::<usize>() + self.count_args.len(),
+        );
         let mut heads = Vec::with_capacity(self.args.len());
 
-        let names_pos: Vec<_> = (0..self.args.len())
-            .map(|i| Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
-            .collect();
-
         // First, build up the static array which will become our precompiled
         // format "string"
         let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);
@@ -787,11 +782,8 @@ fn into_expr(self) -> P<ast::Expr> {
         // of each variable because we don't want to move out of the arguments
         // passed to this function.
         for (i, e) in self.args.into_iter().enumerate() {
-            let name = names_pos[i];
-            let span = self.ecx.with_def_site_ctxt(e.span);
-            pats.push(self.ecx.pat_ident(span, name));
             for arg_ty in self.arg_unique_types[i].iter() {
-                locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
+                args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i));
             }
             heads.push(self.ecx.expr_addr_of(e.span, e));
         }
@@ -800,15 +792,11 @@ fn into_expr(self) -> P<ast::Expr> {
                 Exact(i) => i,
                 _ => panic!("should never happen"),
             };
-            let name = names_pos[index];
             let span = spans_pos[index];
-            counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
+            args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index));
         }
 
-        // Now create a vector containing all the arguments
-        let args = locals.into_iter().chain(counts.into_iter());
-
-        let args_array = self.ecx.expr_vec(self.macsp, args.collect());
+        let args_array = self.ecx.expr_vec(self.macsp, args);
 
         // Constructs an AST equivalent to:
         //
@@ -838,7 +826,7 @@ fn into_expr(self) -> P<ast::Expr> {
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
         let args_match = {
-            let pat = self.ecx.pat_tuple(self.macsp, pats);
+            let pat = self.ecx.pat_ident(self.macsp, Ident::new(sym::_args, self.macsp));
             let arm = self.ecx.arm(self.macsp, pat, args_array);
             let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
             self.ecx.expr_match(self.macsp, head, vec![arm])
@@ -877,10 +865,11 @@ fn format_arg(
         macsp: Span,
         mut sp: Span,
         ty: &ArgumentType,
-        arg: Ident,
+        arg_index: usize,
     ) -> P<ast::Expr> {
         sp = ecx.with_def_site_ctxt(sp);
-        let arg = ecx.expr_ident(sp, arg);
+        let arg = ecx.expr_ident(sp, Ident::new(sym::_args, sp));
+        let arg = ecx.expr(sp, ast::ExprKind::Field(arg, Ident::new(sym::integer(arg_index), sp)));
         let trait_ = match *ty {
             Placeholder(trait_) if trait_ == "<invalid>" => return DummyResult::raw_expr(sp, true),
             Placeholder(trait_) => trait_,
index 4abda33b2aa89fe971bd1e6f61f56ae9766e84f9..3d05fc15b38f4121c22f737cccc040d78f734db2 100644 (file)
@@ -301,7 +301,7 @@ fn report_inline_asm(
         cookie = 0;
     }
     let level = match level {
-        llvm::DiagnosticLevel::Error => Level::Error,
+        llvm::DiagnosticLevel::Error => Level::Error { lint: false },
         llvm::DiagnosticLevel::Warning => Level::Warning,
         llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
     };
index 1f1bd73c7d035d51ae736dae5bfde264980b1d0a..2a6bf7d9b1a4ddac535843a25a4c2e052bd79ac1 100644 (file)
@@ -322,7 +322,7 @@ fn dbg_scope_fn(
         type_names::push_item_name(self.tcx(), def_id, false, &mut name);
 
         // Find the enclosing function, in case this is a closure.
-        let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
+        let enclosing_fn_def_id = self.tcx().typeck_root_def_id(def_id);
 
         // Get_template_parameters() will append a `<...>` clause to the function
         // name if necessary.
index b2edc6c0183a0b8ce13475e2d3b406c18105221a..85d51ea9a207b1cfebe505d9203ee53e55dc9a35 100644 (file)
@@ -1757,7 +1757,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
                     let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
 
                     let mut err = match level {
-                        Level::Error => sess.struct_err(&msg),
+                        Level::Error { lint: false } => sess.struct_err(&msg),
                         Level::Warning => sess.struct_warn(&msg),
                         Level::Note => sess.struct_note_without_error(&msg),
                         _ => bug!("Invalid inline asm diagnostic level"),
index caeeb23feb471bf48f86dcc753c44daf94adf7b1..b4420df5df417a67196e3b4c70c7013449ea2cff 100644 (file)
@@ -20,6 +20,7 @@
     ("aes", Some(sym::arm_target_feature)),
     ("sha2", Some(sym::arm_target_feature)),
     ("i8mm", Some(sym::arm_target_feature)),
+    ("dotprod", Some(sym::arm_target_feature)),
     ("v5te", Some(sym::arm_target_feature)),
     ("v6", Some(sym::arm_target_feature)),
     ("v6k", Some(sym::arm_target_feature)),
index 57af0ff07143373cacfd7f11d2423e7e0bc8cd7c..6d3a89c0a8a5ba3927510556463c1b55d4397baa 100644 (file)
@@ -42,6 +42,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
                     | DefKind::Static
                     | DefKind::ConstParam
                     | DefKind::AnonConst
+                    | DefKind::InlineConst
                     | DefKind::AssocConst
             ),
         "Unexpected DefKind: {:?}",
index 3785c170f6b2b9a931f2eb93143b7c6a6cb2a953..61fd828a430020d9c096a7a559135de424924a77 100644 (file)
@@ -1054,8 +1054,9 @@ fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId)
         let mut fulfillment_cx = traits::FulfillmentContext::new();
         let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
         fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
-        if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&err, None, false);
+        let errors = fulfillment_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
     });
 }
index 1eb497460e63c053ceec0ea015227513c0dfa79a..9db8f751390c110d3993b4468585211540e1c68d 100644 (file)
@@ -66,7 +66,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
 /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
 fn annotation_type_for_level(level: Level) -> AnnotationType {
     match level {
-        Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
+        Level::Bug | Level::Fatal | Level::Error { .. } => AnnotationType::Error,
         Level::Warning => AnnotationType::Warning,
         Level::Note => AnnotationType::Note,
         Level::Help => AnnotationType::Help,
index f2381d75c565fd6d365edf242f363b44c0836722..e5116cd8dfed2c1b7ff840ec2a218900935fa620 100644 (file)
@@ -114,7 +114,7 @@ pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) ->
 
     pub fn is_error(&self) -> bool {
         match self.level {
-            Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true,
+            Level::Bug | Level::Fatal | Level::Error { .. } | Level::FailureNote => true,
 
             Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false,
         }
index b6cf332f511ec2fe39e4eda5fbbd5982d92539a6..21a2eb771c8e2b7c282c5f0445bc38c9a4c0b632 100644 (file)
@@ -411,6 +411,8 @@ pub struct Handler {
 /// as well as inconsistent state observation.
 struct HandlerInner {
     flags: HandlerFlags,
+    /// The number of lint errors that have been emitted.
+    lint_err_count: usize,
     /// The number of errors that have been emitted, including duplicates.
     ///
     /// This is not necessarily the count that's reported to the user once
@@ -550,6 +552,7 @@ pub fn with_emitter_and_flags(
             flags,
             inner: Lock::new(HandlerInner {
                 flags,
+                lint_err_count: 0,
                 err_count: 0,
                 warn_count: 0,
                 deduplicated_err_count: 0,
@@ -726,7 +729,13 @@ pub fn struct_span_err_with_code(
     /// Construct a builder at the `Error` level with the `msg`.
     // FIXME: This method should be removed (every error should have an associated error code).
     pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
-        DiagnosticBuilder::new(self, Level::Error, msg)
+        DiagnosticBuilder::new(self, Level::Error { lint: false }, msg)
+    }
+
+    /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors.
+    #[doc(hidden)]
+    pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        DiagnosticBuilder::new(self, Level::Error { lint: true }, msg)
     }
 
     /// Construct a builder at the `Error` level with the `msg` and the `code`.
@@ -790,11 +799,14 @@ pub fn span_fatal_with_code(
     }
 
     pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
-        self.emit_diag_at_span(Diagnostic::new(Error, msg), span);
+        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
     }
 
     pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
-        self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span);
+        self.emit_diag_at_span(
+            Diagnostic::new_with_code(Error { lint: false }, Some(code), msg),
+            span,
+        );
     }
 
     pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: &str) {
@@ -862,6 +874,9 @@ pub fn err_count(&self) -> usize {
     pub fn has_errors(&self) -> bool {
         self.inner.borrow().has_errors()
     }
+    pub fn has_errors_or_lint_errors(&self) -> bool {
+        self.inner.borrow().has_errors_or_lint_errors()
+    }
     pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.inner.borrow().has_errors_or_delayed_span_bugs()
     }
@@ -979,7 +994,11 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             }
         }
         if diagnostic.is_error() {
-            self.bump_err_count();
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.bump_lint_err_count();
+            } else {
+                self.bump_err_count();
+            }
         } else {
             self.bump_warn_count();
         }
@@ -1073,11 +1092,14 @@ fn err_count(&self) -> usize {
     fn has_errors(&self) -> bool {
         self.err_count() > 0
     }
+    fn has_errors_or_lint_errors(&self) -> bool {
+        self.has_errors() || self.lint_err_count > 0
+    }
     fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.has_errors() || !self.delayed_span_bugs.is_empty()
     }
     fn has_any_message(&self) -> bool {
-        self.err_count() > 0 || self.warn_count > 0
+        self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0
     }
 
     fn abort_if_errors(&mut self) {
@@ -1131,7 +1153,7 @@ fn fatal(&mut self, msg: &str) -> FatalError {
     }
 
     fn err(&mut self, msg: &str) {
-        self.emit_error(Error, msg);
+        self.emit_error(Error { lint: false }, msg);
     }
 
     /// Emit an error; level should be `Error` or `Fatal`.
@@ -1167,6 +1189,11 @@ fn flush_delayed(&mut self, bugs: Vec<Diagnostic>, explanation: &str) {
         }
     }
 
+    fn bump_lint_err_count(&mut self) {
+        self.lint_err_count += 1;
+        self.panic_if_treat_err_as_bug();
+    }
+
     fn bump_err_count(&mut self) {
         self.err_count += 1;
         self.panic_if_treat_err_as_bug();
@@ -1210,7 +1237,10 @@ fn decorate(mut self) -> Diagnostic {
 pub enum Level {
     Bug,
     Fatal,
-    Error,
+    Error {
+        /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
+        lint: bool,
+    },
     Warning,
     Note,
     Help,
@@ -1229,7 +1259,7 @@ impl Level {
     fn color(self) -> ColorSpec {
         let mut spec = ColorSpec::new();
         match self {
-            Bug | Fatal | Error => {
+            Bug | Fatal | Error { .. } => {
                 spec.set_fg(Some(Color::Red)).set_intense(true);
             }
             Warning => {
@@ -1250,7 +1280,7 @@ fn color(self) -> ColorSpec {
     pub fn to_str(self) -> &'static str {
         match self {
             Bug => "error: internal compiler error",
-            Fatal | Error => "error",
+            Fatal | Error { .. } => "error",
             Warning => "warning",
             Note => "note",
             Help => "help",
index 5cb97198765fe4411a8e691f1990e7e9e2a850c6..66f6c008259005da2fc79fabf458e9271b893631 100644 (file)
@@ -273,7 +273,7 @@ fn to_internal(self) -> TokenStream {
 impl ToInternal<rustc_errors::Level> for Level {
     fn to_internal(self) -> rustc_errors::Level {
         match self {
-            Level::Error => rustc_errors::Level::Error,
+            Level::Error => rustc_errors::Level::Error { lint: false },
             Level::Warning => rustc_errors::Level::Warning,
             Level::Note => rustc_errors::Level::Note,
             Level::Help => rustc_errors::Level::Help,
index cb668eb35e093da9b2194eef756f4208e436c677..60761a05de8270180810ca2d6995fab17eb59dac 100644 (file)
@@ -104,8 +104,10 @@ pub enum DefKind {
     Use,
     /// An `extern` block.
     ForeignMod,
-    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}`
+    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`
     AnonConst,
+    /// An inline constant, e.g. `const { 1 + 2 }`
+    InlineConst,
     /// Opaque type, aka `impl Trait`.
     OpaqueTy,
     Field,
@@ -155,6 +157,7 @@ pub fn descr(self, def_id: DefId) -> &'static str {
             DefKind::Use => "import",
             DefKind::ForeignMod => "foreign module",
             DefKind::AnonConst => "constant expression",
+            DefKind::InlineConst => "inline constant",
             DefKind::Field => "field",
             DefKind::Impl => "implementation",
             DefKind::Closure => "closure",
@@ -174,6 +177,7 @@ pub fn article(&self) -> &'static str {
             | DefKind::OpaqueTy
             | DefKind::Impl
             | DefKind::Use
+            | DefKind::InlineConst
             | DefKind::ExternCrate => "an",
             DefKind::Macro(macro_kind) => macro_kind.article(),
             _ => "a",
@@ -207,6 +211,7 @@ pub fn ns(&self) -> Option<Namespace> {
 
             // Not namespaced.
             DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::Field
             | DefKind::LifetimeParam
             | DefKind::ExternCrate
index 2296cc6129ae8594a70f579b546d307a844418ad..5b4a9d9dfad456e43b201933ffe15107eb2f73d9 100644 (file)
@@ -108,7 +108,7 @@ fn make_query_response<T>(
         let tcx = self.tcx;
 
         // Select everything, returning errors.
-        let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new);
+        let true_errors = fulfill_cx.select_where_possible(self);
         debug!("true_errors = {:#?}", true_errors);
 
         if !true_errors.is_empty() {
@@ -118,7 +118,7 @@ fn make_query_response<T>(
         }
 
         // Anything left unselected *now* must be an ambiguity.
-        let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new);
+        let ambig_errors = fulfill_cx.select_all_or_error(self);
         debug!("ambig_errors = {:#?}", ambig_errors);
 
         let region_obligations = self.take_registered_region_obligations();
index 9e04773c5fa2056c9bb4865d9051e938b5a0f86b..3947282aa6217f4dba820c79d75c6596e4294262 100644 (file)
@@ -99,7 +99,7 @@ pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<
     /// function. We can then add implied bounds and the like from the
     /// closure arguments into the environment -- these should only
     /// apply in the closure body, so once we exit, we invoke
-    /// `pop_snapshot_post_closure` to remove them.
+    /// `pop_snapshot_post_typeck_child` to remove them.
     ///
     /// Example:
     ///
@@ -129,12 +129,12 @@ pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<
     /// seems like it'd be readily fixed if we wanted. There are
     /// similar leaks around givens that seem equally suspicious, to
     /// be honest. --nmatsakis
-    pub fn push_snapshot_pre_closure(&self) -> usize {
+    pub fn push_snapshot_pre_typeck_child(&self) -> usize {
         self.region_bound_pairs_accum.len()
     }
 
-    /// See `push_snapshot_pre_closure`.
-    pub fn pop_snapshot_post_closure(&mut self, len: usize) {
+    /// See `push_snapshot_pre_typeck_child`.
+    pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) {
         self.region_bound_pairs_accum.truncate(len);
     }
 
index dce4a87b041189a49910765f763ef7798d781a77..152a395c871be44a6008ba8cb46bd81c9094548a 100644 (file)
@@ -46,30 +46,25 @@ fn register_predicate_obligation(
         obligation: PredicateObligation<'tcx>,
     );
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>>;
 
     fn select_all_with_constness_or_error(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         _constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         self.select_all_or_error(infcx)
     }
 
-    fn select_where_possible(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>)
+    -> Vec<FulfillmentError<'tcx>>;
 
     // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated
     fn select_with_constness_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         _constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         self.select_where_possible(infcx)
     }
 
index 49c3472a20266d9ab82410226d5828907cd858b6..d46829c2ceea693b047305ca5165b8dd0696a9fd 100644 (file)
@@ -797,6 +797,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::ConstParam
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -832,6 +833,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -856,9 +858,11 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
             (true, mir_opt_base)
         }
         // Constants
-        DefKind::AnonConst | DefKind::AssocConst | DefKind::Static | DefKind::Const => {
-            (true, false)
-        }
+        DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::AssocConst
+        | DefKind::Static
+        | DefKind::Const => (true, false),
         // Full-fledged functions
         DefKind::AssocFn | DefKind::Fn => {
             let generics = tcx.generics_of(def_id);
@@ -914,6 +918,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -939,6 +944,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::AssocFn
         | DefKind::AssocConst
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::Impl
         | DefKind::Field
index 8f52e16c2ebe41e7873d6893dc0917be4e1a37a4..d9d0781b37aacefe4afab97366de2b6448907d6e 100644 (file)
@@ -266,7 +266,15 @@ pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
                 };
                 DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
             }
-            Node::AnonConst(_) => DefKind::AnonConst,
+            Node::AnonConst(_) => {
+                let inline = match self.find(self.get_parent_node(hir_id)) {
+                    Some(Node::Expr(&Expr {
+                        kind: ExprKind::ConstBlock(ref anon_const), ..
+                    })) if anon_const.hir_id == hir_id => true,
+                    _ => false,
+                };
+                if inline { DefKind::InlineConst } else { DefKind::AnonConst }
+            }
             Node::Field(_) => DefKind::Field,
             Node::Expr(expr) => match expr.kind {
                 ExprKind::Closure(.., None) => DefKind::Closure,
index 1eba2994ed36e89af4038a3193094648d59e5500..0e70d49ef49d25faa9f12189bb36f4b394d4b220 100644 (file)
@@ -248,8 +248,12 @@ fn struct_lint_level_impl(
             (Level::Warn, None) => sess.struct_warn(""),
             (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""),
             (Level::ForceWarn, None) => sess.struct_force_warn(""),
-            (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
-            (Level::Deny | Level::Forbid, None) => sess.struct_err(""),
+            (Level::Deny | Level::Forbid, Some(span)) => {
+                let mut builder = sess.diagnostic().struct_err_lint("");
+                builder.set_span(span);
+                builder
+            }
+            (Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
         };
 
         // If this code originates in a foreign macro, aka something that this crate
index 8e363cfbff562d594d9850dfa52c0a6ed2ed553e..8e1b887f87da75695eb5c41a6156250db02171e8 100644 (file)
@@ -958,7 +958,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res
             write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })?
         }
         (_, _) if is_function => write!(w, "fn ")?,
-        (DefKind::AnonConst, _) => {} // things like anon const, not an item
+        (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
         _ => bug!("Unexpected def kind {:?}", kind),
     }
 
index 06041bbb02d355537240c012aefb6835520036d4..a9f94b74c5efb2ade9d3fb13dbefe222f31f8386 100644 (file)
     /// additional requirements that the closure's creator must verify.
     query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
-        cache_on_disk_if(tcx) { tcx.is_closure(key.to_def_id()) }
+        cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
     }
     query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc {
index 869b2ab9dbcbc5a02495d8b515f6963ad1f10e6c..27e22ccac02a7fb7c771700ada2318eeace3a841 100644 (file)
@@ -1,7 +1,9 @@
 use crate::mir::interpret::ConstValue;
 use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{ParamEnv, ParamEnvAnd};
+use crate::ty::{
+    self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
+    TyCtxt, TypeFoldable,
+};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -54,6 +56,24 @@ pub fn from_opt_const_arg_anon_const(
 
         let ty = tcx.type_of(def.def_id_for_type_of());
 
+        match Self::try_eval_lit_or_param(tcx, ty, expr) {
+            Some(v) => v,
+            None => tcx.mk_const(ty::Const {
+                val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                    def: def.to_global(),
+                    substs_: None,
+                    promoted: None,
+                }),
+                ty,
+            }),
+        }
+    }
+
+    fn try_eval_lit_or_param(
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Option<&'tcx Self> {
         let lit_input = match expr.kind {
             hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
             hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
@@ -69,7 +89,7 @@ pub fn from_opt_const_arg_anon_const(
             // If an error occurred, ignore that it's a literal and leave reporting the error up to
             // mir.
             if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
-                return c;
+                return Some(c);
             } else {
                 tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const");
             }
@@ -85,7 +105,7 @@ pub fn from_opt_const_arg_anon_const(
         };
 
         use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
-        let val = match expr.kind {
+        match expr.kind {
             ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
                 // Find the name and index of the const parameter by indexing the generics of
                 // the parent item and construct a `ParamConst`.
@@ -95,16 +115,53 @@ pub fn from_opt_const_arg_anon_const(
                 let generics = tcx.generics_of(item_def_id.to_def_id());
                 let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
-                ty::ConstKind::Param(ty::ParamConst::new(index, name))
+                Some(tcx.mk_const(ty::Const {
+                    val: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
+                    ty,
+                }))
             }
-            _ => ty::ConstKind::Unevaluated(ty::Unevaluated {
-                def: def.to_global(),
-                substs_: None,
-                promoted: None,
-            }),
+            _ => None,
+        }
+    }
+
+    pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self {
+        debug!("Const::from_inline_const(def_id={:?})", def_id);
+
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+        let body_id = match tcx.hir().get(hir_id) {
+            hir::Node::AnonConst(ac) => ac.body,
+            _ => span_bug!(
+                tcx.def_span(def_id.to_def_id()),
+                "from_inline_const can only process anonymous constants"
+            ),
         };
 
-        tcx.mk_const(ty::Const { val, ty })
+        let expr = &tcx.hir().body(body_id).value;
+
+        let ty = tcx.typeck(def_id).node_type(hir_id);
+
+        let ret = match Self::try_eval_lit_or_param(tcx, ty, expr) {
+            Some(v) => v,
+            None => {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
+                let parent_substs =
+                    tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
+                let substs =
+                    InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
+                        .substs;
+                tcx.mk_const(ty::Const {
+                    val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                        def: ty::WithOptConstParam::unknown(def_id).to_global(),
+                        substs_: Some(substs),
+                        promoted: None,
+                    }),
+                    ty,
+                })
+            }
+        };
+        debug_assert!(!ret.has_free_regions(tcx));
+        ret
     }
 
     /// Interns the given value as a constant.
index 2bd9415171d7d5d2ac0af852205e531aa736a01c..b14a69892657bcb7bce9c32efc9c9314f5df4b73 100644 (file)
@@ -42,6 +42,7 @@ pub enum TypeError<'tcx> {
     TupleSize(ExpectedFound<usize>),
     FixedArraySize(ExpectedFound<u64>),
     ArgCount,
+    FieldMisMatch(Symbol, Symbol),
 
     RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
     RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
@@ -134,6 +135,7 @@ fn report_maybe_different(
                 pluralize!(values.found)
             ),
             ArgCount => write!(f, "incorrect number of function parameters"),
+            FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
             RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
             RegionsInsufficientlyPolymorphic(br, _) => write!(
                 f,
@@ -224,6 +226,7 @@ pub fn must_include_note(&self) -> bool {
             | ArgumentMutability(_)
             | TupleSize(_)
             | ArgCount
+            | FieldMisMatch(..)
             | RegionsDoesNotOutlive(..)
             | RegionsInsufficientlyPolymorphic(..)
             | RegionsOverlyPolymorphic(..)
index cf47da157d19f7c969eb8e0e9724d06056f052f0..40670f1fdcaefb03ac7b4ec18774be070bfec613 100644 (file)
     Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
     CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
     ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
-    GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
-    PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
-    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
+    GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst,
+    ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig,
+    PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut,
+    UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
 };
 pub use self::trait_def::TraitDef;
 
@@ -1927,7 +1928,8 @@ pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
                 | DefKind::Static
                 | DefKind::AssocConst
                 | DefKind::Ctor(..)
-                | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def),
+                | DefKind::AnonConst
+                | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
                 // If the caller wants `mir_for_ctfe` of a function they should not be using
                 // `instance_mir`, so we'll assume const fn also wants the optimized version.
                 _ => {
index d6069395474ab21ddd877c02e804944deafc7d44..0f8e80806e31e430edc9dc4ff13fc80fb94b4489 100644 (file)
@@ -602,6 +602,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             TupleSize(x) => TupleSize(x),
             FixedArraySize(x) => FixedArraySize(x),
             ArgCount => ArgCount,
+            FieldMisMatch(x, y) => FieldMisMatch(x, y),
             RegionsDoesNotOutlive(a, b) => {
                 return tcx.lift((a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b));
             }
index 874de3366d79213ee7499075d518f5a41f3eb58d..e57075ed33811d59589d3f340ef2f5c0ae272a1a 100644 (file)
@@ -704,6 +704,66 @@ pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
     }
 }
 
+/// An inline const is modeled like
+///
+///     const InlineConst<'l0...'li, T0...Tj, R>: R;
+///
+/// where:
+///
+/// - 'l0...'li and T0...Tj are the generic parameters
+///   inherited from the item that defined the inline const,
+/// - R represents the type of the constant.
+///
+/// When the inline const is instantiated, `R` is substituted as the actual inferred
+/// type of the constant. The reason that `R` is represented as an extra type parameter
+/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
+/// inline const can reference lifetimes that are internal to the creating function.
+#[derive(Copy, Clone, Debug, TypeFoldable)]
+pub struct InlineConstSubsts<'tcx> {
+    /// Generic parameters from the enclosing item,
+    /// concatenated with the inferred type of the constant.
+    pub substs: SubstsRef<'tcx>,
+}
+
+/// Struct returned by `split()`.
+pub struct InlineConstSubstsParts<'tcx, T> {
+    pub parent_substs: &'tcx [GenericArg<'tcx>],
+    pub ty: T,
+}
+
+impl<'tcx> InlineConstSubsts<'tcx> {
+    /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`.
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
+    ) -> InlineConstSubsts<'tcx> {
+        InlineConstSubsts {
+            substs: tcx.mk_substs(
+                parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
+            ),
+        }
+    }
+
+    /// Divides the inline const substs into their respective components.
+    /// The ordering assumed here must match that used by `InlineConstSubsts::new` above.
+    fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> {
+        match self.substs[..] {
+            [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty },
+            _ => bug!("inline const substs missing synthetics"),
+        }
+    }
+
+    /// Returns the substitutions of the inline const's parent.
+    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent_substs
+    }
+
+    /// Returns the type of this inline const.
+    pub fn ty(self) -> Ty<'tcx> {
+        self.split().ty.expect_ty()
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum ExistentialPredicate<'tcx> {
index 2438d1a16021b50aa4f318d5946842e6bc6d4281..73a8e18949de06ad6a4d8d5b3dc0c8329b5c22bf 100644 (file)
@@ -3,7 +3,7 @@
 use crate::mir;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
+use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
 use rustc_hir::def_id::DefId;
@@ -204,6 +204,14 @@ pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> {
         GeneratorSubsts { substs: self }
     }
 
+    /// Interpret these substitutions as the substitutions of an inline const.
+    /// Inline const substitutions have a particular structure controlled by the
+    /// compiler that encodes information like the inferred type;
+    /// see `ty::InlineConstSubsts` struct for more comments.
+    pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> {
+        InlineConstSubsts { substs: self }
+    }
+
     /// Creates an `InternalSubsts` that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
         Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param))
index 2c884813d23187eea6f275f54c9cffb979085a36..6b287445ff032dade94803d5ba345326d7d7ac98 100644 (file)
@@ -423,6 +423,15 @@ pub fn is_closure(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Generator)
     }
 
+    /// Returns `true` if `def_id` refers to a definition that does not have its own
+    /// type-checking context, i.e. closure, generator or inline const.
+    pub fn is_typeck_child(self, def_id: DefId) -> bool {
+        matches!(
+            self.def_kind(def_id),
+            DefKind::Closure | DefKind::Generator | DefKind::InlineConst
+        )
+    }
+
     /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
     pub fn is_trait(self, def_id: DefId) -> bool {
         self.def_kind(def_id) == DefKind::Trait
@@ -440,16 +449,19 @@ pub fn is_constructor(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Ctor(..))
     }
 
-    /// Given the def-ID of a fn or closure, returns the def-ID of
-    /// the innermost fn item that the closure is contained within.
-    /// This is a significant `DefId` because, when we do
-    /// type-checking, we type-check this fn item and all of its
-    /// (transitive) closures together. Therefore, when we fetch the
+    /// Given the `DefId`, returns the `DefId` of the innermost item that
+    /// has its own type-checking context or "inference enviornment".
+    ///
+    /// For example, a closure has its own `DefId`, but it is type-checked
+    /// with the containing item. Similarly, an inline const block has its
+    /// own `DefId` but it is type-checked together with the containing item.
+    ///
+    /// Therefore, when we fetch the
     /// `typeck` the closure, for example, we really wind up
     /// fetching the `typeck` the enclosing fn item.
-    pub fn closure_base_def_id(self, def_id: DefId) -> DefId {
+    pub fn typeck_root_def_id(self, def_id: DefId) -> DefId {
         let mut def_id = def_id;
-        while self.is_closure(def_id) {
+        while self.is_typeck_child(def_id) {
             def_id = self.parent(def_id).unwrap_or_else(|| {
                 bug!("closure {:?} has no parent", def_id);
             });
index 17296a95bc17e26e2c6560ea91001e977c8841e7..b4005ccd1cc42205db0909d37699f2b802fbf561 100644 (file)
@@ -578,7 +578,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
 
             hir::ExprKind::ConstBlock(ref anon_const) => {
                 let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
 
                 ExprKind::ConstBlock { value }
             }
index cb74ae4df2ef86ac4084583730a0d4343f20307e..ce80214c875fc5e46f329f65fc438f031759bed7 100644 (file)
@@ -544,7 +544,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
             let (lit, neg) = match expr.kind {
                 hir::ExprKind::ConstBlock(ref anon_const) => {
                     let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                    let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                    let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
                     if matches!(value.val, ConstKind::Param(_)) {
                         let span = self.tcx.hir().span(anon_const.hir_id);
                         self.errors.push(PatternError::ConstParamInPattern(span));
index e6e4438b6d41afa63bb448bbc1db8b81cfd51e17..595080619da6faaac8be4cf5b91b93beb4cbf45a 100644 (file)
@@ -167,6 +167,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::Use
         | DefKind::ForeignMod
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::Field
         | DefKind::LifetimeParam
@@ -195,7 +196,7 @@ fn emit_unused_generic_params_error<'tcx>(
     generics: &'tcx ty::Generics,
     unused_parameters: &FiniteBitSet<u32>,
 ) {
-    let base_def_id = tcx.closure_base_def_id(def_id);
+    let base_def_id = tcx.typeck_root_def_id(def_id);
     if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) {
         return;
     }
@@ -303,7 +304,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 ControlFlow::CONTINUE
             }
             ty::ConstKind::Unevaluated(uv)
-                if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst =>
+                if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) =>
             {
                 self.visit_child_body(uv.def.did, uv.substs(self.tcx));
                 ControlFlow::CONTINUE
index 5fc8e230d72a3eba67aca78d8a258115f9d21e31..6a8feb041da19f5978c4cf6055f79e127bf61ffc 100644 (file)
@@ -334,9 +334,10 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
     // properly, we can't miss any types.
 
     match expr.kind {
-        // Manually recurse over closures, because they are the only
+        // Manually recurse over closures and inline consts, because they are the only
         // case of nested bodies that share the parent environment.
-        hir::ExprKind::Closure(.., body, _, _) => {
+        hir::ExprKind::Closure(.., body, _, _)
+        | hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
             let body = visitor.tcx.hir().body(body);
             visitor.visit_body(body);
         }
@@ -817,9 +818,9 @@ fn visit_local(&mut self, l: &'tcx Local<'tcx>) {
 }
 
 fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
-    let closure_base_def_id = tcx.closure_base_def_id(def_id);
-    if closure_base_def_id != def_id {
-        return tcx.region_scope_tree(closure_base_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+    if typeck_root_def_id != def_id {
+        return tcx.region_scope_tree(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
index fa34b9abc1e6c9314288ae045f6d1e71dde8ec03..a01efc5d85c6e765bd263855f0575656d1daf247 100644 (file)
@@ -618,6 +618,7 @@ fn update_macro_reachable_def(
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::Field
             | DefKind::GlobalAsm
             | DefKind::Impl
index 238b92a61342b451ce842a09e46a8fc925a00de2..9703f0c3d9605269089498686272447cc188bb9e 100644 (file)
@@ -518,9 +518,22 @@ fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if let Some(result) = result {
+            let prev_fingerprint = tcx
+                .dep_context()
+                .dep_graph()
+                .prev_fingerprint_of(dep_node)
+                .unwrap_or(Fingerprint::ZERO);
             // If `-Zincremental-verify-ich` is specified, re-hash results from
             // the cache and make sure that they have the expected fingerprint.
-            if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+            //
+            // If not, we still seek to verify a subset of fingerprints loaded
+            // from disk. Re-hashing results is fairly expensive, so we can't
+            // currently afford to verify every hash. This subset should still
+            // give us some coverage of potential bugs though.
+            let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
+            if unlikely!(
+                try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich
+            ) {
                 incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
             }
 
index d77a70e5327994dee768eadc67e7ac6dbdc7c440..4173e0fbf5668e546a878ece896cfb026c8b491f 100644 (file)
@@ -967,6 +967,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) {
                 | DefKind::Use
                 | DefKind::ForeignMod
                 | DefKind::AnonConst
+                | DefKind::InlineConst
                 | DefKind::Field
                 | DefKind::LifetimeParam
                 | DefKind::GlobalAsm
index 55931d29f6db0ceb5e8ccfd3d548f0db04f3c19b..39e710cb77f3fafd9129d6ad80061aea48ef3837 100644 (file)
@@ -540,7 +540,7 @@ fn is_late_bound_map<'tcx>(
     def_id: LocalDefId,
 ) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
     match tcx.def_kind(def_id) {
-        DefKind::AnonConst => {
+        DefKind::AnonConst | DefKind::InlineConst => {
             let mut def_id = tcx
                 .parent(def_id.to_def_id())
                 .unwrap_or_else(|| bug!("anon const or closure without a parent"));
@@ -887,10 +887,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                 let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) = c
                     .generic_params
                     .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(param),
-                        _ => None,
-                    })
+                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
                         let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
@@ -1370,9 +1367,8 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
                         let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) =
                             bound_generic_params
                                 .iter()
-                                .filter_map(|param| match param.kind {
-                                    GenericParamKind::Lifetime { .. } => Some(param),
-                                    _ => None,
+                                .filter(|param| {
+                                    matches!(param.kind, GenericParamKind::Lifetime { .. })
                                 })
                                 .enumerate()
                                 .map(|(late_bound_idx, param)| {
@@ -1469,10 +1465,7 @@ fn visit_poly_trait_ref(
         let binders_iter = trait_ref
             .bound_generic_params
             .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => Some(param),
-                _ => None,
-            })
+            .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
             .enumerate()
             .map(|(late_bound_idx, param)| {
                 let pair = Region::late(
@@ -2235,19 +2228,14 @@ fn visit_early_late<F>(
         let binders: Vec<_> = generics
             .params
             .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. }
-                    if self.map.late_bound.contains(&param.hir_id) =>
-                {
-                    Some(param)
-                }
-                _ => None,
+            .filter(|param| {
+                matches!(param.kind, GenericParamKind::Lifetime { .. })
+                    && self.map.late_bound.contains(&param.hir_id)
             })
             .enumerate()
             .map(|(late_bound_idx, param)| {
                 let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
-                let r = late_region_as_bound_region(self.tcx, &pair.1);
-                r
+                late_region_as_bound_region(self.tcx, &pair.1)
             })
             .collect();
         self.map.late_bound_vars.insert(hir_id, binders);
index 543cd0247a53daecd9400c4b4711a6232c54578a..c7f8fe3a88a64b1dc4ea99a8456f852f54083995 100644 (file)
@@ -739,6 +739,7 @@ fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
                 | HirDefKind::ForeignMod
                 | HirDefKind::LifetimeParam
                 | HirDefKind::AnonConst
+                | HirDefKind::InlineConst
                 | HirDefKind::Use
                 | HirDefKind::Field
                 | HirDefKind::GlobalAsm
index 0f6a3ddccbaf0fbc62628cdb6d16b234c038b2be..74b3cfa44c31aaa0e8847ddd5705daa841566e62 100644 (file)
@@ -411,7 +411,7 @@ pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
     pub fn compile_status(&self) -> Result<(), ErrorReported> {
-        if self.has_errors() {
+        if self.diagnostic().has_errors_or_lint_errors() {
             self.diagnostic().emit_stashed_diagnostics();
             Err(ErrorReported)
         } else {
index b9730a1e420bc87dcaa8345a1cba882f7ee72446..99fa9f000944df2b6e66f6227ac44f85105641dd 100644 (file)
         __S,
         __next,
         __try_var,
+        _args,
         _d,
         _e,
         _task_context,
index 01f5c197d2023c477d14277c129d0f2281da8d02..afe8bbb352886a214d1b8bb7f3fd3c3d130b6000 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions};
 
 /// A base target for Nintendo 3DS devices using the devkitARM toolchain.
 ///
@@ -36,7 +36,6 @@ pub fn target() -> Target {
             features: "+vfp2".to_string(),
             pre_link_args,
             exe_suffix: ".elf".to_string(),
-            panic_strategy: PanicStrategy::Abort,
             ..Default::default()
         },
     }
index 53afe4ca068c4cf24f0601ee3c38ddb7a8cbc855..4c80483fc1f1e7750b5c3e68200c75ccb6a6ec23 100644 (file)
@@ -152,11 +152,12 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
             },
             cause,
         );
-        if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
+        let errors = fulfillcx.select_where_possible(&self.infcx);
+        if !errors.is_empty() {
             // This shouldn't happen, except for evaluate/fulfill mismatches,
             // but that's not a reason for an ICE (`predicate_may_hold` is conservative
             // by design).
-            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
+            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
             return None;
         }
         let obligations = fulfillcx.pending_obligations();
index 6452b520452d6802b157c023ecf457620a3da1c3..54f7b91080dd9fb0a9cae74dea7ecd43517972a5 100644 (file)
@@ -187,9 +187,11 @@ pub fn find_auto_trait_generics<A>(
             // an additional sanity check.
             let mut fulfill = FulfillmentContext::new();
             fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy());
-            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
-                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
-            });
+            let errors = fulfill.select_all_or_error(&infcx);
+
+            if !errors.is_empty() {
+                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
+            }
 
             let body_id_map: FxHashMap<_, _> = infcx
                 .inner
index ec62ee400688ca2f62cae140fc32b1f40da8bf5e..2ccb25349173ff300d88e636ad59848fcad44e92 100644 (file)
@@ -49,34 +49,32 @@ fn register_predicate_obligation(
         self.obligations.insert(obligation);
     }
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        if self.obligations.is_empty() {
-            Ok(())
-        } else {
-            let errors = self
-                .obligations
-                .iter()
-                .map(|obligation| FulfillmentError {
-                    obligation: obligation.clone(),
-                    code: FulfillmentErrorCode::CodeAmbiguity,
-                    // FIXME - does Chalk have a notation of 'root obligation'?
-                    // This is just for diagnostics, so it's okay if this is wrong
-                    root_obligation: obligation.clone(),
-                })
-                .collect();
-            Err(errors)
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_where_possible(infcx);
+
+            if !errors.is_empty() {
+                return errors;
+            }
         }
+
+        // any remaining obligations are errors
+        self.obligations
+            .iter()
+            .map(|obligation| FulfillmentError {
+                obligation: obligation.clone(),
+                code: FulfillmentErrorCode::CodeAmbiguity,
+                // FIXME - does Chalk have a notation of 'root obligation'?
+                // This is just for diagnostics, so it's okay if this is wrong
+                root_obligation: obligation.clone(),
+            })
+            .collect()
     }
 
     fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         assert!(!infcx.is_in_snapshot());
 
         let mut errors = Vec::new();
@@ -147,7 +145,7 @@ fn select_where_possible(
             }
         }
 
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+        errors
     }
 
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
index f06f0e32f414b73f90e35192996ba41ba780fcb3..bdd4fdd40438c6fb5e4ce219847bd106146f559a 100644 (file)
@@ -120,7 +120,8 @@ fn drain_fulfillment_cx_or_panic<T>(
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
     // optimization to stop iterating early.
-    if let Err(errors) = fulfill_cx.select_all_or_error(infcx) {
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
         infcx.tcx.sess.delay_span_bug(
             rustc_span::DUMMY_SP,
             &format!("Encountered errors `{:?}` resolving bounds after type-checking", errors),
index 8edb7069fc45f9a19c55f3c66f75a0bc79b9870f..6b5d37c0f43086516d57425d66807dd3b6ca72b7 100644 (file)
@@ -151,7 +151,7 @@ enum FailureKind {
 
     if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) {
         match infcx.tcx.def_kind(uv.def.did) {
-            DefKind::AnonConst => {
+            DefKind::AnonConst | DefKind::InlineConst => {
                 let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
 
                 if mir_body.is_polymorphic {
@@ -495,7 +495,7 @@ pub(super) fn thir_abstract_const<'tcx>(
             // we want to look into them or treat them as opaque projections.
             //
             // Right now we do neither of that and simply always fail to unify them.
-            DefKind::AnonConst => (),
+            DefKind::AnonConst | DefKind::InlineConst => (),
             _ => return Ok(None),
         }
 
index 2689e2134fc6b5e0ded2dd2e01f732375f0e4424..b21936a00b04fae8c104dd81668dc4992de6af37 100644 (file)
@@ -1474,7 +1474,7 @@ fn maybe_note_obligation_cause_for_async_await(
         let span = self.tcx.def_span(generator_did);
 
         let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
         debug!(
             "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
              generator_did_root={:?} in_progress_typeck_results.hir_owner={:?} span={:?}",
index 465d1465d5d3538325def6ae9dcf226b730f9aa6..e121837c987ae9b694ea1b45281abca63da8e8c7 100644 (file)
@@ -126,10 +126,7 @@ pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
     }
 
     /// Attempts to select obligations using `selcx`.
-    fn select(
-        &mut self,
-        selcx: &mut SelectionContext<'a, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
         let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
         let _enter = span.enter();
 
@@ -163,7 +160,7 @@ fn select(
             errors.len()
         );
 
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+        errors
     }
 }
 
@@ -223,41 +220,36 @@ fn register_predicate_obligation(
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(to_fulfillment_error)
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_where_possible(infcx);
+            if !errors.is_empty() {
+                return errors;
+            }
+        }
+
+        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
     }
 
     fn select_all_with_constness_or_error(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         constness: rustc_hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_with_constness_where_possible(infcx, constness)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(to_fulfillment_error)
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    ) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_with_constness_where_possible(infcx, constness);
+            if !errors.is_empty() {
+                return errors;
+            }
+        }
+
+        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
     }
 
     fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         let mut selcx = SelectionContext::new(infcx);
         self.select(&mut selcx)
     }
@@ -266,7 +258,7 @@ fn select_with_constness_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         let mut selcx = SelectionContext::with_constness(infcx, constness);
         self.select(&mut selcx)
     }
index 8f247184e880873d6f1d4a1419ee959c2753b16e..d4a586b0124a20b1bd790bebc98f0ccc991f0611 100644 (file)
@@ -180,8 +180,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
         // Note: we only assume something is `Copy` if we can
         // *definitively* show that it implements `Copy`. Otherwise,
         // assume it is move; linear is always ok.
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => {
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => {
                 debug!(
                     "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
                     ty,
@@ -189,12 +189,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
                 );
                 true
             }
-            Err(e) => {
+            errors => {
                 debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
-                    ty,
-                    infcx.tcx.def_path_str(def_id),
-                    e
+                    ?ty,
+                    bound = %infcx.tcx.def_path_str(def_id),
+                    ?errors,
+                    "type_known_to_meet_bound_modulo_regions"
                 );
                 false
             }
@@ -410,7 +410,10 @@ pub fn fully_normalize<'a, 'tcx, T>(
     }
 
     debug!("fully_normalize: select_all_or_error start");
-    fulfill_cx.select_all_or_error(infcx)?;
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
+        return Err(errors);
+    }
     debug!("fully_normalize: select_all_or_error complete");
     let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
     debug!("fully_normalize: resolved_value={:?}", resolved_value);
@@ -441,7 +444,9 @@ pub fn impossible_predicates<'tcx>(
             fulfill_cx.register_predicate_obligation(&infcx, obligation);
         }
 
-        fulfill_cx.select_all_or_error(&infcx).is_err()
+        let errors = fulfill_cx.select_all_or_error(&infcx);
+
+        !errors.is_empty()
     });
     debug!("impossible_predicates = {:?}", result);
     result
index b5398f8a4353b222599a49f008bb91a8ccc47035..0a85676f4315e36a88893a759201e899d87b0754 100644 (file)
@@ -77,10 +77,11 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
     debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
     fulfill_cx.register_predicate_obligations(infcx, obligations);
-    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
         infcx.tcx.sess.diagnostic().delay_span_bug(
             DUMMY_SP,
-            &format!("errors selecting obligation during MIR typeck: {:?}", e),
+            &format!("errors selecting obligation during MIR typeck: {:?}", errors),
         );
     }
 
index f9867f0671e59fbd7478629fcd114f4dfea652de..f81a74a67dce57626d4fbd66d8cd4365ff50bc02 100644 (file)
@@ -225,8 +225,18 @@ fn fulfill_implication<'a, 'tcx>(
         for oblig in obligations.chain(more_obligations) {
             fulfill_cx.register_predicate_obligation(&infcx, oblig);
         }
-        match fulfill_cx.select_all_or_error(infcx) {
-            Err(errors) => {
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => {
+                debug!(
+                    "fulfill_implication: an impl for {:?} specializes {:?}",
+                    source_trait_ref, target_trait_ref
+                );
+
+                // Now resolve the *substitution* we built for the target earlier, replacing
+                // the inference variables inside with whatever we got from fulfillment.
+                Ok(infcx.resolve_vars_if_possible(target_substs))
+            }
+            errors => {
                 // no dice!
                 debug!(
                     "fulfill_implication: for impls on {:?} and {:?}, \
@@ -238,17 +248,6 @@ fn fulfill_implication<'a, 'tcx>(
                 );
                 Err(())
             }
-
-            Ok(()) => {
-                debug!(
-                    "fulfill_implication: an impl for {:?} specializes {:?}",
-                    source_trait_ref, target_trait_ref
-                );
-
-                // Now resolve the *substitution* we built for the target earlier, replacing
-                // the inference variables inside with whatever we got from fulfillment.
-                Ok(infcx.resolve_vars_if_possible(target_substs))
-            }
         }
     })
 }
index a398e847b935458a003fab06e30ed423802e255c..3d71382227868df2c1ccd43ddb0cbafa19ece152 100644 (file)
@@ -103,7 +103,7 @@ fn type_marked_structural(
     //
     // 2. We are sometimes doing future-incompatibility lints for
     //    now, so we do not want unconditional errors here.
-    fulfillment_cx.select_all_or_error(infcx).is_ok()
+    fulfillment_cx.select_all_or_error(infcx).is_empty()
 }
 
 /// This implements the traversal over the structure of a given type to try to
index 37e007337374fd2553af77fcff1f307c2062e2c1..92f2760e62c7e86ef62e460bc320126f73cb996d 100644 (file)
@@ -128,9 +128,9 @@ fn compute_implied_outlives_bounds<'tcx>(
 
     // Ensure that those obligations that we had to solve
     // get solved *here*.
-    match fulfill_cx.select_all_or_error(infcx) {
-        Ok(()) => Ok(implied_bounds),
-        Err(_) => Err(NoSolution),
+    match fulfill_cx.select_all_or_error(infcx).as_slice() {
+        [] => Ok(implied_bounds),
+        _ => Err(NoSolution),
     }
 }
 
index 84327a2880e18c6499eb4eaa82c41beaae735124..2f187997b55de0fbf10a7028524a44649b5d3a68 100644 (file)
@@ -672,6 +672,17 @@ pub(crate) fn check_impl_trait(
                 err.span_label(span, "explicit generic argument not allowed");
             }
 
+            err.note(
+                "see issue #83701 <https://github.com/rust-lang/rust/issues/83701> \
+                 for more information",
+            );
+            if tcx.sess.is_nightly_build() {
+                err.help(
+                    "add `#![feature(explicit_generic_args_with_impl_trait)]` \
+                     to the crate attributes to enable",
+                );
+            }
+
             err.emit();
         }
 
index 5040c4db95163a48473aace18608b6d7a7d55623..f0a77cb39a62273b1fb3a18e9faa091da3b20840 100644 (file)
@@ -663,8 +663,9 @@ fn check_opaque_meets_bounds<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
 
         // Finally, resolve all regions. This catches wily misuses of
index 410ac24b1f19c84a8659e5186f31f5c264db201d..f7accbb430caae8375fb5a6c318244009f0b15d7 100644 (file)
@@ -92,7 +92,7 @@ fn check_closure(
 
         let parent_substs = InternalSubsts::identity_for_item(
             self.tcx,
-            self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
+            self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
         );
 
         let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
index ad65a0ba62a8cc8b0372214abbc2da99f575a96c..28712e0658269d5338fdd39ace5c3a713cc6838e 100644 (file)
@@ -950,7 +950,7 @@ pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
             };
             let mut fcx = traits::FulfillmentContext::new_in_snapshot();
             fcx.register_predicate_obligations(self, ok.obligations);
-            fcx.select_where_possible(&self).is_ok()
+            fcx.select_where_possible(&self).is_empty()
         })
     }
 
index 7c262dcf723390fbe58ef980b862666e536d2986..3eadb3f2363d2cdf7645292b1f1a3c310b41aaa1 100644 (file)
@@ -391,8 +391,9 @@ fn compare_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -1094,8 +1095,9 @@ fn compare_const_param_types<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return;
         }
 
@@ -1210,8 +1212,9 @@ fn compare_type_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -1427,10 +1430,10 @@ pub fn check_type_bounds<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) =
-            inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
-        {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors =
+            inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
index fd150978f0074d8a5c4aea01e80090906b03221a..bfa0d92ab47ab9546bfde2ee8b4a42f886675343 100644 (file)
@@ -113,9 +113,10 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             }
         }
 
-        if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
+        let errors = fulfillment_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(errors, None, false);
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
index 3cba7991ccaf308f5657233e1b00426d52700c11..a9c0b65a0981ee5f26372aef342ceb82dbd634e4 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::InferOk;
 use rustc_middle::ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
+use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts};
+use rustc_middle::ty::relate::expected_found_bool;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{AdtKind, Visibility};
+use rustc_session::parse::feature_err;
 use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -323,7 +328,9 @@ fn check_expr_kind(
             }
             ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
             ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
-            ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty,
+            ExprKind::ConstBlock(ref anon_const) => {
+                self.check_expr_const_block(anon_const, expected, expr)
+            }
             ExprKind::Repeat(element, ref count) => {
                 self.check_expr_repeat(element, count, expected, expr)
             }
@@ -1166,6 +1173,24 @@ fn check_expr_array(
         self.tcx.mk_array(element_ty, args.len() as u64)
     }
 
+    fn check_expr_const_block(
+        &self,
+        anon_const: &'tcx hir::AnonConst,
+        expected: Expectation<'tcx>,
+        _expr: &'tcx hir::Expr<'tcx>,
+    ) -> Ty<'tcx> {
+        let body = self.tcx.hir().body(anon_const.body);
+
+        // Create a new function context.
+        let fcx = FnCtxt::new(self, self.param_env, body.value.hir_id);
+        crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
+
+        let ty = fcx.check_expr_with_expectation(&body.value, expected);
+        fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
+        fcx.write_ty(anon_const.hir_id, ty);
+        ty
+    }
+
     fn check_expr_repeat(
         &self,
         element: &'tcx hir::Expr<'tcx>,
@@ -1262,49 +1287,17 @@ fn check_expr_struct(
                 .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() });
         }
 
-        let error_happened = self.check_expr_struct_fields(
+        self.check_expr_struct_fields(
             adt_ty,
             expected,
             expr.hir_id,
             qpath.span(),
             variant,
             fields,
-            base_expr.is_none(),
+            base_expr,
             expr.span,
         );
-        if let Some(base_expr) = base_expr {
-            // If check_expr_struct_fields hit an error, do not attempt to populate
-            // the fields with the base_expr. This could cause us to hit errors later
-            // when certain fields are assumed to exist that in fact do not.
-            if !error_happened {
-                self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {});
-                match adt_ty.kind() {
-                    ty::Adt(adt, substs) if adt.is_struct() => {
-                        let fru_field_types = adt
-                            .non_enum_variant()
-                            .fields
-                            .iter()
-                            .map(|f| {
-                                self.normalize_associated_types_in(
-                                    expr.span,
-                                    f.ty(self.tcx, substs),
-                                )
-                            })
-                            .collect();
-
-                        self.typeck_results
-                            .borrow_mut()
-                            .fru_field_types_mut()
-                            .insert(expr.hir_id, fru_field_types);
-                    }
-                    _ => {
-                        self.tcx
-                            .sess
-                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
-                    }
-                }
-            }
-        }
+
         self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
         adt_ty
     }
@@ -1317,9 +1310,9 @@ fn check_expr_struct_fields(
         span: Span,
         variant: &'tcx ty::VariantDef,
         ast_fields: &'tcx [hir::ExprField<'tcx>],
-        check_completeness: bool,
+        base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
         expr_span: Span,
-    ) -> bool {
+    ) {
         let tcx = self.tcx;
 
         let adt_ty_hint = self
@@ -1394,7 +1387,116 @@ fn check_expr_struct_fields(
                 )
                 .emit();
             }
-        } else if check_completeness && !error_happened && !remaining_fields.is_empty() {
+        }
+
+        // If check_expr_struct_fields hit an error, do not attempt to populate
+        // the fields with the base_expr. This could cause us to hit errors later
+        // when certain fields are assumed to exist that in fact do not.
+        if error_happened {
+            return;
+        }
+
+        if let Some(base_expr) = base_expr {
+            // FIXME: We are currently creating two branches here in order to maintain
+            // consistency. But they should be merged as much as possible.
+            let fru_tys = if self.tcx.features().type_changing_struct_update {
+                let base_ty = self.check_expr(base_expr);
+                match adt_ty.kind() {
+                    ty::Adt(adt, substs) if adt.is_struct() => {
+                        match base_ty.kind() {
+                            ty::Adt(base_adt, base_subs) if adt == base_adt => {
+                                variant
+                                    .fields
+                                    .iter()
+                                    .map(|f| {
+                                        let fru_ty = self.normalize_associated_types_in(
+                                            expr_span,
+                                            self.field_ty(base_expr.span, f, base_subs),
+                                        );
+                                        let ident = self.tcx.adjust_ident(f.ident, variant.def_id);
+                                        if let Some(_) = remaining_fields.remove(&ident) {
+                                            let target_ty =
+                                                self.field_ty(base_expr.span, f, substs);
+                                            let cause = self.misc(base_expr.span);
+                                            match self
+                                                .at(&cause, self.param_env)
+                                                .sup(target_ty, fru_ty)
+                                            {
+                                                Ok(InferOk { obligations, value: () }) => {
+                                                    self.register_predicates(obligations)
+                                                }
+                                                // FIXME: Need better diagnostics for `FieldMisMatch` error
+                                                Err(_) => self
+                                                    .report_mismatched_types(
+                                                        &cause,
+                                                        target_ty,
+                                                        fru_ty,
+                                                        FieldMisMatch(
+                                                            variant.ident.name,
+                                                            ident.name,
+                                                        ),
+                                                    )
+                                                    .emit(),
+                                            }
+                                        }
+                                        fru_ty
+                                    })
+                                    .collect()
+                            }
+                            _ => {
+                                return self
+                                    .report_mismatched_types(
+                                        &self.misc(base_expr.span),
+                                        adt_ty,
+                                        base_ty,
+                                        Sorts(expected_found_bool(true, adt_ty, base_ty)),
+                                    )
+                                    .emit();
+                            }
+                        }
+                    }
+                    _ => {
+                        return self
+                            .tcx
+                            .sess
+                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
+                    }
+                }
+            } else {
+                self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {
+                    let base_ty = self.check_expr(base_expr);
+                    let same_adt = match (adt_ty.kind(), base_ty.kind()) {
+                        (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true,
+                        _ => false,
+                    };
+                    if self.tcx.sess.is_nightly_build() && same_adt {
+                        feature_err(
+                            &self.tcx.sess.parse_sess,
+                            sym::type_changing_struct_update,
+                            base_expr.span,
+                            "type changing struct updating is experimental",
+                        )
+                        .emit();
+                    }
+                });
+                match adt_ty.kind() {
+                    ty::Adt(adt, substs) if adt.is_struct() => variant
+                        .fields
+                        .iter()
+                        .map(|f| {
+                            self.normalize_associated_types_in(expr_span, f.ty(self.tcx, substs))
+                        })
+                        .collect(),
+                    _ => {
+                        return self
+                            .tcx
+                            .sess
+                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
+                    }
+                }
+            };
+            self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys);
+        } else if kind_name != "union" && !remaining_fields.is_empty() {
             let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| {
                 !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
             });
@@ -1405,8 +1507,6 @@ fn check_expr_struct_fields(
                 self.report_missing_fields(adt_ty, span, remaining_fields);
             }
         }
-
-        error_happened
     }
 
     fn check_struct_fields_on_error(
index 5308126f2524b2468078d0c6e1db96efebd86506..93b2a595259722923447a3a5de4bbdc192c8f498 100644 (file)
@@ -642,11 +642,12 @@ pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
 
     #[instrument(skip(self), level = "debug")]
     pub(in super::super) fn select_all_obligations_or_error(&self) {
-        if let Err(errors) = self
+        let errors = self
             .fulfillment_cx
             .borrow_mut()
-            .select_all_with_constness_or_error(&self, self.inh.constness)
-        {
+            .select_all_with_constness_or_error(&self, self.inh.constness);
+
+        if !errors.is_empty() {
             self.report_fulfillment_errors(&errors, self.inh.body_id, false);
         }
     }
@@ -657,13 +658,13 @@ pub(in super::super) fn select_obligations_where_possible(
         fallback_has_occurred: bool,
         mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
     ) {
-        let result = self
+        let mut result = self
             .fulfillment_cx
             .borrow_mut()
             .select_with_constness_where_possible(self, self.inh.constness);
-        if let Err(mut errors) = result {
-            mutate_fulfillment_errors(&mut errors);
-            self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
+        if !result.is_empty() {
+            mutate_fulfillment_errors(&mut result);
+            self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
         }
     }
 
@@ -793,14 +794,17 @@ pub(in super::super) fn expected_inputs_for_expected_output(
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        self.save_and_restore_in_snapshot_flag(|_| {
+                        let errors = self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
                             fulfill.select_where_possible(self)
-                        })
-                        .map_err(|_| ())?;
+                        });
+
+                        if !errors.is_empty() {
+                            return Err(());
+                        }
                     }
                     Err(_) => return Err(()),
                 }
index 7450b4a4ef1c3f23c0f1554a044f9c6b708df1b4..d19e99606bcd8eec3f0d54d7e921de2ec1e463a9 100644 (file)
@@ -297,9 +297,9 @@ fn primary_body_of(
 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
-    let outer_def_id = tcx.closure_base_def_id(def_id);
-    if outer_def_id != def_id {
-        return tcx.has_typeck_results(outer_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+    if typeck_root_def_id != def_id {
+        return tcx.has_typeck_results(typeck_root_def_id);
     }
 
     if let Some(def_id) = def_id.as_local() {
@@ -348,9 +348,9 @@ fn typeck_with_fallback<'tcx>(
 ) -> &'tcx ty::TypeckResults<'tcx> {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
-    let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
-    if outer_def_id != def_id {
-        return tcx.typeck(outer_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+    if typeck_root_def_id != def_id {
+        return tcx.typeck(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id);
index dd09474533119d90e12108dfc05bfb3f44702a77..9c53a1d4eb68dacc98fba193e2e9efb3963d9f88 100644 (file)
@@ -826,10 +826,7 @@ fn lookup_op_method(
                     self.obligation_for_method(span, trait_did, lhs_ty, Some(other_tys));
                 let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
                 fulfill.register_predicate_obligation(self, obligation);
-                Err(match fulfill.select_where_possible(&self.infcx) {
-                    Err(errors) => errors,
-                    _ => vec![],
-                })
+                Err(fulfill.select_where_possible(&self.infcx))
             }
         }
     }
index 5aa11cce25fb6d5247d38f9757f3bea37c5d6487..cbf33cf1b78a147112c2ad55cd868a845a813eb3 100644 (file)
@@ -292,7 +292,9 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> A
             // String and byte-string literals result in types `&str` and `&[u8]` respectively.
             // All other literals result in non-reference types.
             // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`.
-            PatKind::Lit(lt) => match self.check_expr(lt).kind() {
+            //
+            // Call `resolve_vars_if_possible` here for inline const blocks.
+            PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
                 ty::Ref(..) => AdjustMode::Pass,
                 _ => AdjustMode::Peel,
             },
index 86d4e4d2b115b5857959bd115066bc850a5a8543..d2d8b14dd9695e917bd27d2dc4a08d7683993991 100644 (file)
@@ -341,6 +341,29 @@ fn visit_fn_body(
         self.visit_region_obligations(body_id.hir_id);
     }
 
+    fn visit_inline_const(&mut self, id: hir::HirId, body: &'tcx hir::Body<'tcx>) {
+        debug!("visit_inline_const(id={:?})", id);
+
+        // Save state of current function. We will restore afterwards.
+        let old_body_id = self.body_id;
+        let old_body_owner = self.body_owner;
+        let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child();
+
+        let body_id = body.id();
+        self.body_id = body_id.hir_id;
+        self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
+
+        self.outlives_environment.save_implied_bounds(body_id.hir_id);
+
+        self.visit_body(body);
+        self.visit_region_obligations(body_id.hir_id);
+
+        // Restore state from previous function.
+        self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot);
+        self.body_id = old_body_id;
+        self.body_owner = old_body_owner;
+    }
+
     fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
         debug!("visit_region_obligations: hir_id={:?}", hir_id);
 
@@ -406,13 +429,13 @@ fn visit_fn(
         // `visit_fn_body`.  We will restore afterwards.
         let old_body_id = self.body_id;
         let old_body_owner = self.body_owner;
-        let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
+        let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child();
 
         let body = self.tcx.hir().body(body_id);
         self.visit_fn_body(hir_id, body, span);
 
         // Restore state from previous function.
-        self.outlives_environment.pop_snapshot_post_closure(env_snapshot);
+        self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot);
         self.body_id = old_body_id;
         self.body_owner = old_body_owner;
     }
@@ -460,6 +483,11 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                 intravisit::walk_expr(self, expr);
             }
 
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.tcx.hir().body(anon_const.body);
+                self.visit_inline_const(anon_const.hir_id, body);
+            }
+
             _ => intravisit::walk_expr(self, expr),
         }
     }
index 774d8078e52ca31171213b8070848902040aae07..5f5d308a3329bdf5c7f3c3fe2cbd1e0a445c4f8c 100644 (file)
@@ -148,10 +148,17 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.kind {
-            let body = self.fcx.tcx.hir().body(body_id);
-            self.visit_body(body);
-            self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+        match expr.kind {
+            hir::ExprKind::Closure(cc, _, body_id, _, _) => {
+                let body = self.fcx.tcx.hir().body(body_id);
+                self.visit_body(body);
+                self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+            }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.fcx.tcx.hir().body(anon_const.body);
+                self.visit_body(body);
+            }
+            _ => {}
         }
 
         intravisit::walk_expr(self, expr);
index d951df94dcf50fbb0a2d137feb5ebf182843a782..fdc8b6b5e64519d57642ad6549ec858d880fcc89 100644 (file)
@@ -282,6 +282,12 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::Field(..) => {
                 self.visit_field_id(e.hir_id);
             }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                self.visit_node_id(e.span, anon_const.hir_id);
+
+                let body = self.tcx().hir().body(anon_const.body);
+                self.visit_body(body);
+            }
             _ => {}
         }
 
index 8cae61e8c22f6ffd3708e706de6fbd333d15f96e..372e83592b9c51335fcc04e529071d6684c5b06a 100644 (file)
@@ -180,14 +180,14 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
 
                 let coerced_fields = fields
                     .iter()
-                    .filter_map(|field| {
+                    .filter(|field| {
                         let ty_a = field.ty(tcx, substs_a);
                         let ty_b = field.ty(tcx, substs_b);
 
                         if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
                             if layout.is_zst() && layout.align.abi.bytes() == 1 {
                                 // ignore ZST fields with alignment of 1 byte
-                                return None;
+                                return false;
                             }
                         }
 
@@ -204,11 +204,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                                 ))
                                 .emit();
 
-                                return None;
+                                return false;
                             }
                         }
 
-                        Some(field)
+                        return true;
                     })
                     .collect::<Vec<_>>();
 
@@ -263,7 +263,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                     }
 
                     // Check that all transitive obligations are satisfied.
-                    if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+                    let errors = fulfill_cx.select_all_or_error(&infcx);
+                    if !errors.is_empty() {
                         infcx.report_fulfillment_errors(&errors, None, false);
                     }
 
@@ -522,7 +523,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
         fulfill_cx.register_predicate_obligation(&infcx, predicate);
 
         // Check that all transitive obligations are satisfied.
-        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+        let errors = fulfill_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
             infcx.report_fulfillment_errors(&errors, None, false);
         }
 
index 18e8ed394e81409615a9de263fd05626cb46cac5..2274db76c05fb264be490cb2043398dbf23e575c 100644 (file)
@@ -1494,13 +1494,15 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                     {
                         Some(parent_def_id.to_def_id())
                     }
-
+                    Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
+                        Some(tcx.typeck_root_def_id(def_id))
+                    }
                     _ => None,
                 }
             }
         }
         Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
-            Some(tcx.closure_base_def_id(def_id))
+            Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
             ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
@@ -1692,6 +1694,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
         }));
     }
 
+    // provide junk type parameter defs for const blocks.
+    if let Node::AnonConst(_) = node {
+        let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+        if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
+            params.push(ty::GenericParamDef {
+                index: type_start,
+                name: Symbol::intern("<const_ty>"),
+                def_id,
+                pure_wrt_drop: false,
+                kind: ty::GenericParamDefKind::Type {
+                    has_default: false,
+                    object_lifetime_default: rl::Set1::Empty,
+                    synthetic: None,
+                },
+            });
+        }
+    }
+
     let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
 
     ty::Generics {
index a6ea8abdf3fa6af554918f4a4aeceb51101a1d9d..04a68250ced0cd0a44387b6fa7d3abf868b03351 100644 (file)
@@ -494,7 +494,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
                     if anon_const.hir_id == hir_id =>
                 {
-                    tcx.typeck(def_id).node_type(anon_const.hir_id)
+                    let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                    substs.as_inline_const().ty()
                 }
 
                 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
index 39bcf8999323d7fb7a9a877cda60ee0d4b355bdb..a49eda6572de2cb3cf3248d6a5e317a3ab8ee893 100644 (file)
@@ -88,7 +88,8 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     ),
                 );
 
-                if let Err(errors) = fulfill.select_all_or_error(&infcx) {
+                let errors = fulfill.select_all_or_error(&infcx);
+                if !errors.is_empty() {
                     tracing::debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
                     for error in errors {
                         if error.obligation.predicate == self.predicate {
index f90cfb8849160055ab7fce45bd5f7ddfd4867123..ba0fd12a2755f480568093ea79f6ee7acde5c994 100644 (file)
@@ -157,10 +157,10 @@ fn require_same_types<'tcx>(
             }
         }
 
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => true,
-            Err(errors) => {
-                infcx.report_fulfillment_errors(&errors, None, false);
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => true,
+            errors => {
+                infcx.report_fulfillment_errors(errors, None, false);
                 false
             }
         }
@@ -352,8 +352,9 @@ fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
                 term_id,
                 cause,
             );
-            if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                infcx.report_fulfillment_errors(&err, None, false);
+            let errors = fulfillment_cx.select_all_or_error(&infcx);
+            if !errors.is_empty() {
+                infcx.report_fulfillment_errors(&errors, None, false);
                 error = true;
             }
         });
index 4ab5fe26abe56098cc4210db94e1c804cd90afbc..91727d57ddf4e498364f9c317b42c8b9f3c614b4 100644 (file)
@@ -83,7 +83,8 @@ fn implied_outlives_bounds(
         // variables. Process these constraints.
         let mut fulfill_cx = FulfillmentContext::new();
         fulfill_cx.register_predicate_obligations(self, result.obligations);
-        if fulfill_cx.select_all_or_error(self).is_err() {
+        let errors = fulfill_cx.select_all_or_error(self);
+        if !errors.is_empty() {
             self.tcx.sess.delay_span_bug(
                 span,
                 "implied_outlives_bounds failed to solve obligations from instantiation",
index 4fb2f0c8530d7e983aad7e7dc57c8071d5589f30..03e33a1ff2bc3b77f1223b8056497f8e40763b29 100644 (file)
@@ -313,6 +313,12 @@ pub struct Rc<T: ?Sized> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !marker::Send for Rc<T> {}
+
+// Note that this negative impl isn't strictly necessary for correctness,
+// as `Rc` transitively contains a `Cell`, which is itself `!Sync`.
+// However, given how important `Rc`'s `!Sync`-ness is,
+// having an explicit negative impl is nice for documentation purposes
+// and results in nicer error messages.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
index 7f14f76c8ba6945c052fab77022e6e768b58e0b4..b02ed04a7e915659eea6fb1607df469b84a30638 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7f14f76c8ba6945c052fab77022e6e768b58e0b4
+Subproject commit b02ed04a7e915659eea6fb1607df469b84a30638
index d154bb3583c2d387d0757a0acb0fddc47ddbf63b..06dc5ecf2ffa610a4f93509ad05e348c2a56b984 100644 (file)
@@ -240,6 +240,11 @@ pub struct Cell<T: ?Sized> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
 
+// Note that this negative impl isn't strictly necessary for correctness,
+// as `Cell` wraps `UnsafeCell`, which is itself `!Sync`.
+// However, given how important `Cell`'s `!Sync`-ness is,
+// having an explicit negative impl is nice for documentation purposes
+// and results in nicer error messages.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Sync for Cell<T> {}
 
index d4875cfe1b066e31d74f4d1ed48fc67ace3d26d8..a799732adde9d7d7aafec92619738a5ff54ace15 100644 (file)
@@ -96,7 +96,8 @@ impl Step for RustcDocs {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/librustc")
+        let builder = run.builder;
+        run.path("rustc-docs").default_condition(builder.config.compiler_docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -106,9 +107,6 @@ fn make_run(run: RunConfig<'_>) {
     /// Builds the `rustc-docs` installer component.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
-        if !builder.config.compiler_docs {
-            return None;
-        }
         builder.default_doc(&[]);
 
         let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
index 2804e7119fbc14e8418365082bb879b22861d299..f0f31c447bda43326b5a20642d5cfa09538d2be1 100644 (file)
@@ -529,7 +529,7 @@ impl Step for Rustc {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.krate("rustc-main").path("compiler").default_condition(builder.config.docs)
+        run.krate("rustc-main").path("compiler").default_condition(builder.config.compiler_docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -560,11 +560,6 @@ fn run(self, builder: &Builder<'_>) {
             })
             .collect::<Vec<_>>();
 
-        if !builder.config.compiler_docs && !builder.was_invoked_explicitly::<Self>() {
-            builder.info("\tskipping - compiler/librustdoc docs disabled");
-            return;
-        }
-
         // This is the intended out directory for compiler documentation.
         let out = builder.compiler_doc_out(target);
         t!(fs::create_dir_all(&out));
@@ -674,7 +669,8 @@ impl Step for $tool {
             const ONLY_HOSTS: bool = true;
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-                run.krate($should_run)
+                let builder = run.builder;
+                run.krate($should_run).default_condition(builder.config.compiler_docs)
             }
 
             fn make_run(run: RunConfig<'_>) {
@@ -705,11 +701,6 @@ fn run(self, builder: &Builder<'_>) {
 
                 let compiler = builder.compiler(stage, builder.config.build);
 
-                if !builder.config.compiler_docs && !builder.was_invoked_explicitly::<Self>() {
-                    builder.info("\tskipping - compiler/tool docs disabled");
-                    return;
-                }
-
                 // Build rustc docs so that we generate relative links.
                 builder.ensure(Rustc { stage, target });
 
index 8594fa42266b41306d242f59c65b27fc5ca732d0..22bf6b8a9d4dce99392222a591a10154fb821e7d 100644 (file)
@@ -763,7 +763,7 @@ impl Step for RustdocJSStd {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/test/rustdoc-js-std")
+        run.suite_path("src/test/rustdoc-js-std")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -783,6 +783,17 @@ fn run(self, builder: &Builder<'_>) {
                 .arg(builder.doc_out(self.target))
                 .arg("--test-folder")
                 .arg(builder.src.join("src/test/rustdoc-js-std"));
+            for path in &builder.paths {
+                if let Some(p) =
+                    util::is_valid_test_suite_arg(path, "src/test/rustdoc-js-std", builder)
+                {
+                    if !p.ends_with(".js") {
+                        eprintln!("A non-js file was given: `{}`", path.display());
+                        panic!("Cannot run rustdoc-js-std tests");
+                    }
+                    command.arg("--test-file").arg(path);
+                }
+            }
             builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage });
             builder.run(&mut command);
         } else {
@@ -803,7 +814,7 @@ impl Step for RustdocJSNotStd {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/test/rustdoc-js")
+        run.suite_path("src/test/rustdoc-js")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -938,8 +949,12 @@ fn run(self, builder: &Builder<'_>) {
             .arg("--tests-folder")
             .arg(builder.build.src.join("src/test/rustdoc-gui"));
         for path in &builder.paths {
-            if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
-                if name.ends_with(".goml") {
+            if let Some(p) = util::is_valid_test_suite_arg(path, "src/test/rustdoc-gui", builder) {
+                if !p.ends_with(".goml") {
+                    eprintln!("A non-goml file was given: `{}`", path.display());
+                    panic!("Cannot run rustdoc-gui tests");
+                }
+                if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
                     command.arg("--file").arg(name);
                 }
             }
@@ -1416,35 +1431,7 @@ fn run(self, builder: &Builder<'_>) {
         // Get test-args by striping suite path
         let mut test_args: Vec<&str> = paths
             .iter()
-            .map(|p| match p.strip_prefix(".") {
-                Ok(path) => path,
-                Err(_) => p,
-            })
-            .filter(|p| p.starts_with(suite_path))
-            .filter(|p| {
-                let exists = p.is_dir() || p.is_file();
-                if !exists {
-                    if let Some(p) = p.to_str() {
-                        builder.info(&format!(
-                            "Warning: Skipping \"{}\": not a regular file or directory",
-                            p
-                        ));
-                    }
-                }
-                exists
-            })
-            .filter_map(|p| {
-                // Since test suite paths are themselves directories, if we don't
-                // specify a directory or file, we'll get an empty string here
-                // (the result of the test suite directory without its suite prefix).
-                // Therefore, we need to filter these out, as only the first --test-args
-                // flag is respected, so providing an empty --test-args conflicts with
-                // any following it.
-                match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
-                    Some(s) if !s.is_empty() => Some(s),
-                    _ => None,
-                }
-            })
+            .filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder))
             .collect();
 
         test_args.append(&mut builder.config.cmd.test_args());
index af6f4bb0e5fcba19c98240a9bdbf80cb8dcad5ef..1317c3f9839757432106992f801522b25519fe3c 100644 (file)
@@ -286,7 +286,6 @@ macro_rules! bootstrap_tool {
         $name:ident, $path:expr, $tool_name:expr
         $(,is_external_tool = $external:expr)*
         $(,is_unstable_tool = $unstable:expr)*
-        $(,features = $features:expr)*
         ;
     )+) => {
         #[derive(Copy, PartialEq, Eq, Clone)]
@@ -349,12 +348,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
                     } else {
                         SourceType::InTree
                     },
-                    extra_features: {
-                        // FIXME(#60643): avoid this lint by using `_`
-                        let mut _tmp = Vec::new();
-                        $(_tmp.extend($features);)*
-                        _tmp
-                    },
+                    extra_features: vec![],
                 }).expect("expected to build -- essential tool")
             }
         }
index 112979b0bebc86f54047968bee5c7f37ec5eb8f4..57178aa382ffd789ac68a6fb9b9cf9051aceb7b8 100644 (file)
@@ -310,3 +310,35 @@ pub fn use_host_linker(target: TargetSelection) -> bool {
         || target.contains("fuchsia")
         || target.contains("bpf"))
 }
+
+pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
+    path: &'a Path,
+    suite_path: P,
+    builder: &Builder<'_>,
+) -> Option<&'a str> {
+    let suite_path = suite_path.as_ref();
+    let path = match path.strip_prefix(".") {
+        Ok(p) => p,
+        Err(_) => path,
+    };
+    if !path.starts_with(suite_path) {
+        return None;
+    }
+    let exists = path.is_dir() || path.is_file();
+    if !exists {
+        if let Some(p) = path.to_str() {
+            builder.info(&format!("Warning: Skipping \"{}\": not a regular file or directory", p));
+        }
+        return None;
+    }
+    // Since test suite paths are themselves directories, if we don't
+    // specify a directory or file, we'll get an empty string here
+    // (the result of the test suite directory without its suite prefix).
+    // Therefore, we need to filter these out, as only the first --test-args
+    // flag is respected, so providing an empty --test-args conflicts with
+    // any following it.
+    match path.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
+        Some(s) if !s.is_empty() => Some(s),
+        _ => None,
+    }
+}
diff --git a/src/doc/unstable-book/src/language-features/type-changing-struct-update.md b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md
new file mode 100644 (file)
index 0000000..9909cf3
--- /dev/null
@@ -0,0 +1,33 @@
+# `type_changing_struct_update`
+
+The tracking issue for this feature is: [#86555]
+
+[#86555]: https://github.com/rust-lang/rust/issues/86555
+
+------------------------
+
+This implements [RFC2528]. When turned on, you can create instances of the same struct
+that have different generic type or lifetime parameters.
+
+[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md
+
+```rust
+#![allow(unused_variables, dead_code)]
+#![feature(type_changing_struct_update)]
+
+fn main () {
+    struct Foo<T, U> {
+        field1: T,
+        field2: U,
+    }
+
+    let base: Foo<String, i32> = Foo {
+        field1: String::from("hello"),
+        field2: 1234,
+    };
+    let updated: Foo<f64, i32> = Foo {
+        field1: 3.14,
+        ..base
+    };
+}
+```
index 9d893f3d06d51978f3f3c05541253224f949da1f..3db0ef17fd81064aa52efd07d4a2ea656a4e3d1d 100644 (file)
@@ -190,7 +190,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
             | rl::Region::Free(_, node_id),
         ) = def
         {
-            if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
+            if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
                 return lt;
             }
         }
@@ -1120,7 +1120,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
 }
 
 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
-    use rustc_hir::GenericParamCount;
     let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let qpath = match kind {
         hir::TyKind::Path(qpath) => qpath,
@@ -1130,7 +1129,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     match qpath {
         hir::QPath::Resolved(None, ref path) => {
             if let Res::Def(DefKind::TyParam, did) = path.res {
-                if let Some(new_ty) = cx.ty_substs.get(&did).cloned() {
+                if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
                     return new_ty;
                 }
                 if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
@@ -1138,97 +1137,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 }
             }
 
-            let mut alias = None;
-            if let Res::Def(DefKind::TyAlias, def_id) = path.res {
-                // Substitute private type aliases
-                if let Some(def_id) = def_id.as_local() {
-                    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
-                    if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
-                        alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
-                    }
-                }
-            };
-
-            if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
-                let provided_params = &path.segments.last().expect("segments were empty");
-                let mut ty_substs = FxHashMap::default();
-                let mut lt_substs = FxHashMap::default();
-                let mut ct_substs = FxHashMap::default();
-                let generic_args = provided_params.args();
-                {
-                    let mut indices: GenericParamCount = Default::default();
-                    for param in generics.params.iter() {
-                        match param.kind {
-                            hir::GenericParamKind::Lifetime { .. } => {
-                                let mut j = 0;
-                                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Lifetime(lt) => {
-                                        if indices.lifetimes == j {
-                                            return Some(lt);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(lt) = lifetime.cloned() {
-                                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                    let cleaned = if !lt.is_elided() {
-                                        lt.clean(cx)
-                                    } else {
-                                        self::types::Lifetime::elided()
-                                    };
-                                    lt_substs.insert(lt_def_id.to_def_id(), cleaned);
-                                }
-                                indices.lifetimes += 1;
-                            }
-                            hir::GenericParamKind::Type { ref default, .. } => {
-                                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                let mut j = 0;
-                                let type_ = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Type(ty) => {
-                                        if indices.types == j {
-                                            return Some(ty);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(ty) = type_ {
-                                    ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
-                                } else if let Some(default) = *default {
-                                    ty_substs
-                                        .insert(ty_param_def_id.to_def_id(), default.clean(cx));
-                                }
-                                indices.types += 1;
-                            }
-                            hir::GenericParamKind::Const { .. } => {
-                                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                let mut j = 0;
-                                let const_ = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Const(ct) => {
-                                        if indices.consts == j {
-                                            return Some(ct);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(ct) = const_ {
-                                    ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
-                                }
-                                // FIXME(const_generics_defaults)
-                                indices.consts += 1;
-                            }
-                        }
-                    }
-                }
-                return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
+            if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
+                expanded
+            } else {
+                let path = path.clean(cx);
+                resolve_type(cx, path)
             }
-            let path = path.clean(cx);
-            resolve_type(cx, path)
         }
         hir::QPath::Resolved(Some(ref qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
@@ -1272,6 +1186,94 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     }
 }
 
+fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
+    let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
+    // Substitute private type aliases
+    let Some(def_id) = def_id.as_local() else { return None };
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+    let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
+        &cx.tcx.hir().expect_item(hir_id).kind
+    } else {
+        return None;
+    };
+    let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
+
+    let provided_params = &path.segments.last().expect("segments were empty");
+    let mut substs = FxHashMap::default();
+    let generic_args = provided_params.args();
+
+    let mut indices: hir::GenericParamCount = Default::default();
+    for param in generics.params.iter() {
+        match param.kind {
+            hir::GenericParamKind::Lifetime { .. } => {
+                let mut j = 0;
+                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) => {
+                        if indices.lifetimes == j {
+                            return Some(lt);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(lt) = lifetime.cloned() {
+                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                    let cleaned = if !lt.is_elided() {
+                        lt.clean(cx)
+                    } else {
+                        self::types::Lifetime::elided()
+                    };
+                    substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
+                }
+                indices.lifetimes += 1;
+            }
+            hir::GenericParamKind::Type { ref default, .. } => {
+                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                let mut j = 0;
+                let type_ = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Type(ty) => {
+                        if indices.types == j {
+                            return Some(ty);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(ty) = type_ {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx)));
+                } else if let Some(default) = *default {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(default.clean(cx)));
+                }
+                indices.types += 1;
+            }
+            hir::GenericParamKind::Const { .. } => {
+                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                let mut j = 0;
+                let const_ = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Const(ct) => {
+                        if indices.consts == j {
+                            return Some(ct);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(ct) = const_ {
+                    substs
+                        .insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx)));
+                }
+                // FIXME(const_generics_defaults)
+                indices.consts += 1;
+            }
+        }
+    }
+
+    Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
+}
+
 impl Clean<Type> for hir::Ty<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         use rustc_hir::*;
index 0dc1c24b16e195c6a03743bc1ce07535ec6d1558..fd4d620c9591e12ab03359b7e5fe6c0177abd807 100644 (file)
@@ -2279,3 +2279,32 @@ impl TypeBinding {
         }
     }
 }
+
+/// The type, lifetime, or constant that a private type alias's parameter should be
+/// replaced with when expanding a use of that type alias.
+///
+/// For example:
+///
+/// ```
+/// type PrivAlias<T> = Vec<T>;
+///
+/// pub fn public_fn() -> PrivAlias<i32> { vec![] }
+/// ```
+///
+/// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
+/// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
+crate enum SubstParam {
+    Type(Type),
+    Lifetime(Lifetime),
+    Constant(Constant),
+}
+
+impl SubstParam {
+    crate fn as_ty(&self) -> Option<&Type> {
+        if let Self::Type(ty) = self { Some(ty) } else { None }
+    }
+
+    crate fn as_lt(&self) -> Option<&Lifetime> {
+        if let Self::Lifetime(lt) = self { Some(lt) } else { None }
+    }
+}
index 2fae3163a1a1a4f19509091f6520929e04bf98f0..2fa7efcc6509b143e69b5192d06cf4bf8d507669 100644 (file)
@@ -430,8 +430,9 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
         | Res::NonMacroAttr(_)
         | Res::Err => return res.def_id(),
         Res::Def(
-            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy
-            | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator,
+            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst
+            | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure
+            | Generator,
             id,
         ) => return id,
     };
index b7251e8f57151cb3024ee2a40b77c2bb7dee9678..92278179a51c96ade994997c336d3e34a811179f 100644 (file)
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     crate active_extern_traits: FxHashSet<DefId>,
-    // The current set of type and lifetime substitutions,
+    // The current set of parameter substitutions,
     // for expanding type aliases at the HIR level:
-    /// Table `DefId` of type parameter -> substituted type
-    crate ty_substs: FxHashMap<DefId, clean::Type>,
-    /// Table `DefId` of lifetime parameter -> substituted lifetime
-    crate lt_substs: FxHashMap<DefId, clean::Lifetime>,
-    /// Table `DefId` of const parameter -> substituted const
-    crate ct_substs: FxHashMap<DefId, clean::Constant>,
+    /// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
+    crate substs: FxHashMap<DefId, clean::SubstParam>,
     /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
     crate impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
     /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -104,25 +100,13 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Call the closure with the given parameters set as
     /// the substitutions for a type alias' RHS.
-    crate fn enter_alias<F, R>(
-        &mut self,
-        ty_substs: FxHashMap<DefId, clean::Type>,
-        lt_substs: FxHashMap<DefId, clean::Lifetime>,
-        ct_substs: FxHashMap<DefId, clean::Constant>,
-        f: F,
-    ) -> R
+    crate fn enter_alias<F, R>(&mut self, substs: FxHashMap<DefId, clean::SubstParam>, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
     {
-        let (old_tys, old_lts, old_cts) = (
-            mem::replace(&mut self.ty_substs, ty_substs),
-            mem::replace(&mut self.lt_substs, lt_substs),
-            mem::replace(&mut self.ct_substs, ct_substs),
-        );
+        let old_substs = mem::replace(&mut self.substs, substs);
         let r = f(self);
-        self.ty_substs = old_tys;
-        self.lt_substs = old_lts;
-        self.ct_substs = old_cts;
+        self.substs = old_substs;
         r
     }
 
@@ -281,9 +265,9 @@ impl<'tcx> DocContext<'tcx> {
                 // Closures' tables come from their outermost function,
                 // as they are part of the same "inference environment".
                 // This avoids emitting errors for the parent twice (see similar code in `typeck_with_fallback`)
-                let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
-                if outer_def_id != def_id {
-                    return tcx.typeck(outer_def_id);
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+                if typeck_root_def_id != def_id {
+                    return tcx.typeck(typeck_root_def_id);
                 }
 
                 let hir = tcx.hir();
@@ -350,9 +334,7 @@ impl<'tcx> DocContext<'tcx> {
         param_env: ParamEnv::empty(),
         external_traits: Default::default(),
         active_extern_traits: Default::default(),
-        ty_substs: Default::default(),
-        lt_substs: Default::default(),
-        ct_substs: Default::default(),
+        substs: Default::default(),
         impl_trait_bounds: Default::default(),
         generated_synthetics: Default::default(),
         auto_traits: tcx
@@ -486,11 +468,13 @@ fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
         };
         if run {
             debug!("running pass {}", p.pass.name);
-            krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt));
+            krate = tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt));
         }
     }
 
-    ctxt.sess().abort_if_errors();
+    if tcx.sess.diagnostic().has_errors_or_lint_errors() {
+        rustc_errors::FatalError.raise();
+    }
 
     let render_options = ctxt.render_options;
     let mut cache = ctxt.cache;
index 9b32ad979e385572cdd3878cdae54ff712b1b811..c10eebf49fc8d657af5b333fcccf83af486d678d 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{ColorConfig, ErrorReported};
+use rustc_errors::{ColorConfig, ErrorReported, FatalError};
 use rustc_hir as hir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit;
 
                 collector
             });
-            compiler.session().abort_if_errors();
+            if compiler.session().diagnostic().has_errors_or_lint_errors() {
+                FatalError.raise();
+            }
 
             let unused_extern_reports = collector.unused_extern_reports.clone();
             let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst);
index 793db16faf38517dd5954e98b1bfaab9804bf425..3979d29b673fd3bd37a8fc6865b6b0ee3e46bcb0 100644 (file)
@@ -134,6 +134,7 @@ fn from(other: DefKind) -> Self {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::OpaqueTy
             | DefKind::Field
             | DefKind::LifetimeParam
index 7eeb9d1fcaa55114b3b08c06320aa8345dd0e5fd..fb252a9c73934b1d243008634dc1caf02da0c047 100644 (file)
@@ -9,6 +9,7 @@
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
 #![feature(in_band_lifetimes)]
+#![feature(let_else)]
 #![feature(nll)]
 #![feature(test)]
 #![feature(crate_visibility_modifier)]
@@ -775,7 +776,7 @@ fn main_options(options: config::Options) -> MainResult {
             // current architecture.
             let resolver = core::create_resolver(queries, sess);
 
-            if sess.has_errors() {
+            if sess.diagnostic().has_errors_or_lint_errors() {
                 sess.fatal("Compilation failed, aborting rustdoc");
             }
 
index 8541e6e18816f5c783800fbe23be99e5780cc1fc..4e5812d7f8429e38a5a5f11042f5912b0a5ee0a4 100644 (file)
@@ -1937,7 +1937,8 @@ fn split(path: &str) -> Option<(&str, &str)> {
                             | Use
                             | LifetimeParam
                             | Ctor(_, _)
-                            | AnonConst => {
+                            | AnonConst
+                            | InlineConst => {
                                 let note = assoc_item_not_allowed(res);
                                 if let Some(span) = sp {
                                     diag.span_label(span, &note);
index f4be3c1c63a84e5d8fda7b09ff7cf076ed3bebe6..84eda08d203bfcacfe288766a7c38bc13888e9ef 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     {
         ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"],
                                                          &match () {
-                                                              () => [],
+                                                              _args => [],
                                                           }));
     };
 }
index 199aee05622beed636c3966d6a00f091fae86cdd..529daab903887de6122e0cbb8eb4b0cb096d0f5b 100644 (file)
@@ -45,7 +45,7 @@ pub fn bar() ({
                                                                                                                                                                      as
                                                                                                                                                                      ())
                                                                                                                                                                {
-                                                                                                                                                               ()
+                                                                                                                                                               _args
                                                                                                                                                                =>
                                                                                                                                                                ([]
                                                                                                                                                                    as
diff --git a/src/test/rustdoc/include_str_cut.rs b/src/test/rustdoc/include_str_cut.rs
new file mode 100644 (file)
index 0000000..cbc1ba8
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![no_std]
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="docblock"]' 'inc2 x'
+#[doc = include_str!("short-line.md")]
+pub fn foo() {}
diff --git a/src/test/rustdoc/short-line.md b/src/test/rustdoc/short-line.md
new file mode 100644 (file)
index 0000000..eff713b
--- /dev/null
@@ -0,0 +1,2 @@
+inc2
+x
index f92bcd213b844a272914c36cf2ceea10bb58ab0f..0d04eb6fcfa968be6ad6f942561531619a719bda 100644 (file)
 //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 #![deny(clippy_group)]
 //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
@@ -30,6 +32,7 @@ fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
 //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
 fn hello() {
     fn lintmetoo() { }
index 2260477a91d39a642d9d83e053c76dbf9bf4c0b5..0f76384ed5ba5001d6325ea8407e1322a53e7222 100644 (file)
@@ -7,19 +7,19 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    = note: `#[warn(renamed_and_removed_lints)]` on by default
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
 warning: unknown lint: `this_lint_does_not_exist`
-  --> $DIR/lint-tool-test.rs:33:8
+  --> $DIR/lint-tool-test.rs:36:8
    |
 LL | #[deny(this_lint_does_not_exist)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,13 +33,13 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
@@ -59,42 +59,60 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 error: item is named 'lintme'
-  --> $DIR/lint-tool-test.rs:18:1
+  --> $DIR/lint-tool-test.rs:20:1
    |
 LL | fn lintme() { }
    | ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]`
 
 error: item is named 'lintmetoo'
-  --> $DIR/lint-tool-test.rs:26:5
+  --> $DIR/lint-tool-test.rs:28:5
    |
 LL |     fn lintmetoo() { }
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
-error: aborting due to 2 previous errors; 11 warnings emitted
+warning: lint name `test_lint` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:9:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:14:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:31:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
+error: aborting due to 2 previous errors; 14 warnings emitted
 
index ef59381f5f26dba34697ef81249380f21f2632e7..e59216fe902704879d0eed6b815942532b9ed004 100644 (file)
@@ -19,8 +19,8 @@ error: unexpected token: `{
     let res =
         ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
                                                             &match (&"u8",) {
-                                                                 (arg0,) =>
-                                                                 [::core::fmt::ArgumentV1::new(arg0,
+                                                                 _args =>
+                                                                 [::core::fmt::ArgumentV1::new(_args.0,
                                                                                                ::core::fmt::Display::fmt)],
                                                              }));
     res
index 36d6450c9a2f0ceb45e23cf0fa4599f3019e9bf2..ee394d64a1dc945d5c072cf2e64f7766771cf292 100644 (file)
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
+                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
index 91926f233d394d83762aa3472334b10838e306c0..11b9fa7e40caa67f2d1a337f727b8c84a8dc60d4 100644 (file)
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
+                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
index 6268a564b06b65dafeccf91f5a895788ddf3ba7c..87e4ad500404439b6fa4c585653f292c0fee2d7c 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
    |                    ^^^^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index 35e42a6857f320cfa429c639e4ae9d6069f538d2..9bde2ca1942e64c09a188bc4d2a58f835ffaa762 100644 (file)
@@ -278,6 +278,7 @@ fn test() {
         let _ = nested::DeprecatedStruct {
             //~^ ERROR use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
             i: 0 //~ ERROR use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text
+            //~| ERROR field `i` of struct `this_crate::nested::DeprecatedStruct` is private
         };
 
         let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
index 20af4f62e6502cc78af28a3b2bf97afcd8878bd6..5d716fa625e5d47793dd0a2e878be4296b3a627f 100644 (file)
@@ -257,97 +257,97 @@ LL |         let _ = nested::DeprecatedStruct {
    |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:283:25
+  --> $DIR/deprecation-lint.rs:284:25
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
    |                         ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:285:31
+  --> $DIR/deprecation-lint.rs:286:31
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
    |                             ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:287:25
+  --> $DIR/deprecation-lint.rs:288:25
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:292:16
+  --> $DIR/deprecation-lint.rs:293:16
    |
 LL |         Trait::trait_deprecated(&foo);
    |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:294:25
+  --> $DIR/deprecation-lint.rs:295:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:296:16
+  --> $DIR/deprecation-lint.rs:297:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:298:25
+  --> $DIR/deprecation-lint.rs:299:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
-  --> $DIR/deprecation-lint.rs:316:13
+  --> $DIR/deprecation-lint.rs:317:13
    |
 LL |             bar();
    |             ^^^
 
 error: use of deprecated trait `this_crate::DeprecatedTrait`: text
-  --> $DIR/deprecation-lint.rs:335:10
+  --> $DIR/deprecation-lint.rs:336:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
 error: use of deprecated trait `this_crate::DeprecatedTrait`: text
-  --> $DIR/deprecation-lint.rs:337:24
+  --> $DIR/deprecation-lint.rs:338:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:389:17
+  --> $DIR/deprecation-lint.rs:390:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:398:13
+  --> $DIR/deprecation-lint.rs:399:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:404:13
+  --> $DIR/deprecation-lint.rs:405:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:409:17
+  --> $DIR/deprecation-lint.rs:410:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:419:13
+  --> $DIR/deprecation-lint.rs:420:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:428:13
+  --> $DIR/deprecation-lint.rs:429:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
@@ -617,124 +617,131 @@ LL |             i: 0
    |             ^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:291:13
+  --> $DIR/deprecation-lint.rs:292:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:293:16
+  --> $DIR/deprecation-lint.rs:294:16
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:295:13
+  --> $DIR/deprecation-lint.rs:296:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:297:16
+  --> $DIR/deprecation-lint.rs:298:16
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:302:13
+  --> $DIR/deprecation-lint.rs:303:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:303:13
+  --> $DIR/deprecation-lint.rs:304:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:362:13
+  --> $DIR/deprecation-lint.rs:363:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:366:17
+  --> $DIR/deprecation-lint.rs:367:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:370:13
+  --> $DIR/deprecation-lint.rs:371:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable2::2`: text
-  --> $DIR/deprecation-lint.rs:378:17
+  --> $DIR/deprecation-lint.rs:379:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Stable2::2`: text
-  --> $DIR/deprecation-lint.rs:383:20
+  --> $DIR/deprecation-lint.rs:384:20
    |
 LL |                    _)
    |                    ^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:391:13
+  --> $DIR/deprecation-lint.rs:392:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:395:17
+  --> $DIR/deprecation-lint.rs:396:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:400:13
+  --> $DIR/deprecation-lint.rs:401:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::0`: text
-  --> $DIR/deprecation-lint.rs:412:17
+  --> $DIR/deprecation-lint.rs:413:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::1`: text
-  --> $DIR/deprecation-lint.rs:414:17
+  --> $DIR/deprecation-lint.rs:415:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::2`: text
-  --> $DIR/deprecation-lint.rs:416:17
+  --> $DIR/deprecation-lint.rs:417:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::0`: text
-  --> $DIR/deprecation-lint.rs:421:14
+  --> $DIR/deprecation-lint.rs:422:14
    |
 LL |             (_,
    |              ^
 
 error: use of deprecated field `this_crate2::Deprecated2::1`: text
-  --> $DIR/deprecation-lint.rs:423:14
+  --> $DIR/deprecation-lint.rs:424:14
    |
 LL |              _,
    |              ^
 
 error: use of deprecated field `this_crate2::Deprecated2::2`: text
-  --> $DIR/deprecation-lint.rs:425:14
+  --> $DIR/deprecation-lint.rs:426:14
    |
 LL |              _)
    |              ^
 
-error: aborting due to 122 previous errors
+error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private
+  --> $DIR/deprecation-lint.rs:280:13
+   |
+LL |             i: 0
+   |             ^^^^ private field
+
+error: aborting due to 123 previous errors
 
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs b/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs
deleted file mode 100644 (file)
index 520c147..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#[derive(Debug)]
-struct Machine<S> {
-    state: S,
-    common_field1: &'static str,
-    common_field2: i32,
-}
-#[derive(Debug)]
-struct State1;
-#[derive(Debug, PartialEq)]
-struct State2;
-
-fn update_to_state2() {
-    let m1: Machine<State1> = Machine {
-        state: State1,
-        common_field1: "hello",
-        common_field2: 2,
-    };
-    let m2: Machine<State2> = Machine {
-        state: State2,
-        ..m1 //~ ERROR mismatched types
-    };
-    // FIXME: this should trigger feature gate
-    assert_eq!(State2, m2.state);
-}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr b/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr
deleted file mode 100644 (file)
index 9934fe6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_changing_struct_update.rs:20:11
-   |
-LL |         ..m1
-   |           ^^ expected struct `State2`, found struct `State1`
-   |
-   = note: expected struct `Machine<State2>`
-              found struct `Machine<State1>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs
new file mode 100644 (file)
index 0000000..e397390
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait A<'a> {
+    type B<'b>: Clone
+    // FIXME(generic_associated_types): Remove one of the below bounds
+    // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085
+    where
+        'a: 'b, Self: 'a, Self: 'b;
+
+    fn a(&'a self) -> Self::B<'a>;
+}
+
+struct C;
+
+impl<'a> A<'a> for C {
+    type B<'b> = impl Clone;
+    //~^ ERROR: lifetime bound not satisfied
+    //~| ERROR: could not find defining uses
+
+    fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
+}
diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr
new file mode 100644 (file)
index 0000000..1948f82
--- /dev/null
@@ -0,0 +1,40 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-88595.rs:19:5
+   |
+LL |     type B<'b> = impl Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+note: but lifetime parameter must outlive the lifetime `'b` as defined here
+  --> $DIR/issue-88595.rs:19:12
+   |
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-88595.rs:23:23
+   |
+LL |     fn a(&'a self) -> Self::B<'a> {}
+   |                       ^^^^^^^^^^^
+   |
+note: lifetime used multiple times
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: could not find defining uses
+  --> $DIR/issue-88595.rs:19:18
+   |
+LL |     type B<'b> = impl Clone;
+   |                  ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/generic-associated-types/issue-90014.rs b/src/test/ui/generic-associated-types/issue-90014.rs
new file mode 100644 (file)
index 0000000..f110b06
--- /dev/null
@@ -0,0 +1,22 @@
+// edition:2018
+
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+use std::future::Future;
+
+trait MakeFut {
+    type Fut<'a> where Self: 'a;
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a>;
+}
+
+impl MakeFut for &'_ mut () {
+    type Fut<'a> = impl Future<Output = ()>;
+    //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime
+
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
+        async { () }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr
new file mode 100644 (file)
index 0000000..125d817
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0477]: the type `&mut ()` does not fulfill the required lifetime
+  --> $DIR/issue-90014.rs:14:5
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: type must outlive the lifetime `'a` as defined here
+  --> $DIR/issue-90014.rs:14:14
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
index 6adc4e6b23968ed57e04443005c220aed915727d..a25c85faf4e352c86d5ef7584fbbb81899aaa999 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     foo::<str>("".to_string());
    |           ^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index 6800b37b5b175aaaee409116c67c9acefa9a4848..90c252537ef82b1b72f94e5fbc0a3fa3f3f9ec05 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     foo::<String>('a');
    |           ^^^^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index db66d461095993f8fb9f5b3ad9a5c711dcadb30f..84b98f71f4f0caefea1347220c2dec8ea761d96b 100644 (file)
@@ -5,6 +5,9 @@ LL |     evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
    |                        ^^^^^^^^^  ^^^^^^^^^^^^^ explicit generic argument not allowed
    |                        |
    |                        explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index 4605e76ac96d28a44cb50f3563daee0b2be0d873..35fb42d6213226918f687979944f6812db7d6278 100644 (file)
@@ -235,6 +235,7 @@ impl <T = impl Debug> T {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
 //~| ERROR `impl Trait` not allowed outside of function and method return types
+//~| ERROR no nominal type found
 
 // Disallowed
 fn in_method_generic_param_default<T = impl Debug>(_: T) {}
index 7f11d30dbaa5faafe272cfcbf75da31e42a04b37..236cf449e85fa5050893e64709a4a507ec310fc0 100644 (file)
@@ -272,19 +272,19 @@ LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:240:40
+  --> $DIR/where-allowed.rs:241:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:246:29
+  --> $DIR/where-allowed.rs:247:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:248:46
+  --> $DIR/where-allowed.rs:249:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
@@ -300,7 +300,7 @@ LL | impl <T = impl Debug> T {}
    = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:240:36
+  --> $DIR/where-allowed.rs:241:36
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                    ^
@@ -308,7 +308,15 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
 
-error: aborting due to 48 previous errors
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/where-allowed.rs:234:23
+   |
+LL | impl <T = impl Debug> T {}
+   |                       ^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to 49 previous errors
 
-Some errors have detailed explanations: E0562, E0658, E0666.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0118, E0562, E0658, E0666.
+For more information about an error, try `rustc --explain E0118`.
diff --git a/src/test/ui/inline-const/const-expr-inference.rs b/src/test/ui/inline-const/const-expr-inference.rs
new file mode 100644 (file)
index 0000000..6aa2a2f
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+
+pub fn todo<T>() -> T {
+    const { todo!() }
+}
+
+fn main() {
+    let _: usize = const { 0 };
+}
diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.rs b/src/test/ui/inline-const/const-expr-lifetime-err.rs
new file mode 100644 (file)
index 0000000..e56cbc9
--- /dev/null
@@ -0,0 +1,30 @@
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+}
+
+fn equate<T>(x: T, y: T){}
+
+fn foo<'a>() {
+    let y = ();
+    equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
+    //~^ ERROR `y` does not live long enough [E0597]
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.stderr b/src/test/ui/inline-const/const-expr-lifetime-err.stderr
new file mode 100644 (file)
index 0000000..30ecd33
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/const-expr-lifetime-err.rs:24:30
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let y = ();
+LL |     equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
+   |            ------------------^^-
+   |            |                 |
+   |            |                 borrowed value does not live long enough
+   |            argument requires that `y` is borrowed for `'a`
+LL |
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/inline-const/const-expr-lifetime.rs b/src/test/ui/inline-const/const-expr-lifetime.rs
new file mode 100644 (file)
index 0000000..f622f2c
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
+fn issue_78174() {
+    let foo = const { "foo" };
+    assert_eq!(foo, "foo");
+}
+
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+fn get_invariant_ref<'a>() -> InvariantRef<'a, ()> {
+    const { InvariantRef::<'a, ()>::new(&()) }
+}
+
+fn get_invariant_ref2<'a>() -> InvariantRef<'a, ()> {
+    // Try some type inference
+    const { InvariantRef::new(&()) }
+}
+
+fn main() {
+    issue_78174();
+    get_invariant_ref();
+    get_invariant_ref2();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-inference.rs b/src/test/ui/inline-const/const-match-pat-inference.rs
new file mode 100644 (file)
index 0000000..61188ed
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+
+fn main() {
+    match 1u64 {
+        0 => (),
+        const { 0 + 1 } => (),
+        const { 2 - 1 } ..= const { u64::MAX } => (),
+    }
+}
diff --git a/src/test/ui/inline-const/const-match-pat-lifetime-err.rs b/src/test/ui/inline-const/const-match-pat-lifetime-err.rs
new file mode 100644 (file)
index 0000000..bc5aa24
--- /dev/null
@@ -0,0 +1,34 @@
+// ignore-test
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+}
+
+fn match_invariant_ref<'a>() {
+    let y = ();
+    match InvariantRef::new(&y) {
+    //~^ ERROR `y` does not live long enough [E0597]
+        // FIXME(nbdd0121): This should give the same error as `InvariantRef::<'a>::NEW` (without
+        // const block)
+        const { InvariantRef::<'a>::NEW } => (),
+    }
+}
+
+fn main() {
+    match_invariant_ref();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-lifetime.rs b/src/test/ui/inline-const/const-match-pat-lifetime.rs
new file mode 100644 (file)
index 0000000..3d986f0
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
+fn issue_78174() {
+    match "foo" {
+        const { concat!("fo", "o") } => (),
+        _ => unreachable!(),
+    }
+}
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+fn match_invariant_ref<'a>() {
+    match const { InvariantRef::<'a, _>::new(&()) } {
+        const { InvariantRef::<'a, ()>::new(&()) } => {
+        }
+    }
+}
+
+fn main() {
+    issue_78174();
+    match_invariant_ref();
+}
index 5a27ea8783a2f3b149f23057929ff84c75b8d8cc..6007eba8c0906a2f9307ee7887ad7cbaab0f3e90 100644 (file)
@@ -15,6 +15,7 @@ mod rusti {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
index bf2794eb632b6281358710aa53b372a0ac762481..7b16fa024f8e44122040c497c86e44b921d76ea7 100644 (file)
@@ -5,6 +5,7 @@
 pub unsafe fn g() {
     return;
     if *ptr::null() {}; //~ ERROR unreachable
+    //~| WARNING dereferencing a null pointer
 }
 
 pub fn main() {}
index bb0221ecb86b448342489a288294386ebd84008f..a9bf2bf763d575b09f91b88f3bd30b0ff026a6b7 100644 (file)
@@ -12,5 +12,13 @@ note: the lint level is defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: dereferencing a null pointer
+  --> $DIR/issue-7246.rs:7:8
+   |
+LL |     if *ptr::null() {};
+   |        ^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: `#[warn(deref_nullptr)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
 
index 38c5487183ca1bfa494fdf22ba7e96bebeea0d68..d9673faa2142e4c5a226143f38a3308f67475ee1 100644 (file)
@@ -4,10 +4,12 @@ mod foo {
 #![allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 
 #[allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 const BAR: f64 = 0.000001;
 
 }
@@ -15,5 +17,6 @@ mod foo {
 #[allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 fn main() {
 }
index 83bea0412ffd52e794962ff65be131f61c820bfe..8fb06df2a481a68297e4b9ff65639fdd632f09e7 100644 (file)
@@ -11,13 +11,13 @@ LL | #![deny(uncommon_codepoints, unused_attributes)]
    |                              ^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:8:9
+  --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:15:9
+  --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
@@ -29,16 +29,34 @@ LL | #![allow(uncommon_codepoints)]
    |          ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:8:9
+  --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:15:9
+  --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:4:10
+   |
+LL | #![allow(uncommon_codepoints)]
+   |          ^^^^^^^^^^^^^^^^^^^
+
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:9:9
+   |
+LL | #[allow(uncommon_codepoints)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:17:9
+   |
+LL | #[allow(uncommon_codepoints)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
index 7d8a398181493b16e1edebef0a3e2739985a38bb..b12fd72da74946bc5355159eb03887cf8ae4339b 100644 (file)
 //~| WARNING previously accepted by the compiler
 //~| ERROR incompatible with previous
 //~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
 fn main() {}
index d8c09e6526a2d6f340b6114792230a7556670730..214e949c11a748990d8b906b48c2b82414d1f3a4 100644 (file)
@@ -75,5 +75,41 @@ LL | #[allow(nonstandard_style)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
-error: aborting due to 6 previous errors
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: aborting due to 9 previous errors
 
index b08fbf6f845f88d2b30656db5b132104e9e0c3cd..3ee55ba96b1378746cd26726d543a88b08108b40 100644 (file)
@@ -13,4 +13,5 @@ macro_rules! evil {
 
 fn main() {
     println!("{}", evil!(*(0 as *const u8)));
+    //~^ WARNING dereferencing a null pointer
 }
index e31c003985ed8e606082245760b56fd0a07650a7..ba425ceb442b216c988b165e2f5e8755651cffcc 100644 (file)
@@ -10,5 +10,13 @@ note: the lint level is defined here
 LL | #![forbid(unsafe_code)]
    |           ^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: dereferencing a null pointer
+  --> $DIR/lint-forbid-internal-unsafe.rs:15:26
+   |
+LL |     println!("{}", evil!(*(0 as *const u8)));
+   |                          ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: `#[warn(deref_nullptr)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
 
index 81a3427a10274b223cd68fe389c6bd2c74696821..ed8e7ddddc5977f370f343b0555b534727db2e18 100644 (file)
@@ -1,6 +1,7 @@
 #![deny(uncommon_codepoints)]
 
 const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints
+//~| WARNING should have an upper case name
 
 fn dijkstra() {} //~ ERROR identifier contains uncommon Unicode codepoints
 
index d435282a6e855cca8c9b571bb9d59113da71e33d..0533da03068ae040d1802b1f8a0d4f6b64ad88dc 100644 (file)
@@ -11,16 +11,24 @@ LL | #![deny(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: identifier contains uncommon Unicode codepoints
-  --> $DIR/lint-uncommon-codepoints.rs:5:4
+  --> $DIR/lint-uncommon-codepoints.rs:6:4
    |
 LL | fn dijkstra() {}
    |    ^^^^^^^
 
 error: identifier contains uncommon Unicode codepoints
-  --> $DIR/lint-uncommon-codepoints.rs:8:9
+  --> $DIR/lint-uncommon-codepoints.rs:9:9
    |
 LL |     let ㇻㇲㇳ = "rust";
    |         ^^^^^^
 
-error: aborting due to 3 previous errors
+warning: constant `µ` should have an upper case name
+  --> $DIR/lint-uncommon-codepoints.rs:3:7
+   |
+LL | const µ: f64 = 0.000001;
+   |       ^ help: convert the identifier to upper case: `Μ`
+   |
+   = note: `#[warn(non_upper_case_globals)]` on by default
+
+error: aborting due to 3 previous errors; 1 warning emitted
 
index f53bcb97e69723ad748e710a63deae7916f00876..e8e477ea4f6849aec68d7c03fc9ba2085393a8cb 100644 (file)
@@ -7,6 +7,7 @@
 fn a() {
     // the cast is unreachable:
     let x = {return} as !; //~ ERROR unreachable
+    //~| ERROR non-primitive cast
 }
 
 fn main() { }
index 3aa15bde9956b57bcb1fbf3a9e2e6239b7537264..6643f1784a1744916b10721961130ab320fdc881 100644 (file)
@@ -13,5 +13,12 @@ note: the lint level is defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0605]: non-primitive cast: `()` as `!`
+  --> $DIR/expr_cast.rs:9:13
+   |
+LL |     let x = {return} as !;
+   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs
new file mode 100644 (file)
index 0000000..1e8b99b
--- /dev/null
@@ -0,0 +1,29 @@
+// gate-test-type_changing_struct_update
+
+#[derive(Debug)]
+struct Machine<S> {
+    state: S,
+    common_field1: &'static str,
+    common_field2: i32,
+}
+#[derive(Debug)]
+struct State1;
+#[derive(Debug, PartialEq)]
+struct State2;
+
+fn update_to_state2() {
+    let m1: Machine<State1> = Machine {
+        state: State1,
+        common_field1: "hello",
+        common_field2: 2,
+    };
+    let m2: Machine<State2> = Machine {
+        state: State2,
+        ..m1
+        //~^ ERROR type changing struct updating is experimental [E0658]
+        //~| ERROR mismatched types [E0308]
+    };
+    assert_eq!(State2, m2.state);
+}
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
new file mode 100644 (file)
index 0000000..2217b8c
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0658]: type changing struct updating is experimental
+  --> $DIR/feature-gate.rs:22:11
+   |
+LL |         ..m1
+   |           ^^
+   |
+   = note: see issue #86555 <https://github.com/rust-lang/rust/issues/86555> for more information
+   = help: add `#![feature(type_changing_struct_update)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate.rs:22:11
+   |
+LL |         ..m1
+   |           ^^ expected struct `State2`, found struct `State1`
+   |
+   = note: expected struct `Machine<State2>`
+              found struct `Machine<State1>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs
new file mode 100644 (file)
index 0000000..df2fef5
--- /dev/null
@@ -0,0 +1,43 @@
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+#[derive(Clone)]
+struct Machine<'a, S> {
+    state: S,
+    lt_str: &'a str,
+    common_field: i32,
+}
+
+#[derive(Clone)]
+struct State1;
+#[derive(Clone)]
+struct State2;
+
+fn update_to_state2() {
+    let s = String::from("hello");
+    let m1: Machine<State1> = Machine {
+        state: State1,
+        lt_str: &s,
+                //~^ ERROR `s` does not live long enough [E0597]
+                // FIXME: The error here actually comes from line 34. The
+                // span of the error message should be corrected to line 34
+        common_field: 2,
+    };
+    // update lifetime
+    let m3: Machine<'static, State1> = Machine {
+        lt_str: "hello, too",
+        ..m1.clone()
+    };
+    // update lifetime and type
+    let m4: Machine<'static, State2> = Machine {
+        state: State2,
+        lt_str: "hello, again",
+        ..m1.clone()
+    };
+    // updating to `static should fail.
+    let m2: Machine<'static, State1> = Machine {
+        ..m1
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
new file mode 100644 (file)
index 0000000..5f93ad6
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/lifetime-update.rs:20:17
+   |
+LL |         lt_str: &s,
+   |                 ^^ borrowed value does not live long enough
+...
+LL |     let m2: Machine<'static, State1> = Machine {
+   |             ------------------------ type annotation requires that `s` is borrowed for `'static`
+...
+LL | }
+   | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs
new file mode 100644 (file)
index 0000000..d8b1396
--- /dev/null
@@ -0,0 +1,57 @@
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+struct Machine<'a, S, M> {
+    state: S,
+    message: M,
+    lt_str: &'a str,
+    common_field: i32,
+}
+
+struct State1;
+struct State2;
+
+struct Message1;
+struct Message2;
+
+fn update() {
+    let m1: Machine<State1, Message1> = Machine {
+        state: State1,
+        message: Message1,
+        lt_str: "hello",
+        common_field: 2,
+    };
+    // single type update
+    let m2: Machine<State2, Message1> = Machine {
+        state: State2,
+        ..m1
+    };
+    // multiple type update
+    let m3: Machine<State2, Message2> = Machine {
+        state: State2,
+        message: Message2,
+        ..m1
+    };
+}
+
+fn fail_update() {
+    let m1: Machine<f64, f64> = Machine {
+        state: 3.2,
+        message: 6.4,
+        lt_str: "hello",
+        common_field: 2,
+    };
+    // single type update fail
+    let m2: Machine<i32, f64> = Machine {
+        ..m1
+        //~^ ERROR mismatched types [E0308]
+    };
+    // multiple type update fail
+    let m3 = Machine::<i32, i32> {
+        ..m1
+        //~^ ERROR mismatched types [E0308]
+        //~| ERROR mismatched types [E0308]
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
new file mode 100644 (file)
index 0000000..fa8d6ee
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/type-generic-update.rs:46:11
+   |
+LL |         ..m1
+   |           ^^ field type mismatch: Machine.state
+   |
+   = note: expected type `i32`
+              found type `f64`
+
+error[E0308]: mismatched types
+  --> $DIR/type-generic-update.rs:51:11
+   |
+LL |         ..m1
+   |           ^^ field type mismatch: Machine.state
+   |
+   = note: expected type `i32`
+              found type `f64`
+
+error[E0308]: mismatched types
+  --> $DIR/type-generic-update.rs:51:11
+   |
+LL |         ..m1
+   |           ^^ field type mismatch: Machine.message
+   |
+   = note: expected type `i32`
+              found type `f64`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 656564fc9e3f8240d66f64182bd4f4e955a47499..ce2726ffde48737c93ce3f6e36804c3d2e8f3d0b 100644 (file)
@@ -1,27 +1,28 @@
 #![feature(staged_api)]
+//~^ ERROR module has missing stability attribute
 
-#[stable(feature = "x", since = "1")]
+#[stable(feature = "a", since = "1")]
 struct StableType;
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "b", issue = "none")]
 struct UnstableType;
 
-#[stable(feature = "x", since = "1")]
+#[stable(feature = "c", since = "1")]
 trait StableTrait {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "d", issue = "none")]
 trait UnstableTrait {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "e", issue = "none")]
 impl UnstableTrait for UnstableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "f", issue = "none")]
 impl StableTrait for UnstableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "g", issue = "none")]
 impl UnstableTrait for StableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "h", issue = "none")]
 //~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
 impl StableTrait for StableType {}
 
index a11479cc8f45cdba0c33c82bbdb8c74776c8ed9d..310f02024ca0a02b6f1a5e0e2eb5841fa9d3ed15 100644 (file)
@@ -1,11 +1,23 @@
 error: an `#[unstable]` annotation here has no effect
-  --> $DIR/stability-attribute-trait-impl.rs:24:1
+  --> $DIR/stability-attribute-trait-impl.rs:25:1
    |
-LL | #[unstable(feature = "x", issue = "none")]
+LL | #[unstable(feature = "h", issue = "none")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[deny(ineffective_unstable_trait_impl)]` on by default
    = note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
 
-error: aborting due to previous error
+error: module has missing stability attribute
+  --> $DIR/stability-attribute-trait-impl.rs:1:1
+   |
+LL | / #![feature(staged_api)]
+LL | |
+LL | |
+LL | | #[stable(feature = "a", since = "1")]
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 2 previous errors
 
index cc78f6cfa53f7127282038e0aaf1990424e8812f..d5645474891062e2a43bddacdcf8fbe0ab450e7f 100644 (file)
@@ -11,7 +11,11 @@ enum Void {}
 
 static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
+//~| ERROR undefined behavior to use this value
+//~| WARN: type `Void` does not permit zero-initialization
 static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
+//~| ERROR undefined behavior to use this value
+//~| WARN: type `Void` does not permit zero-initialization
 
 fn main() {}
index 5d95b29993827ff6b005f528373bafb9b35dc452..c38cf10d6e648bfad53cb16009a3d2c4c5759329 100644 (file)
@@ -34,7 +34,7 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
 error: static of uninhabited type
-  --> $DIR/uninhabited-static.rs:14:1
+  --> $DIR/uninhabited-static.rs:16:1
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,5 +43,47 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
-error: aborting due to 4 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/uninhabited-static.rs:12:1
+   |
+LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 0, align: 1) {}
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/uninhabited-static.rs:16:1
+   |
+LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 0, align: 1) {}
+
+warning: the type `Void` does not permit zero-initialization
+  --> $DIR/uninhabited-static.rs:12:31
+   |
+LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^
+   |                               |
+   |                               this code causes undefined behavior when executed
+   |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: `#[warn(invalid_value)]` on by default
+   = note: enums with no variants have no valid value
+
+warning: the type `Void` does not permit zero-initialization
+  --> $DIR/uninhabited-static.rs:16:32
+   |
+LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: enums with no variants have no valid value
+
+error: aborting due to 6 previous errors; 2 warnings emitted
 
+For more information about this error, try `rustc --explain E0080`.
index cc6412e271a132825e6498267211a4e0235d1468..3bc2d16cf9df2a3c09b7a9f3bd3b0c44d90390b2 100644 (file)
@@ -36,6 +36,7 @@ struct Outer {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
index 101132d05fa0eb98f6a5d0f05e45d20800f5a2b4..5cb9ad31fbfcc0a2ac95366084206839702fa26d 100644 (file)
@@ -3,18 +3,27 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     func::<u8>(42);
    |            ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
   --> $DIR/synthetic-param.rs:23:17
    |
 LL |     Foo::func::<u8>(42);
    |                 ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
   --> $DIR/synthetic-param.rs:26:23
    |
 LL |     Bar::<i8>::func::<u8>(42);
    |                       ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
index 5f3b711b31aa91bac473564d7e63ac574a05d3b5..acbf15dcb6c6a937d5f49b0e3948b0b470bbb587 100644 (file)
@@ -31,7 +31,10 @@ impl Tr for E {
     type V = u8;
     fn f() -> Self::V { 0 }
     //~^ ERROR ambiguous associated item
+    //~| ERROR ambiguous associated item
     //~| WARN this was previously accepted
+    //~| WARN this was previously accepted
+    //~| HELP use fully-qualified syntax
     //~| HELP use fully-qualified syntax
 }
 
index 870b1eec48c0c8a476f386153d72d6264319f10f..f007f71a73c4532323fdaf2324211e1f290d9c9b 100644 (file)
@@ -18,5 +18,24 @@ note: `V` could also refer to the associated type defined here
 LL |     type V;
    |     ^^^^^^^
 
-error: aborting due to previous error
+error: ambiguous associated item
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
+   |
+LL |     fn f() -> Self::V { 0 }
+   |               ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to the variant defined here
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5
+   |
+LL |     V
+   |     ^
+note: `V` could also refer to the associated type defined here
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5
+   |
+LL |     type V;
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
 
index 5fe85954dc8e98f3266d56a11a086e1c39b757bd..ca6b8ba94d1cab407a85482ac1695aebbe843f4f 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(use_nested_groups)]
 #![allow(dead_code)]
 #![deny(unused_imports)]
 
index 987d1dcf5f00de3e1b85d0b6e40f149945dcdd88..6610f8ecd4a28d5ee6290fa368335466b984f6d3 100644 (file)
@@ -1,23 +1,23 @@
 error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
-  --> $DIR/use-nested-groups-unused-imports.rs:16:11
+  --> $DIR/use-nested-groups-unused-imports.rs:15:11
    |
 LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};
    |           ^^^        ^^^^^^^  ^^^^^^^^^   ^
    |
 note: the lint level is defined here
-  --> $DIR/use-nested-groups-unused-imports.rs:3:9
+  --> $DIR/use-nested-groups-unused-imports.rs:2:9
    |
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
 error: unused import: `*`
-  --> $DIR/use-nested-groups-unused-imports.rs:18:24
+  --> $DIR/use-nested-groups-unused-imports.rs:17:24
    |
 LL | use foo::bar::baz::{*, *};
    |                        ^
 
 error: unused import: `foo::{}`
-  --> $DIR/use-nested-groups-unused-imports.rs:20:5
+  --> $DIR/use-nested-groups-unused-imports.rs:19:5
    |
 LL | use foo::{};
    |     ^^^^^^^
index 2bf4cfc50032049e780b88db39ab6fe47ca0dfd8..868923e5932438bf8b8c5d48c0093090e5a01acb 100644 (file)
@@ -28,10 +28,11 @@ pub fn main() {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "vxworks",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "vxworks"))]
 pub fn main() { }
index 94ca096afbf25f670e76e07dca754fcfe27134be..2e2a16e983f597da62bc132eb191bc3276d4b1bb 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 94ca096afbf25f670e76e07dca754fcfe27134be
+Subproject commit 2e2a16e983f597da62bc132eb191bc3276d4b1bb
index e18442515b8fc4ffaf10e5a2c6534e387fbc7551..6b2ac985555dc59fc7014b3c0afeb4267ffd9420 100644 (file)
@@ -77,13 +77,13 @@ fn check_fn(
             if is_future {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
-                let send_result = cx.tcx.infer_ctxt().enter(|infcx| {
+                let send_errors = cx.tcx.infer_ctxt().enter(|infcx| {
                     let cause = traits::ObligationCause::misc(span, hir_id);
                     let mut fulfillment_cx = traits::FulfillmentContext::new();
                     fulfillment_cx.register_bound(&infcx, cx.param_env, ret_ty, send_trait, cause);
                     fulfillment_cx.select_all_or_error(&infcx)
                 });
-                if let Err(send_errors) = send_result {
+                if !send_errors.is_empty() {
                     span_lint_and_then(
                         cx,
                         FUTURE_NOT_SEND,
index eb311983b29276ebf0b21b35ed9e0dcc46750af3..7142df98c3f10fde54afa98e822067dd468532f2 100644 (file)
@@ -1065,7 +1065,10 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                 PatKind::Path(path) => {
                     #[allow(clippy::match_same_arms)]
                     let id = match cx.qpath_res(path, pat.hir_id) {
-                        Res::Def(DefKind::Const | DefKind::ConstParam | DefKind::AnonConst, _) => return,
+                        Res::Def(
+                            DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst,
+                            _,
+                        ) => return,
                         Res::Def(_, id) => id,
                         _ => return,
                     };
index b3a9a1de2ec93daa57b44eace9a0d66d1781f6d3..733cc97c84596546bd0005ab6608749270564f7c 100644 (file)
@@ -3,12 +3,12 @@
 #![deny(clippy::missing_docs_in_private_items)]
 
 use crate::ty::is_type_diagnostic_item;
-use crate::{is_expn_of, last_path_segment, match_def_path, path_to_local_id, paths};
+use crate::{is_expn_of, last_path_segment, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitKind};
 use rustc_hir as hir;
 use rustc_hir::{
-    Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, PatKind, QPath, StmtKind, UnOp,
+    Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StmtKind, UnOp,
 };
 use rustc_lint::LateContext;
 use rustc_span::{sym, symbol, ExpnKind, Span, Symbol};
@@ -513,8 +513,6 @@ pub struct FormatArgsExpn<'tcx> {
     pub format_string_parts: &'tcx [Expr<'tcx>],
     /// Symbols corresponding to [`Self::format_string_parts`]
     pub format_string_symbols: Vec<Symbol>,
-    /// Match arm patterns, the `arg0`, etc. from the next field `args`
-    pub arg_names: &'tcx [Pat<'tcx>],
     /// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
     pub args: &'tcx [Expr<'tcx>],
     /// The final argument passed to `Arguments::new_v1_formatted`, if applicable
@@ -559,7 +557,6 @@ pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
                     _ => None,
                 })
                 .collect();
-            if let PatKind::Tuple(arg_names, None) = arm.pat.kind;
             if let ExprKind::Array(args) = arm.body.kind;
             then {
                 Some(FormatArgsExpn {
@@ -567,7 +564,6 @@ pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
                     value_args,
                     format_string_parts,
                     format_string_symbols,
-                    arg_names,
                     args,
                     fmt_expr,
                 })
@@ -594,10 +590,8 @@ pub fn args(&self) -> Option<Vec<FormatArgsArg<'tcx>>> {
                             if let Ok(i) = usize::try_from(position);
                             let arg = &self.args[i];
                             if let ExprKind::Call(_, [arg_name, _]) = arg.kind;
-                            if let Some(j) = self
-                                .arg_names
-                                .iter()
-                                .position(|pat| path_to_local_id(arg_name, pat.hir_id));
+                            if let ExprKind::Field(_, j) = arg_name.kind;
+                            if let Ok(j) = j.name.as_str().parse::<usize>();
                             then {
                                 Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) })
                             } else {
index 9377eb69b233aca281df4305c86149d13f90b2f6..2498672d77fb04526208e6ec42d9eb8f2772156c 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::excessive_precision)]
 #[deny(clippy::unreadable_literal)]
 
 fn allow_inconsistent_digit_grouping() {
index 9119ef19a7be1aae36193412bcba84b58b204340..be505bda4792c757982e7c51566cbe6d672740d2 100644 (file)
@@ -1,5 +1,5 @@
 error: digits grouped inconsistently by underscores
-  --> $DIR/test.rs:18:18
+  --> $DIR/test.rs:19:18
    |
 LL |     let _fail1 = 100_200_300.123456789;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789`
index d4832daa6895970746de537909bb6339af07331e..9a150c67a21ea583cadad59326c607f33cb8b318 100644 (file)
@@ -52,12 +52,14 @@ macro_rules! m_mut {
     };
 }
 
+#[derive(Copy, Clone)]
 pub struct S;
 impl S {
     pub fn f(&self) -> &Self {
         m!(self)
     }
-    pub fn f_mut(&self) -> &Self {
+    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
+    pub fn f_mut(mut self) -> Self {
         m_mut!(self)
     }
 }
index be7cc669b5b6daf3c0cb855d6fe861e7920e943e..80ba7e9bd0b8202cbe9202343e3dd227000ff95f 100644 (file)
@@ -52,12 +52,14 @@ macro_rules! m_mut {
     };
 }
 
+#[derive(Copy, Clone)]
 pub struct S;
 impl S {
     pub fn f(&self) -> &Self {
         m!(self)
     }
-    pub fn f_mut(&self) -> &Self {
+    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
+    pub fn f_mut(mut self) -> Self {
         m_mut!(self)
     }
 }
index d47dfcb5ba1eab1b8654a2c270700748923a4bee..38a8fbd74dcf61b540b16b34a496b9005d5ba800 100644 (file)
@@ -1,4 +1,5 @@
 #[warn(clippy::double_neg)]
+#[allow(clippy::no_effect)]
 fn main() {
     let x = 1;
     -x;
index d82ed05f0543dbf65a7fb5768c39ac7703561081..7cdb040b6873937266598277e48d240d796c95ca 100644 (file)
@@ -1,5 +1,5 @@
 error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op
-  --> $DIR/double_neg.rs:6:5
+  --> $DIR/double_neg.rs:7:5
    |
 LL |     --x;
    |     ^^^
index 7d6fd607e6545469dc9fa2e0286eae5417d00628..1442ee08e7546aa20056ccb5b3f27e894b6c4cb8 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::fn_params_excessive_bools)]
+#![allow(clippy::too_many_arguments)]
 
 extern "C" {
     fn f(_: bool, _: bool, _: bool, _: bool);
index 4e5dbc261d66bababa570af2a3b283536f668e45..cd9d07fa115d6d3bca7d24f8250925cb0a0aa879 100644 (file)
@@ -1,5 +1,5 @@
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:17:1
+  --> $DIR/fn_params_excessive_bools.rs:18:1
    |
 LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:20:1
+  --> $DIR/fn_params_excessive_bools.rs:21:1
    |
 LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:24:5
+  --> $DIR/fn_params_excessive_bools.rs:25:5
    |
 LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:29:5
+  --> $DIR/fn_params_excessive_bools.rs:30:5
    |
 LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:41:5
+  --> $DIR/fn_params_excessive_bools.rs:42:5
    |
 LL | /     fn n(_: bool, _: u32, _: bool, _: Box<u32>, _: bool, _: bool) {
 LL | |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
@@ -42,7 +42,7 @@ LL | |     }
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:42:9
+  --> $DIR/fn_params_excessive_bools.rs:43:9
    |
 LL |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 0d14807ff1cfcf1f2745b521f0c101c7ca85eddb..471a8e0de6e193047e17ffa3e4273dce9799ac62 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(unused_assignments)]
 #![allow(clippy::if_same_then_else)]
 #![allow(clippy::deref_addrof)]
+#![allow(clippy::nonminimal_bool)]
 
 fn foo() -> bool {
     true
index bde434c7e2e78737ae451a9c8dd776712aba5090..9272cd6048441790c403e0750193c78fa6c56049 100644 (file)
@@ -1,5 +1,5 @@
 error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)`
-  --> $DIR/formatting.rs:15:6
+  --> $DIR/formatting.rs:16:6
    |
 LL |     a =- 35;
    |      ^^^^
@@ -8,7 +8,7 @@ LL |     a =- 35;
    = note: to remove this lint, use either `-=` or `= -`
 
 error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)`
-  --> $DIR/formatting.rs:16:6
+  --> $DIR/formatting.rs:17:6
    |
 LL |     a =* &191;
    |      ^^^^
@@ -16,7 +16,7 @@ LL |     a =* &191;
    = note: to remove this lint, use either `*=` or `= *`
 
 error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)`
-  --> $DIR/formatting.rs:19:6
+  --> $DIR/formatting.rs:20:6
    |
 LL |     b =! false;
    |      ^^^^
@@ -24,7 +24,7 @@ LL |     b =! false;
    = note: to remove this lint, use either `!=` or `= !`
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:28:19
+  --> $DIR/formatting.rs:29:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -33,7 +33,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:32:19
+  --> $DIR/formatting.rs:33:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -41,7 +41,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:69:11
+  --> $DIR/formatting.rs:70:11
    |
 LL |         -1
    |           ^
index e60ce8492fc7716f70f3f490086d03d76904f07f..0cadd5a3da1983e4436d9f946808a84aa45a55b7 100644 (file)
@@ -4,7 +4,7 @@
 #![warn(clippy::zero_prefixed_literal)]
 #![warn(clippy::unseparated_literal_suffix)]
 #![warn(clippy::separated_literal_suffix)]
-#![allow(dead_code)]
+#![allow(dead_code, overflowing_literals)]
 
 fn main() {
     let ok1 = 0xABCD;
index 65769819110eb6f00b05332c7ae0b54c6ba8fa2b..88fcce66873aa3a73b6194eeddcacc88762bffb7 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)]
 #![warn(clippy::many_single_char_names)]
 
 fn bla() {
index 27e62e641ade9c2d3b208922bd7d3367c6d21f0a..ade0f84bc50653be1b7f4574e7ff5fc9afd35cd3 100644 (file)
@@ -1,5 +1,5 @@
 error: 5 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -12,7 +12,7 @@ LL |             let e: i32;
    = note: `-D clippy::many-single-char-names` implied by `-D warnings`
 
 error: 6 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -25,7 +25,7 @@ LL |             let f: i32;
    |                 ^
 
 error: 5 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -36,13 +36,13 @@ LL |             e => panic!(),
    |             ^
 
 error: 8 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:29:13
+  --> $DIR/many_single_char_names.rs:30:13
    |
 LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {}
    |             ^       ^       ^       ^       ^       ^       ^       ^
 
 error: 8 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:32:10
+  --> $DIR/many_single_char_names.rs:33:10
    |
 LL |     let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!();
    |          ^  ^  ^  ^  ^  ^  ^  ^
index 70cdb067d91380cb2b8866110d8c4160a683c1e4..5d57638af43495bea12bce75b930aa600ae51343 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     unused_variables,
+    overflowing_literals,
     clippy::excessive_precision,
     clippy::inconsistent_digit_grouping
 )]
@@ -21,7 +22,6 @@ fn main() {
     let fail25 = 1E2_f32;
     let fail26 = 43E7_f64;
     let fail27 = 243E17_f32;
-    #[allow(overflowing_literals)]
     let fail28 = 241_251_235E723_f64;
     let ok29 = 42279.911_32;
 
index 729990af3998dbc9d36f0e40b3d8d93175da5009..12171452885d2b009bdb0e0373abe765a0c29a04 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     unused_variables,
+    overflowing_literals,
     clippy::excessive_precision,
     clippy::inconsistent_digit_grouping
 )]
@@ -21,7 +22,6 @@ fn main() {
     let fail25 = 1E2_32;
     let fail26 = 43E7_64;
     let fail27 = 243E17_32;
-    #[allow(overflowing_literals)]
     let fail28 = 241251235E723_64;
     let ok29 = 42279.911_32;
 
index b338b8aa6228d5757cc7c79212f6c48bd0b2f1b9..d24543c26e4b0d7e48cbb4647f03ebcd2abf3cb0 100644 (file)
@@ -1,5 +1,5 @@
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:11:18
+  --> $DIR/mistyped_literal_suffix.rs:12:18
    |
 LL |     let fail14 = 2_32;
    |                  ^^^^ help: did you mean to write: `2_i32`
@@ -7,49 +7,49 @@ LL |     let fail14 = 2_32;
    = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:12:18
+  --> $DIR/mistyped_literal_suffix.rs:13:18
    |
 LL |     let fail15 = 4_64;
    |                  ^^^^ help: did you mean to write: `4_i64`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:13:18
+  --> $DIR/mistyped_literal_suffix.rs:14:18
    |
 LL |     let fail16 = 7_8; //
    |                  ^^^ help: did you mean to write: `7_i8`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:14:18
+  --> $DIR/mistyped_literal_suffix.rs:15:18
    |
 LL |     let fail17 = 23_16; //
    |                  ^^^^^ help: did you mean to write: `23_i16`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:17:18
+  --> $DIR/mistyped_literal_suffix.rs:18:18
    |
 LL |     let fail20 = 2__8; //
    |                  ^^^^ help: did you mean to write: `2_i8`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:18:18
+  --> $DIR/mistyped_literal_suffix.rs:19:18
    |
 LL |     let fail21 = 4___16; //
    |                  ^^^^^^ help: did you mean to write: `4_i16`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:21:18
+  --> $DIR/mistyped_literal_suffix.rs:22:18
    |
 LL |     let fail25 = 1E2_32;
    |                  ^^^^^^ help: did you mean to write: `1E2_f32`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:22:18
+  --> $DIR/mistyped_literal_suffix.rs:23:18
    |
 LL |     let fail26 = 43E7_64;
    |                  ^^^^^^^ help: did you mean to write: `43E7_f64`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:23:18
+  --> $DIR/mistyped_literal_suffix.rs:24:18
    |
 LL |     let fail27 = 243E17_32;
    |                  ^^^^^^^^^ help: did you mean to write: `243E17_f32`
index a39d96109f17d8d03e38c4701cc4345d1e51ed30..ad0d694a2174a3a125393790d5767a81afd9c98d 100644 (file)
@@ -38,6 +38,7 @@ struct S2 {}
     //  fn call_with_mut_self<'life0>(self: &'life0 mut Self) {}
     #[rename_my_lifetimes]
     impl T2 for S2 {
+        #[allow(clippy::needless_lifetimes)]
         fn call_with_mut_self(self: &mut Self) {}
     }
 }
index 44a0e6ddeace63bcd54bc6f7284eff4a336ec4e9..b2edbfe4323e16ce6ec4407158daa60f143b335f 100644 (file)
@@ -1,5 +1,5 @@
 error: the type of the `self` parameter does not need to be arbitrary
-  --> $DIR/needless_arbitrary_self_type_unfixable.rs:41:31
+  --> $DIR/needless_arbitrary_self_type_unfixable.rs:42:31
    |
 LL |         fn call_with_mut_self(self: &mut Self) {}
    |                               ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'_ mut self`
index 83ee27f4887a1822d7aa6ae1eb1deca3fc29edba..f105d3d659ac7fb199e5c4fc593ca224c86447e1 100644 (file)
@@ -12,6 +12,7 @@ macro_rules! nonzero {
     };
 }
 
+#[allow(clippy::nonminimal_bool)]
 fn main() {
     let mut i = 1;
     while i < 10 {
index 22b86f25e8f0e44ced23329d1cc378cc31d27e89..b8657c74caa6930c9408ecc4079a9fd7b5893e0d 100644 (file)
@@ -1,5 +1,5 @@
 error: this `else` block is redundant
-  --> $DIR/needless_continue.rs:28:16
+  --> $DIR/needless_continue.rs:29:16
    |
 LL |           } else {
    |  ________________^
@@ -35,7 +35,7 @@ LL | |         }
                    }
 
 error: there is no need for an explicit `else` block for this `if` expression
-  --> $DIR/needless_continue.rs:43:9
+  --> $DIR/needless_continue.rs:44:9
    |
 LL | /         if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
 LL | |             continue;
@@ -55,7 +55,7 @@ LL | |         }
                    }
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:56:9
+  --> $DIR/needless_continue.rs:57:9
    |
 LL |         continue; // should lint here
    |         ^^^^^^^^^
@@ -63,7 +63,7 @@ LL |         continue; // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:63:9
+  --> $DIR/needless_continue.rs:64:9
    |
 LL |         continue; // should lint here
    |         ^^^^^^^^^
@@ -71,7 +71,7 @@ LL |         continue; // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:70:9
+  --> $DIR/needless_continue.rs:71:9
    |
 LL |         continue // should lint here
    |         ^^^^^^^^
@@ -79,7 +79,7 @@ LL |         continue // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:78:9
+  --> $DIR/needless_continue.rs:79:9
    |
 LL |         continue // should lint here
    |         ^^^^^^^^
@@ -87,7 +87,7 @@ LL |         continue // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `else` block is redundant
-  --> $DIR/needless_continue.rs:128:24
+  --> $DIR/needless_continue.rs:129:24
    |
 LL |                   } else {
    |  ________________________^
@@ -110,7 +110,7 @@ LL | |                 }
                            }
 
 error: there is no need for an explicit `else` block for this `if` expression
-  --> $DIR/needless_continue.rs:134:17
+  --> $DIR/needless_continue.rs:135:17
    |
 LL | /                 if condition() {
 LL | |                     continue; // should lint here
index 961f6f409ddd2202916bfe14c17111d208359592..9937005d68d8ae43092952b1a4f307d8f21f816c 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::all)]
-#![allow(unused, clippy::println_empty_string)]
+#![allow(unused, clippy::println_empty_string, non_snake_case)]
 
 #[derive(Clone, Debug)]
 enum MaybeInst {
@@ -14,6 +14,7 @@ struct InstSplit {
 
 impl MaybeInst {
     fn fill(&mut self) {
+        #[allow(non_fmt_panics)]
         let filled = match *self {
             MaybeInst::Split1(goto1) => panic!("1"),
             MaybeInst::Split2(goto2) => panic!("2"),
@@ -36,6 +37,7 @@ fn issue2927() {
 }
 
 fn issue3078() {
+    #[allow(clippy::single_match)]
     match "a" {
         stringify!(a) => {},
         _ => {},
index a0ca46f0efc602cd0a6bccc6c35b48dee5697e5e..116d5da8729c0f2d334d91a4966483158f52bd53 100644 (file)
@@ -1,5 +1,5 @@
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:27:9
+  --> $DIR/non_expressive_names.rs:28:9
    |
 LL |     let _1 = 1; //~ERROR Consider a more descriptive name
    |         ^^
@@ -7,31 +7,31 @@ LL |     let _1 = 1; //~ERROR Consider a more descriptive name
    = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings`
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:28:9
+  --> $DIR/non_expressive_names.rs:29:9
    |
 LL |     let ____1 = 1; //~ERROR Consider a more descriptive name
    |         ^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:29:9
+  --> $DIR/non_expressive_names.rs:30:9
    |
 LL |     let __1___2 = 12; //~ERROR Consider a more descriptive name
    |         ^^^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:49:13
+  --> $DIR/non_expressive_names.rs:51:13
    |
 LL |         let _1 = 1;
    |             ^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:50:13
+  --> $DIR/non_expressive_names.rs:52:13
    |
 LL |         let ____1 = 1;
    |             ^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:51:13
+  --> $DIR/non_expressive_names.rs:53:13
    |
 LL |         let __1___2 = 12;
    |             ^^^^^^^
index 3dd365620ccbf1b4f4eef131819ce9da695f84dd..5649d8dd14c4899fde03e7a75d78bf5309aa4728 100644 (file)
@@ -15,5 +15,6 @@ fn main() {
     #[allow(clippy::needless_return)]
     (|| return 2)();
     (|| -> Option<i32> { None? })();
+    #[allow(clippy::try_err)]
     (|| -> Result<i32, i32> { Err(2)? })();
 }
index 737c8a9f8db43783313ab6d6fdfbfe0341709984..e8a6e940c01cdbebd76dfcceb066bafea11d97cc 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::redundant_else)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::if_same_then_else)]
 
 fn main() {
     loop {
@@ -105,7 +105,7 @@ fn main() {
         1
     };
     // assign
-    let a;
+    let mut a;
     a = if foo() {
         return;
     } else {
index daa073414577c8bfd897f37fe8b9a944eb063fe3..76f6ce9ee6b47f3826824a35e2495c0513d80c23 100644 (file)
@@ -1,5 +1,10 @@
 #![warn(clippy::similar_names)]
-#![allow(unused, clippy::println_empty_string)]
+#![allow(
+    unused,
+    clippy::println_empty_string,
+    clippy::empty_loop,
+    clippy::diverging_sub_expression
+)]
 
 struct Foo {
     apple: i32,
index f621595abaea2ee295423dbcb04b990f63b7184c..faf572b0c6bc27010c8af554b37cd863e295ab2a 100644 (file)
@@ -1,84 +1,84 @@
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:15:9
+  --> $DIR/similar_names.rs:20:9
    |
 LL |     let bpple: i32;
    |         ^^^^^
    |
    = note: `-D clippy::similar-names` implied by `-D warnings`
 note: existing binding defined here
-  --> $DIR/similar_names.rs:13:9
+  --> $DIR/similar_names.rs:18:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:17:9
+  --> $DIR/similar_names.rs:22:9
    |
 LL |     let cpple: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:13:9
+  --> $DIR/similar_names.rs:18:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:41:9
+  --> $DIR/similar_names.rs:46:9
    |
 LL |     let bluby: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:40:9
+  --> $DIR/similar_names.rs:45:9
    |
 LL |     let blubx: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:45:9
+  --> $DIR/similar_names.rs:50:9
    |
 LL |     let coke: i32;
    |         ^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:43:9
+  --> $DIR/similar_names.rs:48:9
    |
 LL |     let cake: i32;
    |         ^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:63:9
+  --> $DIR/similar_names.rs:68:9
    |
 LL |     let xyzeabc: i32;
    |         ^^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:61:9
+  --> $DIR/similar_names.rs:66:9
    |
 LL |     let xyz1abc: i32;
    |         ^^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:67:9
+  --> $DIR/similar_names.rs:72:9
    |
 LL |     let parsee: i32;
    |         ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:65:9
+  --> $DIR/similar_names.rs:70:9
    |
 LL |     let parser: i32;
    |         ^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:88:16
+  --> $DIR/similar_names.rs:93:16
    |
 LL |         bpple: sprang,
    |                ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:87:16
+  --> $DIR/similar_names.rs:92:16
    |
 LL |         apple: spring,
    |                ^^^^^^
index be8bc22bf98a05d062caff083c4c6e1d1d903c85..fcd827a91c7f62d843bfd47a30016a58e9dbbf2d 100644 (file)
@@ -1,6 +1,7 @@
 // aux-build:proc_macro_suspicious_else_formatting.rs
 
 #![warn(clippy::suspicious_else_formatting)]
+#![allow(clippy::if_same_then_else)]
 
 extern crate proc_macro_suspicious_else_formatting;
 use proc_macro_suspicious_else_formatting::DeriveBadSpan;
index d1db195cbb8787bc0003738f2f2c1e37adbf7fe3..ee68eb5a791c45d5ea2c5c3ab4edc2fe8810fc35 100644 (file)
@@ -1,5 +1,5 @@
 error: this looks like an `else {..}` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:16:6
+  --> $DIR/suspicious_else_formatting.rs:17:6
    |
 LL |     } {
    |      ^
@@ -8,7 +8,7 @@ LL |     } {
    = note: to remove this lint, add the missing `else` or add a new line before the next block
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:20:6
+  --> $DIR/suspicious_else_formatting.rs:21:6
    |
 LL |     } if foo() {
    |      ^
@@ -16,7 +16,7 @@ LL |     } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:27:10
+  --> $DIR/suspicious_else_formatting.rs:28:10
    |
 LL |         } if foo() {
    |          ^
@@ -24,7 +24,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:35:10
+  --> $DIR/suspicious_else_formatting.rs:36:10
    |
 LL |         } if foo() {
    |          ^
@@ -32,7 +32,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:44:6
+  --> $DIR/suspicious_else_formatting.rs:45:6
    |
 LL |       } else
    |  ______^
@@ -42,7 +42,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:56:6
+  --> $DIR/suspicious_else_formatting.rs:57:6
    |
 LL |       } else
    |  ______^
@@ -52,7 +52,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:61:6
+  --> $DIR/suspicious_else_formatting.rs:62:6
    |
 LL |       }
    |  ______^
@@ -63,7 +63,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:88:6
+  --> $DIR/suspicious_else_formatting.rs:89:6
    |
 LL |       }
    |  ______^
@@ -75,7 +75,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:96:6
+  --> $DIR/suspicious_else_formatting.rs:97:6
    |
 LL |       }
    |  ______^
index 2f8c7cec50f8ec47f1802a554e3d381a859ba3a3..3201d5de0f35620663dea65c8903b481d8ac9eb6 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::suspicious_operation_groupings)]
+#![allow(clippy::eq_op)]
 
 struct Vec3 {
     x: f64,
@@ -187,7 +188,7 @@ fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool {
     }
 }
 
-fn inside_an_if_statement(s1: &S, s2: &S) {
+fn inside_an_if_statement(s1: &mut S, s2: &S) {
     // There's no `s1.b`
     if s1.a < s2.a && s1.a < s2.b {
         s1.c = s2.c;
index dd6f2f6641d678b14b1d401fac951d98ce43f913..baf9bc74b000ec30468a9e08112d1decaed61346 100644 (file)
@@ -1,5 +1,5 @@
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:14:9
+  --> $DIR/suspicious_operation_groupings.rs:15:9
    |
 LL |         self.x == other.y && self.y == other.y && self.z == other.z
    |         ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
@@ -7,151 +7,151 @@ LL |         self.x == other.y && self.y == other.y && self.z == other.z
    = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:27:20
+  --> $DIR/suspicious_operation_groupings.rs:28:20
    |
 LL |     s1.a < s2.a && s1.a < s2.b
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:75:33
+  --> $DIR/suspicious_operation_groupings.rs:76:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:80:19
+  --> $DIR/suspicious_operation_groupings.rs:81:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:80:19
+  --> $DIR/suspicious_operation_groupings.rs:81:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:85:19
+  --> $DIR/suspicious_operation_groupings.rs:86:19
    |
 LL |     s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:90:19
+  --> $DIR/suspicious_operation_groupings.rs:91:19
    |
 LL |     s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:95:5
+  --> $DIR/suspicious_operation_groupings.rs:96:5
    |
 LL |     s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
    |     ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:100:33
+  --> $DIR/suspicious_operation_groupings.rs:101:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:113:20
+  --> $DIR/suspicious_operation_groupings.rs:114:20
    |
 LL |     (s1.a * s2.a + s1.b * s1.b)
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:118:34
+  --> $DIR/suspicious_operation_groupings.rs:119:34
    |
 LL |     (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
    |                                  ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:123:38
+  --> $DIR/suspicious_operation_groupings.rs:124:38
    |
 LL |     (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
    |                                      ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:128:39
+  --> $DIR/suspicious_operation_groupings.rs:129:39
    |
 LL |     ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
    |                                       ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:133:42
+  --> $DIR/suspicious_operation_groupings.rs:134:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:133:42
+  --> $DIR/suspicious_operation_groupings.rs:134:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:138:40
+  --> $DIR/suspicious_operation_groupings.rs:139:40
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:143:40
+  --> $DIR/suspicious_operation_groupings.rs:144:40
    |
 LL |     ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:148:20
+  --> $DIR/suspicious_operation_groupings.rs:149:20
    |
 LL |     (s1.a * s2.a + s2.b * s2.b) / 2
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:153:35
+  --> $DIR/suspicious_operation_groupings.rs:154:35
    |
 LL |     i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
    |                                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:158:29
+  --> $DIR/suspicious_operation_groupings.rs:159:29
    |
 LL |     s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
    |                             ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:163:17
+  --> $DIR/suspicious_operation_groupings.rs:164:17
    |
 LL |     s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
    |                 ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:172:77
+  --> $DIR/suspicious_operation_groupings.rs:173:77
    |
 LL |     (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
    |                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:186:25
+  --> $DIR/suspicious_operation_groupings.rs:187:25
    |
 LL |         s1.a <= s2.a && s1.a <= s2.b
    |                         ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:192:23
+  --> $DIR/suspicious_operation_groupings.rs:193:23
    |
 LL |     if s1.a < s2.a && s1.a < s2.b {
    |                       ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:199:48
+  --> $DIR/suspicious_operation_groupings.rs:200:48
    |
 LL |     -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
    |                                                ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:204:27
+  --> $DIR/suspicious_operation_groupings.rs:205:27
    |
 LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
    |                           ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
index 04f03a360ab8fef3d9c0ff84de2d39b8a196c717..2c0f433fd2e838ae181f87019b6f1fefe33c6f54 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 04f03a360ab8fef3d9c0ff84de2d39b8a196c717
+Subproject commit 2c0f433fd2e838ae181f87019b6f1fefe33c6f54
index a673e425dfff9d41610b59ae14f014486f911018..4f73a7f634098f2f7d6846e593a083c24877fcb4 100644 (file)
@@ -401,7 +401,8 @@ function showHelp() {
     console.log("  --doc-folder [PATH]        : location of the generated doc folder");
     console.log("  --help                     : show this message then quit");
     console.log("  --crate-name [STRING]      : crate name to be used");
-    console.log("  --test-file [PATH]         : location of the JS test file");
+    console.log("  --test-file [PATHs]        : location of the JS test files (can be called " +
+                "multiple times)");
     console.log("  --test-folder [PATH]       : location of the JS tests folder");
     console.log("  --resource-suffix [STRING] : suffix to refer to the correct files");
 }
@@ -412,7 +413,7 @@ function parseOptions(args) {
         "resource_suffix": "",
         "doc_folder": "",
         "test_folder": "",
-        "test_file": "",
+        "test_file": [],
     };
     var correspondences = {
         "--resource-suffix": "resource_suffix",
@@ -429,7 +430,11 @@ function parseOptions(args) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
                 return null;
             }
-            opts[correspondences[args[i - 1]]] = args[i];
+            if (args[i - 1] !== "--test-file") {
+                opts[correspondences[args[i - 1]]] = args[i];
+            } else {
+                opts[correspondences[args[i - 1]]].push(args[i]);
+            }
         } else if (args[i] === "--help") {
             showHelp();
             process.exit(0);
@@ -471,9 +476,10 @@ function main(argv) {
     var errors = 0;
 
     if (opts["test_file"].length !== 0) {
-        errors += checkFile(opts["test_file"], opts, loaded, index);
-    }
-    if (opts["test_folder"].length !== 0) {
+        opts["test_file"].forEach(function(file) {
+            errors += checkFile(file, opts, loaded, index);
+        });
+    } else if (opts["test_folder"].length !== 0) {
         fs.readdirSync(opts["test_folder"]).forEach(function(file) {
             if (!file.endsWith(".js")) {
                 return;