Skip to content

Commit

Permalink
Rollup merge of rust-lang#125608 - oli-obk:subsequent_lifetime_errors…
Browse files Browse the repository at this point in the history
…, r=BoxyUwU

Avoid follow-up errors if the number of generic parameters already doesn't match

fixes rust-lang#125604

best reviewed commit-by-commit
  • Loading branch information
Noratrieb authored Jun 4, 2024
2 parents 57129ee + d498eb5 commit 8f97610
Show file tree
Hide file tree
Showing 21 changed files with 226 additions and 194 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
pub(crate) fn complain_about_missing_assoc_tys(
&self,
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
potential_assoc_types: Vec<Span>,
potential_assoc_types: Vec<usize>,
trait_bounds: &[hir::PolyTraitRef<'_>],
) {
if associated_types.values().all(|v| v.is_empty()) {
Expand Down
28 changes: 9 additions & 19 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,11 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
if let Some(&param) = params.peek() {
if param.index == 0 {
if let GenericParamDefKind::Type { .. } = param.kind {
assert_eq!(&args[..], &[]);
args.push(
self_ty
.map(|ty| ty.into())
.unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
.unwrap_or_else(|| ctx.inferred_kind(&args, param, true)),
);
params.next();
}
Expand Down Expand Up @@ -267,7 +268,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
// Since this is a const impl, we need to insert a host arg at the end of
// `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
// To work around this, we infer all arguments until we reach the host param.
args.push(ctx.inferred_kind(Some(&args), param, infer_args));
args.push(ctx.inferred_kind(&args, param, infer_args));
params.next();
}
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
Expand All @@ -281,7 +282,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
GenericParamDefKind::Const { .. },
_,
) => {
args.push(ctx.provided_kind(param, arg));
args.push(ctx.provided_kind(&args, param, arg));
args_iter.next();
params.next();
}
Expand All @@ -292,7 +293,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
) => {
// We expected a lifetime argument, but got a type or const
// argument. That means we're inferring the lifetimes.
args.push(ctx.inferred_kind(None, param, infer_args));
args.push(ctx.inferred_kind(&args, param, infer_args));
force_infer_lt = Some((arg, param));
params.next();
}
Expand Down Expand Up @@ -388,7 +389,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
(None, Some(&param)) => {
// If there are fewer arguments than parameters, it means
// we're inferring the remaining arguments.
args.push(ctx.inferred_kind(Some(&args), param, infer_args));
args.push(ctx.inferred_kind(&args, param, infer_args));
params.next();
}

Expand Down Expand Up @@ -474,16 +475,9 @@ pub(crate) fn check_generic_arg_count(
return Ok(());
}

if provided_args > max_expected_args {
invalid_args.extend(
gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()),
);
};
invalid_args.extend(min_expected_args..provided_args);

let gen_args_info = if provided_args > min_expected_args {
invalid_args.extend(
gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()),
);
let num_redundant_args = provided_args - min_expected_args;
GenericArgsInfo::ExcessLifetimes { num_redundant_args }
} else {
Expand Down Expand Up @@ -538,11 +532,7 @@ pub(crate) fn check_generic_arg_count(
let num_default_params = expected_max - expected_min;

let gen_args_info = if provided > expected_max {
invalid_args.extend(
gen_args.args[args_offset + expected_max..args_offset + provided]
.iter()
.map(|arg| arg.span()),
);
invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
let num_redundant_args = provided - expected_max;

// Provide extra note if synthetic arguments like `impl Trait` are specified.
Expand Down Expand Up @@ -610,7 +600,7 @@ pub(crate) fn check_generic_arg_count(
explicit_late_bound,
correct: lifetimes_correct
.and(args_correct)
.map_err(|reported| GenericArgCountMismatch { reported: Some(reported), invalid_args }),
.map_err(|reported| GenericArgCountMismatch { reported, invalid_args }),
}
}

Expand Down
78 changes: 47 additions & 31 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>;
Expand Down Expand Up @@ -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.
Expand All @@ -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> {
Expand All @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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();
}
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 {
Expand All @@ -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 {
Expand All @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/impl_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ fn enforce_impl_params_are_constrained(
let impl_predicates = tcx.predicates_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);

impl_trait_ref.error_reported()?;

let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
cgp::identify_constrained_generic_params(
tcx,
Expand Down
32 changes: 18 additions & 14 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
}
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -1272,6 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

fn provided_kind(
&mut self,
_preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
Expand Down Expand Up @@ -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> {
Expand All @@ -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.
Expand All @@ -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();
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {

fn provided_kind(
&mut self,
_preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
Expand Down Expand Up @@ -419,7 +420,7 @@ impl<'a, 'tcx> ConfirmContext<'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> {
Expand Down
20 changes: 0 additions & 20 deletions tests/crashes/121134.rs

This file was deleted.

Loading

0 comments on commit 8f97610

Please sign in to comment.