1
Fork 0

Report an error if a lang item has the wrong number of generic arguments

This commit is contained in:
Fabian Wolff 2021-05-15 19:53:16 +02:00
parent b439be03c9
commit 7217d767b2
12 changed files with 212 additions and 7 deletions

View file

@ -303,8 +303,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
opt_input_types: Option<&[Ty<'tcx>]>,
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
debug!(
"lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?})",
self_ty, m_name, trait_def_id
"lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?}, opt_input_types={:?})",
self_ty, m_name, trait_def_id, opt_input_types
);
// Construct a trait-reference `self_ty : Trait<input_tys>`

View file

@ -795,6 +795,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lhs_ty, op, opname, trait_did
);
// Catches cases like #83893, where a lang item is declared with the
// wrong number of generic arguments. Should have yielded an error
// elsewhere by now, but we have to catch it here so that we do not
// index `other_tys` out of bounds (if the lang item has too many
// generic arguments, `other_tys` is too short).
if let Some(trait_did) = trait_did {
let generics = self.tcx.generics_of(trait_did);
let expected_num = match op {
// Binary ops have a generic right-hand side, unary ops don't
Op::Binary(..) => 1,
Op::Unary(..) => 0,
} + if generics.has_self { 1 } else { 0 };
let num_generics = generics.count();
if num_generics != expected_num {
return Err(());
}
}
let method = trait_did.and_then(|trait_did| {
let opname = Ident::with_dummy_span(opname);
self.lookup_method_in_trait(span, opname, trait_did, lhs_ty, Some(other_tys))

View file

@ -153,6 +153,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref),
PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index),
};
// If the lang item was declared incorrectly, stop here so that we don't
// run into an ICE (#83893). The error is reported where the lang item is
// declared.
if let Some(trait_did) = imm_tr {
let generics = self.tcx.generics_of(trait_did);
let expected_num = match op {
PlaceOp::Deref => 0,
PlaceOp::Index => 1,
} + if generics.has_self { 1 } else { 0 };
let num_generics = generics.count();
if num_generics != expected_num {
return None;
}
}
imm_tr.and_then(|trait_did| {
self.lookup_method_in_trait(
span,
@ -177,6 +193,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PlaceOp::Deref => (self.tcx.lang_items().deref_mut_trait(), sym::deref_mut),
PlaceOp::Index => (self.tcx.lang_items().index_mut_trait(), sym::index_mut),
};
// If the lang item was declared incorrectly, stop here so that we don't
// run into an ICE (#83893). The error is reported where the lang item is
// declared.
if let Some(trait_did) = mut_tr {
let generics = self.tcx.generics_of(trait_did);
let expected_num = match op {
PlaceOp::Deref => 0,
PlaceOp::Index => 1,
} + if generics.has_self { 1 } else { 0 };
let num_generics = generics.count();
if num_generics != expected_num {
return None;
}
}
mut_tr.and_then(|trait_did| {
self.lookup_method_in_trait(
span,