about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2020-02-22 01:55:35 +0000
committervarkor <github@varkor.com>2020-02-22 11:34:29 +0000
commit76fb26b8c2ad48a8194dceb06073b636ca7ae6d6 (patch)
tree462fa1334b359b096a5915fe3c135afce8100bcd
parent33143fd756f3765daa00809da2d1f66b5d3ac9fc (diff)
downloadrust-76fb26b8c2ad48a8194dceb06073b636ca7ae6d6.tar.gz
rust-76fb26b8c2ad48a8194dceb06073b636ca7ae6d6.zip
Add invalid argument spans to `GenericArgCountMismatch`
-rw-r--r--src/librustc_ast_passes/ast_validation.rs2
-rw-r--r--src/librustc_typeck/astconv.rs72
-rw-r--r--src/librustc_typeck/check/method/confirm.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs8
4 files changed, 47 insertions, 37 deletions
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index d55efeda3c1..25455ff629b 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -8,7 +8,7 @@
 
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, struct_span_err, Applicability, FatalError};
+use rustc_errors::{error_code, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
 use rustc_session::lint::LintBuffer;
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 42613532655..9a80452aef3 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -134,8 +134,12 @@ enum GenericArgPosition {
 
 /// A marker denoting that the generic arguments that were
 /// provided did not match the respective generic parameters.
-/// The field indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
-pub struct GenericArgCountMismatch(pub Option<ErrorReported>);
+pub struct GenericArgCountMismatch {
+    /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
+    pub reported: Option<ErrorReported>,
+    /// A list of spans of arguments provided that were not valid.
+    pub invalid_args: Vec<Span>,
+}
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     pub fn ast_region_to_region(
@@ -279,7 +283,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             def.parent.is_none() && def.has_self, // `has_self`
             seg.infer_args || suppress_mismatch,  // `infer_args`
         )
-        .0
     }
 
     /// Checks that the correct number of generic arguments have been provided.
@@ -292,7 +295,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         position: GenericArgPosition,
         has_self: bool,
         infer_args: bool,
-    ) -> (Result<(), GenericArgCountMismatch>, Vec<Span>) {
+    ) -> Result<(), GenericArgCountMismatch> {
         // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
         // that lifetimes will proceed types. So it suffices to check the number of each generic
         // arguments in order to validate them with respect to the generic parameters.
@@ -328,12 +331,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 if position == GenericArgPosition::Value
                     && arg_counts.lifetimes != param_counts.lifetimes
                 {
-                    explicit_lifetimes = Err(GenericArgCountMismatch(Some(ErrorReported)));
+                    explicit_lifetimes = Err(true);
                     let mut err = tcx.sess.struct_span_err(span, msg);
                     err.span_note(span_late, note);
                     err.emit();
                 } else {
-                    explicit_lifetimes = Err(GenericArgCountMismatch(None));
+                    explicit_lifetimes = Err(false);
                     let mut multispan = MultiSpan::from_span(span);
                     multispan.push_span_label(span_late, note.to_string());
                     tcx.struct_span_lint_hir(
@@ -407,7 +410,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
                 err.emit();
 
-                Err(GenericArgCountMismatch(Some(ErrorReported)))
+                Err(true)
             };
 
         let mut arg_count_correct = explicit_lifetimes;
@@ -416,40 +419,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if arg_count_correct.is_ok()
             && (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes)
         {
-            arg_count_correct = arg_count_correct.and(check_kind_count(
+            arg_count_correct = check_kind_count(
                 "lifetime",
                 param_counts.lifetimes,
                 param_counts.lifetimes,
                 arg_counts.lifetimes,
                 0,
                 &mut unexpected_spans,
-            ));
+            )
+            .and(arg_count_correct);
         }
         // FIXME(const_generics:defaults)
         if !infer_args || arg_counts.consts > param_counts.consts {
-            arg_count_correct = arg_count_correct.and(check_kind_count(
+            arg_count_correct = check_kind_count(
                 "const",
                 param_counts.consts,
                 param_counts.consts,
                 arg_counts.consts,
                 arg_counts.lifetimes + arg_counts.types,
                 &mut unexpected_spans,
-            ));
+            )
+            .and(arg_count_correct);
         }
         // Note that type errors are currently be emitted *after* const errors.
         if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize
         {
-            arg_count_correct = arg_count_correct.and(check_kind_count(
+            arg_count_correct = check_kind_count(
                 "type",
                 param_counts.types - defaults.types - has_self as usize,
                 param_counts.types - has_self as usize,
                 arg_counts.types,
                 arg_counts.lifetimes,
                 &mut unexpected_spans,
-            ));
+            )
+            .and(arg_count_correct);
         }
 
-        (arg_count_correct, unexpected_spans)
+        arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
+            reported: if reported_err { Some(ErrorReported) } else { None },
+            invalid_args: unexpected_spans,
+        })
     }
 
     /// Report an error that a generic argument did not match the generic parameter that was
@@ -501,7 +510,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         parent_substs: &[subst::GenericArg<'tcx>],
         has_self: bool,
         self_ty: Option<Ty<'tcx>>,
-        arg_count_correct: Result<(), GenericArgCountMismatch>,
+        arg_count_correct: bool,
         args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
         provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
         mut inferred_kind: impl FnMut(
@@ -595,7 +604,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 // another. This is an error. However, if we already know that
                                 // the arguments don't match up with the parameters, we won't issue
                                 // an additional error, as the user already knows what's wrong.
-                                if arg_count_correct.is_ok() {
+                                if arg_count_correct {
                                     Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr());
                                 }
 
@@ -621,7 +630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         //  2.  We've inferred some lifetimes, which have been provided later (i.e.
                         //      after a type or const). We want to throw an error in this case.
 
-                        if arg_count_correct.is_ok() {
+                        if arg_count_correct {
                             let kind = arg.descr();
                             assert_eq!(kind, "lifetime");
                             let provided =
@@ -686,7 +695,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         generic_args: &'a hir::GenericArgs<'_>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Vec<Span>) {
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Result<(), GenericArgCountMismatch>)
+    {
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
@@ -712,7 +722,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             assert!(self_ty.is_none() && parent_substs.is_empty());
         }
 
-        let (arg_count_correct, potential_assoc_types) = Self::check_generic_arg_count(
+        let arg_count_correct = Self::check_generic_arg_count(
             tcx,
             span,
             &generic_params,
@@ -745,7 +755,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             parent_substs,
             self_ty.is_some(),
             self_ty,
-            arg_count_correct,
+            arg_count_correct.is_ok(),
             // Provide the generic args, and whether types should be inferred.
             |did| {
                 if did == def_id {
@@ -858,7 +868,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             generic_params, self_ty, substs
         );
 
-        (substs, assoc_bindings, potential_assoc_types)
+        (substs, assoc_bindings, arg_count_correct)
     }
 
     crate fn create_substs_for_associated_item(
@@ -989,7 +999,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
-    ) -> Vec<Span> {
+    ) -> Result<(), GenericArgCountMismatch> {
         let trait_def_id = trait_ref.trait_def_id();
 
         debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
@@ -1006,7 +1016,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         } else {
             trait_ref.path.span
         };
-        let (substs, assoc_bindings, potential_assoc_types) = self.create_substs_for_ast_trait_ref(
+        let (substs, assoc_bindings, arg_count_correct) = self.create_substs_for_ast_trait_ref(
             path_span,
             trait_def_id,
             self_ty,
@@ -1036,7 +1046,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             trait_ref, bounds, poly_trait_ref
         );
 
-        potential_assoc_types
+        arg_count_correct
     }
 
     /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
@@ -1064,7 +1074,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         constness: Constness,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
-    ) -> Vec<Span> {
+    ) -> Result<(), GenericArgCountMismatch> {
         self.instantiate_poly_trait_ref_inner(
             &poly_trait_ref.trait_ref,
             poly_trait_ref.span,
@@ -1153,7 +1163,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         trait_segment: &'a hir::PathSegment<'a>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Vec<Span>) {
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Result<(), GenericArgCountMismatch>)
+    {
         debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
 
         self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
@@ -1498,13 +1509,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let mut potential_assoc_types = Vec::new();
         let dummy_self = self.tcx().types.trait_object_dummy_self;
         for trait_bound in trait_bounds.iter().rev() {
-            let cur_potential_assoc_types = self.instantiate_poly_trait_ref(
+            if let Err(GenericArgCountMismatch {
+                invalid_args: cur_potential_assoc_types, ..
+            }) = self.instantiate_poly_trait_ref(
                 trait_bound,
                 Constness::NotConst,
                 dummy_self,
                 &mut bounds,
-            );
-            potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
+            ) {
+                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
+            }
         }
 
         // Expand trait aliases recursively and check that only one regular (non-auto) trait
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 38773abeef2..108affe5a86 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -313,7 +313,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             parent_substs,
             false,
             None,
-            arg_count_correct,
+            arg_count_correct.is_ok(),
             // Provide the generic args, and whether types should be inferred.
             |def_id| {
                 // The last component of the returned tuple here is unimportant.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index daedeafbcc3..3738afb2c3d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5452,7 +5452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // parameter internally, but we don't allow users to specify the
             // parameter's value explicitly, so we have to do some error-
             // checking here.
-            if let Err(GenericArgCountMismatch(Some(ErrorReported))) =
+            if let Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }) =
                 AstConv::check_generic_arg_count_for_call(
                     tcx, span, &generics, &seg, false, // `is_method_call`
                 )
@@ -5521,11 +5521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &[][..],
                 has_self,
                 self_ty,
-                if infer_args_for_err.is_empty() {
-                    Ok(())
-                } else {
-                    Err(GenericArgCountMismatch(Some(ErrorReported)))
-                },
+                infer_args_for_err.is_empty(),
                 // Provide the generic args, and whether types should be inferred.
                 |def_id| {
                     if let Some(&PathSeg(_, index)) =