mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Implement changes suggested by varkor
This commit is contained in:
parent
7217d767b2
commit
4efa4a5273
@ -182,6 +182,8 @@ impl LanguageItemCollector<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Like collect_item() above, but also checks whether the lang item is declared
|
||||
// with the right number of generic arguments if it is a trait.
|
||||
fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
|
||||
let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
|
||||
let lang_item = LangItem::from_u32(item_index as u32).unwrap();
|
||||
@ -190,10 +192,15 @@ impl LanguageItemCollector<'tcx> {
|
||||
self.collect_item(item_index, item_def_id);
|
||||
|
||||
// Now check whether the lang_item has the expected number of generic
|
||||
// arguments. Binary and indexing operations have one (for the RHS/index),
|
||||
// unary operations have no generic arguments.
|
||||
// arguments if it is a trait. Generally speaking, binary and indexing
|
||||
// operations have one (for the RHS/index), unary operations have none,
|
||||
// and the rest also have none except for the closure traits (one for
|
||||
// the argument list), generators (one for the resume argument),
|
||||
// ordering/equality relations (one for the RHS), and various conversion
|
||||
// traits.
|
||||
|
||||
let expected_num = match lang_item {
|
||||
// Binary operations
|
||||
LangItem::Add
|
||||
| LangItem::Sub
|
||||
| LangItem::Mul
|
||||
@ -215,11 +222,48 @@ impl LanguageItemCollector<'tcx> {
|
||||
| LangItem::ShlAssign
|
||||
| LangItem::ShrAssign
|
||||
| LangItem::Index
|
||||
| LangItem::IndexMut => Some(1),
|
||||
| LangItem::IndexMut
|
||||
|
||||
LangItem::Neg | LangItem::Not | LangItem::Deref | LangItem::DerefMut => Some(0),
|
||||
// Miscellaneous
|
||||
| LangItem::Unsize
|
||||
| LangItem::CoerceUnsized
|
||||
| LangItem::DispatchFromDyn
|
||||
| LangItem::Fn
|
||||
| LangItem::FnMut
|
||||
| LangItem::FnOnce
|
||||
| LangItem::Generator
|
||||
| LangItem::PartialEq
|
||||
| LangItem::PartialOrd
|
||||
=> Some(1),
|
||||
|
||||
// FIXME: add more cases?
|
||||
// Unary operations
|
||||
LangItem::Neg
|
||||
| LangItem::Not
|
||||
|
||||
// Miscellaneous
|
||||
| LangItem::Deref
|
||||
| LangItem::DerefMut
|
||||
| LangItem::Sized
|
||||
| LangItem::StructuralPeq
|
||||
| LangItem::StructuralTeq
|
||||
| LangItem::Copy
|
||||
| LangItem::Clone
|
||||
| LangItem::Sync
|
||||
| LangItem::DiscriminantKind
|
||||
| LangItem::PointeeTrait
|
||||
| LangItem::Freeze
|
||||
| LangItem::Drop
|
||||
| LangItem::Receiver
|
||||
| LangItem::Future
|
||||
| LangItem::Unpin
|
||||
| LangItem::Termination
|
||||
| LangItem::Try
|
||||
| LangItem::Send
|
||||
| LangItem::UnwindSafe
|
||||
| LangItem::RefUnwindSafe
|
||||
=> Some(0),
|
||||
|
||||
// Not a trait
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
@ -1190,3 +1190,17 @@ fn fatally_break_rust(sess: &Session) {
|
||||
fn potentially_plural_count(count: usize, word: &str) -> String {
|
||||
format!("{} {}{}", count, word, pluralize!(count))
|
||||
}
|
||||
|
||||
fn has_expected_num_generic_args<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_did: Option<DefId>,
|
||||
mut expected: usize,
|
||||
) -> bool {
|
||||
trait_did.map_or(true, |trait_did| {
|
||||
let generics = tcx.generics_of(trait_did);
|
||||
if generics.has_self {
|
||||
expected += 1;
|
||||
}
|
||||
generics.count() == expected
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Code related to processing overloaded binary and unary operators.
|
||||
|
||||
use super::method::MethodCallee;
|
||||
use super::FnCtxt;
|
||||
use super::{has_expected_num_generic_args, FnCtxt};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
@ -800,17 +800,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 {
|
||||
if !has_expected_num_generic_args(
|
||||
self.tcx,
|
||||
trait_did,
|
||||
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(());
|
||||
}
|
||||
},
|
||||
) {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let method = trait_did.and_then(|trait_did| {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::check::method::MethodCallee;
|
||||
use crate::check::{FnCtxt, PlaceOp};
|
||||
use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp};
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::InferOk;
|
||||
@ -157,16 +157,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 {
|
||||
if !has_expected_num_generic_args(
|
||||
self.tcx,
|
||||
imm_tr,
|
||||
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;
|
||||
}
|
||||
},
|
||||
) {
|
||||
return None;
|
||||
}
|
||||
|
||||
imm_tr.and_then(|trait_did| {
|
||||
@ -197,16 +196,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// 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 {
|
||||
if !has_expected_num_generic_args(
|
||||
self.tcx,
|
||||
mut_tr,
|
||||
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;
|
||||
}
|
||||
},
|
||||
) {
|
||||
return None;
|
||||
}
|
||||
|
||||
mut_tr.and_then(|trait_did| {
|
||||
|
Loading…
Reference in New Issue
Block a user