diff options
| author | varkor <github@varkor.com> | 2020-02-22 01:55:35 +0000 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2020-02-22 11:34:29 +0000 |
| commit | 76fb26b8c2ad48a8194dceb06073b636ca7ae6d6 (patch) | |
| tree | 462fa1334b359b096a5915fe3c135afce8100bcd | |
| parent | 33143fd756f3765daa00809da2d1f66b5d3ac9fc (diff) | |
| download | rust-76fb26b8c2ad48a8194dceb06073b636ca7ae6d6.tar.gz rust-76fb26b8c2ad48a8194dceb06073b636ca7ae6d6.zip | |
Add invalid argument spans to `GenericArgCountMismatch`
| -rw-r--r-- | src/librustc_ast_passes/ast_validation.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 72 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/confirm.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 8 |
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)) = |
