Auto merge of #123240 - compiler-errors:assert-args-compat, r=fmease
Assert that args are actually compatible with their generics, rather than just their count Right now we just check that the number of args is right, rather than actually checking the kinds. Uplift a helper fn that I wrote from trait selection to do just that. Found a couple bugs along the way. r? `@lcnr` or `@fmease` (or anyone really lol)
This commit is contained in:
commit
b4acbe4233
10 changed files with 151 additions and 114 deletions
|
@ -1,4 +1,4 @@
|
|||
use crate::traits::{check_args_compatible, specialization_graph};
|
||||
use crate::traits::specialization_graph;
|
||||
|
||||
use super::assembly::structural_traits::AsyncCallableRelevantTypes;
|
||||
use super::assembly::{self, structural_traits, Candidate};
|
||||
|
@ -247,7 +247,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
|||
assoc_def.defining_node,
|
||||
);
|
||||
|
||||
if !check_args_compatible(tcx, assoc_def.item, args) {
|
||||
if !tcx.check_args_compatible(assoc_def.item.def_id, args) {
|
||||
return error_response(
|
||||
ecx,
|
||||
"associated item has mismatched generic item arguments",
|
||||
|
|
|
@ -61,12 +61,12 @@ pub use self::specialize::{
|
|||
pub use self::structural_match::search_for_structural_match_violation;
|
||||
pub use self::structural_normalize::StructurallyNormalizeExt;
|
||||
pub use self::util::elaborate;
|
||||
pub use self::util::{
|
||||
check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds,
|
||||
transitive_bounds_that_define_assoc_item, SupertraitDefIds,
|
||||
};
|
||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
|
||||
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
||||
pub use self::util::{
|
||||
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
|
||||
SupertraitDefIds,
|
||||
};
|
||||
pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
||||
|
||||
pub use rustc_infer::traits::*;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use super::check_args_compatible;
|
||||
use super::specialization_graph;
|
||||
use super::translate_args;
|
||||
use super::util;
|
||||
|
@ -2030,7 +2029,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
|||
} else {
|
||||
ty.map_bound(|ty| ty.into())
|
||||
};
|
||||
if !check_args_compatible(tcx, assoc_ty.item, args) {
|
||||
if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
|
||||
let err = Ty::new_error_with_message(
|
||||
tcx,
|
||||
obligation.cause.span,
|
||||
|
|
|
@ -344,48 +344,6 @@ pub enum TupleArgumentsFlag {
|
|||
No,
|
||||
}
|
||||
|
||||
// Verify that the trait item and its implementation have compatible args lists
|
||||
pub fn check_args_compatible<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
assoc_item: ty::AssocItem,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> bool {
|
||||
fn check_args_compatible_inner<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generics: &'tcx ty::Generics,
|
||||
args: &'tcx [ty::GenericArg<'tcx>],
|
||||
) -> bool {
|
||||
if generics.count() != args.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let (parent_args, own_args) = args.split_at(generics.parent_count);
|
||||
|
||||
if let Some(parent) = generics.parent
|
||||
&& let parent_generics = tcx.generics_of(parent)
|
||||
&& !check_args_compatible_inner(tcx, parent_generics, parent_args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (param, arg) in std::iter::zip(&generics.params, own_args) {
|
||||
match (¶m.kind, arg.unpack()) {
|
||||
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
|
||||
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
|
||||
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
let generics = tcx.generics_of(assoc_item.def_id);
|
||||
// Chop off any additional args (RPITIT) args
|
||||
let args = &args[0..generics.count().min(args.len())];
|
||||
check_args_compatible_inner(tcx, generics, args)
|
||||
}
|
||||
|
||||
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
|
||||
/// and then replaces these placeholders with the original bound variables in the result.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue