-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Avoid follow-up errors if the number of generic parameters already doesn't match #125608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aebe8a7
61c4b7f
4dec6bb
24af952
2e3842b
adb2ac0
063b26a
108a1e5
d498eb5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,12 +215,11 @@ pub(crate) enum GenericArgPosition { | |
|
||
/// A marker denoting that the generic arguments that were | ||
/// provided did not match the respective generic parameters. | ||
#[derive(Clone, Default, Debug)] | ||
#[derive(Clone, Debug)] | ||
pub struct GenericArgCountMismatch { | ||
/// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`). | ||
pub reported: Option<ErrorGuaranteed>, | ||
/// A list of spans of arguments provided that were not valid. | ||
pub invalid_args: Vec<Span>, | ||
pub reported: ErrorGuaranteed, | ||
/// A list of indices of arguments provided that were not valid. | ||
pub invalid_args: Vec<usize>, | ||
} | ||
|
||
/// Decorates the result of a generic argument count mismatch | ||
|
@@ -240,13 +239,14 @@ pub trait GenericArgsLowerer<'a, 'tcx> { | |
|
||
fn provided_kind( | ||
&mut self, | ||
preceding_args: &[ty::GenericArg<'tcx>], | ||
param: &ty::GenericParamDef, | ||
arg: &GenericArg<'tcx>, | ||
) -> ty::GenericArg<'tcx>; | ||
|
||
fn inferred_kind( | ||
&mut self, | ||
args: Option<&[ty::GenericArg<'tcx>]>, | ||
preceding_args: &[ty::GenericArg<'tcx>], | ||
param: &ty::GenericParamDef, | ||
infer_args: bool, | ||
) -> ty::GenericArg<'tcx>; | ||
|
@@ -404,10 +404,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
self_ty.is_some(), | ||
); | ||
|
||
if let Err(err) = &arg_count.correct | ||
&& let Some(reported) = err.reported | ||
{ | ||
self.set_tainted_by_errors(reported); | ||
if let Err(err) = &arg_count.correct { | ||
self.set_tainted_by_errors(err.reported); | ||
} | ||
|
||
// Skip processing if type has no generic parameters. | ||
|
@@ -425,6 +423,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
span: Span, | ||
inferred_params: Vec<Span>, | ||
infer_args: bool, | ||
incorrect_args: &'a Result<(), GenericArgCountMismatch>, | ||
} | ||
|
||
impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> { | ||
|
@@ -439,11 +438,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
|
||
fn provided_kind( | ||
&mut self, | ||
preceding_args: &[ty::GenericArg<'tcx>], | ||
param: &ty::GenericParamDef, | ||
arg: &GenericArg<'tcx>, | ||
) -> ty::GenericArg<'tcx> { | ||
let tcx = self.lowerer.tcx(); | ||
|
||
if let Err(incorrect) = self.incorrect_args { | ||
if incorrect.invalid_args.contains(&(param.index as usize)) { | ||
return param.to_error(tcx, preceding_args); | ||
} | ||
} | ||
|
||
let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { | ||
if has_default { | ||
tcx.check_optional_stability( | ||
|
@@ -506,11 +512,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
|
||
fn inferred_kind( | ||
&mut self, | ||
args: Option<&[ty::GenericArg<'tcx>]>, | ||
preceding_args: &[ty::GenericArg<'tcx>], | ||
param: &ty::GenericParamDef, | ||
infer_args: bool, | ||
) -> ty::GenericArg<'tcx> { | ||
let tcx = self.lowerer.tcx(); | ||
|
||
if let Err(incorrect) = self.incorrect_args { | ||
if incorrect.invalid_args.contains(&(param.index as usize)) { | ||
return param.to_error(tcx, preceding_args); | ||
} | ||
} | ||
match param.kind { | ||
GenericParamDefKind::Lifetime => self | ||
.lowerer | ||
|
@@ -529,15 +541,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
GenericParamDefKind::Type { has_default, .. } => { | ||
if !infer_args && has_default { | ||
// No type parameter provided, but a default exists. | ||
let args = args.unwrap(); | ||
if args.iter().any(|arg| match arg.unpack() { | ||
GenericArgKind::Type(ty) => ty.references_error(), | ||
_ => false, | ||
}) { | ||
if let Some(prev) = | ||
preceding_args.iter().find_map(|arg| match arg.unpack() { | ||
GenericArgKind::Type(ty) => ty.error_reported().err(), | ||
_ => None, | ||
}) | ||
{ | ||
// Avoid ICE #86756 when type error recovery goes awry. | ||
return Ty::new_misc_error(tcx).into(); | ||
return Ty::new_error(tcx, prev).into(); | ||
Comment on lines
-532
to
+551
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fishy ICE workaround, but I rather preserved it for now instead of looking into it |
||
} | ||
tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into() | ||
tcx.at(self.span) | ||
.type_of(param.def_id) | ||
.instantiate(tcx, preceding_args) | ||
.into() | ||
} else if infer_args { | ||
self.lowerer.ty_infer(Some(param), self.span).into() | ||
} else { | ||
|
@@ -557,7 +573,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
// FIXME(effects) see if we should special case effect params here | ||
if !infer_args && has_default { | ||
tcx.const_param_default(param.def_id) | ||
.instantiate(tcx, args.unwrap()) | ||
.instantiate(tcx, preceding_args) | ||
.into() | ||
} else { | ||
if infer_args { | ||
|
@@ -571,6 +587,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
} | ||
} | ||
} | ||
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness | ||
&& generics.has_self | ||
&& !tcx.has_attr(def_id, sym::const_trait) | ||
{ | ||
let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { | ||
span, | ||
modifier: constness.as_str(), | ||
}); | ||
self.set_tainted_by_errors(reported); | ||
arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] }); | ||
} | ||
|
||
let mut args_ctx = GenericArgsCtxt { | ||
lowerer: self, | ||
|
@@ -579,19 +606,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
generic_args: segment.args(), | ||
inferred_params: vec![], | ||
infer_args: segment.infer_args, | ||
incorrect_args: &arg_count.correct, | ||
}; | ||
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness | ||
&& generics.has_self | ||
&& !tcx.has_attr(def_id, sym::const_trait) | ||
{ | ||
let e = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { | ||
span, | ||
modifier: constness.as_str(), | ||
}); | ||
self.set_tainted_by_errors(e); | ||
arg_count.correct = | ||
Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] }); | ||
} | ||
let args = lower_generic_args( | ||
tcx, | ||
def_id, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1118,7 +1118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
// to add defaults. If the user provided *too many* types, that's | ||
// a problem. | ||
|
||
let mut infer_args_for_err = FxHashSet::default(); | ||
let mut infer_args_for_err = None; | ||
|
||
let mut explicit_late_bound = ExplicitLateBound::No; | ||
for &GenericPathSegment(def_id, index) in &generic_segments { | ||
|
@@ -1136,9 +1136,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
explicit_late_bound = ExplicitLateBound::Yes; | ||
} | ||
|
||
if let Err(GenericArgCountMismatch { reported: Some(e), .. }) = arg_count.correct { | ||
infer_args_for_err.insert(index); | ||
self.set_tainted_by_errors(e); // See issue #53251. | ||
if let Err(GenericArgCountMismatch { reported, .. }) = arg_count.correct { | ||
infer_args_for_err | ||
.get_or_insert_with(|| (reported, FxHashSet::default())) | ||
.1 | ||
.insert(index); | ||
self.set_tainted_by_errors(reported); // See issue #53251. | ||
} | ||
} | ||
|
||
|
@@ -1232,15 +1235,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
}; | ||
let def_id = res.def_id(); | ||
|
||
let arg_count = GenericArgCountResult { | ||
explicit_late_bound, | ||
correct: if infer_args_for_err.is_empty() { | ||
Ok(()) | ||
} else { | ||
Err(GenericArgCountMismatch::default()) | ||
}, | ||
let (correct, infer_args_for_err) = match infer_args_for_err { | ||
Some((reported, args)) => { | ||
(Err(GenericArgCountMismatch { reported, invalid_args: vec![] }), args) | ||
} | ||
None => (Ok(()), Default::default()), | ||
}; | ||
|
||
let arg_count = GenericArgCountResult { explicit_late_bound, correct }; | ||
|
||
struct CtorGenericArgsCtxt<'a, 'tcx> { | ||
fcx: &'a FnCtxt<'a, 'tcx>, | ||
span: Span, | ||
|
@@ -1272,6 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
|
||
fn provided_kind( | ||
&mut self, | ||
_preceding_args: &[ty::GenericArg<'tcx>], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could actually allow generic const generics now here, but there's probably other work required elsewhere to support it properly There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah basically nothing is set up for that at all lol |
||
param: &ty::GenericParamDef, | ||
arg: &GenericArg<'tcx>, | ||
) -> ty::GenericArg<'tcx> { | ||
|
@@ -1314,7 +1318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
|
||
fn inferred_kind( | ||
&mut self, | ||
args: Option<&[ty::GenericArg<'tcx>]>, | ||
preceding_args: &[ty::GenericArg<'tcx>], | ||
param: &ty::GenericParamDef, | ||
infer_args: bool, | ||
) -> ty::GenericArg<'tcx> { | ||
|
@@ -1328,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
// If we have a default, then it doesn't matter that we're not | ||
// inferring the type arguments: we provide the default where any | ||
// is missing. | ||
tcx.type_of(param.def_id).instantiate(tcx, args.unwrap()).into() | ||
tcx.type_of(param.def_id).instantiate(tcx, preceding_args).into() | ||
} else { | ||
// If no type arguments were provided, we have to infer them. | ||
// This case also occurs as a result of some malformed input, e.g. | ||
|
@@ -1353,7 +1357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |
} else if !infer_args { | ||
return tcx | ||
.const_param_default(param.def_id) | ||
.instantiate(tcx, args.unwrap()) | ||
.instantiate(tcx, preceding_args) | ||
.into(); | ||
} | ||
} | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this not give a backwards range (i.e.
2..1
) if you have afn foo<'a: 'a, 'b: 'b>
and you call itfoo::<'static>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but that's the prev behaviour. I just merged the two loops